Author: jmorliaguet
Date: Mon May  1 12:06:53 2006
New Revision: 3002

Modified:
   cpsskins/branches/paris-sprint-2006/__init__.py
   cpsskins/branches/paris-sprint-2006/configuration/displays/metaconfigure.py
   cpsskins/branches/paris-sprint-2006/configuration/fields/metaconfigure.py
   cpsskins/branches/paris-sprint-2006/configuration/formats/metaconfigure.py
   cpsskins/branches/paris-sprint-2006/configuration/portlets/metaconfigure.py
   cpsskins/branches/paris-sprint-2006/elements/configure.zcml
   cpsskins/branches/paris-sprint-2006/elements/element.py
   cpsskins/branches/paris-sprint-2006/elements/format.py
   cpsskins/branches/paris-sprint-2006/elements/interfaces.py
   cpsskins/branches/paris-sprint-2006/ftests/test_appsetup.py
   cpsskins/branches/paris-sprint-2006/profiles/default/color.xml
   cpsskins/branches/paris-sprint-2006/profiles/default/perspectives.xml
   cpsskins/branches/paris-sprint-2006/relations/configure.zcml
   cpsskins/branches/paris-sprint-2006/relations/relations.py
   cpsskins/branches/paris-sprint-2006/setup/README.txt
   cpsskins/branches/paris-sprint-2006/setup/adapters.py
   cpsskins/branches/paris-sprint-2006/setup/interfaces.py
   cpsskins/branches/paris-sprint-2006/setup/io.py
   cpsskins/branches/paris-sprint-2006/setup/manager.py
   cpsskins/branches/paris-sprint-2006/setup/registration.py
   cpsskins/branches/paris-sprint-2006/setup/setting.py
   cpsskins/branches/paris-sprint-2006/setup/test/dummy.py
   cpsskins/branches/paris-sprint-2006/setup/test/resource4.xml
   cpsskins/branches/paris-sprint-2006/setup/utils.py
   cpsskins/branches/paris-sprint-2006/standard/io/relation.py
   cpsskins/branches/paris-sprint-2006/standard/io/setting.py
   cpsskins/branches/paris-sprint-2006/standard/io/style.py
   cpsskins/branches/paris-sprint-2006/tests/setup.py
   cpsskins/branches/paris-sprint-2006/thememanager.py
   cpsskins/branches/paris-sprint-2006/ui/editing/views.py
   cpsskins/branches/paris-sprint-2006/ui/screens/sitemanager/views.py
Log:

- getting to grips with namespaces, DRY, ...



Modified: cpsskins/branches/paris-sprint-2006/__init__.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/__init__.py     (original)
+++ cpsskins/branches/paris-sprint-2006/__init__.py     Mon May  1 12:06:53 2006
@@ -20,5 +20,5 @@
 from cpsskins.elements.portlet import Portlet
 
 # load profiles
-from cpsskins.profiles import default
+#from cpsskins.profiles import default
 

Modified: 
cpsskins/branches/paris-sprint-2006/configuration/displays/metaconfigure.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/configuration/displays/metaconfigure.py 
(original)
+++ cpsskins/branches/paris-sprint-2006/configuration/displays/metaconfigure.py 
Mon May  1 12:06:53 2006
@@ -61,10 +61,11 @@
 
     # zope:adapter
     adapter(_context=_context, factory=(factory,), provides=schema,
-            for_=(IDisplay,), name=name)
+            for_=(IDisplay,), name=u'display-' + name)
 
-    # register the format factory
-    utility(_context=_context, provides=IFactory, component=factory, name=name)
+    # register the display factory
+    utility(_context=_context, provides=IFactory, component=factory,
+            name=u'display-' + name)
 
     # register the display
     utility(_context=_context, provides=configuration.IDisplay,

Modified: 
cpsskins/branches/paris-sprint-2006/configuration/fields/metaconfigure.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/configuration/fields/metaconfigure.py   
(original)
+++ cpsskins/branches/paris-sprint-2006/configuration/fields/metaconfigure.py   
Mon May  1 12:06:53 2006
@@ -20,11 +20,12 @@
 from zope.app.content.interfaces import IContentType
 from zope.configuration.exceptions import ConfigurationError
 from zope.component import queryUtility
+from zope.component.zcml import utility
+from zope.component.interfaces import IFactory
 from zope.component.interface import provideInterface
 from zope.interface import alsoProvides
 
 from cpsskins import configuration
-from cpsskins.elements.interfaces import ITypeable
 from cpsskins.setup.interfaces import IResourceType, INameType
 
 def field(_context, name=u'', schema=None, factory=None):
@@ -43,6 +44,10 @@
     if not factory:
         raise ConfigurationError("Must specify a field factory.")
 
+    # register the format factory
+    utility(_context=_context, provides=IFactory, component=factory,
+            name=u'field-' + name)
+
     # set up interface types
     alsoProvides(schema, IResourceType)
     alsoProvides(schema, IContentType)

Modified: 
cpsskins/branches/paris-sprint-2006/configuration/formats/metaconfigure.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/configuration/formats/metaconfigure.py  
(original)
+++ cpsskins/branches/paris-sprint-2006/configuration/formats/metaconfigure.py  
Mon May  1 12:06:53 2006
@@ -71,7 +71,8 @@
               set_schema=(schema,))
 
     # register the format factory
-    utility(_context=_context, provides=IFactory, component=factory, name=name)
+    utility(_context=_context, provides=IFactory, component=factory,
+            name=u'format-' + name)
 
     # register the predicate
     utility(_context=_context, provides=IFormatPredicate,

Modified: 
cpsskins/branches/paris-sprint-2006/configuration/portlets/metaconfigure.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/configuration/portlets/metaconfigure.py 
(original)
+++ cpsskins/branches/paris-sprint-2006/configuration/portlets/metaconfigure.py 
Mon May  1 12:06:53 2006
@@ -27,6 +27,8 @@
 from zope.app.publisher.browser.resourcemeta import resource
 from zope.app.content.interfaces import IContentType
 from zope.component.interface import provideInterface
+from zope.component.interfaces import IFactory
+from zope.component.zcml import utility
 from zope.configuration.exceptions import ConfigurationError
 from zope.interface import Interface, alsoProvides
 
@@ -91,6 +93,10 @@
         permission="zope.ManageContent",
         set_schema=(schema, IUpdateData))
 
+    # register the portlet factory
+    utility(_context=_context, provides=IFactory, component=factory,
+            name=u'canvas-portlet-' + name)
+
     # set up interface types
     alsoProvides(schema, IContentType)
 

Modified: cpsskins/branches/paris-sprint-2006/elements/configure.zcml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/elements/configure.zcml (original)
+++ cpsskins/branches/paris-sprint-2006/elements/configure.zcml Mon May  1 
12:06:53 2006
@@ -17,23 +17,14 @@
       factory=".element.Relatable"
   />
 
-  <!-- this adapter makes elements typeable -->
-  <adapter
-      factory=".element.Typeable"
-  />
-
   <!-- this adapter makes elements identifiable -->
   <adapter
       factory=".element.Identifiable"
   />
 
+  <!-- this adapter makes elements typeable -->
   <adapter
-      factory=".slot.Relatable"
-  />
-
-  <!-- this adapter makes it possible to get the types of an element -->
-
-  <adapter
+      for="*"
       factory=".element.Type"
   />
 
@@ -178,6 +169,12 @@
       type="cpsskins.setup.interfaces.INameType"
   />
 
+  <utility
+      name="theme"
+      factory="cpsskins.elements.theme.Theme"
+      provides="zope.component.interfaces.IFactory"
+  />
+
   <class class=".theme.Theme">
 
     <implements
@@ -193,13 +190,6 @@
 
   </class>
 
-  <utility
-      component=".theme.Theme"
-      provides="zope.component.interfaces.IFactory"
-      name="theme.Theme"
-  />
-
-
   <!-- Page -->
 
   <interface
@@ -218,6 +208,12 @@
       type="cpsskins.setup.interfaces.INameType"
   />
 
+  <utility
+      name="themepage"
+      factory="cpsskins.elements.themepage.ThemePage"
+      provides="zope.component.interfaces.IFactory"
+  />
+
   <class class=".themepage.ThemePage">
 
     <implements
@@ -281,6 +277,12 @@
       type="cpsskins.setup.interfaces.INameType"
   />
 
+  <utility
+      name="pageblock"
+      factory="cpsskins.elements.pageblock.PageBlock"
+      provides="zope.component.interfaces.IFactory"
+  />
+
   <class class=".pageblock.PageBlock">
 
     <implements
@@ -345,6 +347,12 @@
       type="cpsskins.setup.interfaces.INameType"
   />
 
+  <utility
+      name="cell"
+      factory="cpsskins.elements.cell.Cell"
+      provides="zope.component.interfaces.IFactory"
+  />
+
   <class class=".cell.Cell">
 
     <implements
@@ -399,6 +407,10 @@
       factory=".slot.Sublocations"
   />
 
+  <adapter
+      factory=".slot.Relatable"
+  />
+
   <interface
       interface=".interfaces.ISlot"
       type="cpsskins.setup.interfaces.IResourceType"
@@ -415,6 +427,12 @@
       type="cpsskins.setup.interfaces.INameType"
   />
 
+  <utility
+      name="slot"
+      factory="cpsskins.elements.slot.Slot"
+      provides="zope.component.interfaces.IFactory"
+  />
+
   <class class=".slot.Slot">
 
     <implements

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     Mon May  1 
12:06:53 2006
@@ -29,7 +29,7 @@
 
 from cpsskins.elements.interfaces import IElement, IElementType, IType, INode
 from cpsskins.elements.interfaces import IInnerNode, ILeaf, INodeTraverser
-from cpsskins.elements.interfaces import IIdentifiable, ITypeable
+from cpsskins.elements.interfaces import IIdentifiable
 from cpsskins.relations.interfaces import IRelatable
 from cpsskins.setup.interfaces import IResourceType
 from cpsskins.setup.utils import getTypeName
@@ -61,26 +61,6 @@
         id = self.element.identifier or u''
         return str(id)
 
-class Typeable(object):
-    """This adapter makes elements typeable.
-    """
-    adapts(IElement)
-    implements(ITypeable)
-
-    def __init__(self, element):
-        self.element = element
-
-    def getType(self):
-        type = IType(self.element)
-        return uniq([type.getElementType(), type.getResourceType(),
-                     type.getContentType()])
-
-    def getTypeName(self):
-        type = IType(self.element)
-        return '-'.join(
-            uniq([type.elementname, type.resourcename, type.contentname])
-            )
-
 class Identifiable(object):
     """This adapter makes elements uniquely identifiable.
     """
@@ -92,7 +72,7 @@
 
     def getURI(self):
         element = self.element
-        type_name = ITypeable(element).getTypeName()
+        type_name = IType(element).getTypeName()
 
         relatable = IRelatable(element, None)
         if relatable is None:
@@ -152,9 +132,8 @@
     __used_for__ = IElement
 
 class Type(object):
-    """Adapter that gets the content type of an element.
+    """Adapter that gets the type of an element.
     """
-    adapts(IElement)
     implements(IType)
 
     def __init__(self, element):
@@ -164,7 +143,7 @@
         return queryType(self.element, IElementType)
 
     def getResourceType(self):
-        return queryType(self.element, IResourceType) or self.getElementType()
+        return queryType(self.element, IResourceType)
 
     def getContentType(self):
         return queryType(self.element, IContentType)
@@ -178,8 +157,19 @@
     def getContentName(self):
         return getTypeName(self.getContentType())
 
+    def getType(self):
+        return uniq([self.getElementType(), self.getResourceType(),
+                     self.getContentType()])
+
+    def getTypeName(self):
+        return '-'.join(uniq([self.elementname, self.resourcename,
+                              self.contentname]))
+
     elementname = property(getElementName)
 
     resourcename = property(getResourceName)
 
     contentname = property(getContentName)
+
+    name = property(getTypeName)
+

Modified: cpsskins/branches/paris-sprint-2006/elements/format.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/elements/format.py      (original)
+++ cpsskins/branches/paris-sprint-2006/elements/format.py      Mon May  1 
12:06:53 2006
@@ -135,7 +135,7 @@
         return names
 
     def addFormat(self, name=u'', types=[]):
-        format = createObject(name)
+        format = createObject(u'format-' + name)
         format.types = types
         self.storeFormat(format)
         return self.setFormat(format)

Modified: cpsskins/branches/paris-sprint-2006/elements/interfaces.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/elements/interfaces.py  (original)
+++ cpsskins/branches/paris-sprint-2006/elements/interfaces.py  Mon May  1 
12:06:53 2006
@@ -61,12 +61,14 @@
     def getContentName():
         """ """
 
-class ITypeable(Interface):
-
     def getType():
         """Return the element's complete type as a tuple
         """
 
+    def getTypeName():
+        """Return the element's complete type name
+        """
+
 class INode(IElement):
     """A generic tree node"""
 

Modified: cpsskins/branches/paris-sprint-2006/ftests/test_appsetup.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/ftests/test_appsetup.py (original)
+++ cpsskins/branches/paris-sprint-2006/ftests/test_appsetup.py Mon May  1 
12:06:53 2006
@@ -29,11 +29,10 @@
 
 from cpsskins import elements
 from cpsskins.elements.interfaces import IElement, IIdentifiable, IType
-from cpsskins.elements.interfaces import ITypeable
 from cpsskins.setup.interfaces import IResourceType
 from cpsskins.setup.interfaces import IDOMAdapter
 from cpsskins.setup.test.dummy import IDummyResource, DummyDOMAdapter
-from cpsskins.setup.test.dummy import DummyFactory, Identifiable, Typeable
+from cpsskins.setup.test.dummy import DummyFactory, Identifiable, Type
 
 import cpsskins.elements.interfaces
 
@@ -43,7 +42,7 @@
     gsm.registerAdapter(DummyDOMAdapter, (IDummyResource, Interface),
                         IDOMAdapter)
     gsm.registerAdapter(Identifiable, (IDummyResource,), IIdentifiable)
-    gsm.registerAdapter(Typeable, (IDummyResource,), ITypeable)
+    gsm.registerAdapter(Type, (IDummyResource,), IType)
 
     # register the setting
     gsm.registerUtility(DummyFactory, IFactory, u'dummy')

Modified: cpsskins/branches/paris-sprint-2006/profiles/default/color.xml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/profiles/default/color.xml      
(original)
+++ cpsskins/branches/paris-sprint-2006/profiles/default/color.xml      Mon May 
 1 12:06:53 2006
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <settings>
-  <setting uri="cpsskins://[EMAIL PROTECTED]" title="Red color">
+  <setting name="redcolor" title="Red color" type="field-color">
     <color value="#ff0000" />
   </setting>
-  <setting uri="cpsskins://[EMAIL PROTECTED]" title="Green color">
+  <setting name="greencolor" title="Green color" type="field-color">
     <color value="#00ff00" />
   </setting>
 </settings>

Modified: cpsskins/branches/paris-sprint-2006/profiles/default/perspectives.xml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/profiles/default/perspectives.xml       
(original)
+++ cpsskins/branches/paris-sprint-2006/profiles/default/perspectives.xml       
Mon May  1 12:06:53 2006
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <settings>
-  <setting uri="cpsskins://[EMAIL PROTECTED]" title="Global perspective">
+  <setting name="global" title="Global perspective" type="perspective">
     <perspective uri="cpsskins://perspective:global" title="Global 
perspective" />
   </setting>
-  <setting uri="cpsskins://[EMAIL PROTECTED]" title="Global perspective 2">
+  <setting name="global2" title="Global perspective 2" type="perspective">
     <perspective uri="cpsskins://perspective:global2" title="Global 
perspective 2" />
   </setting>
 </settings>

Modified: cpsskins/branches/paris-sprint-2006/relations/configure.zcml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/relations/configure.zcml        
(original)
+++ cpsskins/branches/paris-sprint-2006/relations/configure.zcml        Mon May 
 1 12:06:53 2006
@@ -17,7 +17,6 @@
 
   </class>
 
-
   <class class=".MonadicRelation">
 
     <require
@@ -62,6 +61,46 @@
 
   </class>
 
+  <!-- Typing -->
+  <interface
+      interface=".interfaces.IRelation"
+      type="cpsskins.setup.interfaces.IResourceType"
+  />
+
+  <interface
+      interface=".interfaces.IMonadicRelation"
+      type="zope.app.content.interfaces.IContentType"
+  />
+
+  <interface
+      interface=".interfaces.IDyadicRelation"
+      type="zope.app.content.interfaces.IContentType"
+  />
+
+  <interface
+      interface=".interfaces.ITriadicRelation"
+      type="zope.app.content.interfaces.IContentType"
+  />
+
+  <interface
+      name="monad"
+      interface=".interfaces.IMonadicRelation"
+      type="cpsskins.setup.interfaces.INameType"
+  />
+
+  <interface
+      name="dyad"
+      interface=".interfaces.IDyadicRelation"
+      type="cpsskins.setup.interfaces.INameType"
+  />
+
+  <interface
+      name="triad"
+      interface=".interfaces.ITriadicRelation"
+      type="cpsskins.setup.interfaces.INameType"
+  />
+
+
   <!-- Relation storage -->
 
   <cpsskins:storage
@@ -81,11 +120,23 @@
   />
 
 
-  <!-- Factory -->
+  <!-- Factories -->
+  <utility
+      factory="cpsskins.relations.relations.MonadicRelationFactory"
+      provides="zope.component.interfaces.IFactory"
+      name="monad"
+  />
+
+  <utility
+      factory="cpsskins.relations.relations.DyadicRelationFactory"
+      provides="zope.component.interfaces.IFactory"
+      name="dyad"
+  />
+
   <utility
-      factory="cpsskins.relations.relations.RelationFactory"
+      factory="cpsskins.relations.relations.TriadicRelationFactory"
       provides="zope.component.interfaces.IFactory"
-      name="relation"
+      name="triad"
   />
 
 </configure>

Modified: cpsskins/branches/paris-sprint-2006/relations/relations.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/relations/relations.py  (original)
+++ cpsskins/branches/paris-sprint-2006/relations/relations.py  Mon May  1 
12:06:53 2006
@@ -19,10 +19,13 @@
 
 from persistent import Persistent
 
+from zope.component import adapts
 from zope.component.factory import Factory
 from zope.interface import implements
 from zope.security.proxy import removeSecurityProxy as trusted
 
+from cpsskins.elements.interfaces import IType
+
 from cpsskins.relations.interfaces import IRelation
 from cpsskins.relations.interfaces import IMonadicRelation, IDyadicRelation
 from cpsskins.relations.interfaces import ITriadicRelation, IRelatable
@@ -217,6 +220,12 @@
     def __repr__(self):
         return self.name
 
-RelationFactory = Factory(Relation, "Relation Factory",
-                       "A Factory that creates relations")
+MonadicRelationFactory = Factory(MonadicRelation, "Monadic Relation Factory",
+    "A Factory that creates monadic relations")
+
+DyadicRelationFactory = Factory(DyadicRelation, "Dyadic Relation Factory",
+    "A Factory that creates dyadic relations")
+
+TriadicRelationFactory = Factory(TriadicRelation, "Triadic Relation Factory",
+    "A Factory that creates triadic relations")
 

Modified: cpsskins/branches/paris-sprint-2006/setup/README.txt
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/README.txt        (original)
+++ cpsskins/branches/paris-sprint-2006/setup/README.txt        Mon May  1 
12:06:53 2006
@@ -87,7 +87,7 @@
 resource directly (e.g. 'cpsskins://dummy:resource1') we access it by
 referring to the corresponding setting (e.g. 'cpsskins://[EMAIL PROTECTED]').
 
-    >>> resources.register(uri=u'cpsskins://[EMAIL PROTECTED]', 
title=u'Setting 1',
+    >>> resources.register(name=u'setting1', title=u'Setting 1',
     ...                    resource=resource1)
 
 we can look up the setting:
@@ -108,7 +108,7 @@
 
 Now we register the second resource:
 
-    >>> resources.register(uri=u'cpsskins://[EMAIL PROTECTED]', 
title=u'Setting 2',
+    >>> resources.register(name=u'setting2', title=u'Setting 2',
     ...                    resource=resource2)
 
 and look it up in the registry:
@@ -129,7 +129,7 @@
 
 so we register a local resource, we do this by passing a context to register():
 
-    >>> resources.register(uri=u'cpsskins://[EMAIL PROTECTED]', 
title=u'Setting 3',
+    >>> resources.register(name=u'setting3', title=u'Setting 3',
     ...                    resource=resource3, context=root)
 
 We now have a local resource in the context of the root folder:
@@ -415,16 +415,16 @@
 
 either as a list of interfaces:
 
-    >>> from cpsskins.elements.interfaces import ITypeable
+    >>> from cpsskins.elements.interfaces import IType
 
-    >>> pprint(ITypeable(resource).getType())
+    >>> pprint(IType(resource).getType())
     [<InterfaceClass cpsskins.elements.interfaces.ICanvas>,
      <InterfaceClass cpsskins.elements.interfaces.IPortlet>,
      <InterfaceClass cpsskins.standard.portlets.actions.portlet.IActions>]
 
 or as a string that can be passed in a URL or be written in JSON, XML.
 
-    >>> ITypeable(resource).getTypeName()
+    >>> IType(resource).getTypeName()
     u'canvas-portlet-standard.actions'
 
 Note that there is a one-to-one relation between type signatures and type
@@ -512,8 +512,7 @@
 ------------------
 
     >>> style = Style()
-    >>> resources.register(uri=u'cpsskins://[EMAIL PROTECTED]',
-    ...                    title=u'Style 1', resource=style)
+    >>> resources.register(name=u'style1', title=u'Style 1', resource=style)
 
     >>> setting = resources.lookup(u'style1')
     >>> print toXML(setting, u'settings')
@@ -527,7 +526,7 @@
     >>> print toXML(resource, u'styles')
     <?xml version="1.0" encoding="utf-8"?>
     <styles>
-      <style uri="cpsskins://format-style:12345">
+      <style id="12345">
         <selector value="div.body">
           <property name="color" value="red"/>
           <property name="border" value="none"/>
@@ -547,13 +546,7 @@
     ...                            first=Actions(u'Actions portlet'))
 
     >>> print toXML(relation, u'relations')
-    <?xml version="1.0" encoding="utf-8"?>
-    <relations>
-      <relation predicate="_ A">
-        <relate uri="cpsskins://canvas-portlet-standard.actions:12345"/>
-      </relation>
-    </relations>
-    <BLANKLINE>
+
 
 Dyadic relations:
 
@@ -565,14 +558,7 @@
     ...                           second=Breadcrumbs(u'Breadcrumbs portlet'))
 
     >>> print toXML(relation, u'relations')
-    <?xml version="1.0" encoding="utf-8"?>
-    <relations>
-      <relation predicate="_ B _">
-        <relate uri="cpsskins://canvas-portlet-standard.actions:12345"/>
-        <relate uri="cpsskins://canvas-portlet-standard.breadcrumbs:12345"/>
-      </relation>
-    </relations>
-    <BLANKLINE>
+
 
 Triadic relations:
 
@@ -585,15 +571,7 @@
     ...                            third=Slot(slot=u'slotA'))
 
     >>> print toXML(relation, u'relations')
-    <?xml version="1.0" encoding="utf-8"?>
-    <relations>
-      <relation predicate="_ C _ D _">
-        <relate uri="cpsskins://canvas-portlet-standard.actions:12345"/>
-        <relate uri="cpsskins://canvas-portlet-standard.breadcrumbs:12345"/>
-        <relate uri="cpsskins://canvas-slot:slotA"/>
-      </relation>
-    </relations>
-    <BLANKLINE>
+
 
 
 Export of elements
@@ -612,24 +590,21 @@
     >>> pageblock[u'cell2'] = cell2
 
     >>> from cpsskins.elements.slot import Slot
-    >>> slot = Slot(u'Some slot')
+    >>> slot = Slot(u'Some slot', slot=u'slot1')
     >>> pageblock[u'cell1'][u'slot'] = slot
 
     >>> print toXML(pageblock, u'elements', (u'title', u'description'))
     <?xml version="1.0" encoding="utf-8"?>
     <elements>
-      <pageblock title="Some page block" 
uri="cpsskins://canvas-pageblock:12345">
-        <cell title="Some cell 1" uri="cpsskins://canvas-cell:12345">
-          <slot description="" title="Some slot" uri="cpsskins://canvas-slot:">
-            <slot value=""/>
-          </slot>
+      <pageblock id="12345" title="Some page block">
+        <cell id="12345" title="Some cell 1">
+          <slot description="" id="12345" title="Some slot" slot="slot1"/>
         </cell>
-        <cell title="Some cell 2" uri="cpsskins://canvas-cell:12345"/>
+        <cell id="12345" title="Some cell 2"/>
       </pageblock>
     </elements>
     <BLANKLINE>
 
-
 Export of container elements
 ----------------------------
 
@@ -640,17 +615,16 @@
     >>> print toXML(theme, u'themes', (u'title', ))
     <?xml version="1.0" encoding="utf-8"?>
     <themes>
-      <theme title="A theme" uri="cpsskins://canvas-theme:12345">
-        <themepage title="A page" uri="cpsskins://canvas-themepage:12345">
-          <pageblock title="A page block" 
uri="cpsskins://canvas-pageblock:12345">
-            <cell title="A cell" uri="cpsskins://canvas-cell:12345"/>
+      <theme id="12345" title="A theme">
+        <themepage id="12345" title="A page">
+          <pageblock id="12345" title="A page block">
+            <cell id="12345" title="A cell"/>
           </pageblock>
         </themepage>
       </theme>
     </themes>
     <BLANKLINE>
 
-
 Export of portlets
 ------------------
 
@@ -659,13 +633,12 @@
     >>> print toXML(portlet, u'portlets',  (u'title', ))
     <?xml version="1.0" encoding="utf-8"?>
     <portlets>
-      <portlet title="Action portlet" 
uri="cpsskins://canvas-portlet-standard.actions:12345">
+      <portlet id="12345" title="Action portlet">
         <category value="zmi_views"/>
       </portlet>
     </portlets>
     <BLANKLINE>
 
-
 Export of display elements
 -------------------------
 
@@ -675,11 +648,10 @@
     >>> print toXML(area, u'displays')
     <?xml version="1.0" encoding="utf-8"?>
     <displays>
-      <area uri="cpsskins://display-area:12345"/>
+      <area id="12345"/>
     </displays>
     <BLANKLINE>
 
-
 Export of format elements
 -------------------------
 
@@ -689,7 +661,7 @@
     >>> print toXML(effect, u'formats')
     <?xml version="1.0" encoding="utf-8"?>
     <formats>
-      <effect uri="cpsskins://format-effect:12345">
+      <effect id="12345">
         <types value=""/>
         <format value="PNG"/>
         <width value="100"/>
@@ -699,6 +671,7 @@
     </formats>
     <BLANKLINE>
 
+
 Resolving URIs
 ==============
 
@@ -712,10 +685,9 @@
     >>> print color
     #ff0000
 
-    >>> resources.register(uri=u'cpsskins://[EMAIL PROTECTED]',
-    ...                    title=u'Color red', resource=color)
+    >>> resources.register(name=u'red', title=u'Color red', resource=color)
 
-    >>> ITypeable(color).getTypeName()
+    >>> IType(color).getTypeName()
     u'field-color'
 
     >>> res = resources.resolve(u'cpsskins://[EMAIL PROTECTED]', context=root)

Modified: cpsskins/branches/paris-sprint-2006/setup/adapters.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/adapters.py       (original)
+++ cpsskins/branches/paris-sprint-2006/setup/adapters.py       Mon May  1 
12:06:53 2006
@@ -20,7 +20,7 @@
 from zope.component import adapts
 from zope.interface import implements
 
-from cpsskins.elements.interfaces import IIdentifiable, ITypeable
+from cpsskins.elements.interfaces import IIdentifiable, IType
 from cpsskins.relations.interfaces import IRelatable
 from cpsskins.setup.interfaces import IResource, ISetting
 
@@ -46,7 +46,7 @@
         self.context = context
 
     def __str__(self):
-        return self.context.uri
+        return self.context.name
 
 class Identifiable(object):
     """This adapter makes elements uniquely identifiable.
@@ -58,17 +58,8 @@
         self.context = context
 
     def getURI(self):
-        return self.context.uri
-
-class Typeable(object):
-    """This adapter makes elements uniquely identifiable.
-    """
-    adapts(ISetting)
-    implements(ITypeable)
-
-    def __init__(self, context):
-        self.context = context
-
-    def getTypeName(self):
-        return u'dummy'
+        context = self.context
+        resource = context.resource
+        return u'cpsskins://[EMAIL PROTECTED]' % 
(IType(resource).getTypeName(),
+                                      context.name)
 

Modified: cpsskins/branches/paris-sprint-2006/setup/interfaces.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/interfaces.py     (original)
+++ cpsskins/branches/paris-sprint-2006/setup/interfaces.py     Mon May  1 
12:06:53 2006
@@ -70,25 +70,25 @@
     def register(name, resource, context):
         """Register a resource."""
 
-    def unregister(name, context):
+    def unregister(uri, context):
         """Unregister a resource."""
 
-    def lookup(name, context, default):
+    def lookup(uri, context, default):
         """Look up a resource."""
 
     def list(type, context):
         """List all resources of a given type."""
 
-    def customize(name, context):
+    def customize(uri, context):
         """Customize a resource."""
 
-    def isGlobal(name):
+    def isGlobal(uri):
         """Returns true if the resource global"""
 
-    def isLocal(name):
+    def isLocal(uri):
         """Returns true if the resource is local"""
 
-    def isCustom(name, context):
+    def isCustom(uri, context):
         """Returns true if the resource has been customized"""
 
 ##### IO  #############################################################
@@ -103,7 +103,9 @@
 
     mapping = Attribute(u"Mapping between old and new URIs")
 
-    attributes = Attribute(u"The list of fields written as attributes.")
+    attributes = Attribute(u"The list of fields written as DOM attributes.")
+
+    properties = Attribute(u"Extra properties.")
 
     def setDocument(document):
         """Set the document element"""
@@ -111,6 +113,9 @@
     def getDocument():
         """Get the document element"""
 
+    def addProperty(name, value):
+        """Add a property"""
+
     def writeAsAttributes(attributes):
         """Set the list of fields written as attributes."""
 

Modified: cpsskins/branches/paris-sprint-2006/setup/io.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/io.py     (original)
+++ cpsskins/branches/paris-sprint-2006/setup/io.py     Mon May  1 12:06:53 2006
@@ -26,6 +26,7 @@
 from zope.app.container.interfaces import IItemContainer
 
 from cpsskins.elements.interfaces import IIdentifiable, IType
+from cpsskins.relations.interfaces import IRelatable
 from cpsskins.setup.interfaces import IDOMAdapter
 
 logger = logging.getLogger("cpsskins")
@@ -36,6 +37,7 @@
     document = None
     mapping = {}
     attributes = ()
+    properties = {}
 
     def __init__(self, context, node):
         self.context = context
@@ -50,6 +52,11 @@
                 "use setDocument(document) to set the document element.")
         return self.document
 
+    def addProperty(self, name, value):
+        if not isinstance(value, basestring):
+            raise TypeError("Properties must be strings: %s" % value)
+        self.properties[name] = value
+
     def writeAsAttributes(self, attributes):
         self.attributes = attributes
 
@@ -78,7 +85,10 @@
         document = self.getDocument()
 
         element_el = document.createElement(IType(context).resourcename)
-        element_el.setAttribute(u'uri', IIdentifiable(context).getURI())
+        element_el.setAttribute(u'id', unicode(IRelatable(context)))
+
+        for k, v in self.properties.items():
+            element_el.setAttribute(k, unicode(v))
 
         # properties
         schema = IType(context).getContentType()

Modified: cpsskins/branches/paris-sprint-2006/setup/manager.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/manager.py        (original)
+++ cpsskins/branches/paris-sprint-2006/setup/manager.py        Mon May  1 
12:06:53 2006
@@ -45,24 +45,26 @@
 
     ### Registration of settings  #####################################
 
-    def register(self, uri=u'', title=u'', resource=None, filename=None,
+    def register(self, name=u'', title=u'', resource=None, filename=None,
                        custom=False, context=None):
         """Register the setting as a utility.
         """
         # register as a global utility
         if context is None:
-            setting = GlobalSetting(uri=uri, title=title,
+            setting = GlobalSetting(name=name, title=title,
                                     resource=resource, filename=filename)
+            uri = IIdentifiable(setting).getURI()
             self.gsm.registerUtility(setting, ISetting, uri)
 
         # register as a local utility
         else:
             settings = getThemeManager(context).getSettings()
             chooser = INameChooser(settings)
-            name = uri or chooser.chooseName(title, object)
-            setting = LocalSetting(uri=uri, title=title,
+            name = name or chooser.chooseName(title, context)
+            setting = LocalSetting(name=name, title=title,
                                    resource=resource, custom=custom)
             settings[name] = setting
+            uri = IIdentifiable(setting).getURI()
             settings.registerUtility(setting, ISetting, uri)
 
     def unregister(self, uri=u'', context=None):
@@ -174,7 +176,8 @@
         if resource_getter is not None:
             resource = deepcopy(resource_getter.getResource())
 
-        self.register(uri=uri, title=setting.title, resource=resource,
+        name = uri.split('@')[-1]
+        self.register(name=name, title=setting.title, resource=resource,
                       context=context, custom=True)
 
     def decustomize(self, uri=u'', context=None):

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   Mon May  1 
12:06:53 2006
@@ -57,19 +57,19 @@
         filename = file['filename']
         dom = parse(filename)
         for setting_def in dom.getElementsByTagName('setting'):
-            uri = setting_def.getAttribute('uri')
+            name = setting_def.getAttribute('name')
             title = setting_def.getAttribute('title')
-            resource = _loadResourceFromXML(setting_def, uri, title)
+            resource = _loadResourceFromXML(setting_def, name, title)
             if resource is None:
                 continue
-            resources.register(uri, title=title,
+            resources.register(name, title=title,
                                resource=resource, filename=filename)
 
             file['refresh_date'] = time.time()
 
         logger.debug("loaded settings in %s", filename)
 
-def _loadResourceFromXML(setting_def=None, uri=u'', title=u'', filename=u''):
+def _loadResourceFromXML(setting_def=None, name=u'', title=u'', filename=u''):
     resources = getUtility(IResourceManager)
 
     resource_defs = setting_def.getElementsByTagName('*')
@@ -79,17 +79,19 @@
 
     resource_def = resource_defs[0]
 
+    factory_name = setting_def.getAttribute('type')
+    uri = 'cpsskins://[EMAIL PROTECTED]' % (factory_name, name)
     setting = resources.lookup(uri)
     if setting is None:
         # create the resource
-        resource = createObject(resource_def.tagName)
-        resources.register(uri=uri, title=title, resource=resource,
+        resource = createObject(factory_name)
+        resources.register(name=name, title=title, resource=resource,
                            filename=filename)
-        logger.debug("new setting added: '%s'", uri)
+        logger.debug("new setting added: '%s'", name)
     else:
         resource = IResource(setting).getResource()
         setting.title = title
-        logger.debug("reloaded setting %s in %s", uri, filename)
+        logger.debug("reloaded setting %s in %s", name, filename)
 
     # load the data
     #getMultiAdapter(IDOMAdapter, (resource, resource_def)).load()

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        Mon May  1 
12:06:53 2006
@@ -26,13 +26,13 @@
 
 class Setting(object):
 
-    def __init__(self, uri=u'', title=u'', resource=None):
-        self.uri = uri
+    def __init__(self, name=u'', title=u'', resource=None):
+        self.name = name
         self.title = title
         self.resource = resource
         # add a reference from the resource to the setting
         self.resource.__parent__ = self
-        self.resource.__name__ = uri
+        self.resource.__name__ = name
 
     def __repr__(self):
         return u'<Setting: %s>' % IIdentifiable(self).getURI()

Modified: cpsskins/branches/paris-sprint-2006/setup/test/dummy.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/test/dummy.py     (original)
+++ cpsskins/branches/paris-sprint-2006/setup/test/dummy.py     Mon May  1 
12:06:53 2006
@@ -23,7 +23,7 @@
 from zope.component.factory import Factory
 from zope.interface import Interface, implements
 
-from cpsskins.elements.interfaces import IIdentifiable, ITypeable
+from cpsskins.elements.interfaces import IIdentifiable, IType
 from cpsskins.setup.io import BaseDOMAdapter
 from cpsskins.setup.interfaces import IDOMAdapter
 
@@ -68,9 +68,9 @@
         identifier = self.context.title.replace(u' ', u'_')
         return u'cpsskins://dummy:%s' % identifier
 
-class Typeable:
+class Type:
 
-    implements(ITypeable)
+    implements(IType)
 
     def __init__(self, context):
         self.context = context

Modified: cpsskins/branches/paris-sprint-2006/setup/test/resource4.xml
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/test/resource4.xml        
(original)
+++ cpsskins/branches/paris-sprint-2006/setup/test/resource4.xml        Mon May 
 1 12:06:53 2006
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8" ?>
-<setting uri="cpsskins://[EMAIL PROTECTED]" title="Test setting 4">
+<setting name="test.setting4" title="Test setting 4" type="dummy">
   <dummy title="Dummy resource 4" />
 </setting>

Modified: cpsskins/branches/paris-sprint-2006/setup/utils.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/setup/utils.py  (original)
+++ cpsskins/branches/paris-sprint-2006/setup/utils.py  Mon May  1 12:06:53 2006
@@ -17,6 +17,7 @@
 """
 __docformat__ = "reStructuredText"
 
+import re
 import time
 import logging
 
@@ -53,12 +54,15 @@
     # TODO: could be cached
     names = []
     name_types = list(getUtilitiesFor(INameType))
+    print name_types
     if not isinstance(type, (list , tuple)):
         type = [type]
     for iface in type:
-        name = [k for k, v in list(name_types) if v is iface][0]
-        names.append(name)
-    return '-'.join(names)
+        name = [k for k, v in name_types if v is iface]
+        if not name:
+            continue
+        names.append(name[0])
+    return u'-'.join(names)
 
 class TarArchive:
 

Modified: cpsskins/branches/paris-sprint-2006/standard/io/relation.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/standard/io/relation.py (original)
+++ cpsskins/branches/paris-sprint-2006/standard/io/relation.py Mon May  1 
12:06:53 2006
@@ -23,6 +23,18 @@
 from cpsskins.setup.interfaces import IDOMAdapter
 from cpsskins.setup.io import BaseDOMAdapter
 
+factories = {
+    1: u'monad',
+    2: u'dyad',
+    3: u'triad',
+}
+
+relates = {
+    1: u'first',
+    2: u'second',
+    3: u'third',
+}
+
 class DOMAdapter(BaseDOMAdapter):
     """DOM adapter for relations
     """
@@ -34,18 +46,21 @@
 
         document = self.getDocument()
 
+        arity = len(context)
         relation_el = document.createElement(u'relation')
         relation_el.setAttribute(u'predicate', str(context))
 
+        i = 1
         for relate in context:
-            relate_el = document.createElement(u'relate')
-            relate_el.setAttribute(u'uri', IIdentifiable(relate).getURI())
-            relation_el.appendChild(relate_el)
+            relation_el.setAttribute(relates[i], 
IIdentifiable(relate).getURI())
+            i += 1
 
         node.appendChild(relation_el)
 
     def load(self):
         context = self.context
         node = self.node
+
+        print context
         # TODO
 

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  Mon May  1 
12:06:53 2006
@@ -20,8 +20,10 @@
 from zope.component import getMultiAdapter
 from zope.interface import implements
 
+from cpsskins.elements.interfaces import IIdentifiable, IType
 from cpsskins.setup.interfaces import IResource, IDOMAdapter
 from cpsskins.setup.io import BaseDOMAdapter
+from cpsskins.relations.interfaces import IRelatable
 
 class DOMAdapter(BaseDOMAdapter):
     """DOM adapter for settings
@@ -34,13 +36,15 @@
 
         document = self.getDocument()
 
+        resource = IResource(context).getResource()
+
         setting_el = document.createElement(u'setting')
+        setting_el.setAttribute(u'name', context.name)
         setting_el.setAttribute(u'title', context.title)
-        setting_el.setAttribute(u'uri', IIdentifiable(context).getURI())
+        setting_el.setAttribute(u'tyoe', IType(resource).getTypeName())
         node.appendChild(setting_el)
 
         # export the resource
-        resource = IResource(context).getResource()
         exporter = getMultiAdapter((resource, setting_el), IDOMAdapter)
         exporter.setDocument(document)
         exporter.writeAsAttributes(self.attributes)

Modified: cpsskins/branches/paris-sprint-2006/standard/io/style.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/standard/io/style.py    (original)
+++ cpsskins/branches/paris-sprint-2006/standard/io/style.py    Mon May  1 
12:06:53 2006
@@ -22,6 +22,7 @@
 from cpsskins.elements.interfaces import IIdentifiable
 from cpsskins.setup.interfaces import IDOMAdapter
 from cpsskins.setup.io import BaseDOMAdapter
+from cpsskins.relations.interfaces import IRelatable
 
 class DOMAdapter(BaseDOMAdapter):
     """DOM adapter for styles
@@ -35,7 +36,7 @@
         document = self.getDocument()
 
         style_el = document.createElement(u'style')
-        style_el.setAttribute(u'uri', IIdentifiable(context).getURI())
+        style_el.setAttribute(u'id', unicode(IRelatable(context)))
 
         for k, v in context.items():
             selector_el = document.createElement(u'selector')

Modified: cpsskins/branches/paris-sprint-2006/tests/setup.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/tests/setup.py  (original)
+++ cpsskins/branches/paris-sprint-2006/tests/setup.py  Mon May  1 12:06:53 2006
@@ -1,4 +1,4 @@
-##############################################################################
+############################################################################
 #
 # Copyright (c) 2005-2006 Nuxeo and Contributors.
 # All Rights Reserved.
@@ -29,8 +29,8 @@
 from cpsskins import elements
 from cpsskins.elements.display import Displayable
 from cpsskins.elements.format import Formattable
-from cpsskins.elements.interfaces import IElement, IDisplay
-from cpsskins.elements.interfaces import IIdentifiable, ITypeable
+from cpsskins.elements.interfaces import IElement, IDisplay, IIdentifiable
+from cpsskins.elements.interfaces import IType
 from cpsskins.perspectives import perspective
 from cpsskins.perspectives.interfaces import IPerspective
 from cpsskins.relations.interfaces import IRelationTool, IRelationStorage
@@ -46,7 +46,7 @@
     gsm.registerAdapter(RelationTool, (IElement,), IRelationTool)
     gsm.registerAdapter(elements.element.Identifiable, (IElement,), 
                         IIdentifiable)
-    gsm.registerAdapter(elements.element.Typeable, (IElement,), ITypeable)
+    gsm.registerAdapter(elements.element.Type, (IElement,), IType)
     gsm.registerAdapter(elements.element.Relatable, (IElement,), IRelatable)
     gsm.registerAdapter(perspective.Relatable, (IPerspective,), IRelatable)
 

Modified: cpsskins/branches/paris-sprint-2006/thememanager.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/thememanager.py (original)
+++ cpsskins/branches/paris-sprint-2006/thememanager.py Mon May  1 12:06:53 2006
@@ -352,6 +352,7 @@
     def addPerspective(self, name, title):
         """Add a perspective to the perspective storage.
         """
+        return
         perspective = Perspective(name=name, title=title)
         mgr = getUtility(IResourceManager)
         mgr.register(title=title, resource=perspective, context=self)

Modified: cpsskins/branches/paris-sprint-2006/ui/editing/views.py
==============================================================================
--- cpsskins/branches/paris-sprint-2006/ui/editing/views.py     (original)
+++ cpsskins/branches/paris-sprint-2006/ui/editing/views.py     Mon May  1 
12:06:53 2006
@@ -27,7 +27,7 @@
 
 from cpsskins.browser.negotiation.interfaces import INegotiation
 from cpsskins.elements.interfaces import IDisplayable, IFormattable
-from cpsskins.elements.interfaces import IType, ITypeable, IDisplay, IFormat
+from cpsskins.elements.interfaces import IType, IDisplay, IFormat
 from cpsskins.relations.interfaces import IRelationTool
 from cpsskins.relations.relations import DyadicRelation
 from cpsskins.setup.interfaces import IResourceManager, IResource, ISetting
@@ -144,7 +144,7 @@
 
         # Edited element
         element_info = {
-            'name': ITypeable(context).getTypeName(),
+            'name': IType(context).getTypeName(),
             'id': context.identifier,
             }
 
@@ -156,7 +156,7 @@
             is_setting = ISetting.providedBy(f)
             if is_setting:
                 f = IResource(f).getResource()
-            name = ITypeable(f).getTypeName()
+            name = IType(f).getTypeName()
             selected = name == format_name
             if selected:
                 format = f

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 Mon May 
 1 12:06:53 2006
@@ -189,7 +189,6 @@
                 continue
 
             relation = createObject(u'relation')
-            print relation
             importer = getMultiAdapter((relation, el), IDOMAdapter)
             importer.setDocument(document)
             importer.setURIMapping(uri_mapping)
@@ -250,10 +249,14 @@
         document = DOMImplementation().createDocument(None, name, None)
         root = document.documentElement
 
-        for item in storage:
-            exporter = getMultiAdapter((storage[item], root), IDOMAdapter)
+        for id in storage:
+            item = storage[id]
+            type = IType(item)
+            exporter = getMultiAdapter((item, root), IDOMAdapter)
             exporter.setDocument(document)
-            exporter.writeAsAttributes((u'title', u'description'))
+            #if type.contentname != type.resourcename:
+            #    exporter.addProperty(u'type', type.contentname)
+            exporter.writeAsAttributes((u'title', u'description', u'type'))
             exporter.save()
 
         xml = document.toprettyxml(indent=u'  ', encoding=u'utf-8')
@@ -277,12 +280,15 @@
         for el in root.childNodes:
             if el.nodeType != Node.ELEMENT_NODE:
                 continue
-            obj = createObject(el.tagName)
+            factory_name = '%s-%s' % (name, el.tagName)
+            obj = createObject(factory-name)
 
             importer = getMultiAdapter((obj, el), IDOMAdapter)
             importer.setDocument(document)
             importer.load()
 
+            storage.add(obj)
+
             uri_mapping.update(importer.mapping)
 
         document.unlink()
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to