diff --git a/product/ERP5Type/Core/Folder.py b/product/ERP5Type/Core/Folder.py
index 8a60e6796ca6caa1fd333b0b98612c54f31d7107..e89827edeebd7a5cdc11aed9b7d36b11f446b8f1 100644
--- a/product/ERP5Type/Core/Folder.py
+++ b/product/ERP5Type/Core/Folder.py
@@ -148,24 +148,15 @@ class FolderMixIn(ExtensionClass.Base):
           'portal_trash' not in container.getPhysicalPath():
         raise ValueError('Disallowed subobject type: %s' % portal_type)
 
-    # Use the factory even if the parent is already a temp object,
-    # like this we do not call the classic way, indeed, we do not
-    # need to call init script, security settings on temp objects.
-    if temp_object or temp_container:
-      type_info = pt.getTypeInfo(portal_type)
-      if not type_info.factory or not type_info.factory.startswith('add'):
-        raise ValueError('Product factory for %s is invalid: %s' %
-                         (portal_type, type_info.factory))
-      p = container.manage_addProduct[type_info.product]
-      m = getattr(p, 'newTemp' + type_info.factory[3:])
-      new_instance = m(new_id, container)
-      if hasattr(new_instance, '_setPortalTypeName'):
-        new_instance._setPortalTypeName(portal_type)
-    else:
-      pt.constructContent( type_name=portal_type,
+    type_info = pt.getTypeInfo(portal_type)
+    if type_info is None:
+      raise ValueError('No such content type: %s' % portal_type)
+
+    new_instance = type_info.constructInstance(
                            container=container,
                            id=new_id,
                            created_by_builder=created_by_builder,
+                           temp_object=temp_object or temp_container,
                            activate_kw=activate_kw,
                            reindex_kw=reindex_kw,
                            is_indexable=is_indexable
@@ -173,7 +164,6 @@ class FolderMixIn(ExtensionClass.Base):
       # 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()
diff --git a/product/ERP5Type/ERP5Type.py b/product/ERP5Type/ERP5Type.py
index 8d470379cc96de0fa49fd74fca5c03deb978e5a0..fa17a3ee30c17d234292705fd81b9c99572d17a6 100644
--- a/product/ERP5Type/ERP5Type.py
+++ b/product/ERP5Type/ERP5Type.py
@@ -30,6 +30,7 @@ from Products.CMFCore.Expression import Expression
 from Products.CMFCore.exceptions import AccessControl_Unauthorized
 from Products.CMFCore.utils import _checkPermission
 from Products.ERP5Type import interfaces, Constraint, Permissions, PropertySheet
+from Products.ERP5Type.Base import getClassPropertyList
 from Products.ERP5Type.UnrestrictedMethod import UnrestrictedMethod
 from Products.ERP5Type.Utils import deprecated, createExpressionContext
 from Products.ERP5Type.XMLObject import XMLObject
@@ -376,14 +377,24 @@ class ERP5TypeInformation(XMLObject,
         return default
 
     security.declarePublic('constructInstance')
-    def constructInstance( self, container, id,
-                           created_by_builder=0, *args, **kw ):
-        """
-        Build a "bare" instance of the appropriate type in
-        'container', using 'id' as its id.
-        Call the init_script for the portal_type.
-        Returns the object.
-        """
+    def constructInstance(self, container, id, created_by_builder=0,
+                          temp_object=0, *args, **kw ):
+      """
+      Build a "bare" instance of the appropriate type in
+      'container', using 'id' as its id.
+      Call the init_script for the portal_type.
+      Returns the object.
+      """
+      if temp_object:
+        if not self.factory or not self.factory.startswith('add'):
+          raise ValueError('Product factory for %s is invalid: %s'
+                            % (self.getId(), self.factory))
+        p = container.manage_addProduct[self.product]
+        m = getattr(p, 'newTemp' + self.factory[3:])
+        ob = m(id, container)
+        if hasattr(ob, '_setPortalTypeName'):
+          ob.portal_type = self.getId()
+      else:
         # This is part is copied from CMFCore/TypesTool/constructInstance
         # In case of temp object, we don't want to check security
         if (not (hasattr(container, 'isTempObject')
@@ -418,7 +429,12 @@ class ERP5TypeInformation(XMLObject,
           kw['created_by_builder'] = created_by_builder
           getattr(ob, init_script)(*args, **kw)
 
-        return ob
+      return ob
+
+    def _getPropertyHolder(self):
+      ob = self.constructInstance(self, '', temp_object=1)
+      ob._aq_dynamic('id')
+      return ob.aq_portal_type[ob._aq_key()]
 
     security.declarePrivate('updatePropertySheetDefinitionDict')
     def updatePropertySheetDefinitionDict(self, definition_dict):
@@ -451,61 +467,27 @@ class ERP5TypeInformation(XMLObject,
                               'getInstanceBaseCategoryList')
     def getInstanceBaseCategoryList(self):
       """ Return all base categories of the portal type """
-      # try to get categories from a temporary object if possible
-      module = self.getPortalObject().getDefaultModule(self.getId())
-      if module is not None:
-        return module.newContent(portal_type=self.getId(), temp_object=1).getBaseCategoryList()
-
-      # XXX The following does not return the list of all categories currently
-      #     (as implementation does not follow exactly the accessor generation,
-      #     like for Expression evaluation). Should be probably better to get
-      #     the list from property holder and not from property sheet
-      # get categories from portal type
-      base_category_set = set(self.getTypeBaseCategoryList())
-
-      # get categories from property sheet
-      ps_list = [getattr(PropertySheet, p, None)
-                 for p in self.getTypePropertySheetList()]
-      # from the property sheets defined on the class
-      m = Products.ERP5Type._m
-      if m.has_key(self.factory):
-        klass = m[self.factory].klass
-        if klass is not None:
-          from Products.ERP5Type.Base import getClassPropertyList
-          ps_list += getClassPropertyList(klass)
-
-      # XXX Can't return set to restricted code in Zope 2.8.
-      return list(base_category_set.union(category
-        for base in ps_list
-        for category in getattr(base, '_categories', ())))
+      return list(self._getPropertyHolder()._categories)
 
     security.declareProtected(Permissions.AccessContentsInformation,
                               'getInstancePropertyAndBaseCategoryList')
     def getInstancePropertyAndBaseCategoryList(self):
       """Return all the properties and base categories of the portal type. """
-      return_set = set()
+      # PropertHolder._properties doesn't contain 'content' properties.
+      ob = self.constructInstance(self, '', temp_object=1)
+      property_list = list(getattr(ob.__class__, '_properties', []))
+      self.updatePropertySheetDefinitionDict({'_properties': property_list})
+      for property_sheet in getClassPropertyList(ob.__class__):
+        property_list += property_sheet._properties
 
-      # get the property sheet list for the portal type
-      ps_list = [getattr(PropertySheet, p, None)
-                 for p in self.getTypePropertySheetList()]
-      m = Products.ERP5Type._m
-      if m.has_key(self.factory):
-        klass = m[self.factory].klass
-        if klass is not None:
-          from Products.ERP5Type.Base import getClassPropertyList
-          ps_list += getClassPropertyList(klass)
-      # get all properties from the property sheet list
-      for base in ps_list:
-        property_list = getattr(base, '_properties', None)
-        if property_list:
-          for property in property_list:
-            if property['type'] == 'content':
-              for suffix in property['acquired_property_id']:
-                return_set.add(property['id'] + '_' + suffix)
-            else:
-              return_set.add(property['id'])
-      # get base categories
-      for category in self.getInstanceBaseCategoryList():
+      return_set = set()
+      for property in property_list:
+        if property['type'] == 'content':
+          for suffix in property['acquired_property_id']:
+            return_set.add(property['id'] + '_' + suffix)
+        else:
+          return_set.add(property['id'])
+      for category in ob.getBaseCategoryList():
         return_set.add(category)
         return_set.add(category + '_free_text')
 
@@ -517,22 +499,8 @@ class ERP5TypeInformation(XMLObject,
     def getInstancePropertyMap(self):
       """
       Returns the list of properties which are specific to the portal type.
-
-      We do this by creating a temp object at the root of the portal
-      and invoking propertyMap
       """
-      # Access the factory method for temp object by guessing it
-      # according to ERP5 naming conventions (not very nice)
-      factory_method_id = self.factory.replace('add', 'newTemp', 1)
-      if not factory_method_id.startswith('newTemp'):
-        raise
-      factory_method = getattr(Products.ERP5Type.Document, factory_method_id)
-      id = "some_very_unlikely_temp_object_id_which_should_not_exist"
-      portal = self.getPortalObject()
-      portal_ids = portal.objectIds()
-      while id in portal_ids:
-        id = id + "d"
-      return factory_method(portal, id).propertyMap()
+      return self.constructInstance(self, '', temp_object=1).propertyMap()
 
     def _edit(self, *args, **kw):
       """
diff --git a/product/ERP5Type/TranslationProviderBase.py b/product/ERP5Type/TranslationProviderBase.py
index 9c4daf11be444b4415b8fa29a0f063f6dd4d1c18..7a59e5b2f1ca605d34e5dbedd35dfd577388d00e 100644
--- a/product/ERP5Type/TranslationProviderBase.py
+++ b/product/ERP5Type/TranslationProviderBase.py
@@ -58,34 +58,18 @@ class TranslationProviderBase(object):
     """
     property_domain_dict = {}
 
-    # get the property sheet list for the portal type
-    ps_list = [getattr(PropertySheet, p, None)
-                for p in self.getTypePropertySheetList()]
-    m = Products.ERP5Type._m
-    if m.has_key(self.factory):
-      klass = m[self.factory].klass
-      if klass is not None:
-        from Products.ERP5Type.Base import getClassPropertyList
-        ps_list += getClassPropertyList(klass)
-    # create TranslationInformation object for each property
-    for base in ps_list:
-      for prop in getattr(base, '_properties', ()):
-        prop_id = prop['id']
-        if prop.get('translatable') and prop_id not in property_domain_dict:
-          domain_name = prop.get('translation_domain')
-          property_domain_dict[prop_id] = TranslationInformation(prop_id,
-                                                                 domain_name)
+    for prop in self._getPropertyHolder()._properties:
+      prop_id = prop['id']
+      if prop.get('translatable') and prop_id not in property_domain_dict:
+        domain_name = prop.get('translation_domain')
+        property_domain_dict[prop_id] = TranslationInformation(prop_id,
+                                                               domain_name)
 
     original_property_domain_dict = getattr(aq_base(self),
                                             '_property_domain_dict', _MARKER)
-    original_property_domain_keys = original_property_domain_dict.keys()
-    property_domain_keys = property_domain_dict.keys()
-    property_domain_keys.sort()
-    original_property_domain_keys.sort()
-
     # Only update if required in order to prevent ZODB from growing
     if original_property_domain_dict is _MARKER or\
-          property_domain_keys != original_property_domain_keys:
+       sorted(property_domain_dict) != sorted(original_property_domain_dict):
       # Update existing dict
       property_domain_dict.update(original_property_domain_dict)
       # And store