[CMF-checkins] SVN: CMF/trunk/ - added ISetupEnviron, a small subset of ISetupContext, to be used by adapters

Yvo Schubbe y.2005- at wcm-solutions.de
Mon Dec 12 05:33:42 EST 2005


Log message for revision 40715:
  - added ISetupEnviron, a small subset of ISetupContext, to be used by adapters
  - INodeExporter and INodeImporter are now INode (this saves us a lot of writing)
  - made node adapters multi adapters for the interface of the configured object and ISetupEnviron (no more need to pass around mode and logger)
  - registered body adapters as well for ISetupEnviron (instead of ISetupContext)
  - replaced manage_addActionForm and manage_addActionCategoryForm by add views (allows to reuse code and template from GenericSetup.browser)
  

Changed:
  U   CMF/trunk/CHANGES.txt
  U   CMF/trunk/CMFCore/ActionInformation.py
  U   CMF/trunk/CMFCore/__init__.py
  A   CMF/trunk/CMFCore/browser/actions.py
  U   CMF/trunk/CMFCore/browser/configure.zcml
  U   CMF/trunk/CMFCore/browser/typeinfo.py
  U   CMF/trunk/CMFCore/configure.zcml
  U   CMF/trunk/CMFCore/exportimport/actions.py
  U   CMF/trunk/CMFCore/exportimport/cachingpolicymgr.py
  U   CMF/trunk/CMFCore/exportimport/configure.zcml
  U   CMF/trunk/CMFCore/exportimport/contenttyperegistry.py
  U   CMF/trunk/CMFCore/exportimport/cookieauth.py
  U   CMF/trunk/CMFCore/exportimport/properties.py
  U   CMF/trunk/CMFCore/exportimport/skins.py
  U   CMF/trunk/CMFCore/exportimport/tests/test_actions.py
  U   CMF/trunk/CMFCore/exportimport/tests/test_skins.py
  U   CMF/trunk/CMFCore/exportimport/tests/test_workflow.py
  U   CMF/trunk/CMFCore/exportimport/typeinfo.py
  U   CMF/trunk/CMFCore/exportimport/workflow.py
  D   CMF/trunk/CMFCore/www/addAction.zpt
  D   CMF/trunk/CMFCore/www/addActionCategory.zpt
  U   CMF/trunk/DCWorkflow/browser/workflow.py
  U   CMF/trunk/DCWorkflow/configure.zcml
  U   CMF/trunk/GenericSetup/MailHost/configure.zcml
  U   CMF/trunk/GenericSetup/MailHost/exportimport.py
  U   CMF/trunk/GenericSetup/OFSP/configure.zcml
  U   CMF/trunk/GenericSetup/OFSP/exportimport.py
  U   CMF/trunk/GenericSetup/PluginIndexes/configure.zcml
  U   CMF/trunk/GenericSetup/PluginIndexes/exportimport.py
  U   CMF/trunk/GenericSetup/PythonScripts/configure.zcml
  U   CMF/trunk/GenericSetup/ZCTextIndex/configure.zcml
  U   CMF/trunk/GenericSetup/ZCTextIndex/exportimport.py
  U   CMF/trunk/GenericSetup/ZCatalog/configure.zcml
  U   CMF/trunk/GenericSetup/ZCatalog/exportimport.py
  U   CMF/trunk/GenericSetup/ZCatalog/tests/test_exportimport.py
  U   CMF/trunk/GenericSetup/browser/utils.py
  U   CMF/trunk/GenericSetup/context.py
  U   CMF/trunk/GenericSetup/interfaces.py
  U   CMF/trunk/GenericSetup/testing.py
  U   CMF/trunk/GenericSetup/tests/common.py
  U   CMF/trunk/GenericSetup/tests/test_utils.py
  U   CMF/trunk/GenericSetup/utils.py

-=-
Modified: CMF/trunk/CHANGES.txt
===================================================================
--- CMF/trunk/CHANGES.txt	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CHANGES.txt	2005-12-12 10:33:40 UTC (rev 40715)
@@ -45,14 +45,14 @@
 
     - CMFCore and GenericSetup: Added catalog tool setup handlers.
       This includes node adapters for PluginIndexes, ZCTextIndex and ZCatalog.
-      Support for additional indexes can be added by providing INodeExporter
-      and INodeImporter adapters. All indexes are cleared by this handler, so
-      please make sure to re-catalog existing content if necessary.
+      Support for additional indexes can be added by providing INode adapters.
+      All indexes are cleared by this handler, so please make sure to
+      re-catalog existing content if necessary.
 
     - GenericSetup.utils: Added new sub-framework for XML im- and export.
       Instead of using ConfiguratorBase configurators should now implement
-      INodeExporter and INodeImporter. These node adapters should subclass
-      from NodeAdapterBase and mix in ObjectManagerHelpers and / or
+      IBody or INode. These adapters should subclass from XMLAdapterBase or
+      NodeAdapterBase and mix in ObjectManagerHelpers and / or
       PropertyManagerHelpers if needed.
 
     - CMFCore.exportimport:  Added framework and interfaces for exporting

Modified: CMF/trunk/CMFCore/ActionInformation.py
===================================================================
--- CMF/trunk/CMFCore/ActionInformation.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/ActionInformation.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -16,7 +16,6 @@
 """
 
 from UserDict import UserDict
-from xml.dom.minidom import parseString
 
 from AccessControl import ClassSecurityInfo
 from Acquisition import aq_base, aq_inner, aq_parent
@@ -24,12 +23,8 @@
 from OFS.ObjectManager import IFAwareObjectManager
 from OFS.OrderedFolder import OrderedFolder
 from OFS.SimpleItem import SimpleItem
-from Products.PageTemplates.PageTemplateFile import PageTemplateFile
-
 from zope.interface import implements
 
-from Products.GenericSetup.interfaces import INodeImporter
-
 from Expression import Expression
 from interfaces import IAction
 from interfaces import IActionCategory
@@ -53,8 +48,6 @@
     implements(IActionCategory)
     __implements__ = OrderedFolder.__implements__
 
-    meta_type = 'CMF Action Category'
-
     _product_interfaces = (IActionCategory, IAction)
 
     security = ClassSecurityInfo()
@@ -75,19 +68,7 @@
 
 InitializeClass(ActionCategory)
 
-manage_addActionCategoryForm = PageTemplateFile('addActionCategory.zpt',
-                                                _wwwdir)
 
-def manage_addActionCategory(self, id, REQUEST=None):
-    """Add a new CMF Action Category object with ID *id*.
-    """
-    obj = ActionCategory(id)
-    self._setObject(id, obj)
-
-    if REQUEST:
-        return self.manage_main(self, REQUEST, update_menu=1)
-
-
 class Action(SimpleItemWithProperties):
 
     """ Reference to an action.
@@ -95,7 +76,6 @@
 
     implements(IAction)
 
-    meta_type = 'CMF Action'
     i18n_domain = 'cmf_default'
 
     security = ClassSecurityInfo()
@@ -173,85 +153,6 @@
 InitializeClass(Action)
 
 
-def manage_addActionForm(self):
-    """Form for adding a new CMF Action object.
-    """
-    profiles = []
-
-    stool = getToolByName(self, 'portal_setup', None)
-    if stool:
-        for info in stool.listContextInfos():
-            action_paths = []
-            context = stool._getImportContext(info['id'])
-            body = context.readDataFile('actions.xml')
-            if body is None:
-                continue
-            root = parseString(body).documentElement
-            for node in root.childNodes:
-                if node.nodeName != 'object':
-                    continue
-                action_paths += _extractChildren(node)
-            action_paths.sort()
-            profiles.append({'id': info['id'],
-                             'title': info['title'],
-                             'action_paths': tuple(action_paths)})
-
-    template = PageTemplateFile('addAction.zpt', _wwwdir).__of__(self)
-    return template(profiles=tuple(profiles))
-
-def _extractChildren(node):
-    action_paths = []
-    category_id = node.getAttribute('name')
-    for child in node.childNodes:
-        if child.nodeName != 'object':
-            continue
-        if child.getAttribute('meta_type') == Action.meta_type:
-            action_id = child.getAttribute('name')
-            action_paths.append(action_id)
-        else:
-            action_paths += _extractChildren(child)
-    return [ ('%s/%s' % (category_id, path)) for path in action_paths ]
-
-def manage_addAction(self, id, settings_id='', REQUEST=None):
-    """Add a new CMF Action object with ID *id*.
-    """
-    settings_node = None
-    if settings_id:
-        stool = getToolByName(self, 'portal_setup', None)
-        if stool:
-            path = settings_id.split('/')
-            context = stool._getImportContext(path.pop(0))
-            body = context.readDataFile('actions.xml')
-            if body is not None:
-                root = parseString(body).documentElement
-                for node in root.childNodes:
-                    if node.nodeName != 'object':
-                        continue
-                    for obj_id in path:
-                        for child in node.childNodes:
-                            if child.nodeName != 'object':
-                                continue
-                            if child.getAttribute('name') != obj_id:
-                                continue
-                            if child.getAttribute(
-                                             'meta_type') == Action.meta_type:
-                                settings_node = child
-                            else:
-                                node = child
-                            break
-                    if settings_node:
-                        if not id:
-                            id = obj_id
-                        break
-    obj = Action(id)
-    if settings_node:
-        INodeImporter(obj).importNode(settings_node)
-    self._setObject(id, obj)
-
-    if REQUEST:
-        return self.manage_main(self, REQUEST)
-
-
 class ActionInfo(UserDict):
 
     """ A lazy dictionary for Action infos.

Modified: CMF/trunk/CMFCore/__init__.py
===================================================================
--- CMF/trunk/CMFCore/__init__.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/__init__.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -34,10 +34,7 @@
 import CMFBTreeFolder
 import utils
 
-from interfaces import IAction
-from interfaces import IActionCategory
 from permissions import AddPortalFolders
-from permissions import ManagePortal
 
 
 bases = (
@@ -124,24 +121,10 @@
         icon = 'images/registry.gif'
         )
 
-    context.registerClass(
-        ActionInformation.ActionCategory,
-        permission=ManagePortal,
-        constructors=(ActionInformation.manage_addActionCategoryForm,
-                      ActionInformation.manage_addActionCategory),
-        icon='images/cmf_action_category.gif',
-        visibility=None,
-        interfaces=(IActionCategory,))
-
-    context.registerClass(
-        ActionInformation.Action,
-        permission=ManagePortal,
-        constructors=(ActionInformation.manage_addActionForm,
-                      ActionInformation.manage_addAction),
-        icon='images/cmf_action.gif',
-        visibility=None,
-        interfaces=(IAction,))
-
+    utils.registerIcon(ActionInformation.ActionCategory,
+                       'images/cmf_action_category.gif', globals())
+    utils.registerIcon(ActionInformation.Action,
+                       'images/cmf_action.gif', globals())
     utils.registerIcon(TypesTool.FactoryTypeInformation,
                        'images/typeinfo.gif', globals())
     utils.registerIcon(TypesTool.ScriptableTypeInformation,

Added: CMF/trunk/CMFCore/browser/actions.py
===================================================================
--- CMF/trunk/CMFCore/browser/actions.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/browser/actions.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -0,0 +1,121 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""TypeInformation browser views.
+
+$Id$
+"""
+
+from xml.dom.minidom import parseString
+
+from zope.app import zapi
+
+from Products.CMFCore.ActionInformation import Action
+from Products.CMFCore.ActionInformation import ActionCategory
+from Products.CMFCore.utils import getToolByName
+from Products.GenericSetup.browser.utils import AddWithPresettingsViewBase
+from Products.GenericSetup.interfaces import INode
+
+
+class ActionAddView(AddWithPresettingsViewBase):
+
+    """Add view for Action.
+    """
+
+    klass = Action
+
+    description = u'An Action object represents a reference to an action.'
+
+    def getProfileInfos(self):
+        profiles = []
+        stool = getToolByName(self, 'portal_setup', None)
+        if stool:
+            for info in stool.listContextInfos():
+                obj_ids = []
+                context = stool._getImportContext(info['id'])
+                body = context.readDataFile('actions.xml')
+                if body is None:
+                    continue
+                root = parseString(body).documentElement
+                for node in root.childNodes:
+                    if node.nodeName != 'object':
+                        continue
+                    obj_ids += self._extractChildren(node)
+                obj_ids.sort()
+                profiles.append({'id': info['id'],
+                                 'title': info['title'],
+                                 'obj_ids': tuple(obj_ids)})
+        return tuple(profiles)
+
+    def _extractChildren(self, node):
+        action_paths = []
+        category_id = node.getAttribute('name')
+        for child in node.childNodes:
+            if child.nodeName != 'object':
+                continue
+            if child.getAttribute('meta_type') == self.klass.meta_type:
+                action_id = child.getAttribute('name')
+                action_paths.append(action_id)
+            else:
+                action_paths += self._extractChildren(child)
+        return [ ('%s/%s' % (category_id, path)) for path in action_paths ]
+
+    def _initSettings(self, obj, profile_id, obj_path):
+        stool = getToolByName(self, 'portal_setup', None)
+        if stool is None:
+            return
+
+        context = stool._getImportContext(profile_id)
+        body = context.readDataFile('actions.xml')
+        if body is None:
+            return
+
+        settings_node = None
+        root = parseString(body).documentElement
+        for node in root.childNodes:
+            if node.nodeName != 'object':
+                continue
+            for obj_id in obj_path:
+                for child in node.childNodes:
+                    if child.nodeName != 'object':
+                        continue
+                    if child.getAttribute('name') != obj_id:
+                        continue
+                    if child.getAttribute('meta_type') == self.klass.meta_type:
+                        settings_node = child
+                    else:
+                        node = child
+                    break
+
+        importer = zapi.queryMultiAdapter((obj, context), INode)
+        if importer is None:
+            return
+
+        importer.node = settings_node
+        return
+
+
+class ActionCategoryAddView(AddWithPresettingsViewBase):
+
+    """Add view for ActionCategory.
+    """
+
+    klass = ActionCategory
+
+    description = \
+            u'An Action Category object represents a group of Action objects.'
+
+    def getProfileInfos(self):
+        return []
+
+    def _initSettings(self, obj, profile_id, obj_path):
+        pass


Property changes on: CMF/trunk/CMFCore/browser/actions.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Modified: CMF/trunk/CMFCore/browser/configure.zcml
===================================================================
--- CMF/trunk/CMFCore/browser/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/browser/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -5,14 +5,34 @@
     i18n_domain="cmf"
     >
 
-  <five:traversable class="Products.CMFCore.WorkflowTool.WorkflowTool"/>
+  <five:traversable class="Products.CMFCore.ActionInformation.ActionCategory"/>
 
+  <five:traversable class="Products.CMFCore.ActionsTool.ActionsTool"/>
+
   <five:traversable class="Products.CMFCore.TypesTool.TypesTool"/>
 
+  <five:traversable class="Products.CMFCore.WorkflowTool.WorkflowTool"/>
+
   <configure package="Products.GenericSetup.browser">
 
     <browser:page
         for="zope.app.container.interfaces.IAdding"
+        name="addAction.html"
+        template="addWithPresettings.pt"
+        class="Products.CMFCore.browser.actions.ActionAddView"
+        permission="cmf.ManagePortal"
+        />
+
+    <browser:page
+        for="zope.app.container.interfaces.IAdding"
+        name="addActionCategory.html"
+        template="addWithPresettings.pt"
+        class="Products.CMFCore.browser.actions.ActionCategoryAddView"
+        permission="cmf.ManagePortal"
+        />
+
+    <browser:page
+        for="zope.app.container.interfaces.IAdding"
         name="addFactoryTypeInformation.html"
         template="addWithPresettings.pt"
         class="Products.CMFCore.browser.typeinfo.FactoryTypeInformationAddView"

Modified: CMF/trunk/CMFCore/browser/typeinfo.py
===================================================================
--- CMF/trunk/CMFCore/browser/typeinfo.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/browser/typeinfo.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -63,7 +63,7 @@
                                  'obj_ids': tuple(obj_ids)})
         return tuple(profiles)
 
-    def _initSettings(self, obj, profile_id, obj_id):
+    def _initSettings(self, obj, profile_id, obj_path):
         stool = getToolByName(self, 'portal_setup', None)
         if stool is None:
             return
@@ -80,7 +80,7 @@
             new_id = root.getAttribute('name')
             if not new_id:
                 new_id = root.getAttribute('id')
-            if new_id != obj_id:
+            if new_id != obj_path[0]:
                 continue
 
             if root.getAttribute('meta_type') != self.klass.meta_type:

Modified: CMF/trunk/CMFCore/configure.zcml
===================================================================
--- CMF/trunk/CMFCore/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -8,6 +8,22 @@
   <include package=".exportimport"/>
 
   <five:registerClass
+      class=".ActionInformation.ActionCategory"
+      meta_type="CMF Action Category"
+      addview="addActionCategory.html"
+      permission="cmf.ManagePortal"
+      global="False"
+      />
+
+  <five:registerClass
+      class=".ActionInformation.Action"
+      meta_type="CMF Action"
+      addview="addAction.html"
+      permission="cmf.ManagePortal"
+      global="False"
+      />
+
+  <five:registerClass
       class=".TypesTool.FactoryTypeInformation"
       meta_type="Factory-based Type Information"
       addview="addFactoryTypeInformation.html"

Modified: CMF/trunk/CMFCore/exportimport/actions.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/actions.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/actions.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -18,7 +18,6 @@
 from zope.app import zapi
 
 from Products.GenericSetup.interfaces import IBody
-from Products.GenericSetup.interfaces import PURGE, UPDATE
 from Products.GenericSetup.utils import I18NURI
 from Products.GenericSetup.utils import NodeAdapterBase
 from Products.GenericSetup.utils import ObjectManagerHelpers
@@ -45,26 +44,30 @@
 
     __used_for__ = IActionCategory
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.appendChild(self._extractProperties())
         node.appendChild(self._extractObjects())
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        purge = self.environ.shouldPurge()
+        if node.getAttribute('purge'):
+            purge = self._convertToBoolean(node.getAttribute('purge'))
+        if purge:
             self._purgeProperties()
             self._purgeObjects()
 
-        self._initProperties(node, mode)
-        self._initObjects(node, mode)
+        self._initProperties(node)
+        self._initObjects(node)
 
+    node = property(_exportNode, _importNode)
 
+
 class ActionNodeAdapter(NodeAdapterBase, PropertyManagerHelpers):
 
     """Node im- and exporter for Action.
@@ -72,23 +75,27 @@
 
     __used_for__ = IAction
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.appendChild(self._extractProperties())
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        purge = self.environ.shouldPurge()
+        if node.getAttribute('purge'):
+            purge = self._convertToBoolean(node.getAttribute('purge'))
+        if purge:
             self._purgeProperties()
 
-        self._initProperties(node, mode)
+        self._initProperties(node)
 
+    node = property(_exportNode, _importNode)
 
+
 class ActionsToolXMLAdapter(XMLAdapterBase, ObjectManagerHelpers):
 
     """XML im- and exporter for ActionsTool.
@@ -98,10 +105,9 @@
 
     _LOGGER_ID = 'actions'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.setAttribute('xmlns:i18n', I18NURI)
         node.appendChild(self._extractProviders())
@@ -110,15 +116,15 @@
         self._logger.info('Actions tool exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeProviders()
             self._purgeObjects()
 
-        self._initObjects(node, mode)
-        self._initProviders(node, mode)
+        self._initObjects(node)
+        self._initProviders(node)
 
         self._logger.info('Actions tool imported.')
 
@@ -170,7 +176,7 @@
         for provider_id in self.context.listActionProviders():
             self.context.deleteActionProvider(provider_id)
 
-    def _initProviders(self, node, mode):
+    def _initProviders(self, node):
         for child in node.childNodes:
             if child.nodeName != 'action-provider':
                 continue
@@ -189,9 +195,9 @@
                 self.context.addActionProvider(provider_id)
 
             # BBB: for CMF 1.5 profiles
-            self._initOldstyleActions(child, mode)
+            self._initOldstyleActions(child)
 
-    def _initOldstyleActions(self, node, mode):
+    def _initOldstyleActions(self, node):
         # BBB: for CMF 1.5 profiles
         doc = node.ownerDocument
         fragment = doc.createDocumentFragment()
@@ -204,11 +210,13 @@
                 newnode = doc.createElement('object')
                 newnode.setAttribute('name', str(category_id))
                 newnode.setAttribute('meta_type', 'CMF Action Category')
+                newnode.setAttribute('purge', 'False')
                 parent.appendChild(newnode)
                 parent = newnode
             newnode = doc.createElement('object')
             newnode.setAttribute('name', str(child.getAttribute('action_id')))
             newnode.setAttribute('meta_type', 'CMF Action')
+            newnode.setAttribute('purge', 'False')
 
             mapping = {'title': 'title',
                        'url_expr': 'url_expr',
@@ -232,7 +240,7 @@
 
             parent.appendChild(newnode)
 
-        self._initObjects(fragment, UPDATE)
+        self._initObjects(fragment)
 
 
 def importActionProviders(context):

Modified: CMF/trunk/CMFCore/exportimport/cachingpolicymgr.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/cachingpolicymgr.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/cachingpolicymgr.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -18,9 +18,7 @@
 from zope.app import zapi
 
 from Products.GenericSetup.interfaces import IBody
-from Products.GenericSetup.interfaces import INodeExporter
-from Products.GenericSetup.interfaces import INodeImporter
-from Products.GenericSetup.interfaces import PURGE
+from Products.GenericSetup.interfaces import INode
 from Products.GenericSetup.utils import NodeAdapterBase
 from Products.GenericSetup.utils import XMLAdapterBase
 
@@ -38,10 +36,9 @@
 
     __used_for__ = ICachingPolicy
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         obj = self.context
         node = self._doc.createElement('caching-policy')
         node.setAttribute('name', obj.getPolicyId())
@@ -72,7 +69,7 @@
             node.setAttribute('post_check', str(post_check))
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         info = {}
@@ -113,7 +110,9 @@
             info['post_check'] = int(post_check)
         self.context.__init__(**info)
 
+    node = property(_exportNode, _importNode)
 
+
 class CachingPolicyManagerXMLAdapter(XMLAdapterBase):
 
     """XML im- and exporter for CachingPolicyManager.
@@ -123,39 +122,37 @@
 
     _LOGGER_ID = 'cachingpolicies'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.appendChild(self._extractCachingPolicies())
 
         self._logger.info('Caching policy manager exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeCachingPolicies()
 
-        self._initCachingPolicies(node, mode)
+        self._initCachingPolicies(node)
 
         self._logger.info('Caching policy manager imported.')
 
     def _extractCachingPolicies(self):
         fragment = self._doc.createDocumentFragment()
         for policy_id, policy in self.context.listPolicies():
-            exporter = INodeExporter(policy, None)
-            if exporter is None:
-                continue
-            fragment.appendChild(exporter.exportNode(self._doc))
+            exporter = zapi.queryMultiAdapter((policy, self.environ), INode)
+            if exporter:
+                fragment.appendChild(exporter.node)
         return fragment
 
     def _purgeCachingPolicies(self):
         self.context.__init__()
 
-    def _initCachingPolicies(self, node, mode):
+    def _initCachingPolicies(self, node):
         for child in node.childNodes:
             if child.nodeName != 'caching-policy':
                 continue
@@ -167,7 +164,9 @@
                                  0, 0, 0, 0, '', '')
 
             policy = self.context._policies[policy_id]
-            INodeImporter(policy).importNode(child, mode)
+            importer = zapi.queryMultiAdapter((policy, self.environ), INode)
+            if importer:
+                importer.node = child
 
 
 def importCachingPolicyManager(context):

Modified: CMF/trunk/CMFCore/exportimport/configure.zcml
===================================================================
--- CMF/trunk/CMFCore/exportimport/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -4,52 +4,37 @@
 
   <adapter
       factory=".actions.ActionCategoryNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.CMFCore.interfaces.IActionCategory"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.CMFCore.interfaces.IActionCategory
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".actions.ActionCategoryNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.CMFCore.interfaces.IActionCategory"
-      />
-
-  <adapter
       factory=".actions.ActionNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.CMFCore.interfaces.IAction"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.CMFCore.interfaces.IAction
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".actions.ActionNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.CMFCore.interfaces.IAction"
-      />
-
-  <adapter
       factory=".actions.ActionsToolXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.IActionsTool
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
       factory=".cachingpolicymgr.CachingPolicyNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.CMFCore.interfaces.ICachingPolicy"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.CMFCore.interfaces.ICachingPolicy
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".cachingpolicymgr.CachingPolicyNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.CMFCore.interfaces.ICachingPolicy"
-      />
-
-  <adapter
       factory=".cachingpolicymgr.CachingPolicyManagerXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.ICachingPolicyManager
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
@@ -68,61 +53,56 @@
       factory=".contenttyperegistry.ContentTypeRegistryXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.IContentTypeRegistry
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
       factory=".cookieauth.CookieCrumblerXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.ICookieCrumbler
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
       factory=".properties.PropertiesXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.ISiteRoot
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
       factory=".skins.DirectoryViewNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.CMFCore.interfaces.IDirectoryView"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.CMFCore.interfaces.IDirectoryView
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".skins.DirectoryViewNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.CMFCore.interfaces.IDirectoryView"
-      />
-
-  <adapter
       factory=".skins.SkinsToolXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.ISkinsTool
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
       factory=".typeinfo.TypeInformationXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.ITypeInformation
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
       factory=".typeinfo.TypesToolXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.ITypesTool
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
       factory=".workflow.WorkflowToolXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.IWorkflowTool
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
 </configure>

Modified: CMF/trunk/CMFCore/exportimport/contenttyperegistry.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/contenttyperegistry.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/contenttyperegistry.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -18,7 +18,6 @@
 from zope.app import zapi
 
 from Products.GenericSetup.interfaces import IBody
-from Products.GenericSetup.interfaces import PURGE
 from Products.GenericSetup.utils import XMLAdapterBase
 
 from Products.CMFCore.interfaces import IContentTypeRegistry
@@ -36,23 +35,22 @@
 
     _LOGGER_ID = 'contenttypes'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.appendChild(self._extractPredicates())
 
         self._logger.info('Content type registry exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgePredicates()
 
-        self._initPredicates(node, mode)
+        self._initPredicates(node)
 
         self._logger.info('Content type registry imported.')
 
@@ -73,7 +71,7 @@
     def _purgePredicates(self):
         self.context.__init__()
 
-    def _initPredicates(self, node, mode):
+    def _initPredicates(self, node):
         for child in node.childNodes:
             if child.nodeName != 'predicate':
                 continue

Modified: CMF/trunk/CMFCore/exportimport/cookieauth.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/cookieauth.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/cookieauth.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -18,7 +18,6 @@
 from zope.app import zapi
 
 from Products.GenericSetup.interfaces import IBody
-from Products.GenericSetup.interfaces import PURGE
 from Products.GenericSetup.utils import PropertyManagerHelpers
 from Products.GenericSetup.utils import XMLAdapterBase
 
@@ -37,23 +36,22 @@
 
     _LOGGER_ID = 'cookies'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.appendChild(self._extractProperties())
 
         self._logger.info('Cookie crumbler exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeProperties()
 
-        self._initProperties(node, mode)
+        self._initProperties(node)
 
         self._logger.info('Cookie crumbler imported.')
 

Modified: CMF/trunk/CMFCore/exportimport/properties.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/properties.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/properties.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -18,7 +18,6 @@
 from zope.app import zapi
 
 from Products.GenericSetup.interfaces import IBody
-from Products.GenericSetup.interfaces import PURGE
 from Products.GenericSetup.utils import PropertyManagerHelpers
 from Products.GenericSetup.utils import XMLAdapterBase
 
@@ -36,23 +35,22 @@
 
     _LOGGER_ID = 'properties'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._doc.createElement('site')
         node.appendChild(self._extractProperties())
 
         self._logger.info('Site properties exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeProperties()
 
-        self._initProperties(node, mode)
+        self._initProperties(node)
 
         self._logger.info('Site properties imported.')
 

Modified: CMF/trunk/CMFCore/exportimport/skins.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/skins.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/skins.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -15,10 +15,11 @@
 $Id$
 """
 
+from Acquisition import aq_inner
+from Acquisition import aq_parent
 from zope.app import zapi
 
 from Products.GenericSetup.interfaces import IBody
-from Products.GenericSetup.interfaces import PURGE
 from Products.GenericSetup.utils import exportObjects
 from Products.GenericSetup.utils import importObjects
 from Products.GenericSetup.utils import NodeAdapterBase
@@ -40,20 +41,21 @@
 
     __used_for__ = IDirectoryView
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.setAttribute('directory', self.context.getDirPath())
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         self.context.manage_properties(str(node.getAttribute('directory')))
 
+    node = property(_exportNode, _importNode)
 
+
 class SkinsToolXMLAdapter(XMLAdapterBase, ObjectManagerHelpers):
 
     """XML im- and exporter for SkinsTool.
@@ -63,10 +65,9 @@
 
     _LOGGER_ID = 'skins'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.setAttribute('default_skin', self.context.default_skin)
         node.setAttribute('request_varname', self.context.request_varname)
@@ -79,12 +80,12 @@
         self._logger.info('Skins tool exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         obj = self.context
 
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             obj.default_skin = ''
             obj.request_varname = 'portal_skin'
             obj.allow_any = 0
@@ -102,13 +103,13 @@
         if node.hasAttribute('cookie_persistence'):
             persistence = node.getAttribute('cookie_persistence')
             obj.cookie_persistence = int(self._convertToBoolean(persistence))
-        self._initObjects(node, mode)
-        self._initBBBObjects(node, mode)
-        self._initSkinPaths(node, mode)
+        self._initObjects(node)
+        self._initBBBObjects(node)
+        self._initSkinPaths(node)
 
         self._logger.info('Skins tool imported.')
 
-    def _initBBBObjects(self, node, mode):
+    def _initBBBObjects(self, node):
         for child in node.childNodes:
             if child.nodeName != 'skin-directory':
                 continue
@@ -134,7 +135,7 @@
     def _purgeSkinPaths(self):
         self.context._getSelections().clear()
 
-    def _initSkinPaths(self, node, mode):
+    def _initSkinPaths(self, node):
         for child in node.childNodes:
             if child.nodeName != 'skin-path':
                 continue
@@ -157,13 +158,12 @@
         # Purge and rebuild the skin path, now that we have added our stuff.
         # Don't bother if no REQUEST is present, e.g. when running unit tests
         #
-        site = self.environ.getSite()
-        request = getattr(site, 'REQUEST', None)
-        if request is not None:
-            site.clearCurrentSkin()
-            site.setupCurrentSkin(request)
+        request = getattr(self.context, 'REQUEST', None)
+        skinnable = aq_parent(aq_inner(self.context))
+        if request is not None and skinnable is not None:
+            skinnable.clearCurrentSkin()
+            skinnable.setupCurrentSkin(request)
 
-
     def _updatePath(self, path, node):
         path = [ name.strip() for name in path.split(',') if name.strip() ]
 

Modified: CMF/trunk/CMFCore/exportimport/tests/test_actions.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/tests/test_actions.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/tests/test_actions.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -17,8 +17,6 @@
 
 import unittest
 import Testing
-import Zope2
-Zope2.startup()
 
 import Products
 from Acquisition import Implicit
@@ -274,11 +272,11 @@
         self.assertEqual(obj.visible, True)
 
     def setUp(self):
-        import Products.CMFCore.exportimport
+        import Products.CMFCore
         from Products.CMFCore.ActionInformation import Action
 
         NodeAdapterTestCase.setUp(self)
-        zcml.load_config('configure.zcml', Products.CMFCore.exportimport)
+        zcml.load_config('configure.zcml', Products.CMFCore)
 
         self._obj = Action('foo_action')
         self._XML = _ACTION_XML
@@ -302,11 +300,11 @@
         self.assertEqual(obj.title, '')
 
     def setUp(self):
-        import Products.CMFCore.exportimport
+        import Products.CMFCore
         from Products.CMFCore.ActionInformation import ActionCategory
 
         NodeAdapterTestCase.setUp(self)
-        zcml.load_config('configure.zcml', Products.CMFCore.exportimport)
+        zcml.load_config('configure.zcml', Products.CMFCore)
 
         self._obj = ActionCategory('foo_category')
         self._XML = _ACTIONCATEGORY_XML
@@ -336,11 +334,11 @@
         self.assertEqual(obj.action_providers[0], 'portal_actions')
 
     def setUp(self):
-        import Products.CMFCore.exportimport
+        import Products.CMFCore
         from Products.CMFCore.ActionsTool import ActionsTool
 
         BodyAdapterTestCase.setUp(self)
-        zcml.load_config('configure.zcml', Products.CMFCore.exportimport)
+        zcml.load_config('configure.zcml', Products.CMFCore)
 
         site = DummySite('site')
         site._setObject('portal_actions', ActionsTool('portal_actions'))
@@ -390,7 +388,8 @@
         PlacelessSetup.setUp(self)
         BaseRegistryTests.setUp(self)
         zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('configure.zcml', Products.CMFCore.exportimport)
+        zcml.load_config('permissions.zcml', Products.Five)
+        zcml.load_config('configure.zcml', Products.CMFCore)
 
     def tearDown(self):
         BaseRegistryTests.tearDown(self)

Modified: CMF/trunk/CMFCore/exportimport/tests/test_skins.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/tests/test_skins.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/tests/test_skins.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -331,7 +331,8 @@
         site = DummySite()
         fsdvs = [ (id, DirectoryView(id, 'CMFCore/exportimport/tests/%s' %
                                          id)) for id in ids ]
-        site.portal_skins = DummySkinsTool(selections, fsdvs)
+        site._setObject('portal_skins', DummySkinsTool(selections, fsdvs))
+        site.REQUEST = 'exists'
         return site
 
     def setUp(self):

Modified: CMF/trunk/CMFCore/exportimport/tests/test_workflow.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/tests/test_workflow.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/tests/test_workflow.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -51,7 +51,7 @@
       factory="Products.CMFCore.exportimport.tests.test_workflow.DummyWorkflowBodyAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.CMFCore.interfaces.IWorkflowDefinition
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 </configure>
 """
@@ -185,7 +185,7 @@
 
 class DummyWorkflowBodyAdapter(BodyAdapterBase):
 
-    pass
+    body = property(BodyAdapterBase._exportBody, BodyAdapterBase._importBody)
 
 
 class WorkflowToolXMLAdapterTests(BodyAdapterTestCase):

Modified: CMF/trunk/CMFCore/exportimport/typeinfo.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/typeinfo.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/typeinfo.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -21,7 +21,6 @@
 from zope.app import zapi
 
 from Products.GenericSetup.interfaces import IBody
-from Products.GenericSetup.interfaces import PURGE
 from Products.GenericSetup.utils import exportObjects
 from Products.GenericSetup.utils import I18NURI
 from Products.GenericSetup.utils import importObjects
@@ -45,10 +44,9 @@
 
     _LOGGER_ID = 'types'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.setAttribute('xmlns:i18n', I18NURI)
         node.appendChild(self._extractProperties())
@@ -58,18 +56,18 @@
         self._logger.info('%r type info exported.' % self.context.getId())
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeProperties()
             self._purgeAliases()
             self._purgeActions()
 
-        self._initOldstyleProperties(node, mode)
-        self._initProperties(node, mode)
-        self._initAliases(node, mode)
-        self._initActions(node, mode)
+        self._initOldstyleProperties(node)
+        self._initProperties(node)
+        self._initAliases(node)
+        self._initActions(node)
 
         self._logger.info('%r type info imported.' % self.context.getId())
 
@@ -87,7 +85,7 @@
     def _purgeAliases(self):
         self.context.setMethodAliases({})
 
-    def _initAliases(self, node, mode):
+    def _initAliases(self, node):
         aliases = self.context.getMethodAliases()
         for child in node.childNodes:
             # BBB: for CMF 1.5 profiles
@@ -129,7 +127,7 @@
     def _purgeActions(self):
         self.context._actions = ()
 
-    def _initActions(self, node, mode):
+    def _initActions(self, node):
         for child in node.childNodes:
             if child.nodeName != 'action':
                 continue
@@ -152,7 +150,7 @@
             self.context.addAction(id, title, action, condition,
                                    tuple(permissions), category, visible)
 
-    def _initOldstyleProperties(self, node, mode):
+    def _initOldstyleProperties(self, node):
         if not node.hasAttribute('title'):
             return
         # BBB: for CMF 1.5 profiles
@@ -207,10 +205,9 @@
 
     _LOGGER_ID = 'types'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.appendChild(self._extractProperties())
         node.appendChild(self._extractObjects())
@@ -218,20 +215,20 @@
         self._logger.info('Types tool exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeProperties()
             self._purgeObjects()
 
-        self._initProperties(node, mode)
-        self._initObjects(node, mode)
-        self._initBBBObjects(node, mode)
+        self._initProperties(node)
+        self._initObjects(node)
+        self._initBBBObjects(node)
 
         self._logger.info('Types tool imported.')
 
-    def _initBBBObjects(self, node, mode):
+    def _initBBBObjects(self, node):
         for child in node.childNodes:
             if child.nodeName != 'type':
                 continue
@@ -242,6 +239,7 @@
                 filename = str(child.getAttribute('filename'))
                 if not filename:
                     filename = 'types/%s.xml' % obj_id.replace(' ', '_')
+                # cheating here for BBB: readDataFile is no interface method
                 body = self.environ.readDataFile(filename)
                 if body is None:
                     break

Modified: CMF/trunk/CMFCore/exportimport/workflow.py
===================================================================
--- CMF/trunk/CMFCore/exportimport/workflow.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/exportimport/workflow.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -19,7 +19,6 @@
 from zope.app import zapi
 
 from Products.GenericSetup.interfaces import IBody
-from Products.GenericSetup.interfaces import PURGE
 from Products.GenericSetup.utils import exportObjects
 from Products.GenericSetup.utils import importObjects
 from Products.GenericSetup.utils import ObjectManagerHelpers
@@ -42,10 +41,9 @@
 
     _LOGGER_ID = 'workflow'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.appendChild(self._extractProperties())
         node.appendChild(self._extractObjects())
@@ -54,22 +52,22 @@
         self._logger.info('Workflow tool exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeProperties()
             self._purgeObjects()
             self._purgeChains()
 
-        self._initProperties(node, mode)
-        self._initObjects(node, mode)
-        self._initBBBObjects(node, mode)
-        self._initChains(node, mode)
+        self._initProperties(node)
+        self._initObjects(node)
+        self._initBBBObjects(node)
+        self._initChains(node)
 
         self._logger.info('Workflow tool imported.')
 
-    def _initBBBObjects(self, node, mode):
+    def _initBBBObjects(self, node):
         for child in node.childNodes:
             if child.nodeName != 'workflow':
                 continue
@@ -113,7 +111,7 @@
         if self.context._chains_by_type is not None:
             self.context._chains_by_type.clear()
 
-    def _initChains(self, node, mode):
+    def _initChains(self, node):
         for child in node.childNodes:
             if child.nodeName != 'bindings':
                 continue

Deleted: CMF/trunk/CMFCore/www/addAction.zpt
===================================================================
--- CMF/trunk/CMFCore/www/addAction.zpt	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/www/addAction.zpt	2005-12-12 10:33:40 UTC (rev 40715)
@@ -1,45 +0,0 @@
-<h1 tal:replace="structure context/manage_page_header">PAGE HEADER</h1>
-<h2 tal:define="form_title string:Add CMF Action"
-    tal:replace="structure context/manage_form_title">FORM TITLE</h2>
-
-<p class="form-help">An Action object represents a reference to an action.</p>
-
-<form action="manage_addAction" method="post">
-<table cellspacing="0" cellpadding="2" border="0">
- <tr>
-  <td>
-   <div class="form-label">ID</div>
-  </td>
-  <td>
-   <input type="text" name="id" size="40" />
-  </td>
- </tr>
- <tr>
-  <td>
-   <div class="form-label">Presettings</div>
-  </td>
-  <td>
-   <select name="settings_id">
-    <option value="" selected="selected">(None)</option>
-    <optgroup label="PROFILE_TITLE"
-       tal:repeat="profile options/profiles"
-       tal:attributes="label profile/title">
-     <option value="SETTINGS_ID"
-             tal:repeat="action_path profile/action_paths"
-             tal:attributes="value string:${profile/id}/${action_path}"
-             tal:content="action_path">ACTION PATH</option></optgroup>
-   </select>
-  </td>
- </tr>
- <tr>
-  <td>
-   &nbsp;
-  </td>
-  <td>
-   <input class="form-element" type="submit" name="submit" value="Add" /> 
-  </td>
- </tr>
-</table>
-</form>
-
-<h1 tal:replace="structure context/manage_page_footer">PAGE FOOTER</h1>

Deleted: CMF/trunk/CMFCore/www/addActionCategory.zpt
===================================================================
--- CMF/trunk/CMFCore/www/addActionCategory.zpt	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/CMFCore/www/addActionCategory.zpt	2005-12-12 10:33:40 UTC (rev 40715)
@@ -1,29 +0,0 @@
-<h1 tal:replace="structure context/manage_page_header">PAGE HEADER</h1>
-<h2 tal:define="form_title string:Add CMF Action Category"
-    tal:replace="structure context/manage_form_title">FORM TITLE</h2>
-
-<p class="form-help">An Action Category object represents a group of Action
- objects.</p>
-
-<form action="manage_addActionCategory" method="post">
-<table cellspacing="0" cellpadding="2" border="0">
- <tr>
-  <td>
-   <div class="form-label">ID</div>
-  </td>
-  <td>
-   <input type="text" name="id" size="40" />
-  </td>
- </tr>
- <tr>
-  <td>
-   &nbsp;
-  </td>
-  <td>
-   <input class="form-element" type="submit" name="submit" value="Add" /> 
-  </td>
- </tr>
-</table>
-</form>
-
-<h1 tal:replace="structure context/manage_page_footer">PAGE FOOTER</h1>

Modified: CMF/trunk/DCWorkflow/browser/workflow.py
===================================================================
--- CMF/trunk/DCWorkflow/browser/workflow.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/DCWorkflow/browser/workflow.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -59,7 +59,7 @@
                                  'obj_ids': tuple(obj_ids)})
         return tuple(profiles)
 
-    def _initSettings(self, obj, profile_id, obj_id):
+    def _initSettings(self, obj, profile_id, obj_path):
         stool = getToolByName(self, 'portal_setup', None)
         if stool is None:
             return
@@ -73,7 +73,7 @@
                 continue
 
             root = parseString(body).documentElement
-            if not root.getAttribute('workflow_id') == obj_id:
+            if not root.getAttribute('workflow_id') == obj_path[0]:
                 continue
 
             importer = zapi.queryMultiAdapter((obj, context), IBody)

Modified: CMF/trunk/DCWorkflow/configure.zcml
===================================================================
--- CMF/trunk/DCWorkflow/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/DCWorkflow/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -17,7 +17,7 @@
       factory=".exportimport.DCWorkflowDefinitionBodyAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for=".interfaces.IDCWorkflowDefinition
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
 </configure>

Modified: CMF/trunk/GenericSetup/MailHost/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/MailHost/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/MailHost/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -6,7 +6,7 @@
       factory=".exportimport.MailHostXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.MailHost.interfaces.IMailHost
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
 </configure>

Modified: CMF/trunk/GenericSetup/MailHost/exportimport.py
===================================================================
--- CMF/trunk/GenericSetup/MailHost/exportimport.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/MailHost/exportimport.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -15,7 +15,6 @@
 $Id$
 """
 
-from Products.GenericSetup.interfaces import PURGE
 from Products.GenericSetup.utils import XMLAdapterBase
 
 from Products.MailHost.interfaces import IMailHost
@@ -30,10 +29,9 @@
 
     _LOGGER_ID = 'mailhost'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.setAttribute('smtp_host', str(self.context.smtp_host))
         node.setAttribute('smtp_port', str(self.context.smtp_port))
@@ -43,7 +41,7 @@
         self._logger.info('Mailhost exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         self.context.smtp_host = str(node.getAttribute('smtp_host'))

Modified: CMF/trunk/GenericSetup/OFSP/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/OFSP/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/OFSP/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -6,7 +6,7 @@
       factory=".exportimport.FolderXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="OFS.interfaces.IFolder
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
 </configure>

Modified: CMF/trunk/GenericSetup/OFSP/exportimport.py
===================================================================
--- CMF/trunk/GenericSetup/OFSP/exportimport.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/OFSP/exportimport.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -15,7 +15,6 @@
 $Id$
 """
 
-from Products.GenericSetup.interfaces import PURGE
 from Products.GenericSetup.utils import XMLAdapterBase
 from Products.GenericSetup.utils import ObjectManagerHelpers
 from Products.GenericSetup.utils import PropertyManagerHelpers
@@ -33,10 +32,9 @@
 
     _LOGGER_ID = 'ofs'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.appendChild(self._extractProperties())
         node.appendChild(self._extractObjects())
@@ -44,15 +42,15 @@
         self._logger.info('Folder exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeProperties()
             self._purgeObjects()
 
-        self._initProperties(node, mode)
-        self._initObjects(node, mode)
+        self._initProperties(node)
+        self._initObjects(node)
 
         self._logger.info('Folder imported.')
 

Modified: CMF/trunk/GenericSetup/PluginIndexes/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/PluginIndexes/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/PluginIndexes/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -4,86 +4,58 @@
 
   <adapter
       factory=".exportimport.PluggableIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.PluginIndexes.interfaces.IPluggableIndex"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.PluginIndexes.interfaces.IPluggableIndex
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".exportimport.PluggableIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.PluginIndexes.interfaces.IPluggableIndex"
-      />
-
-  <adapter
       factory=".exportimport.DateIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.PluginIndexes.interfaces.IDateIndex"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.PluginIndexes.interfaces.IDateIndex
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".exportimport.DateIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.PluginIndexes.interfaces.IDateIndex"
-      />
-
-  <adapter
       factory=".exportimport.DateRangeIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.PluginIndexes.interfaces.IDateRangeIndex"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.PluginIndexes.interfaces.IDateRangeIndex
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".exportimport.DateRangeIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.PluginIndexes.interfaces.IDateRangeIndex"
-      />
-
-  <adapter
       factory=".exportimport.PathIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.PluginIndexes.interfaces.IPathIndex"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.PluginIndexes.interfaces.IPathIndex
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".exportimport.PathIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.PluginIndexes.interfaces.IPathIndex"
-      />
-
-  <adapter
       factory=".exportimport.VocabularyNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.PluginIndexes.interfaces.IVocabulary"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.PluginIndexes.interfaces.IVocabulary
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
       factory=".exportimport.TextIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.PluginIndexes.interfaces.ITextIndex"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.PluginIndexes.interfaces.ITextIndex
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
       factory=".exportimport.FilteredSetNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.PluginIndexes.interfaces.IFilteredSet"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.PluginIndexes.interfaces.IFilteredSet
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".exportimport.FilteredSetNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.PluginIndexes.interfaces.IFilteredSet"
-      />
-
-  <adapter
       factory=".exportimport.TopicIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.PluginIndexes.interfaces.ITopicIndex"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.PluginIndexes.interfaces.ITopicIndex
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
-  <adapter
-      factory=".exportimport.TopicIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.PluginIndexes.interfaces.ITopicIndex"
-      />
-
 </configure>

Modified: CMF/trunk/GenericSetup/PluginIndexes/exportimport.py
===================================================================
--- CMF/trunk/GenericSetup/PluginIndexes/exportimport.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/PluginIndexes/exportimport.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -15,9 +15,9 @@
 $Id$
 """
 
-from Products.GenericSetup.interfaces import INodeExporter
-from Products.GenericSetup.interfaces import INodeImporter
-from Products.GenericSetup.interfaces import PURGE
+from zope.app import zapi
+
+from Products.GenericSetup.interfaces import INode
 from Products.GenericSetup.utils import NodeAdapterBase
 from Products.GenericSetup.utils import PropertyManagerHelpers
 
@@ -38,10 +38,9 @@
 
     __used_for__ = IPluggableIndex
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('index')
         for value in self.context.getIndexSourceNames():
             child = self._doc.createElement('indexed_attr')
@@ -49,7 +48,7 @@
             node.appendChild(child)
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         indexed_attrs = []
@@ -60,7 +59,9 @@
         self.context.indexed_attrs = indexed_attrs
         self.context.clear()
 
+    node = property(_exportNode, _importNode)
 
+
 class DateIndexNodeAdapter(NodeAdapterBase, PropertyManagerHelpers):
 
     """Node im- and exporter for DateIndex.
@@ -68,24 +69,25 @@
 
     __used_for__ = IDateIndex
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('index')
         node.appendChild(self._extractProperties())
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeProperties()
 
-        self._initProperties(node, mode)
+        self._initProperties(node)
         self.context.clear()
 
+    node = property(_exportNode, _importNode)
 
+
 class DateRangeIndexNodeAdapter(NodeAdapterBase):
 
     """Node im- and exporter for DateRangeIndex.
@@ -93,23 +95,24 @@
 
     __used_for__ = IDateRangeIndex
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('index')
         node.setAttribute('since_field', self.context.getSinceField())
         node.setAttribute('until_field', self.context.getUntilField())
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         self.context._edit(node.getAttribute('since_field').encode('utf-8'),
                            node.getAttribute('until_field').encode('utf-8'))
         self.context.clear()
 
+    node = property(_exportNode, _importNode)
 
+
 class PathIndexNodeAdapter(NodeAdapterBase):
 
     """Node im- and exporter for PathIndex.
@@ -117,13 +120,14 @@
 
     __used_for__ = IPathIndex
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         return self._getObjectNode('index')
 
+    node = property(_exportNode, NodeAdapterBase._importNode)
 
+
 class VocabularyNodeAdapter(NodeAdapterBase):
 
     """Node im- and exporter for Vocabulary.
@@ -131,15 +135,16 @@
 
     __used_for__ = IVocabulary
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.setAttribute('deprecated', 'True')
         return node
 
+    node = property(_exportNode, NodeAdapterBase._importNode)
 
+
 class TextIndexNodeAdapter(NodeAdapterBase):
 
     """Node im- and exporter for TextIndex.
@@ -147,15 +152,16 @@
 
     __used_for__ = ITextIndex
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('index')
         node.setAttribute('deprecated', 'True')
         return node
 
+    node = property(_exportNode, NodeAdapterBase._importNode)
 
+
 class FilteredSetNodeAdapter(NodeAdapterBase):
 
     """Node im- and exporter for FilteredSet.
@@ -163,22 +169,23 @@
 
     __used_for__ = IFilteredSet
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('filtered_set')
         node.setAttribute('expression', self.context.getExpression())
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         self.context.setExpression(
                               node.getAttribute('expression').encode('utf-8'))
         self.context.clear()
 
+    node = property(_exportNode, _importNode)
 
+
 class TopicIndexNodeAdapter(NodeAdapterBase):
 
     """Node im- and exporter for TopicIndex.
@@ -186,16 +193,16 @@
 
     __used_for__ = ITopicIndex
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('index')
         for set in self.context.filteredSets.values():
-            node.appendChild(INodeExporter(set).exportNode(doc))
+            exporter = zapi.queryMultiAdapter((set, self.environ), INode)
+            node.appendChild(exporter.node)
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         for child in node.childNodes:
@@ -204,5 +211,8 @@
                 set_meta_type = str(child.getAttribute('meta_type'))
                 self.context.addFilteredSet(set_id, set_meta_type, '')
                 set = self.context.filteredSets[set_id]
-                INodeImporter(set).importNode(child)
+                importer = zapi.queryMultiAdapter((set, self.environ), INode)
+                importer.node = child
         self.context.clear()
+
+    node = property(_exportNode, _importNode)

Modified: CMF/trunk/GenericSetup/PythonScripts/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/PythonScripts/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/PythonScripts/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -7,7 +7,7 @@
       factory=".exportimport.PythonScriptBodyAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for=".interfaces.IPythonScript
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <five:implements

Modified: CMF/trunk/GenericSetup/ZCTextIndex/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/ZCTextIndex/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/ZCTextIndex/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -4,26 +4,16 @@
 
   <adapter
       factory=".exportimport.ZCLexiconNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.ZCTextIndex.interfaces.IZCLexicon"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.ZCTextIndex.interfaces.IZCLexicon
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
   <adapter
-      factory=".exportimport.ZCLexiconNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.ZCTextIndex.interfaces.IZCLexicon"
-      />
-
-  <adapter
       factory=".exportimport.ZCTextIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeExporter"
-      for="Products.ZCTextIndex.interfaces.IZCTextIndex"
+      provides="Products.GenericSetup.interfaces.INode"
+      for="Products.ZCTextIndex.interfaces.IZCTextIndex
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
-  <adapter
-      factory=".exportimport.ZCTextIndexNodeAdapter"
-      provides="Products.GenericSetup.interfaces.INodeImporter"
-      for="Products.ZCTextIndex.interfaces.IZCTextIndex"
-      />
-
 </configure>

Modified: CMF/trunk/GenericSetup/ZCTextIndex/exportimport.py
===================================================================
--- CMF/trunk/GenericSetup/ZCTextIndex/exportimport.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/ZCTextIndex/exportimport.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -19,7 +19,6 @@
 from BTrees.Length import Length
 from BTrees.OIBTree import OIBTree
 
-from Products.GenericSetup.interfaces import PURGE
 from Products.GenericSetup.utils import NodeAdapterBase
 
 from Products.ZCTextIndex.interfaces import IZCLexicon
@@ -34,10 +33,9 @@
 
     __used_for__ = IZCLexicon
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         for element in self.context._pipeline:
             group, name = self._getKeys(element)
@@ -47,7 +45,7 @@
             node.appendChild(child)
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         pipeline = []
@@ -63,6 +61,8 @@
         self.context._words = IOBTree()
         self.context.length = Length()
 
+    node = property(_exportNode, _importNode)
+
     def _getKeys(self, element):
         for group in element_factory.getFactoryGroups():
             for name, factory in element_factory._groups[group].items():
@@ -77,10 +77,9 @@
 
     __used_for__ = IZCTextIndex
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('index')
 
         for value in self.context.getIndexSourceNames():
@@ -100,7 +99,7 @@
 
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
         indexed_attrs = []
@@ -110,3 +109,5 @@
                                   child.getAttribute('value').encode('utf-8'))
         self.context.indexed_attrs = indexed_attrs
         self.context.clear()
+
+    node = property(_exportNode, _importNode)

Modified: CMF/trunk/GenericSetup/ZCatalog/configure.zcml
===================================================================
--- CMF/trunk/GenericSetup/ZCatalog/configure.zcml	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/ZCatalog/configure.zcml	2005-12-12 10:33:40 UTC (rev 40715)
@@ -6,7 +6,7 @@
       factory=".exportimport.ZCatalogXMLAdapter"
       provides="Products.GenericSetup.interfaces.IBody"
       for="Products.ZCatalog.interfaces.IZCatalog
-           Products.GenericSetup.interfaces.ISetupContext"
+           Products.GenericSetup.interfaces.ISetupEnviron"
       />
 
 </configure>

Modified: CMF/trunk/GenericSetup/ZCatalog/exportimport.py
===================================================================
--- CMF/trunk/GenericSetup/ZCatalog/exportimport.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/ZCatalog/exportimport.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -15,9 +15,9 @@
 $Id$
 """
 
-from Products.GenericSetup.interfaces import INodeExporter
-from Products.GenericSetup.interfaces import INodeImporter
-from Products.GenericSetup.interfaces import PURGE
+from zope.app import zapi
+
+from Products.GenericSetup.interfaces import INode
 from Products.GenericSetup.utils import ObjectManagerHelpers
 from Products.GenericSetup.utils import PropertyManagerHelpers
 from Products.GenericSetup.utils import XMLAdapterBase
@@ -40,10 +40,9 @@
 
     _LOGGER_ID = 'catalog'
 
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
         node = self._getObjectNode('object')
         node.appendChild(self._extractProperties())
         node.appendChild(self._extractObjects())
@@ -53,19 +52,19 @@
         self._logger.info('Catalog exported.')
         return node
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
-        if mode == PURGE:
+        if self.environ.shouldPurge():
             self._purgeProperties()
             self._purgeObjects()
             self._purgeIndexes()
             self._purgeColumns()
 
-        self._initProperties(node, mode)
-        self._initObjects(node, mode)
-        self._initIndexes(node, mode)
-        self._initColumns(node, mode)
+        self._initProperties(node)
+        self._initObjects(node)
+        self._initIndexes(node)
+        self._initColumns(node)
 
         self._logger.info('Catalog imported.')
 
@@ -74,17 +73,16 @@
         indexes = self.context.getIndexObjects()[:]
         indexes.sort(lambda x,y: cmp(x.getId(), y.getId()))
         for idx in indexes:
-            exporter = INodeExporter(idx, None)
-            if exporter is None:
-                continue
-            fragment.appendChild(exporter.exportNode(self._doc))
+            exporter = zapi.queryMultiAdapter((idx, self.environ), INode)
+            if exporter:
+                fragment.appendChild(exporter.node)
         return fragment
 
     def _purgeIndexes(self):
         for idx_id in self.context.indexes():
             self.context.delIndex(idx_id)
 
-    def _initIndexes(self, node, mode):
+    def _initIndexes(self, node):
         for child in node.childNodes:
             if child.nodeName != 'index':
                 continue
@@ -106,7 +104,9 @@
                 zcatalog.addIndex(idx_id, meta_type, extra)
 
             idx = zcatalog._catalog.getIndex(idx_id)
-            INodeImporter(idx).importNode(child, mode)
+            importer = zapi.queryMultiAdapter((idx, self.environ), INode)
+            if importer:
+                importer.node = child
 
     def _extractColumns(self):
         fragment = self._doc.createDocumentFragment()
@@ -122,7 +122,7 @@
         for col in self.context.schema()[:]:
             self.context.delColumn(col)
 
-    def _initColumns(self, node, mode):
+    def _initColumns(self, node):
         for child in node.childNodes:
             if child.nodeName != 'column':
                 continue

Modified: CMF/trunk/GenericSetup/ZCatalog/tests/test_exportimport.py
===================================================================
--- CMF/trunk/GenericSetup/ZCatalog/tests/test_exportimport.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/ZCatalog/tests/test_exportimport.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -25,7 +25,7 @@
 
 from Products.GenericSetup.interfaces import IBody
 from Products.GenericSetup.testing import BodyAdapterTestCase
-from Products.GenericSetup.tests.common import DummyExportContext
+from Products.GenericSetup.testing import DummySetupEnviron
 
 
 class _extra:
@@ -132,7 +132,9 @@
         obj.addIndex('foo_text', 'TextIndex')
 
     def setUp(self):
-        import Products.GenericSetup
+        import Products.GenericSetup.PluginIndexes
+        import Products.GenericSetup.ZCatalog
+        import Products.GenericSetup.ZCTextIndex
         from Products.ZCatalog.ZCatalog import ZCatalog
 
         BodyAdapterTestCase.setUp(self)
@@ -146,9 +148,9 @@
 
     def test_body_get_special(self):
         self._populate_special(self._obj)
-        context = DummyExportContext(None)
-        exporter = zapi.getMultiAdapter((self._obj, context), IBody)
-        self.assertEqual(exporter.body,
+        context = DummySetupEnviron()
+        adapted = zapi.getMultiAdapter((self._obj, context), IBody)
+        self.assertEqual(adapted.body,
                          _CATALOG_BODY % (_VOCABULARY_XML, _TEXT_XML))
 
 

Modified: CMF/trunk/GenericSetup/browser/utils.py
===================================================================
--- CMF/trunk/GenericSetup/browser/utils.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/browser/utils.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -27,10 +27,12 @@
         if submit_add:
             obj = self.klass('temp')
             if settings_id:
-                profile_id, obj_id = settings_id.split('/')
+                ids = settings_id.split('/')
+                profile_id = ids[0]
+                obj_path = ids[1:]
                 if not add_input_name:
-                    self.request.set('add_input_name', obj_id)
-                self._initSettings(obj, profile_id, obj_id)
+                    self.request.set('add_input_name', obj_path[-1])
+                self._initSettings(obj, profile_id, obj_path)
             self.context.add(obj)
             self.request.response.redirect(self.context.nextURL())
             return ''

Modified: CMF/trunk/GenericSetup/context.py
===================================================================
--- CMF/trunk/GenericSetup/context.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/context.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -104,6 +104,7 @@
         self._loggers = {}
         self._messages = []
         self._encoding = encoding
+        self._should_purge = True
 
     security.declareProtected( ManagePortal, 'getSite' )
     def getSite( self ):
@@ -146,7 +147,14 @@
         """
         self._messages[:] = []
 
+    security.declareProtected( ManagePortal, 'shouldPurge' )
+    def shouldPurge( self ):
 
+        """ See ISetupContext.
+        """
+        return self._should_purge
+
+
 class DirectoryImportContext( BaseContext ):
 
     implements(IImportContext)
@@ -224,13 +232,6 @@
 
         return [ name for name in names if name not in skip ]
 
-    security.declareProtected( ManagePortal, 'shouldPurge' )
-    def shouldPurge( self ):
-
-        """ See IImportContext.
-        """
-        return self._should_purge
-
 InitializeClass( DirectoryImportContext )
 
 

Modified: CMF/trunk/GenericSetup/interfaces.py
===================================================================
--- CMF/trunk/GenericSetup/interfaces.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/interfaces.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -20,7 +20,6 @@
 from zope.schema import TextLine
 
 BASE, EXTENSION = range(1, 3)
-PURGE, UPDATE = range(1, 3)
 
 
 class IPseudoInterface( Interface ):
@@ -28,8 +27,23 @@
     """ API documentation;  not testable / enforceable.
     """
 
-class ISetupContext( Interface ):
 
+class ISetupEnviron(Interface):
+
+    """Context for im- and export adapters.
+    """
+
+    def getLogger(name):
+        """Get a logger with the specified name, creating it if necessary.
+        """
+
+    def shouldPurge():
+        """When installing, should the existing setup be purged?
+        """
+
+
+class ISetupContext(ISetupEnviron):
+
     """ Context used for export / import plugins.
     """
     def getSite():
@@ -49,10 +63,6 @@
         o Return None if the data should not be encoded.
         """
 
-    def getLogger(name):
-        """ Get a logger with the specified name, creating it if necessary.
-        """
-
     def listNotes():
         """ Return notes recorded by this context.
         
@@ -118,11 +128,7 @@
         o If 'path' does not point to a directory / folder, return None.
         """
 
-    def shouldPurge():
 
-        """ When installing, should the existing setup be purged?
-        """
-
 class IImportPlugin( IPseudoInterface ):
 
     """ Signature for callables used to import portions of site configuration.
@@ -588,38 +594,26 @@
         """
 
 
-class IBody(Interface):
+class INode(Interface):
 
-    """Body im- and exporter.
+    """Node im- and exporter.
     """
 
-    body = Text(description=u'Im- and export the object as a file body.')
+    node = Text(description=u'Im- and export the object as a DOM node.')
 
-    mime_type = TextLine(description=u'MIME type of the file body.')
 
-    suffix = TextLine(description=u'Suffix for the file.')
+class IBody(INode):
 
-
-class INodeExporter(Interface):
-
-    """Node exporter.
+    """Body im- and exporter.
     """
 
-    def exportNode(doc):
-        """Export the object as a DOM node.
-        """
+    body = Text(description=u'Im- and export the object as a file body.')
 
+    mime_type = TextLine(description=u'MIME type of the file body.')
 
-class INodeImporter(Interface):
+    suffix = TextLine(description=u'Suffix for the file.')
 
-    """Node importer.
-    """
 
-    def importNode(node, mode=PURGE):
-        """Import the object from the DOM node.
-        """
-
-
 class IFilesystemExporter(Interface):
     """ Plugin interface for site structure export.
     """

Modified: CMF/trunk/GenericSetup/testing.py
===================================================================
--- CMF/trunk/GenericSetup/testing.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/testing.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -23,14 +23,12 @@
 import Products.Five
 from Products.Five import zcml
 from zope.app import zapi
+from zope.interface import implements
 from zope.interface.verify import verifyClass
 
 from interfaces import IBody
-from interfaces import INodeExporter
-from interfaces import INodeImporter
-from tests.common import DummyExportContext
-from tests.common import DummyImportContext
-from utils import PrettyDocument
+from interfaces import INode
+from interfaces import ISetupEnviron
 
 try:
     from zope.app.testing.placelesssetup import PlacelessSetup
@@ -38,8 +36,38 @@
     from zope.app.tests.placelesssetup import PlacelessSetup
 
 
-class BodyAdapterTestCase(PlacelessSetup, unittest.TestCase):
+class DummyLogger:
 
+    def __init__(self, id, messages):
+        self._id = id
+        self._messages = messages
+
+    def info(self, msg, *args, **kwargs):
+        self._messages.append((20, self._id, msg))
+
+    def warning(self, msg, *args, **kwargs):
+        self._messages.append((30, self._id, msg))
+
+
+class DummySetupEnviron(object):
+
+    """Context for body im- and exporter.
+    """
+
+    implements(ISetupEnviron)
+
+    def __init__(self):
+        self._notes = []
+
+    def getLogger(self, name):
+        return DummyLogger(name, self._notes)
+
+    def shouldPurge(self):
+        return True
+
+
+class _AdapterTestCaseBase(PlacelessSetup, unittest.TestCase):
+
     def _populate(self, obj):
         pass
 
@@ -51,56 +79,40 @@
         zcml.load_config('meta.zcml', Products.Five)
         zcml.load_config('permissions.zcml', Products.Five)
 
-    def tearDown(self):
-        PlacelessSetup.tearDown(self)
 
+class BodyAdapterTestCase(_AdapterTestCaseBase):
+
     def test_z3interfaces(self):
         verifyClass(IBody, self._getTargetClass())
 
     def test_body_get(self):
         self._populate(self._obj)
-        context = DummyExportContext(None)
-        exporter = zapi.getMultiAdapter((self._obj, context), IBody)
-        self.assertEqual(exporter.body, self._BODY)
+        context = DummySetupEnviron()
+        adapted = zapi.getMultiAdapter((self._obj, context), IBody)
+        self.assertEqual(adapted.body, self._BODY)
 
     def test_body_set(self):
-        context = DummyImportContext(None)
-        importer = zapi.getMultiAdapter((self._obj, context), IBody)
-        importer.body = self._BODY
+        context = DummySetupEnviron()
+        adapted = zapi.getMultiAdapter((self._obj, context), IBody)
+        adapted.body = self._BODY
         self._verifyImport(self._obj)
-        context = DummyExportContext(None)
-        exporter = zapi.getMultiAdapter((self._obj, context), IBody)
-        self.assertEqual(exporter.body, self._BODY)
+        self.assertEqual(adapted.body, self._BODY)
 
 
-class NodeAdapterTestCase(PlacelessSetup, unittest.TestCase):
+class NodeAdapterTestCase(_AdapterTestCaseBase):
 
-    def _populate(self, obj):
-        pass
-
-    def _verifyImport(self, obj):
-        pass
-
-    def setUp(self):
-        PlacelessSetup.setUp(self)
-        zcml.load_config('meta.zcml', Products.Five)
-        zcml.load_config('permissions.zcml', Products.Five)
-
-    def tearDown(self):
-        PlacelessSetup.tearDown(self)
-
     def test_z3interfaces(self):
-        verifyClass(INodeExporter, self._getTargetClass())
-        verifyClass(INodeImporter, self._getTargetClass())
+        verifyClass(INode, self._getTargetClass())
 
-    def test_exportNode(self):
+    def test_node_get(self):
         self._populate(self._obj)
-        node = INodeExporter(self._obj).exportNode(PrettyDocument())
-        self.assertEqual(node.toprettyxml(' '), self._XML)
+        context = DummySetupEnviron()
+        adapted = zapi.getMultiAdapter((self._obj, context), INode)
+        self.assertEqual(adapted.node.toprettyxml(' '), self._XML)
 
-    def test_importNode(self):
-        node = parseString(self._XML).documentElement
-        self.assertEqual(INodeImporter(self._obj).importNode(node), None)
+    def test_node_set(self):
+        context = DummySetupEnviron()
+        adapted = zapi.getMultiAdapter((self._obj, context), INode)
+        adapted.node = parseString(self._XML).documentElement
         self._verifyImport(self._obj)
-        node = INodeExporter(self._obj).exportNode(PrettyDocument())
-        self.assertEqual(node.toprettyxml(' '), self._XML)
+        self.assertEqual(adapted.node.toprettyxml(' '), self._XML)

Modified: CMF/trunk/GenericSetup/tests/common.py
===================================================================
--- CMF/trunk/GenericSetup/tests/common.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/tests/common.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -25,6 +25,7 @@
 
 from Products.GenericSetup.interfaces import IExportContext
 from Products.GenericSetup.interfaces import IImportContext
+from Products.GenericSetup.testing import DummyLogger
 
 
 class OmnipotentUser(Implicit):
@@ -179,19 +180,6 @@
         self._compareDOM( found, data )
 
 
-class DummyLogger:
-
-    def __init__(self, id, messages):
-        self._id = id
-        self._messages = messages
-
-    def info(self, msg, *args, **kwargs):
-        self._messages.append((20, self._id, msg))
-
-    def warning(self, msg, *args, **kwargs):
-        self._messages.append((30, self._id, msg))
-
-
 class DummyExportContext:
 
     implements(IExportContext)

Modified: CMF/trunk/GenericSetup/tests/test_utils.py
===================================================================
--- CMF/trunk/GenericSetup/tests/test_utils.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/tests/test_utils.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -20,8 +20,8 @@
 
 from xml.dom.minidom import parseString
 
-from Products.GenericSetup.interfaces import PURGE, UPDATE
 from Products.GenericSetup.utils import PrettyDocument
+from Products.GenericSetup.testing import DummySetupEnviron
 
 
 _EMPTY_PROPERTY_EXPORT = """\
@@ -210,7 +210,7 @@
         obj._setProperty('foo_selection', 'foobarbaz', 'selection')
         obj._setProperty('foo_mselection', 'foobarbaz', 'multiple selection')
         obj._setProperty('foo_boolean0', '', 'boolean')
-        self.helpers = self._makeOne(obj)
+        self.helpers = self._makeOne(obj, DummySetupEnviron())
 
     def _populate(self, obj):
         obj._updateProperty('foo_boolean', 'True')
@@ -245,7 +245,7 @@
 
     def test__initProperties_normal(self):
         node = parseString(_NORMAL_PROPERTY_EXPORT).documentElement
-        self.helpers._initProperties(node, PURGE)
+        self.helpers._initProperties(node)
         self.assertEqual(type(self.helpers.context.foo_int), int)
         self.assertEqual(type(self.helpers.context.foo_string), str)
         self.assertEqual(type(self.helpers.context.foo_tokens), tuple)
@@ -260,7 +260,7 @@
 
     def test__initProperties_fixed(self):
         node = parseString(_FIXED_PROPERTY_EXPORT).documentElement
-        self.helpers._initProperties(node, PURGE)
+        self.helpers._initProperties(node)
 
         doc = self.helpers._doc = PrettyDocument()
         node = doc.createElement('dummy')
@@ -271,7 +271,7 @@
 
     def test__initProperties_special(self):
         node = parseString(_SPECIAL_IMPORT).documentElement
-        self.helpers._initProperties(node, UPDATE)
+        self.helpers._initProperties(node)
 
         doc = self.helpers._doc = PrettyDocument()
         node = doc.createElement('dummy')

Modified: CMF/trunk/GenericSetup/utils.py
===================================================================
--- CMF/trunk/GenericSetup/utils.py	2005-12-12 01:58:02 UTC (rev 40714)
+++ CMF/trunk/GenericSetup/utils.py	2005-12-12 10:33:40 UTC (rev 40715)
@@ -41,10 +41,8 @@
 
 from exceptions import BadRequest
 from interfaces import IBody
-from interfaces import INodeExporter
-from interfaces import INodeImporter
+from interfaces import INode
 from interfaces import ISetupContext
-from interfaces import PURGE, UPDATE
 from permissions import ManagePortal
 
 
@@ -403,12 +401,12 @@
             node.writexml(writer, indent, addindent, newl)
 
 
-class BodyAdapterBase(object):
+class NodeAdapterBase(object):
 
-    """Body im- and exporter base.
+    """Node im- and exporter base.
     """
 
-    implements(IBody)
+    implements(INode)
 
     _LOGGER_ID = ''
 
@@ -416,49 +414,25 @@
         self.context = context
         self.environ = environ
         self._logger = environ.getLogger(self._LOGGER_ID)
+        self._doc = PrettyDocument()
 
-    def _exportBody(self):
-        """Export the object as a file body.
-        """
-        return ''
-
-    def _importBody(self, body):
-        """Import the object from the file body.
-        """
-
-    body = property(_exportBody, _importBody)
-
-    mime_type = 'text/plain'
-
-    suffix = ''
-
-
-class NodeAdapterBase(object):
-
-    """Node im- and exporter base.
-    """
-
-    implements(INodeExporter, INodeImporter)
-
-    def __init__(self, context):
-        self.context = context
-
-    def exportNode(self, doc):
+    def _exportNode(self):
         """Export the object as a DOM node.
         """
-        self._doc = doc
-        return self._getObjectNode('object')
+        return self._getObjectNode('object', False)
 
-    def importNode(self, node, mode=PURGE):
+    def _importNode(self, node):
         """Import the object from the DOM node.
         """
 
-    def _getObjectNode(self, name):
+    node = property(_exportNode, _importNode)
+
+    def _getObjectNode(self, name, i18n=True):
         node = self._doc.createElement(name)
         node.setAttribute('name', self.context.getId())
         node.setAttribute('meta_type', self.context.meta_type)
         i18n_domain = getattr(self.context, 'i18n_domain', None)
-        if i18n_domain:
+        if i18n and i18n_domain:
             node.setAttributeNS(I18NURI, 'i18n:domain', i18n_domain)
             self._i18n_props = ('title', 'description')
         return node
@@ -476,23 +450,46 @@
         return val.lower() in ('true', 'yes', '1')
 
 
-class XMLAdapterBase(BodyAdapterBase, NodeAdapterBase):
+class BodyAdapterBase(NodeAdapterBase):
 
+    """Body im- and exporter base.
+    """
+
+    implements(IBody)
+
+    def _exportBody(self):
+        """Export the object as a file body.
+        """
+        return ''
+
+    def _importBody(self, body):
+        """Import the object from the file body.
+        """
+
+    body = property(_exportBody, _importBody)
+
+    mime_type = 'text/plain'
+
+    suffix = ''
+
+
+class XMLAdapterBase(NodeAdapterBase):
+
     """XML im- and exporter base.
     """
 
+    implements(IBody)
+
     def _exportBody(self):
         """Export the object as a file body.
         """
-        doc = PrettyDocument()
-        doc.appendChild(self.exportNode(doc))
-        return doc.toprettyxml(' ')
+        self._doc.appendChild(self._exportNode())
+        return self._doc.toprettyxml(' ')
 
     def _importBody(self, body):
         """Import the object from the file body.
         """
-        mode = self.environ.shouldPurge() and PURGE or UPDATE
-        self.importNode(parseString(body).documentElement, mode=mode)
+        self._importNode(parseString(body).documentElement)
 
     body = property(_exportBody, _importBody)
 
@@ -512,24 +509,16 @@
         if not IOrderedContainer.providedBy(self.context):
             objects.sort(lambda x,y: cmp(x.getId(), y.getId()))
         for obj in objects:
-            exporter = INodeExporter(obj, None)
+            exporter = zapi.queryMultiAdapter((obj, self.environ), INode)
             if exporter:
-                node = exporter.exportNode(self._doc)
-                fragment.appendChild(node)
-            else:
-                adapters = zapi.getService(zapi.servicenames.Adapters)
-                if adapters.lookup((providedBy(obj), ISetupContext), IBody):
-                    node = self._doc.createElement('object')
-                    node.setAttribute('name', obj.getId())
-                    node.setAttribute('meta_type', obj.meta_type)
-                    fragment.appendChild(node)
+                fragment.appendChild(exporter.node)
         return fragment
 
     def _purgeObjects(self):
         for obj_id in self.context.objectIds():
             self.context._delObject(obj_id)
 
-    def _initObjects(self, node, mode):
+    def _initObjects(self, node):
         for child in node.childNodes:
             if child.nodeName != 'object':
                 continue
@@ -569,9 +558,9 @@
                         pass
 
             obj = getattr(self.context, obj_id)
-            importer = INodeImporter(obj, None)
+            importer = zapi.queryMultiAdapter((obj, self.environ), INode)
             if importer:
-                importer.importNode(child, mode)
+                importer.node = child
 
 
 class PropertyManagerHelpers(object):
@@ -630,7 +619,7 @@
                     prop_value = ''
                 self.context._updateProperty(prop_id, prop_value)
 
-    def _initProperties(self, node, mode):
+    def _initProperties(self, node):
         self.context.i18n_domain = node.getAttribute('i18n:domain')
         for child in node.childNodes:
             if child.nodeName != 'property':



More information about the CMF-checkins mailing list