diff --git a/product/ERP5Type/Core/Folder.py b/product/ERP5Type/Core/Folder.py
deleted file mode 100644
index a61dcdd8aa73865987083018e188e75ccc40a8d9..0000000000000000000000000000000000000000
--- a/product/ERP5Type/Core/Folder.py
+++ /dev/null
@@ -1,875 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
-#          Jean-Paul Smets-Solanes <jp@nexedi.com>
-#
-# WARNING: This program as such is intended to be used by professional
-# programmers who take the whole responsability of assessing all potential
-# consequences resulting from its eventual inadequacies and bugs
-# End users who are looking for a ready-to-use solution with commercial
-# garantees and support are strongly adviced to contract a Free Software
-# Service Company
-#
-# This program is Free Software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-#
-##############################################################################
-
-from AccessControl import ClassSecurityInfo
-from Acquisition import aq_base, aq_self
-from OFS.History import Historical
-import ExtensionClass
-
-from Products.CMFCore.utils import _getAuthenticatedUser
-from Products.CMFCore.CMFCatalogAware import CMFCatalogAware
-
-from Products.ERP5Type.Base import Base
-from Products.ERP5Type.CopySupport import CopyContainer
-from Products.ERP5Type import PropertySheet, Permissions
-from Products.ERP5Type.XMLExportImport import Folder_asXML
-from Products.ERP5Type.Cache import CachingMethod
-from Products.ERP5Type.Utils import sortValueList
-
-try:
-  from Products.CMFCore.CMFBTreeFolder import CMFBTreeFolder
-except ImportError:
-  from Products.BTreeFolder2.CMFBTreeFolder import CMFBTreeFolder
-from AccessControl import getSecurityManager
-from Products.ERP5Type import Permissions
-from random import randint
-
-import os
-
-from zLOG import LOG, PROBLEM
-
-# Dummy Functions for update / upgrade
-def dummyFilter(object,REQUEST=None):
-  return 1
-
-def dummyTestAfter(object,REQUEST=None):
-  return []
-
-class FolderMixIn(ExtensionClass.Base):
-  """A mixin class for folder operations, add content, delete content etc.
-  """
-
-  # Declarative security
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-
-  security.declarePublic('newContent')
-  def newContent(self, id=None, portal_type=None, id_group=None,
-          default=None, method=None, immediate_reindex=0,
-          container=None, created_by_builder=0, activate_kw=None,
-          is_indexable=None, temp_object=0, **kw):
-    """Creates a new content.
-    This method is public, since TypeInformation.constructInstance will perform
-    the security check.
-    """
-    if container is None:
-      container = self
-    if id is None:
-      new_id = str(container.generateNewId(id_group = id_group,
-                                           default=default, method=method))
-    else:
-      new_id = str(id)
-    if portal_type is None:
-      # XXX This feature is very confusing 
-      # And made the code more difficult to update
-      portal_type = container.allowedContentTypes()[0].id
-
-    if temp_object:
-      from Products.ERP5Type import Document
-      # we get an object from factory only for first temp container object
-      # otherwise we get an id so we can use the classic way
-      if not hasattr(container, 'isTempObject') or \
-             (hasattr(container, 'isTempObject') and not container.isTempObject()):
-        factory_name = 'newTemp%s' %(portal_type.replace(' ', ''))
-        m = getattr(Document, factory_name)
-        return m(container, new_id)
-
-    self.portal_types.constructContent(type_name=portal_type,
-                                       container=container,
-                                       id=new_id,
-                                       created_by_builder=created_by_builder,
-                                       activate_kw=activate_kw,
-                                       is_indexable=is_indexable
-                                       ) # **kw) removed due to CMF bug
-    # TODO :the **kw makes it impossible to create content not based on
-    # ERP5TypeInformation, because factory method often do not support
-    # keywords arguments.
-    
-    new_instance = container[new_id]
-    if kw != {} : new_instance._edit(force_update=1, **kw)
-    if immediate_reindex: new_instance.immediateReindexObject()
-    return new_instance
-  
-  security.declareProtected(
-            Permissions.DeletePortalContent, 'deleteContent')
-  def deleteContent(self, id):
-    """ delete items in this folder.
-      `id` can be a list or a string.
-    """
-    if isinstance(id, str):
-      self._delObject(id)
-    elif isinstance(id, list) or isinstance(id, tuple):
-      for my_id in id:
-        self._delObject(my_id)
-    else:
-      raise TypeError, 'deleteContent only accepts string or list, '\
-                       'not %s' % type(id)
-
-  def _generateRandomId(self):
-    """
-      Generate a random Id.
-      10000 factor makes the odd to generate an already existing Id of 1 out
-      of 10000, not depending on the number of objects present in this folder.
-      len(self)+1 to make sure generation works on an empty Folder.
-    """
-    return '%X' % (randint(1, 10000 * (len(self) + 1)), )
- 
-  def _generateNextId(self):
-    """
-      Get the last generated Id, increment it until no object with generated
-      Id exist, then save the Id.
-    """
-    try:
-      my_id = int(self.getLastId())
-    except TypeError:
-      my_id = 1
-    while self.hasContent(str(my_id)):
-      my_id = my_id + 1
-    my_id = str(my_id)
-    self._setLastId(my_id) # Make sure no reindexing happens
-    return my_id
-
-  # Automatic ID Generation method
-  security.declareProtected(Permissions.View, 'generateNewId')
-  def generateNewId(self,id_group=None,default=None,method=None):
-    """
-      Generate a new Id which has not been taken yet in this folder.
-      Eventually increment the id number until an available id
-      can be found
-
-      Permission is view because we may want to add content to a folder
-      without changing the folder content itself.
-      XXX
-    """
-    my_id = None
-    if id_group is None:
-      id_group = self.getIdGroup()
-    if id_group in (None, 'None'):
-      id_generator = self.getIdGenerator()
-      if not isinstance(id_generator, str):
-        LOG('Folder.generateNewId', 0, '%s.id_generator is not a string. Falling back on default behaviour.' % (self.absolute_url(), ))
-        id_generator = ''
-      if id_generator != '': # Custom aq_dynamic function (like the one defined on WebSite objects) can find an object which has no name. So we must recognise the default value of id_generator and force safe fallback in this case.
-        idGenerator = getattr(self, id_generator, None)
-        if idGenerator is None:
-          idGenerator = self._generateNextId
-      else:
-        idGenerator = self._generateNextId
-      my_id = idGenerator()
-      while self.hasContent(my_id):
-        my_id = _generateNextId()
-    else:
-      my_id = str(self.portal_ids.generateNewId(id_group=id_group,default=default,method=method))
-    return my_id
-
-  security.declareProtected(Permissions.View, 'hasContent')
-  def hasContent(self,id):
-    return self.hasObject(id)
-
-  # Get the content
-  security.declareProtected(Permissions.View, 'searchFolder')
-  def searchFolder(self, **kw):
-    """
-      Search the content of a folder by calling
-      the portal_catalog.
-    """
-    if not kw.has_key('parent_uid'): #WHY ????
-      kw['parent_uid'] = self.getUid()
-
-    # Make sure that if we use parent base category
-    # We do not have conflicting parent uid values
-    delete_parent_uid = 0
-    if kw.has_key('selection_domain'):
-      if kw['selection_domain'].asDomainDict().has_key('parent'):
-        delete_parent_uid = 1
-    if kw.has_key('selection_report'):
-      if kw['selection_report'].asDomainDict().has_key('parent'):
-        delete_parent_uid = 1
-    if delete_parent_uid:
-      del kw['parent_uid']
-
-    kw2 = {}
-    # Remove useless matter before calling the
-    # catalog. In particular, consider empty
-    # strings as None values
-    for cname in kw.keys():
-      if kw[cname] != '' and kw[cname] != None:
-        kw2[cname] = kw[cname]
-    # The method to call to search the folder
-    # content has to be called z_search_folder
-    method = self.portal_catalog.portal_catalog
-    return method(**kw2)
-
-  security.declareProtected(Permissions.View, 'countFolder')
-  def countFolder(self, **kw):
-    """
-      Search the content of a folder by calling
-      the portal_catalog.
-    """
-    if not kw.has_key('parent_uid'): #WHY ????
-      kw['parent_uid'] = self.getUid()
-
-    # Make sure that if we use parent base category
-    # We do not have conflicting parent uid values
-    delete_parent_uid = 0
-    if kw.has_key('selection_domain'):
-      if kw['selection_domain'].asDomainDict().has_key('parent'):
-        delete_parent_uid = 1
-    if kw.has_key('selection_report'):
-      if kw['selection_report'].asDomainDict().has_key('parent'):
-        delete_parent_uid = 1
-    if delete_parent_uid:
-      del kw['parent_uid']
-
-    kw2 = {}
-    # Remove useless matter before calling the
-    # catalog. In particular, consider empty
-    # strings as None values
-    for cname in kw.keys():
-      if kw[cname] != '' and kw[cname]!=None:
-        kw2[cname] = kw[cname]
-    # The method to call to search the folder
-    # content has to be called z_search_folder
-    method = self.portal_catalog.countResults
-    return method(**kw2)
-
-  # Count objects in the folder
-  security.declarePrivate('_count')
-  def _count(self, **kw):
-    """
-      Returns the number of items in the folder.
-    """
-    return self.countFolder(**kw)[0][0]
-
-class Folder( CopyContainer, CMFBTreeFolder, Base, FolderMixIn):
-  """
-  A Folder is a subclass of Base but not of XMLObject.
-  Folders are not considered as documents and are therefore
-  not synchronisable.
-
-  ERP5 folders are implemented as CMFBTreeFolder objects
-  and can store up to a million documents on a standard
-  computer.
-  ERP5 folders will eventually use in the near future the
-  AdaptableStorage implementation in order to reach performances
-  of 10 or 100 millions of documents in a single folder.
-
-  ERP5 folders include an automatic id generation feature
-  which allows user not to define an id when they create
-  a new document in a folder.
-
-  ERP5 folders use the ZSQLCatalog to search for objects
-  or display content. This requires a method called
-  *z_search_folder* to be put inside the ZSQLCatalog object
-  of the ERP5 portal.
-
-  An ERP5 Binder document class will eventually be defined
-  in order to implement a binder of documents which can itself
-  be categorized.
-  """
-
-  meta_type = 'ERP5 Folder'
-  portal_type = 'Folder'
-  add_permission = Permissions.AddPortalContent
-  isPortalContent = 1
-  isRADContent = 1
-
-  # Declarative security
-  security = ClassSecurityInfo()
-  security.declareObjectProtected(Permissions.AccessContentsInformation)
-  
-  manage_options = ( CMFBTreeFolder.manage_options +
-                     Historical.manage_options +
-                     CMFCatalogAware.manage_options
-                   )
-  # Declarative properties
-  property_sheets = ( PropertySheet.Base
-                    , PropertySheet.XMLObject
-                    , PropertySheet.SimpleItem
-                    , PropertySheet.Folder
-                    )
-
-  # Class inheritance fixes
-  security.declareProtected( Permissions.ModifyPortalContent, 'edit' )
-  edit = Base.edit
-  security.declareProtected( Permissions.ModifyPortalContent, '_edit' )
-  _edit = Base._edit
-  _setPropValue = Base._setPropValue
-  _propertyMap = Base._propertyMap # are there any others XXX ?
-
-  # Override Zope default by folder id generation
-  def _get_id(self, id):
-    if self._getOb(id, None) is None :
-      return id
-    return self.generateNewId()
-    
-  #security.declareProtected( Permissions.DeletePortalContent, 'manage_delObjects' )
-  #manage_delObjects = CopyContainer.manage_delObjects
-
-  # Implementation
-#   security.declarePrivate('_setObject')
-#   def _setObject(self, id, object, roles=None, user=None, set_owner=1):
-#     """
-#       This method is here in order to dynamically update old
-#       folders into the new BTree folder type.
-#       This method is destructive in the sens that objects
-#       of the old folder will be lost during the update
-#     """
-#     # First make sur the folder has been initialized
-#     if not hasattr(self, '_tree'):
-#       CMFBTreeFolder.__init__(self, self.id)
-#     if not self._tree:
-#       CMFBTreeFolder.__init__(self, self.id)
-#     # Then insert the object
-#     CMFBTreeFolder._setObject(self, id, object, roles=roles, user=user, set_owner=set_owner)
-# This method destroys the title when we create new object in empty folder
-
-  security.declareProtected(Permissions.View, 'hasContent')
-  def hasContent(self,id):
-    return self.hasObject(id)
-
-  security.declareProtected( Permissions.ModifyPortalContent, 'exportAll' )
-  def exportAll(self,dir=None):
-    """
-    Allows to export all object inside a particular folder, one by one
-    """
-    folder_id = self.getId()
-    if dir != None:
-      for id in self.objectIds():
-        f = os.path.join(dir, '%s___%s.zexp' % (folder_id,id))
-        ob = self._getOb(id)
-        ob._p_jar.exportFile(ob._p_oid,f)
-      get_transaction().commit()
-
-  security.declareProtected( Permissions.ModifyPortalContent, 'recursiveApply')
-  def recursiveApply(self, filter=dummyFilter, method=None,
-                    test_after=dummyTestAfter, include=1, REQUEST=None, **kw):
-    """
-      Apply a method to self and to all children
-
-      filter      --    only instances which return 1 when applied filter
-                        are considered
-
-      method      --    the method to apply to acceptable instances
-
-      test_after  --    test to apply after calling method in order to search
-                        for inconsistencies
-
-      include     --    if set to 1 (default), apply method to self
-
-
-      REQUEST     --    the http REQUEST (if needed)
-
-      **kw        --    optional parameters passed to method
-    """
-    update_list = []
-    #LOG('Folder, recursiveApply ',0,"first one self.path: %s" % self.getPath())
-
-    # Only apply method to self if filter is to 1 and filter returns 1
-    if include==1 and filter(object=self.getObject(),REQUEST=REQUEST):
-      method_message = method(object=self.getObject(),REQUEST=REQUEST, **kw)
-      if type(method_message) is type([]):
-        update_list += method_message
-      update_list += test_after(object=self.getObject(),REQUEST=REQUEST)
-
-    for o in self.objectValues(): # contentValues sometimes fail in BTreeFolder
-      # Test on each sub object if method should be applied
-      if filter(object=o,REQUEST=REQUEST):
-        method_message = method(object=o,REQUEST=REQUEST, **kw)
-        if type(method_message) is type([]):
-          update_list += method_message
-        update_list += test_after(o,REQUEST=REQUEST)
-      # And commit subtransaction
-      #get_transaction().commit(1)
-      get_transaction().commit() # we may use commit(1) some day XXX
-      # Recursively call recursiveApply if o has a recursiveApply method (not acquired)
-      obase = aq_base(o)
-      if hasattr(obase, 'recursiveApply'):
-        #LOG('Found recursiveApply', 0, o.absolute_url())
-        update_list += o.recursiveApply(filter=filter, \
-                              method=method, test_after=test_after,REQUEST=REQUEST,include=0,**kw)
-
-    return update_list
-
-  security.declareProtected( Permissions.ModifyPortalContent, 'updateAll' )
-  def updateAll(self, filter=None, method=None, test_after=None, request=None, include=1,**kw):
-    """
-    update all objects inside this particular folder wich
-    returns not None to the test.
-
-    filter have to be a method with one parameter (the object)
-    wich returns None if we must not update the object
-
-    test_after have to be a method with one parameter (the object)
-    wich returns a string
-
-    method is the update method with also one parameter
-
-    """
-    update_list = []
-    #LOG('Folder, updateAll ',0,"first one self.path: %s" % self.getPath())
-
-    if include==1 and filter(object=self.getObject(),request=request):
-      method_message = method(object=self.getObject(),request=request)
-      if type(method_message) is type([]):
-        update_list += method_message
-      update_list += test_after(object=self.getObject(),request=request)
-
-    for o in self.objectValues():
-      # Test if we must apply the upgrade
-      if filter(object=o,request=request):
-        method_message = method(object=o,request=request)
-        if type(method_message) is type([]):
-          update_list += method_message
-        update_list += test_after(object=o,request=request)
-      #for object in o.objectValues():
-        #LOG('Folder, updateAll ',0,"object.id: %s" % object.id)
-      obase = aq_base(o)
-      get_transaction().commit()
-      if hasattr(obase, 'updateAll'):
-        update_list += o.updateAll(filter=filter, \
-                              method=method, test_after=test_after,request=request,include=0,**kw)
-
-    return update_list
-
-  security.declareProtected( Permissions.ModifyPortalContent, 'upgradeObjectClass' )
-  def upgradeObjectClass(self, test_before=None, from_class=None,\
-                         to_class=None, test_after=None):
-    """
-    upgrade the class of all objects inside this
-    particular folder
-     test have to be a method with one parameter
-     migrations is a dictionnary of class, { from_class : to_class }
-    """
-    #LOG("upradeObjectClass: folder ",0,self.id)
-    test_list = []
-    folder = self.getObject()
-    for o in self.listFolderContents():
-      # Make sure this sub object is not the same as object
-      if o.getPhysicalPath() != self.getPhysicalPath():
-        id = o.getId()
-        obase = aq_base(o)
-        # Check if the subobject have to also be upgraded
-        if hasattr(obase,'upgradeObjectClass'):
-          test_list += o.upgradeObjectClass(test_before=test_before, \
-                          from_class=from_class, to_class=to_class,
-                          test_after=test_after)
-        # Test if we must apply the upgrade
-        if test_before(o) is not None:
-          LOG("upradeObjectClass: id ",0,id)
-          klass = obase.__class__
-          LOG("upradeObjectClass: klass ",0,str(klass))
-          LOG("upradeObjectClass: from_class ",0,str(from_class))
-          if klass == from_class:
-            try:
-                newob = to_class(obase.id)
-                newob.id = obase.id # This line activates obase.
-            except AttributeError:
-                newob = to_class(id)
-                newob.id = id
-            keys = obase.__dict__.keys()
-            for k in keys:
-              if k not in ('id', 'meta_type', '__class__'):
-                setattr(newob,k,obase.__dict__[k])
-
-            self.manage_delObjects(id)
-            LOG("upradeObjectClass: ",0,"add new object: %s" % str(newob.id))
-            get_transaction().commit() # XXX this commit should be after _setObject
-            LOG("upradeObjectClass: ",0,"newob.__class__: %s" % str(newob.__class__))
-            self._setObject(id, newob)
-            object_to_test = self._getOb(id)
-            test_list += test_after(object_to_test)
-
-    return test_list
-
-
-  # Catalog related
-  security.declarePublic( 'reindexObject' )
-  def reindexObject(self, *args, **kw):
-    """
-      Fixes the hierarchy structure (use of Base class)
-      XXXXXXXXXXXXXXXXXXXXXXXX
-      BUG here : when creating a new base category
-    """
-    return Base.reindexObject(self, *args, **kw)
-
-  security.declareProtected(Permissions.ModifyPortalContent, 'reindexObjectSecurity')
-  def reindexObjectSecurity(self):
-    """
-        Reindex security-related indexes on the object
-        (and its descendants).
-    """
-    # In ERP5, simply reindex all objects.
-    self.recursiveReindexObject()
-
-  security.declarePublic( 'recursiveReindexObject' )
-  def recursiveReindexObject(self, *args, **kw):
-    """
-      Fixes the hierarchy structure (use of Base class)
-      XXXXXXXXXXXXXXXXXXXXXXXX
-      BUG here : when creating a new base category
-    """
-    if self.isIndexable:
-      self.activate(group_method_id='portal_catalog/catalogObjectList', expand_method_id='getIndexableChildValueList', alternate_method_id='alternateReindexObject', **kw).recursiveImmediateReindexObject(*args, **kw)
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'getIndexableChildValueList' )
-  def getIndexableChildValueList(self):
-    """
-      Get indexable childen recursively.
-    """
-    value_list = []
-    if self.isIndexable:
-      value_list.append(self)
-      for c in self.objectValues():
-        if hasattr(aq_base(c), 'getIndexableChildValueList'):
-          value_list.extend(c.getIndexableChildValueList())
-    return value_list
-
-  security.declarePublic( 'recursiveImmediateReindexObject' )
-  def recursiveImmediateReindexObject(self, *args, **kw):
-      """
-        Applies immediateReindexObject recursively
-      """
-      # Reindex self
-      root_indexable = int(getattr(self.getPortalObject(),'isIndexable',1))
-      if self.isIndexable and root_indexable:
-        self.flushActivity(invoke = 0, method_id='immediateReindexObject') # This might create a recursive lock
-        self.flushActivity(invoke = 0, method_id='recursiveImmediateReindexObject') # This might create a recursive lock
-        self.immediateReindexObject(*args, **kw)
-      # Reindex contents
-      #LOG('recursiveImmediateReindexObject', 0, 'self = %r, self.objectValues = %r' % (self, self.objectValues()))
-      for c in self.objectValues():
-        if hasattr(aq_base(c), 'recursiveImmediateReindexObject'):
-          c.recursiveImmediateReindexObject(*args, **kw)
-
-  security.declareProtected( Permissions.ModifyPortalContent, 'recursiveMoveObject' )
-  def recursiveMoveObject(self):
-    """
-      Called when the base of a hierarchy is renamed
-    """
-    # Reindex self
-    if self.isIndexable:
-      self.moveObject()
-    # Reindex contents
-    for c in self.objectValues():
-      if hasattr(aq_base(c), 'recursiveMoveObject'):
-        c.recursiveMoveObject()
-
-  # Special Relation keyword : 'content' and 'container'
-  security.declareProtected( Permissions.AccessContentsInformation, '_getCategoryMembershipList' )
-  def _getCategoryMembershipList(self, category,
-                          spec=(), filter=None, portal_type=(), base=0 ):
-    if category == 'content':
-      content_list = self.searchFolder(portal_type=spec)
-      return map(lambda x: x.relative_url, content_list)
-    else:
-      return Base.getCategoryMembershipList(self, category,
-          spec=spec, filter=filter, portal_type=portal_type,  base=base)
-
-  # Alias - class inheritance resolution
-  security.declareProtected( Permissions.View, 'Title' )
-  Title = Base.Title
-
-  security.declareProtected(Permissions.AccessContentsInformation,
-                            'checkConsistency')
-  def checkConsistency(self, fixit=0):
-    """
-    Check the consistency of this object, then
-    check recursively the consistency of every sub object.
-    """
-    error_list = []
-    # Fix BTree
-    if fixit:
-      btree_ok = self._cleanup()
-      if not btree_ok:
-        # We must commit if we want to keep on recursing
-        get_transaction().commit(1)
-        error_list += [(self.getRelativeUrl(), 'BTree Inconsistency',
-                       199, '(fixed)')]
-    # Call superclass
-    error_list += Base.checkConsistency(self, fixit=fixit)
-    # We must commit before listing folder contents
-    # in case we erased some data
-    if fixit:
-      get_transaction().commit(1)
-    # Then check the consistency on all sub objects
-    for obj in self.contentValues():
-      if fixit:
-        extra_errors = obj.fixConsistency()
-      else:
-        extra_errors = obj.checkConsistency()
-      if len(extra_errors) > 0:
-        error_list += extra_errors
-    # We should also return an error if any
-    return error_list
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'asXML' )
-  def asXML(self, ident=0):
-    """
-        Generate an xml text corresponding to the content of this object
-    """
-    return Folder_asXML(self,ident=ident)
-
-  # Optimized Menu System
-  security.declarePublic('getVisibleAllowedContentTypeList')
-  def getVisibleAllowedContentTypeList(self):
-    """
-      List portal_types' names wich can be added in this folder / object.
-      Cache results.
-
-      This function is *much* similar to allowedContentTypes, except it does
-      not returns portal types but their ids and filter out those listed as
-      hidden content types. It allows to be much faster when only the type id
-      is needed.
-    """
-    if not getSecurityManager().checkPermission(
-                      Permissions.AddPortalContent, self):
-      return []
-
-    portal = self.getPortalObject()
-
-    def _getVisibleAllowedContentTypeList():
-      hidden_type_list = portal.portal_types.getTypeInfo(self).getHiddenContentTypeList()
-      return [type.id for type in CMFBTreeFolder.allowedContentTypes(self) if type.id not in hidden_type_list]
-
-    user = str(_getAuthenticatedUser(self))
-    portal_type = self.getPortalType()
-    portal_path = portal.getPhysicalPath()
-
-    _getVisibleAllowedContentTypeList = CachingMethod(_getVisibleAllowedContentTypeList,
-                                                      id=("_getAllowedContentTypeTitleList",
-                                                          user, portal_path, portal_type),
-                                                      cache_duration=None)
-    return _getVisibleAllowedContentTypeList()
-  
-  security.declarePublic('allowedContentTypes')
-  def allowedContentTypes( self ):
-    """ List portal_types which can be added in this folder / object.
-        Cache results.
-        Only paths are cached, because we must not cache objects.
-        This makes the result, even if based on cache, O(n) so it becomes quite 
-        costly with many allowed content types.
-        Example:
-         on Person (12 allowed content types): 1000 calls take 3s.
-         on Person Module (1 allowed content type): 1000 calls take 0.3s.
-    """
-    # if we don't have add portal content permission, return directly.
-    # this prevents returning cached allowed types when the user no longer have
-    # the permission to any content type. (security definitions in workflows
-    # usually remove some permission once an object is "Valid")
-    # This also prevents filling the cache with an empty list, when the user
-    # does not have the permission to add any content yet.
-
-    # XXX this works just fine, unless some objects can be added with another
-    # permission that "Add portal content". For now, this is only the case for
-    # Role Definition objects, but this shows that generally speaking, this is
-    # not the right approach.
-    if not getSecurityManager().checkPermission(
-                      Permissions.AddPortalContent, self):
-      return []
-    
-    def _allowedContentTypes( portal_type=None, user=None, portal_path=None ):
-      # Sort the list for convenience -yo
-      # XXX This is not the best solution, because this does not take
-      # account i18n into consideration.
-      # XXX So sorting should be done in skins, after translation is performed.
-      def compareTypes(a, b): return cmp(a.title or a.id, b.title or b.id)
-      type_list = CMFBTreeFolder.allowedContentTypes(self)
-      type_list.sort(compareTypes)
-      return ['/'.join(x.getPhysicalPath()) for x in type_list]
-    
-    _allowedContentTypes = CachingMethod( _allowedContentTypes,
-                                          id = 'allowedContentTypes',
-                                          cache_duration = None)
-    user = str(_getAuthenticatedUser(self))
-    portal_type = self.getPortalType()
-    portal = self.getPortalObject()
-    portal_path = portal.getPhysicalPath()
-    return [portal.restrictedTraverse(path) for path in
-              _allowedContentTypes( portal_type = portal_type,
-                                    user = user,
-                                    portal_path = portal_path )]
-
-  # Multiple Inheritance Priority Resolution
-  _setProperty = Base._setProperty
-  setProperty = Base.setProperty
-  getProperty = Base.getProperty
-  hasProperty = Base.hasProperty
-  view = Base.view
-
-  # Aliases
-  getObjectIds = CMFBTreeFolder.objectIds
-
-  # Overloading
-  security.declareProtected( Permissions.AccessContentsInformation, 'getParentSQLExpression' )
-  def getParentSQLExpression(self, table = 'catalog', strict_membership = 0):
-    """
-      Builds an SQL expression to search children and subclidren
-    """
-    if strict_membership:
-      return Base.getParentSQLExpression(self, table=table, strict_membership=strict_membership)
-    result = "%s.parent_uid = %s" % (table, self.getUid())
-    for o in self.objectValues():
-      if hasattr(aq_base(o), 'objectValues'):
-        # Do not consider non folder objects
-        result = "%s OR %s" % (result, o.getParentSQLExpression(table=table, strict_membership=strict_membership))
-    return "( %s )" % result
-
-
-  def mergeContent(self,from_object=None,to_object=None, delete=1,**kw):
-    """
-    This method will merge two objects.
-
-    When we have to different objects wich represent the same content, we
-    may want to merge them. In this case, we want to be sure to report
-
-    """
-    if from_object is None or to_object is None:
-      return
-
-    from_object_related_object_list = self.portal_categories.getRelatedValueList(from_object)
-    to_object_url = to_object.getRelativeUrl()
-    from_object_url = from_object.getRelativeUrl()
-    corrected_list = []
-    for object in from_object_related_object_list:
-      #LOG('Folder.mergeContent, working on object:',0,object)
-      object_url = object.getRelativeUrl()
-      new_category_list = []
-      found = 0
-      for category in object.getCategoryList(): # so ('destination/person/1',...)
-        #LOG('Folder.mergeContent, working on category:',0,category)
-        linked_object_url = '/'.join(category.split('/')[1:])
-        if linked_object_url == from_object_url:
-          base_category = category.split('/')[0]
-          found = 1
-          new_category_list.append(base_category + '/' + to_object_url)
-        else:
-          new_category_list.append(category)
-      if found:
-        corrected_list.append(object)
-        object.setCategoryList(new_category_list)
-        object.immediateReindexObject()
-    if delete:
-      if len(from_object.portal_categories.getRelatedValueList(from_object))==0:
-        parent = from_object.getParentValue()
-        parent.manage_delObjects(from_object.getId())
-    return corrected_list
-
-  security.declareProtected( Permissions.AccessContentsInformation,
-                             'objectValues' )
-  def objectValues(self, spec=None, meta_type=None, portal_type=None,
-                   sort_on=None, sort_order=None, **kw):
-    """
-    Returns a list containing object contained in this folder.
-    """
-    if meta_type is not None:
-      spec = meta_type
-    # when an object inherits from Folder after it was instanciated, it lacks
-    # its BTreeFolder properties.
-    if getattr(self, '_tree', None) is None:
-      try:
-        self._initBTrees()
-      except AttributeError:
-        from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2Base
-        BTreeFolder2Base.__init__(self, self.getId())
-    object_list = CMFBTreeFolder.objectValues(self, spec=spec)
-    if portal_type is not None:
-      if type(portal_type) == type(''):
-        portal_type = (portal_type,)
-      object_list = filter(lambda x: x.getPortalType() in portal_type, object_list)
-    object_list = sortValueList(object_list, sort_on, sort_order, **kw)
-    return object_list
-
-  security.declareProtected( Permissions.AccessContentsInformation,
-                             'contentValues' )
-  def contentValues(self, spec=None, meta_type=None, portal_type=None,
-                    sort_on=None, sort_order=None, **kw):
-    """
-    Returns a list containing object contained in this folder.
-    Filter objects with appropriate permissions (as in contentValues)
-    """
-    if meta_type is not None:
-      spec = meta_type
-    if portal_type is not None:
-      kw['portal_type'] = portal_type
-    filter = kw.pop('filter', {}) or {}
-    kw.update(filter)
-    object_list = CMFBTreeFolder.contentValues(self, spec=spec, filter=kw)
-    object_list = sortValueList(object_list, sort_on, sort_order, **kw)
-    return object_list
-
-  # Override security declaration of CMFCore/PortalFolder (used by CMFBTreeFolder)
-  security.declareProtected(Permissions.ModifyPortalContent,'setDescription')
-  security.declareProtected( Permissions.ModifyPortalContent, 'setTitle' )
-
-  security.declareProtected( Permissions.AccessContentsInformation, 'manage_copyObjects' ) # XXX Why this one doesn't work in CopySupport ?
-  security.declareProtected( Permissions.AddPortalContent, 'manage_pasteObjects' ) # XXX Why this one doesn't work in CopySupport ?
-
-  # Template Management
-  security.declareProtected(Permissions.View, 'getDocumentTemplateList')
-  def getDocumentTemplateList(self) :
-    """
-      Returns the list of allowed templates for this folder
-      by calling the preference tool
-    """
-    return self.getPortalObject().portal_preferences.getDocumentTemplateList(self)
-  
-  security.declareProtected(Permissions.ModifyPortalContent,'makeTemplate')
-  def makeTemplate(self):
-    """
-      Make document behave as a template.
-      A template is no longer indexable
-
-      TODO:
-         - prevent from changing templates or invoking workflows
-    """
-    Base.makeTemplate(self)
-    for o in self.objectValues():
-      if hasattr(aq_base(o), 'makeTemplate'): o.makeTemplate()
-
-  security.declareProtected(Permissions.ModifyPortalContent,'makeTemplateInstance')
-  def makeTemplateInstance(self):
-    """
-      Make document behave as standard document (indexable)
-    """
-    Base.makeTemplateInstance(self)
-    for o in self.objectValues():
-      if hasattr(aq_base(o), 'makeTemplateInstance'): o.makeTemplateInstance()
-  
-  def _delObject(self, id, dp=1):
-    """
-      _delObject is redefined here in order to make sure
-      we do not do silent except while we remove objects
-      from catalog
-    """
-    object = self._getOb(id)
-    object.manage_beforeDelete(object, self)
-    self._delOb(id)
-
-# Overwrite Zope setTitle()
-Folder.setTitle = Base.setTitle