Author: jmorliaguet
Date: Sat May  6 16:26:14 2006
New Revision: 3055

Added:
   cpsskins/branches/paris-sprint-2006/setup/io/
   cpsskins/branches/paris-sprint-2006/setup/io/__init__.py   (contents, props 
changed)
   cpsskins/branches/paris-sprint-2006/setup/io/adapters.py   (contents, props 
changed)
   cpsskins/branches/paris-sprint-2006/setup/io/configure.zcml   (contents, 
props changed)
   cpsskins/branches/paris-sprint-2006/setup/io/fields.py   (contents, props 
changed)
   cpsskins/branches/paris-sprint-2006/setup/io/interfaces.py   (contents, 
props changed)
   cpsskins/branches/paris-sprint-2006/setup/io/utils.py   (contents, props 
changed)
   cpsskins/branches/paris-sprint-2006/uids.py   (contents, props changed)
Removed:
   cpsskins/branches/paris-sprint-2006/setup/io.py
Modified:
   cpsskins/branches/paris-sprint-2006/DEPENDENCIES.txt
   cpsskins/branches/paris-sprint-2006/__init__.py
   cpsskins/branches/paris-sprint-2006/controllers/theme.py
   cpsskins/branches/paris-sprint-2006/doc/registration.txt
   cpsskins/branches/paris-sprint-2006/elements/element.py
   cpsskins/branches/paris-sprint-2006/profiles/default/__init__.py
   cpsskins/branches/paris-sprint-2006/setup/configure.zcml
   cpsskins/branches/paris-sprint-2006/setup/registration.py
   cpsskins/branches/paris-sprint-2006/setup/setting.py
   cpsskins/branches/paris-sprint-2006/setup/settings.py
   cpsskins/branches/paris-sprint-2006/standard/io/configure.zcml
   cpsskins/branches/paris-sprint-2006/standard/io/setting.py
   cpsskins/branches/paris-sprint-2006/thememanager.py
   cpsskins/branches/paris-sprint-2006/ui/authoring/views.py
   cpsskins/branches/paris-sprint-2006/ui/screens/sitemanager/views.py
   cpsskins/branches/paris-sprint-2006/utils.py

Log:

- a lot of cleanup / refactoring:

  a new package (cpsskins.setup.io) contains all the I/O code

- added support for global themes (i.e. themes located on the filesystem that
  are not persisted in the ZODB)



Modified: cpsskins/branches/paris-sprint-2006/DEPENDENCIES.txt
==============================================================================
--- cpsskins/branches/paris-sprint-2006/DEPENDENCIES.txt        (original)
+++ cpsskins/branches/paris-sprint-2006/DEPENDENCIES.txt        Sat May  6 
16:26:14 2006
@@ -4,7 +4,7 @@
 Dependencies
 ============
 
-[1] Zope3 (trunk rev >= 39098 ) (svn://svn.zope.org/repos/main/Zope3/trunk)
+[1] Zope3 (trunk rev >= 67956) (svn://svn.zope.org/repos/main/Zope3/trunk)
 
 
 Optional products

Modified: cpsskins/branches/paris-sprint-2006/__init__.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/__init__.py     (original)
+++ cpsskins/branches/paris-sprint-2006/__init__.py     Sat May  6 16:26:14 2006
@@ -22,5 +22,5 @@
 defineFrom('cpsskins.elements.portlet', 'Portlet')
 
 # load profiles
-#from cpsskins.profiles import default
+from cpsskins.profiles import default
 

Modified: cpsskins/branches/paris-sprint-2006/controllers/theme.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/controllers/theme.py    (original)
+++ cpsskins/branches/paris-sprint-2006/controllers/theme.py    Sat May  6 
16:26:14 2006
@@ -37,5 +37,3 @@
         if tmutil.getDefaultTheme() is None:
             tmutil.setAsDefault(element)
 
-        # XXX for testing
-        tmutil.addPerspective(name=u'local', title=u'Local perspective')

Modified: cpsskins/branches/paris-sprint-2006/doc/registration.txt
==============================================================================
--- cpsskins/branches/paris-sprint-2006/doc/registration.txt    (original)
+++ cpsskins/branches/paris-sprint-2006/doc/registration.txt    Sat May  6 
16:26:14 2006
@@ -191,3 +191,38 @@
 
     >>> gsm.queryUtility(ISomeType, u'a name') is conf
     True
+
+
+Global themes
+-------------
+
+Global themes are registered as global utilities. They are not persistent.
+
+    >>> gtmutil = ThemeManagementFolder()
+    >>> gsm.registerUtility(gtmutil, IThemeManagementFolder)
+
+    >>> gsm.getUtility(IThemeManagementFolder) is gtmutil
+    True
+
+    >>> getThemeManager() is gtmutil
+    True
+
+    >>> gtmutil[u'storage'] = storage = Storage()
+    >>> gtmutil.registerUtility(storage, IStorage)
+
+    >>> gtmutil.getUtility(IStorage) is storage
+    True
+
+    >>> from cpsskins.uids import IUids, Uids
+
+    >>> uids = Uids()
+    >>> gtmutil.registerUtility(uids, IUids)
+
+    >>> gtmutil[u'uids'] = uids
+
+    >>> from cpsskins.elements.theme import Theme
+    >>> obj = Theme()
+    >>> id = uids.register(obj)
+
+    >>> isinstance(id, int)
+    True

Modified: cpsskins/branches/paris-sprint-2006/elements/element.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/elements/element.py     (original)
+++ cpsskins/branches/paris-sprint-2006/elements/element.py     Sat May  6 
16:26:14 2006
@@ -18,12 +18,12 @@
 __docformat__ = "reStructuredText"
 
 from persistent import Persistent
+
 from zope.app.container.contained import Contained
 from zope.app.container.ordered import OrderedContainer
 from zope.interface import implements
 
-from cpsskins.elements.interfaces import IElement, INode
-from cpsskins.elements.interfaces import IInnerNode, ILeaf
+from cpsskins.elements.interfaces import IElement, INode, IInnerNode, ILeaf
 
 class Element(Contained):
     """An element

Modified: cpsskins/branches/paris-sprint-2006/profiles/default/__init__.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/profiles/default/__init__.py    
(original)
+++ cpsskins/branches/paris-sprint-2006/profiles/default/__init__.py    Sat May 
 6 16:26:14 2006
@@ -17,7 +17,10 @@
 """
 __docformat__ = "reStructuredText"
 
-from cpsskins.setup.registration import register
+from cpsskins.setup.registration import registerSite, registerSettings
+
+#registerSite('cpsskins.profiles.default', 'site-2006-05-06-10.24.15.tgz')
+
+#registerSettings('cpsskins.profiles.default', 'perspectives.xml')
+#registerSettings('cpsskins.profiles.default', 'color.xml')
 
-register('cpsskins.profiles.default', 'perspectives.xml')
-register('cpsskins.profiles.default', 'color.xml')

Modified: cpsskins/branches/paris-sprint-2006/setup/configure.zcml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/configure.zcml    (original)
+++ cpsskins/branches/paris-sprint-2006/setup/configure.zcml    Sat May  6 
16:26:14 2006
@@ -39,9 +39,9 @@
       factory="cpsskins.setup.adapters.Identifiable"
   />
 
-  <!-- register global application settings -->
+  <!-- register global application sites and settings -->
   <subscriber
-      handler=".registration.loadSettingsEvent"
+      handler=".registration.loadEvent"
       for="zope.app.appsetup.IDatabaseOpenedEvent"
   />
 
@@ -60,7 +60,7 @@
         />
 
   </class>
-  
+
   <class class="cpsskins.setup.setting.LocalSetting">
 
     <require
@@ -69,7 +69,7 @@
         />
 
   </class>
-  
+
   <!-- snapshot storage -->
   <cpsskins:storage
       id="snapshots"
@@ -95,43 +95,6 @@
 
   </class>
 
-
-  <!-- field IO -->
-
-  <adapter
-      factory="cpsskins.setup.io.ListField"
-  />
-
-  <adapter
-      factory="cpsskins.setup.io.TextField"
-  />
-
-  <adapter
-      factory="cpsskins.setup.io.TextLineField"
-  />
-
-  <adapter
-      factory="cpsskins.setup.io.IntField"
-  />
-
-  <adapter
-      factory="cpsskins.setup.io.BoolField"
-  />
-
-  <adapter
-      factory="cpsskins.setup.io.BytesLineField"
-  />
-
-  <adapter
-      factory="cpsskins.setup.io.BytesField"
-  />
-
-  <adapter
-      factory="cpsskins.setup.io.FloatField"
-  />
-
-  <adapter
-      factory="cpsskins.setup.io.ChoiceField"
-  />
+  <include package=".io" />
 
 </configure>

Added: cpsskins/branches/paris-sprint-2006/setup/io/__init__.py
==============================================================================
--- (empty file)
+++ cpsskins/branches/paris-sprint-2006/setup/io/__init__.py    Sat May  6 
16:26:14 2006
@@ -0,0 +1,25 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 Nuxeo 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+from zope.deferredimport import defineFrom
+
+defineFrom('cpsskins.setup.io.adapters', 'BaseDOMAdapter', 'DOMAdapter')
+defineFrom('cpsskins.setup.io.interfaces', 'IDOMAdapter')
+defineFrom('cpsskins.setup.io.utils', 'importSite', 'exportSite',
+           'exportSetting')

Added: cpsskins/branches/paris-sprint-2006/setup/io/adapters.py
==============================================================================
--- (empty file)
+++ cpsskins/branches/paris-sprint-2006/setup/io/adapters.py    Sat May  6 
16:26:14 2006
@@ -0,0 +1,221 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 Nuxeo 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import logging
+from xml.dom.minidom import Node
+
+import zope.schema
+
+from zope.component import getMultiAdapter
+from zope.component import createObject
+from zope.interface import implements
+from zope.app.container.interfaces import IItemContainer, INameChooser
+
+from cpsskins.relations.interfaces import IRelatable
+from cpsskins.setup.interfaces import IType
+from cpsskins.setup.io.interfaces import IDOMAdapter, IFieldIO, IBinaryFieldIO
+from cpsskins.storage.interfaces import IStorage
+
+logger = logging.getLogger("cpsskins")
+
+class BaseDOMAdapter(object):
+    """Base class for DOM adapters.
+    """
+    archive = None
+
+    document = None
+
+    object_type = u''
+
+    mapping = {}
+
+    ignored_fields = ()
+
+    _fields_as_attributes = ()
+
+    reserved_attrs = ()
+
+    def __init__(self, context, node):
+        self.context = context
+        self.node = node
+
+    def save(self):
+        """Save data in the DOM fragment.
+        """
+        raise NotImplementedError
+
+    def load(self):
+        """Load data from the DOM node.
+        """
+        raise NotImplementedError
+
+    def updateURIMapping(self):
+        uri = u'cpsskins://%s:%s' % (IType(self.context).name,
+                                     self.node.getAttribute(u'id'))
+        self.mapping.update({uri: self.context})
+
+    def clone(self, other):
+        """Clone the DOM adapter.
+        """
+        self.archive = other.archive
+        self.document = other.document
+        self.object_type = other.object_type
+        self.ignored_fields = other.ignored_fields
+        self.fields_as_attributes = other.fields_as_attributes
+        self.mapping = other.mapping
+
+    def getFieldsAsAttr(self):
+        return self._fields_as_attributes
+
+    def setFieldsAsAttr(self, fields):
+        for attr in self.reserved_attrs:
+            if attr in fields:
+                raise ValueError("'%s' is a reserved attribute." % attr)
+        self._fields_as_attributes = fields
+
+    fields_as_attributes = property(getFieldsAsAttr, setFieldsAsAttr)
+
+
+class DOMAdapter(BaseDOMAdapter):
+    """Generic DOM adapter
+    """
+    implements(IDOMAdapter)
+
+    reserved_attrs = u'id', u'type', u'value'
+
+    def save(self):
+        context = self.context
+        node = self.node
+
+        archive = self.archive
+        document = self.document
+
+        type = IType(context)
+
+        element_el = document.createElement(type.resourcename)
+        element_id = unicode(IRelatable(context))
+        element_el.setAttribute(u'id', element_id)
+
+        if type.contentname != type.resourcename:
+            element_el.setAttribute(u'type', unicode(type.contentname))
+
+        # properties
+        schema = type.getContentType()
+        for attr, field in zope.schema.getFieldsInOrder(schema):
+            if attr in self.ignored_fields:
+                continue
+
+            obj = getattr(context, attr)
+
+            field_io = IFieldIO(field, None)
+            if field_io is None:
+                raise TypeError("No field adapter found for '%s'." % field)
+
+            value = field_io.dump(obj)
+            # the field IO adapter provides support for binary attachments
+            # the value stored in the DOM is the name of the attachment in
+            # the archive.
+            if IBinaryFieldIO.providedBy(field_io):
+                value = u'%s_%s%s' % (element_id, attr, value)
+                archive[value] = obj
+
+            # set the property as an attribute,
+            if attr in self.fields_as_attributes:
+                element_el.setAttribute(attr, value)
+
+            # or as a child element
+            else:
+                prop_el = document.createElement(attr)
+                prop_el.setAttribute(u'value', value)
+
+                element_el.appendChild(prop_el)
+
+        node.appendChild(element_el)
+
+        # child nodes
+        if IItemContainer.providedBy(context):
+            for child in context:
+                exporter = getMultiAdapter((context[child], element_el),
+                                            IDOMAdapter)
+                exporter.clone(self)
+                exporter.save()
+
+    def load(self):
+        context = self.context
+        node = self.node
+
+        archive = self.archive
+
+        # properties
+        schema = IType(context).getContentType()
+        for name, field in zope.schema.getFieldsInOrder(schema):
+            if name in self.ignored_fields:
+                continue
+
+            text = node.getAttribute(name)
+
+            field_io = IFieldIO(field, None)
+            if field_io is None:
+                raise TypeError("No field adapter found for '%s'." % field)
+            if text:
+                value = field_io.load(text)
+                # the field IO adapter provides support for binary attachments
+                # the value stored in the DOM is the name of the attachment
+                # the archive.
+                if IBinaryFieldIO.providedBy(field_io):
+                    filename = value
+                    value = archive[filename]
+                setattr(context, name, value)
+
+
+        # child nodes
+        for child_el in node.childNodes:
+            if child_el.nodeType != Node.ELEMENT_NODE:
+                continue
+
+            if child_el.hasAttribute(u'value'):
+                field_name = child_el.tagName
+                if name == field_name:
+                    text = child_el.getAttribute(u'value')
+                    value = field_io.load(text)
+                    if IBinaryFieldIO.providedBy(field_io):
+                        filename = value
+                        value = archive[filename]
+                    setattr(context, name, value)
+                continue
+
+            contentname = child_el.getAttribute(u'type') or child_el.tagName
+            factory_name = u'cpsskins.%s.%s' % (self.object_type, contentname)
+
+            # create the object
+            element = createObject(factory_name)
+
+            # add it to the container
+            if IStorage.providedBy(context):
+                context.add(element, contentname)
+            else:
+                name = INameChooser(context).chooseName(contentname, element)
+                context[name] = element
+
+            # load data into the object
+            importer = getMultiAdapter((element, child_el), IDOMAdapter)
+            importer.clone(self)
+            importer.updateURIMapping()
+            importer.load()
+

Added: cpsskins/branches/paris-sprint-2006/setup/io/configure.zcml
==============================================================================
--- (empty file)
+++ cpsskins/branches/paris-sprint-2006/setup/io/configure.zcml Sat May  6 
16:26:14 2006
@@ -0,0 +1,42 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope";>
+
+  <!-- field IO -->
+
+  <adapter
+      factory=".fields.ListField"
+  />
+
+  <adapter
+      factory=".fields.TextField"
+  />
+
+  <adapter
+      factory=".fields.TextLineField"
+  />
+
+  <adapter
+      factory=".fields.IntField"
+  />
+
+  <adapter
+      factory=".fields.BoolField"
+  />
+
+  <adapter
+      factory=".fields.BytesLineField"
+  />
+
+  <adapter
+      factory=".fields.BytesField"
+  />
+
+  <adapter
+      factory=".fields.FloatField"
+  />
+
+  <adapter
+      factory=".fields.ChoiceField"
+  />
+
+</configure>

Added: cpsskins/branches/paris-sprint-2006/setup/io/fields.py
==============================================================================
--- (empty file)
+++ cpsskins/branches/paris-sprint-2006/setup/io/fields.py      Sat May  6 
16:26:14 2006
@@ -0,0 +1,119 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 Nuxeo 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import logging
+import mimetypes
+
+import zope.schema
+
+from zope.component import adapts
+from zope.interface import implements
+from zope.app.file.image import getImageInfo
+
+from cpsskins.setup.io.interfaces import IFieldIO, IBinaryFieldIO
+
+logger = logging.getLogger("cpsskins")
+
+class BaseFieldIO:
+
+    def __init__(self, field):
+        self.field = field
+
+    def load(self, text):
+        return self.field.fromUnicode(text)
+
+    def dump(self, obj):
+        return unicode(obj)
+
+class ListField(BaseFieldIO):
+    """A list field.
+    """
+    adapts(zope.schema.interfaces.IList)
+    implements(IFieldIO)
+
+    def dump(self, obj):
+        # TODO escape ','
+        return u', '.join(obj)
+
+    def load(self, text):
+        # TODO unescape ','
+        obj = text.split(', ')
+        self.field.validate(obj)
+        return obj
+
+class IntField(BaseFieldIO):
+    """An integer field.
+    """
+    adapts(zope.schema.interfaces.IInt)
+    implements(IFieldIO)
+
+class TextField(BaseFieldIO):
+    """A text line field.
+    """
+    adapts(zope.schema.interfaces.IText)
+    implements(IFieldIO)
+
+class TextLineField(BaseFieldIO):
+    """A text line field.
+    """
+    adapts(zope.schema.interfaces.ITextLine)
+    implements(IFieldIO)
+
+class BytesField(BaseFieldIO):
+    """A bytes field.
+    """
+    adapts(zope.schema.interfaces.IBytes)
+    implements(IBinaryFieldIO)
+
+    def dump(self, obj):
+        """Instead of storing the data, the name of the attachment is returned.
+        """
+        name = u''
+        # Attempt to guess the data encoding
+        encoding, width, height = getImageInfo(obj)
+        if width and height:
+            name += u'_%sx%s' % (width, height)
+        if encoding:
+            name += mimetypes.guess_extension(encoding) or u'.bin'
+        return name
+
+class BytesLineField(BaseFieldIO):
+    """A bytes line field.
+    """
+    adapts(zope.schema.interfaces.IBytesLine)
+    implements(IFieldIO)
+
+class FloatField(BaseFieldIO):
+    """A float field.
+    """
+    adapts(zope.schema.interfaces.IFloat)
+    implements(IFieldIO)
+
+class BoolField(BaseFieldIO):
+    """A boolean field.
+    """
+    adapts(zope.schema.interfaces.IBool)
+    implements(IFieldIO)
+
+class ChoiceField(BaseFieldIO):
+    """A choice field.
+    """
+    adapts(zope.schema.interfaces.IChoice)
+    implements(IFieldIO)
+

Added: cpsskins/branches/paris-sprint-2006/setup/io/interfaces.py
==============================================================================
--- (empty file)
+++ cpsskins/branches/paris-sprint-2006/setup/io/interfaces.py  Sat May  6 
16:26:14 2006
@@ -0,0 +1,60 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 Nuxeo 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+from zope.interface import Attribute, Interface
+
+class IDOMAdapter(Interface):
+    """A DOM adapter for loading and saving objects as DOM fragments."""
+
+    archive = Attribute(u"The archive")
+
+    document = Attribute(u"The document element.")
+
+    object_type = Attribute(u"Type name of objects.")
+
+    mapping = Attribute(u"Mapping between old and new URIs")
+
+    ignored_fields = Attribute(u"The list of ignored fields.")
+
+    fields_as_attributes = Attribute(u"The list of fields written as DOM "
+                                      "attributes.")
+
+    reserved_fields = Attribute(u"Reserved fields.")
+
+    def save():
+        """Save data as a DOM fragment."""
+
+    def updateURIMapping():
+        """Update the URI mapping."""
+
+    def load():
+        """Load data from a DOM fragment."""
+
+class IFieldIO(Interface):
+    """A field importer / exporter"""
+
+    def dump(obj):
+        """convert the object into a string"""
+
+    def load(text):
+        """convert the string into an object"""
+
+class IBinaryFieldIO(IFieldIO):
+    """A binary field importer / exporter."""
+

Added: cpsskins/branches/paris-sprint-2006/setup/io/utils.py
==============================================================================
--- (empty file)
+++ cpsskins/branches/paris-sprint-2006/setup/io/utils.py       Sat May  6 
16:26:14 2006
@@ -0,0 +1,234 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 Nuxeo 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import logging
+
+from xml.dom.minidom import parseString, DOMImplementation, Node
+
+from zope.component import getUtility, createObject, getMultiAdapter
+
+from cpsskins import configuration
+from cpsskins.setup.archives import TarArchive
+from cpsskins.setup.interfaces import IResourceManager
+from cpsskins.setup.io.interfaces import IDOMAdapter
+from cpsskins.setup.utils import getTypeName
+from cpsskins.utils import getThemeManager
+
+logger = logging.getLogger("cpsskins")
+
+site_files = []
+settings_files = []
+
+def importSite(file, context=None):
+    archive = TarArchive(mode='r', data=file.read())
+    mgr = getThemeManager(context)
+
+    uri_mapping = {}
+
+    # themes
+    uri_mapping.update(importThemes(archive, context))
+
+    # storages
+    for name in u'formats', u'displays', u'portlets':
+        uri_mapping.update(importStorage(name, archive, context))
+
+    # relations
+    relations = mgr.getRelationStorage()
+    relations.purge()
+
+    document = parseString(archive[u'relations.xml'])
+    root = document.documentElement
+
+    for el in root.childNodes:
+        if el.nodeType != Node.ELEMENT_NODE:
+            continue
+
+        contentname = el.tagName
+        factory_name = u'cpsskins.relation.%s' % contentname
+        relation = createObject(factory_name)
+
+        importer = getMultiAdapter((relation, el), IDOMAdapter)
+        importer.archive = archive
+        importer.document = document
+        importer.mapping = uri_mapping
+        importer.load()
+
+        relations.add(relation)
+
+    document.unlink()
+
+def exportSite(context=None):
+    """Export the entire site an XML file.
+    """
+    archive = TarArchive(mode='w')
+
+    exportThemes(archive, context)
+    exportSettings(archive, context)
+
+    for name in u'formats', u'displays', u'portlets', u'relations':
+        exportStorage(name, archive, context)
+
+    return archive()
+
+def importThemes(archive=None, context=None):
+    """Import themes from XML
+    """
+    document = parseString(archive[u'themes.xml'])
+    root = document.documentElement
+
+    uri_mapping = {}
+
+    mgr = getThemeManager(context)
+    mgr.deleteAllThemes()
+
+    for el in root.getElementsByTagName(u'theme'):
+        if el.nodeType != Node.ELEMENT_NODE:
+             continue
+
+        theme = createObject(u'cpsskins.canvas.theme')
+        mgr.addTheme(theme)
+
+        importer = getMultiAdapter((theme, el), IDOMAdapter)
+        importer.archive = archive
+        importer.document = document
+        importer.object_type = u'canvas'
+        importer.updateURIMapping()
+
+        importer.load()
+
+        uri_mapping.update(importer.mapping)
+
+    document.unlink()
+    return uri_mapping
+
+def exportThemes(archive=None, context=None):
+    """Export the themes
+    """
+    document = DOMImplementation().createDocument(None, u'themes', None)
+    root = document.documentElement
+
+    for theme in getThemeManager(context).getThemes():
+        exporter = getMultiAdapter((theme, root), IDOMAdapter)
+        exporter.archive = archive
+        exporter.document = document
+        exporter.fields_as_attributes = u'title', u'description'
+        exporter.ignored_fields = u'slot',
+        exporter.save()
+
+    archive[u'themes.xml'] = document.toprettyxml(indent=u'  ',
+                                                  encoding=u'utf-8')
+    document.unlink()
+
+def importStorage(name=u'', archive=None, context=None):
+    if not name:
+        raise KeyError("Must specify a storage name.")
+
+    mgr = getThemeManager(context)
+
+    storage = mgr[name]
+    storage.purge()
+
+    document = parseString(archive[u'%s.xml' % name])
+    root = document.documentElement
+
+    uri_mapping = {}
+
+    storage_configuration = getUtility(configuration.IStorage, name)
+    typename = getTypeName(storage_configuration.itemtype)
+
+    for el in root.childNodes:
+        if el.nodeType != Node.ELEMENT_NODE:
+            continue
+
+        contentname = el.getAttribute('type') or el.tagName
+        factory_name = u'cpsskins.%s.%s' % (typename, contentname)
+        obj = createObject(factory_name)
+        storage.add(obj)
+
+        importer = getMultiAdapter((obj, el), IDOMAdapter)
+        importer.archive = archive
+        importer.document = document
+        importer.object_type = typename
+        importer.updateURIMapping()
+        importer.load()
+
+        uri_mapping.update(importer.mapping)
+
+    document.unlink()
+    return uri_mapping
+
+def exportStorage(name=u'', archive=None, context=None):
+    """Export the storage as XML.
+    """
+    if not name:
+        raise KeyError("Must specify a storage name.")
+
+    mgr = getThemeManager(context)
+    storage = mgr[name]
+
+    document = DOMImplementation().createDocument(None, name, None)
+    root = document.documentElement
+
+    for id in storage:
+        exporter = getMultiAdapter((storage[id], root), IDOMAdapter)
+        exporter.archive = archive
+        exporter.document = document
+        exporter.fields_as_attributes = u'title', u'description'
+        exporter.save()
+
+    archive['%s.xml' % name] = document.toprettyxml(indent=u'  ',
+                                                    encoding=u'utf-8')
+    document.unlink()
+
+def exportSettings(archive=None, context=None):
+    """Export the settings to an archive.
+    """
+    mgr = getThemeManager(context)
+    settings = mgr.getSettings()
+
+    document = DOMImplementation().createDocument(None, u'settings', None)
+    root = document.documentElement
+
+    for name in settings:
+        exporter = getMultiAdapter((settings[name], root), IDOMAdapter)
+        exporter.archive = archive
+        exporter.document = document
+        exporter.save()
+
+    archive[u'settings.xml'] = document.toprettyxml(indent=u'  ',
+                                                    encoding=u'utf-8')
+
+def exportSetting(uri=u'', context=None):
+    """Export the setting as an XML file.
+    """
+    if not uri:
+        raise KeyError("Must specify a setting's URI.")
+
+    resources = getUtility(IResourceManager)
+    setting = resources.lookup(uri=uri, context=context)
+
+    document = DOMImplementation().createDocument(None, u'setting', None)
+    root = document.documentElement
+
+    exporter = getMultiAdapter((setting, root), IDOMAdapter)
+    exporter.document = document
+    exporter.save()
+
+    return document.toprettyxml(indent=u'  ', encoding=u'utf-8')
+

Modified: cpsskins/branches/paris-sprint-2006/setup/registration.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/registration.py   (original)
+++ cpsskins/branches/paris-sprint-2006/setup/registration.py   Sat May  6 
16:26:14 2006
@@ -26,26 +26,58 @@
 from xml.parsers.expat import ExpatError
 
 from zope.component import getUtility, createObject, getMultiAdapter
+from zope.component import getGlobalSiteManager
 
 from cpsskins.setup.interfaces import IResourceManager, IResource, IDOMAdapter
+from cpsskins.setup.io.utils import importSite
+from cpsskins.thememanager import ThemeManagementFolder, IThemeManagementFolder
 
 logger = logging.getLogger("cpsskins")
 
-files = []
+site_files = []
+settings_files = []
 
-#######################################################################
-# Registering and loading settings
-#######################################################################
+### Registration  #####################################################
 
-def register(profile, file):
+def registerSite(profile, file):
     base_path = os.path.dirname(sys.modules.get(profile).__file__)
-    files.append({'filename': os.path.join(base_path, file)})
+    site_files.append({'filename': os.path.join(base_path, file)})
 
-#######################################################################
-# Events
-#######################################################################
+def registerSettings(profile, file):
+    base_path = os.path.dirname(sys.modules.get(profile).__file__)
+    settings_files.append({'filename': os.path.join(base_path, file)})
+
+### Loading sites, settings  ##########################################
+
+def loadEvent(event):
+    registerGlobalThemeManager()
+    loadSettings(settings_files)
+    loadSites(site_files)
+
+def registerGlobalThemeManager():
+    gsm = getGlobalSiteManager()
+    gtmutil = ThemeManagementFolder()
+    gsm.registerUtility(gtmutil, IThemeManagementFolder)
+    gtmutil.registerUtilities()
+
+### Sites  ############################################################
 
-def loadSettings():
+def loadSites(files):
+    """Load all registered sites.
+    """
+    for site_file in files:
+        filename = site_file['filename']
+        file = open(filename)
+        importSite(file)
+        file.close()
+        logger.debug("loaded site from %s", filename)
+
+### Settings  #########################################################
+
+def refreshSettingsEvent(event):
+    refreshSettings()
+
+def loadSettings(files):
     """Load all registered settings.
     """
     resources = getUtility(IResourceManager)
@@ -64,7 +96,9 @@
 
             file['refresh_date'] = time.time()
 
-        logger.debug("loaded settings in %s", filename)
+        logger.debug("loaded settings from %s", filename)
+
+# To refactor: see cpsskins.setup.io.utils
 
 def _loadResourceFromXML(setting_def=None, name=u'', title=u'', filename=u''):
     resources = getUtility(IResourceManager)
@@ -94,11 +128,10 @@
     getMultiAdapter(IDOMAdapter, (resource, resource_def)).load()
     return resource
 
-
 def refreshSettings():
     """Refresh all settings that have been modified on the filesystem.
     """
-    for file in files:
+    for file in settings_files:
         refresh_date = file.get('refresh_date', 0)
         filename = file['filename']
         if refresh_date > os.path.getmtime(filename):
@@ -106,16 +139,6 @@
         _reload(filename=filename)
         file['refresh_date'] = time.time()
 
-def refreshSettingsEvent(event):
-    refreshSettings()
-
-def loadSettingsEvent(event):
-    loadSettings()
-
-#######################################################################
-# Reloading settings
-#######################################################################
-
 def reloadSetting(uri=u''):
     """Reload a setting by name.
     """

Modified: cpsskins/branches/paris-sprint-2006/setup/setting.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/setting.py        (original)
+++ cpsskins/branches/paris-sprint-2006/setup/setting.py        Sat May  6 
16:26:14 2006
@@ -20,7 +20,6 @@
 from persistent import Persistent
 from zope.app.container.contained import Contained
 from zope.interface import implements
-from zope.security.proxy import removeSecurityProxy
 
 from cpsskins.setup.interfaces import IIdentifiable
 from cpsskins.setup.interfaces import IGlobalSetting, ILocalSetting, ISetting

Modified: cpsskins/branches/paris-sprint-2006/setup/settings.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/settings.py       (original)
+++ cpsskins/branches/paris-sprint-2006/setup/settings.py       Sat May  6 
16:26:14 2006
@@ -20,8 +20,7 @@
 from zope.app.container.btree import BTreeContainer
 from zope.component.interfaces import IComponentLookup
 from zope.component.persistentregistry import PersistentComponents
-from zope.interface import implements, Interface
-
+from zope.interface import implements
 
 class ISettings(IComponentLookup):
     """Settings registry"""

Modified: cpsskins/branches/paris-sprint-2006/standard/io/configure.zcml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/standard/io/configure.zcml      
(original)
+++ cpsskins/branches/paris-sprint-2006/standard/io/configure.zcml      Sat May 
 6 16:26:14 2006
@@ -6,7 +6,7 @@
       for="cpsskins.elements.interfaces.IElement *"
       factory="cpsskins.setup.io.DOMAdapter"
       permission="zope.ManageContent"
-      provides="cpsskins.setup.interfaces.IDOMAdapter"
+      provides="cpsskins.setup.io.interfaces.IDOMAdapter"
   />
 
   <!-- perspectives -->
@@ -14,7 +14,7 @@
       for="cpsskins.perspectives.interfaces.IPerspective *"
       factory="cpsskins.setup.io.DOMAdapter"
       permission="zope.ManageContent"
-      provides="cpsskins.setup.interfaces.IDOMAdapter"
+      provides="cpsskins.setup.io.interfaces.IDOMAdapter"
   />
 
   <!-- settings -->
@@ -22,7 +22,7 @@
       for="cpsskins.setup.interfaces.ISetting *"
       factory="cpsskins.standard.io.setting.DOMAdapter"
       permission="zope.ManageContent"
-      provides="cpsskins.setup.interfaces.IDOMAdapter"
+      provides="cpsskins.setup.io.interfaces.IDOMAdapter"
   />
 
   <!-- portlets -->
@@ -30,7 +30,7 @@
       for="cpsskins.elements.interfaces.IPortlet *"
       factory="cpsskins.setup.io.DOMAdapter"
       permission="zope.ManageContent"
-      provides="cpsskins.setup.interfaces.IDOMAdapter"
+      provides="cpsskins.setup.io.interfaces.IDOMAdapter"
   />
 
   <!-- relations -->
@@ -38,7 +38,7 @@
       for="cpsskins.relations.interfaces.IRelation *"
       factory="cpsskins.standard.io.relation.DOMAdapter"
       permission="zope.ManageContent"
-      provides="cpsskins.setup.interfaces.IDOMAdapter"
+      provides="cpsskins.setup.io.interfaces.IDOMAdapter"
   />
 
   <!-- styles -->
@@ -46,7 +46,7 @@
       for="cpsskins.standard.formats.style.IStyle *"
       factory="cpsskins.standard.io.style.DOMAdapter"
       permission="zope.ManageContent"
-      provides="cpsskins.setup.interfaces.IDOMAdapter"
+      provides="cpsskins.setup.io.interfaces.IDOMAdapter"
   />
 
   <!-- layouts -->
@@ -54,7 +54,7 @@
       for="cpsskins.standard.formats.layout.ILayout *"
       factory="cpsskins.standard.io.layout.DOMAdapter"
       permission="zope.ManageContent"
-      provides="cpsskins.setup.interfaces.IDOMAdapter"
+      provides="cpsskins.setup.io.interfaces.IDOMAdapter"
   />
 
 </configure>

Modified: cpsskins/branches/paris-sprint-2006/standard/io/setting.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/standard/io/setting.py  (original)
+++ cpsskins/branches/paris-sprint-2006/standard/io/setting.py  Sat May  6 
16:26:14 2006
@@ -21,7 +21,7 @@
 from zope.interface import implements
 
 from cpsskins.setup.interfaces import IResource, IDOMAdapter, IType
-from cpsskins.setup.io import BaseDOMAdapter
+from cpsskins.setup.io.adapters import BaseDOMAdapter
 
 class DOMAdapter(BaseDOMAdapter):
     """DOM adapter for settings

Modified: cpsskins/branches/paris-sprint-2006/thememanager.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/thememanager.py (original)
+++ cpsskins/branches/paris-sprint-2006/thememanager.py Sat May  6 16:26:14 2006
@@ -23,8 +23,6 @@
 from zope.app.container.interfaces import INameChooser
 from zope.component.persistentregistry import PersistentComponents
 from zope.component import getUtility
-from zope.app.intid import IntIds
-from zope.app.intid.interfaces import IIntIds
 from zope.traversing.api import getParent
 from zope.interface import implements, Interface
 from zope.i18nmessageid import MessageFactory
@@ -34,8 +32,6 @@
 from cpsskins.caching import ImageCache, IImageCache
 from cpsskins.elements.interfaces import IFormattable
 from cpsskins.elements.interfaces import ITheme, IThemePage, IThemeContainer
-from cpsskins.standard.displays.storage import DisplayStorage, IDisplayStorage
-from cpsskins.standard.formats.storage import FormatStorage, IFormatStorage
 from cpsskins.ontology import isDefault, hasFormat, hasDisplay
 from cpsskins.perspectives import Perspective
 from cpsskins.perspectives.interfaces import IPerspective
@@ -46,6 +42,9 @@
 from cpsskins.setup.interfaces import IResourceManager, IResource
 from cpsskins.setup.settings import Settings, ISettings
 from cpsskins.setup.storage import ISnapshotStorage, SnapshotStorage
+from cpsskins.standard.displays.storage import DisplayStorage, IDisplayStorage
+from cpsskins.standard.formats.storage import FormatStorage, IFormatStorage
+from cpsskins.uids import IUids, Uids
 
 logger = logging.getLogger("cpsskins")
 
@@ -151,7 +150,7 @@
         # negotiation strategy
         self.negotiation = negotiation
         # registries, storages, etc.
-        self[u'uids'] = IntIds()
+        self[u'uids'] = Uids()
         self[u'imagecache'] = ImageCache()
         self[u'settings'] = Settings()
         self[u'relations'] = RelationStorage()
@@ -162,14 +161,15 @@
         self[u'snapshots'] = SnapshotStorage()
 
     def getSite(self):
-        return zapi.getParent(self)
+        # XXX
+        return self
 
     ###################################################################
     # Local utilities
     ###################################################################
 
     def registerUtilities(self):
-        self.registerUtility(self[u'uids'], IIntIds)
+        self.registerUtility(self[u'uids'], IUids)
         self.registerUtility(self[u'snapshots'], ISnapshotStorage)
         self.registerUtility(self[u'imagecache'], IImageCache)
         self.registerUtility(self[u'settings'], ISettings)
@@ -179,7 +179,7 @@
         self.registerUtility(self[u'formats'], IFormatStorage)
 
     def getIdRegistry(self):
-        return self.getUtility(IIntIds)
+        return self.getUtility(IUids)
 
     def getImageCache(self):
         return self.getUtility(IImageCache)
@@ -211,11 +211,11 @@
         id = intids.queryId(element)
         if id is None:
             id = intids.register(element)
+            # store the element's id in the element itself.
+            element.identifier = id
         else:
             logger.debug("The element %s is already registered. "
                          "No need to register it again.", repr(element))
-        # store the element's id in the element itself.
-        element.identifier = id
         return id
 
     def unregisterElement(self, element):

Modified: cpsskins/branches/paris-sprint-2006/ui/authoring/views.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/ui/authoring/views.py   (original)
+++ cpsskins/branches/paris-sprint-2006/ui/authoring/views.py   Sat May  6 
16:26:14 2006
@@ -62,6 +62,12 @@
     def getThemeManager(self):
         return self.tmutil
 
+    def getGlobalThemeManager(self):
+        try:
+            return getThemeManager()
+        except ValueError:
+            return None
+
     def _redirect(self):
         request = self.request
         target = request.get('HTTP_REFERER', '.')

Modified: cpsskins/branches/paris-sprint-2006/ui/screens/sitemanager/views.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/ui/screens/sitemanager/views.py 
(original)
+++ cpsskins/branches/paris-sprint-2006/ui/screens/sitemanager/views.py Sat May 
 6 16:26:14 2006
@@ -17,21 +17,14 @@
 """
 __docformat__ = "reStructuredText"
 
-from xml.dom.minidom import parseString, DOMImplementation, Node
-
-from zope.app.interface import queryType
-from zope.component import getUtilitiesFor, getUtility, getMultiAdapter
-from zope.component import createObject
+from zope.component import getUtility
 
 from cpsskins import minjson as json
-from cpsskins import configuration
-from cpsskins.setup.archives import TarArchive
-from cpsskins.setup.interfaces import ISetting, IGlobalSetting, IDOMAdapter
 from cpsskins.setup.interfaces import IType, IIdentifiable
-from cpsskins.setup.interfaces import IResourceType, IResourceManager, 
IResource
+from cpsskins.setup.interfaces import IResourceManager, IResource
+from cpsskins.setup.io import importSite, exportSite, exportSetting
 from cpsskins.setup.registration import reloadSetting, refreshSettings
 from cpsskins.setup.snapshot import Snapshot
-from cpsskins.setup.utils import getTypeName
 from cpsskins.utils import getThemeManager
 
 class SiteDesignerView:
@@ -87,136 +80,35 @@
     def exportSetting(self, uri=u''):
         """Export the setting as an XML file.
         """
-        if not uri:
-            raise KeyError("Must specify a setting's URI.")
-
-        context = self.context
-        request = self.request
-
-        resources = getUtility(IResourceManager)
-        setting = resources.lookup(uri=uri, context=context)
-        resource = IResource(setting).getResource()
-        resource_type = queryType(resource, IResourceType)
-
-        document = DOMImplementation().createDocument(None, u'setting', None)
-        root = document.documentElement
-
-        exporter = getMultiAdapter((setting, root), IDOMAdapter)
-        exporter.document = document
-        exporter.save()
-
-        return document.toprettyxml(indent=u'  ', encoding=u'utf-8')
+        return exportSetting(uri, self.context)
 
     def reloadSetting(self, uri=u''):
         """Reload the setting from the file-system
         """
         if not uri:
             raise KeyError("Must specify a setting's URI.")
-        reloadSetting(name)
+        reloadSetting(uri)
 
     def refreshSettings(self):
         """Refresh all settings stored on the file-system
         """
         refreshSettings()
 
-    def exportSettings(self, archive=None):
-        """Export the settings as an XML file.
-        """
-        context = self.context
-        request = self.request
-
-        mgr = getThemeManager(context)
-        settings = mgr.getSettings()
-
-        document = DOMImplementation().createDocument(None, u'settings', None)
-        root = document.documentElement
-
-        for name in settings:
-            exporter = getMultiAdapter((settings[name], root), IDOMAdapter)
-            exporter.archive = archive
-            exporter.document = document
-            exporter.save()
-
-        archive[u'setting.xml'] = document.toprettyxml(indent=u'  ',
-                                                       encoding=u'utf-8')
-
-    def importSettings(self, archive=None):
-        """Import site settings
-        """
-        context = self.context
-        request = self.request
-
-        mgr = getThemeManager(context)
-        settings = mgr.getSettings()
-
-        settings.purge()
-
-        dom = parseString(archive[u'setting.xml'])
-        importer = getMultiAdapter((mgr, dom), IDOMAdapter, name=u'settings')
-        importer.archive = archive
-        importer.load()
-
-
-    ### Site  #########################################################
-
-    def exportSite(self):
-        """Export the entire site an XML file.
-        """
-        archive = TarArchive(mode='w')
-
-        self.exportThemes(archive)
-        self.exportSettings(archive)
-
-        for name in u'formats', u'displays', u'portlets', u'relations':
-            self.exportStorage(name, archive)
-
-        return archive()
+    ### Sites  #########################################################
 
     def importSite(self, file=None):
-        archive = TarArchive(mode='r', data=file.read())
-        mgr = getThemeManager(self.context)
-
-        uri_mapping = {}
-
-        # themes
-        uri_mapping.update(self.importThemes(archive))
-
-        # storages
-        for name in u'formats', u'displays', u'portlets':
-            uri_mapping.update(self.importStorage(name, archive))
-
-        # relations
-        relations = mgr.getRelationStorage()
-        relations.purge()
-
-        document = parseString(archive[u'relations.xml'])
-        root = document.documentElement
-
-        for el in root.childNodes:
-            if el.nodeType != Node.ELEMENT_NODE:
-                continue
-
-            contentname = el.tagName
-            factory_name = u'cpsskins.relation.%s' % contentname
-            relation = createObject(factory_name)
-
-            importer = getMultiAdapter((relation, el), IDOMAdapter)
-            importer.archive = archive
-            importer.document = document
-            importer.mapping = uri_mapping
-            importer.load()
+        importSite(file, self.context)
 
-            relations.add(relation)
-
-        document.unlink()
+    def exportSite(self):
+        return exportSite(self.context)
 
-    ### Snapshots  ####################################################
+    ### Snapshots  #####################################################
 
     def getSnapshotStorage(self):
         return getThemeManager(self.context).getSnapshotStorage()
 
     def createSnapshot(self):
-        data = self.exportSite()
+        data = exportSite(self.context)
         snapshots = self.getSnapshotStorage()
         snapshot = Snapshot(data=data)
         snapshots.add(snapshot, snapshot.filename)
@@ -247,7 +139,7 @@
             raise ValueError("No snapshot filename specified.")
 
         snapshots = self.getSnapshotStorage()
-        self.importSite(snapshots[filename])
+        importSite(snapshots[filename], self.context)
 
     def uploadSnapshot(self, file=None):
         if file is None:
@@ -257,117 +149,4 @@
         snapshots = self.getSnapshotStorage()
         snapshots.add(Snapshot(data), file.filename)
 
-    ### Storage  ######################################################
-
-    def exportStorage(self, name=u'', archive=None):
-        """Export the storage as XML.
-        """
-        if not name:
-            raise KeyError("Must specify a storage name.")
-
-        mgr = getThemeManager(self.context)
-        storage = mgr[name]
-
-        document = DOMImplementation().createDocument(None, name, None)
-        root = document.documentElement
-
-        for id in storage:
-            exporter = getMultiAdapter((storage[id], root), IDOMAdapter)
-            exporter.archive = archive
-            exporter.document = document
-            exporter.fields_as_attributes = u'title', u'description'
-            exporter.save()
-
-        archive['%s.xml' % name] = document.toprettyxml(indent=u'  ',
-                                                        encoding=u'utf-8')
-        document.unlink()
-
-    def importStorage(self, name=u'', archive=None):
-        if not name:
-            raise KeyError("Must specify a storage name.")
-
-        mgr = getThemeManager(self.context)
-
-        storage = mgr[name]
-        storage.purge()
-
-        document = parseString(archive[u'%s.xml' % name])
-        root = document.documentElement
-
-        uri_mapping = {}
-
-        storage_configuration = getUtility(configuration.IStorage, name)
-        typename = getTypeName(storage_configuration.itemtype)
-
-        for el in root.childNodes:
-            if el.nodeType != Node.ELEMENT_NODE:
-                continue
-
-            contentname = el.getAttribute('type') or el.tagName
-            factory_name = u'cpsskins.%s.%s' % (typename, contentname)
-            obj = createObject(factory_name)
-            storage.add(obj)
-
-            importer = getMultiAdapter((obj, el), IDOMAdapter)
-            importer.archive = archive
-            importer.document = document
-            importer.object_type = typename
-            importer.updateURIMapping()
-            importer.load()
-
-            uri_mapping.update(importer.mapping)
-
-        document.unlink()
-        return uri_mapping
-
-    ### Themes  #######################################################
-
-    def exportThemes(self, archive=None):
-        """Export the themes
-        """
-        document = DOMImplementation().createDocument(None, u'themes', None)
-        root = document.documentElement
-
-        for theme in getThemeManager(self.context).getThemes():
-            exporter = getMultiAdapter((theme, root), IDOMAdapter)
-            exporter.archive = archive
-            exporter.document = document
-            exporter.fields_as_attributes = u'title', u'description'
-            exporter.ignored_fields = u'slot',
-            exporter.save()
-
-        archive[u'themes.xml'] = document.toprettyxml(indent=u'  ',
-                                                      encoding=u'utf-8')
-        document.unlink()
-
-    def importThemes(self, archive=None):
-        """Import themes from XML
-        """
-        document = parseString(archive[u'themes.xml'])
-        root = document.documentElement
-
-        uri_mapping = {}
-
-        mgr = getThemeManager(self.context)
-        mgr.deleteAllThemes()
-
-        for el in root.getElementsByTagName(u'theme'):
-            if el.nodeType != Node.ELEMENT_NODE:
-                continue
-
-            theme = createObject(u'cpsskins.canvas.theme')
-            mgr.addTheme(theme)
-
-            importer = getMultiAdapter((theme, el), IDOMAdapter)
-            importer.archive = archive
-            importer.document = document
-            importer.object_type = u'canvas'
-            importer.updateURIMapping()
-
-            importer.load()
-
-            uri_mapping.update(importer.mapping)
-
-        document.unlink()
-        return uri_mapping
 

Added: cpsskins/branches/paris-sprint-2006/uids.py
==============================================================================
--- (empty file)
+++ cpsskins/branches/paris-sprint-2006/uids.py Sat May  6 16:26:14 2006
@@ -0,0 +1,71 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 Nuxeo 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.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+from zope.app.intid import IntIds
+from zope.app.intid.interfaces import IIntIds
+from zope.app.keyreference.interfaces import IKeyReference, NotYet
+from zope.app.keyreference.testing import SimpleKeyReference
+from zope.security.proxy import removeSecurityProxy
+
+class IUids(IIntIds):
+    pass
+
+class Uids(IntIds):
+
+    def getId(self, ob):
+        try:
+            key = IKeyReference(ob)
+        except TypeError:
+            raise KeyError(ob)
+        except NotYet:
+            key = SimpleKeyReference(ob)
+
+        try:
+            return self.ids[key]
+        except KeyError:
+            raise KeyError(ob)
+
+    def register(self, ob):
+        ob = removeSecurityProxy(ob)
+        try:
+            key = IKeyReference(ob)
+        except NotYet:
+            key = SimpleKeyReference(ob)
+
+        if key in self.ids:
+            return self.ids[key]
+        uid = self._generateId()
+        self.refs[uid] = key
+        self.ids[key] = uid
+        return uid
+
+    def unregister(self, ob):
+        ob = removeSecurityProxy(ob)
+        try:
+            key = IKeyReference(ob)
+        except NotYet:
+            key = SimpleKeyReference(ob)
+
+        if key is None:
+            return
+
+        uid = self.ids[key]
+        del self.refs[uid]
+        del self.ids[key]
+

Modified: cpsskins/branches/paris-sprint-2006/utils.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/utils.py        (original)
+++ cpsskins/branches/paris-sprint-2006/utils.py        Sat May  6 16:26:14 2006
@@ -17,16 +17,26 @@
 """
 __docformat__ = "reStructuredText"
 
-from zope.component import getSiteManager
+from zope.component import getSiteManager, getGlobalSiteManager
 from zope.app.zapi import getParent
 
 from cpsskins.thememanager import IThemeManagementFolder
 
-def getThemeManager(context):
+def getThemeManager(context=None):
+    # global utility
+    if context is None:
+        gsm = getGlobalSiteManager()
+        mgr = gsm.queryUtility(IThemeManagementFolder)
+        if mgr is None:
+            raise ValueError("No global theme management folder was found.")
+        return mgr
+
+    # local utility
     mgr = getSiteManager(context).queryUtility(IThemeManagementFolder)
     if mgr is not None:
         return mgr
 
+    # folder in context or in a parent folder
     ob = context
     while ob is not None:
         if IThemeManagementFolder.providedBy(ob):
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to