Author: jmorliaguet
Date: Fri Nov  4 16:12:15 2005
New Revision: 28979

Added:
   z3lab/cpsskins/branches/jmo-perspectives/registry/
   z3lab/cpsskins/branches/jmo-perspectives/registry/README.txt   (contents, 
props changed)
   z3lab/cpsskins/branches/jmo-perspectives/registry/__init__.py   (contents, 
props changed)
   z3lab/cpsskins/branches/jmo-perspectives/registry/configure.zcml   
(contents, props changed)
   z3lab/cpsskins/branches/jmo-perspectives/registry/interfaces.py   (contents, 
props changed)
   z3lab/cpsskins/branches/jmo-perspectives/registry/storage.py   (contents, 
props changed)
Modified:
   z3lab/cpsskins/branches/jmo-perspectives/configure.zcml
Log:

- saving work (current a basic container implementation of a global utility
  that registers ISomeItem objects.)



Modified: z3lab/cpsskins/branches/jmo-perspectives/configure.zcml
==============================================================================
--- z3lab/cpsskins/branches/jmo-perspectives/configure.zcml     (original)
+++ z3lab/cpsskins/branches/jmo-perspectives/configure.zcml     Fri Nov  4 
16:12:15 2005
@@ -49,7 +49,6 @@
 
   <include package=".controllers" />
 
-  <include package=".storage" />
 
   <include package=".elements" />
 
@@ -67,4 +66,8 @@
 
   <include package=".configuration.engines" />
 
+  <include package=".registry" />
+
+  <include package=".storage" />
+
 </configure>

Added: z3lab/cpsskins/branches/jmo-perspectives/registry/README.txt
==============================================================================
--- (empty file)
+++ z3lab/cpsskins/branches/jmo-perspectives/registry/README.txt        Fri Nov 
 4 16:12:15 2005
@@ -0,0 +1,206 @@
+
+$id:$
+
+=====================
+STORAGE-LIKE REGISTRY
+=====================
+
+This package provides a storage that implements the component architecture's
+utility-based registration mechanism to register objects.
+
+Description
+-----------
+
+A storage-like registry contains objects (resources, images, portlets, ...)
+that are used by the application. Objects can be stored in the ZODB or be
+filesystem resources. The objects are accessed as if they were stored in a
+single container, although they may be part of different registries (global /
+local).
+
+Design goals
+------------
+
+The main design goal of this type of registry is to allow transparent access to
+objects located in the storage independently of the way in which they have been
+created (i.e. TTW or via the filesystem) or registered.
+
+Filesystem-based vs. persistent objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Filesystem-based configurations (e.g. zope configuration system) store
+information about objects on the filesystem: when the application server is
+started the server stores objects in memory based on the configuration.
+The objects can be modified by the application, but the modifications are lost
+as soon the server is restarted.
+
+Unless users have access to the filesystem, the objects created in this way
+can be considered as read-only resources. This poses a problem in case the
+objects need to be modified by users who only work through the web.
+
+A solution is to create such objects as persistent content classes from the
+beginning, but this make filesystem-based development difficult.
+
+Different patterns
+~~~~~~~~~~~~~~~~~~
+
+The main issue is that the patterns used when working with filesystem-based
+objects and with persistent objects are quite different:
+
+- objects configured on the filesystem are considered by the application as
+  simple resources stored in a registry. They are not supposed to be
+  manipulated by users.
+
+- objects stored in the ZODB are meant to be manipulated by users but
+  they are difficult to access via a registry unless they are cataloged.
+
+The results is that different APIs get implemented based on the type of
+object, and sometimes it is the entire application that supports one way of
+working with objects or the other.
+
+
+Use case 1: application developer
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Developing an application through-the-web is not very efficient.
+
+Application developers will most likely take the filesystem-based configuration
+approach for creating application resources (actions, skins, templates,
+workflows, ...). This makes it easier to collaborate on software repositories.
+
+
+Use case 2: site designers
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Site designers will most likely want to work directly through-the-web and
+export site configurations to the filesystem when they are satisfied with the
+results.
+
+Conflicting interests
+~~~~~~~~~~~~~~~~~~~~~
+
+This situation causes conflicts of interests since the developers will claim
+that resources ought be stored on the filesystem and site designers will claim
+that working through-the-web is a better approach.
+
+The result is that some of the resources in the application shared by both
+developers and by site designers cannot be considered as "filesystem-only"
+or as "TTW-only" resources, they have to be considered as both.
+
+The current pattern in Zope3 is to not support TTW development. This partly
+solves the issue, but only if by "development" one really means development.
+
+It can be argued that site creation is not done by developers but by site
+designers. If this former category of users is to be empowered, a model that
+mixes filesystem-based and through-the-web "development" is needed.
+
+The storage described here treats filesystem-based objects as if they were
+read-only objects stored in the ZODB.
+
+
+Implementation
+--------------
+
+Interfaces
+~~~~~~~~~~
+
+Each storage implements the base IStorage interface and may also implement more
+specific interfaces depending on the type of object stored::
+
+class IStorage(Interface):
+
+    def add(object, name):
+        """Add an object to the storage. Return the added object.
+        The object's name can be specified.
+        """
+
+    def remove(objects):
+        """Remove a list of objects from the storage."""
+
+    def duplicate(object):
+        """Duplicate an object in the storage. Return the duplicated object."""
+
+    def __setitem__(object):
+        """Set an object into the storage."""
+
+    def __getitem__(item):
+        """Get an item from the storage."""
+
+    def customize(object):
+        """Turn a filesystem object into a persistent object."""
+
+    def decustomize(object):
+        """Convert a customized object back into a filesystem object."""
+
+
+The storage interface is also used to identify the storage.::
+
+class IMyStorage(IStorage):
+
+    contains(ISomeTypeOfObject)
+
+    def doSomethingSpecial():
+        """Do something special with the stored objects"""
+
+
+Registration
+~~~~~~~~~~~~
+
+Storages are registered in ZCML::
+
+<configure
+    xmlns:cpsskins="http://namespaces.zope.org/cpsskins";>
+
+  <cpsskins:storage
+      id="mystorage"
+      title="My storage"
+      description="A description of my storage"
+      factory=".mystorage.MyStorage"
+      interface=".mystorage.IMyStorage"
+  />
+
+</configure>
+
+
+Adding filessystem objects to the storage
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When an object is registered in ZCML it is possible to specify the
+storage to which it will be add. This can be done in metaconfigure.py
+
+instead of writing::
+
+   some_registry = getUtility(ISomeRegistry)
+   some_registry.register(name, some_object)
+
+
+one would write:
+
+   some_storage = queryUtility(IMyStorage)
+   some_storage.add(some_object)
+
+The object is physically stored in memory but for the application it appears as
+though the object is located in the storage with other ZODB objects.
+
+It is the responsibility of the ZCML configuration handler to add objects
+to the registry. Hence the storage is unaware of the configuration method.
+
+Customizing objects
+~~~~~~~~~~~~~~~~~~~
+
+Sometimes an object configured on the filesystem needs to become persistent
+This is the equivalent of the "Customize" function in Zope2's portal skins.
+A copy of the original object is created and replaces the customized object.
+
+Decustomizing objects
+~~~~~~~~~~~~~~~~~~~~~
+
+Customized objects are not destroyed, hence it is easy to reverse the
+customization.
+
+Access
+~~~~~~
+
+Filesystem-based objects are to be considered as read-only, hence they should
+appear as being locked or not being writable by the application.
+
+(...)

Added: z3lab/cpsskins/branches/jmo-perspectives/registry/__init__.py
==============================================================================
--- (empty file)
+++ z3lab/cpsskins/branches/jmo-perspectives/registry/__init__.py       Fri Nov 
 4 16:12:15 2005
@@ -0,0 +1,19 @@
+##############################################################################
+#
+# Copyright (c) 2005 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"
+

Added: z3lab/cpsskins/branches/jmo-perspectives/registry/configure.zcml
==============================================================================
--- (empty file)
+++ z3lab/cpsskins/branches/jmo-perspectives/registry/configure.zcml    Fri Nov 
 4 16:12:15 2005
@@ -0,0 +1,48 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope";
+    xmlns:browser="http://namespaces.zope.org/browser";>
+
+    <localUtility class=".storage.Storage">
+
+      <require
+          permission="zope.ManageServices"
+          interface=".storage.IStorage"
+          />
+
+    </localUtility>
+
+    <content class=".storage.SomeItem">
+
+      <implements 
+           interface="zope.app.annotation.IAttributeAnnotatable" />
+
+      <require permission="zope.View"
+           interface=".storage.ISomeItem" />
+
+      <require permission="zope.ManageContent"
+           set_schema=".storage.ISomeItem" />
+
+    </content>
+
+    <browser:addMenuItem
+        title="Some item"
+        description="Some item"
+        class=".storage.SomeItem"
+        permission="zope.ManageContent"
+    />
+
+    <browser:addMenuItem
+        title="Storage-like registry"
+        description="Registry"
+        class=".storage.Storage"
+        permission="zope.ManageServices"
+    />
+
+    <browser:containerViews
+        for=".storage.IStorage"
+        contents="zope.ManageContent"
+        index="zope.View"
+        add="zope.ManageContent"
+    />
+
+</configure>

Added: z3lab/cpsskins/branches/jmo-perspectives/registry/interfaces.py
==============================================================================
--- (empty file)
+++ z3lab/cpsskins/branches/jmo-perspectives/registry/interfaces.py     Fri Nov 
 4 16:12:15 2005
@@ -0,0 +1,24 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.container.interfaces import IContainer
+
+class IStorage(IContainer):
+    """A storage-like registry."""

Added: z3lab/cpsskins/branches/jmo-perspectives/registry/storage.py
==============================================================================
--- (empty file)
+++ z3lab/cpsskins/branches/jmo-perspectives/registry/storage.py        Fri Nov 
 4 16:12:15 2005
@@ -0,0 +1,83 @@
+##############################################################################
+#
+# Copyright (c) 2005 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.component import provideUtility, queryUtility, getUtilitiesFor
+from zope.app.component import queryNextUtility
+from persistent import Persistent
+from zope.interface import implements, Interface
+from zope.app.container.contained import Contained
+
+from interfaces import IStorage
+
+class ISomeItem(Interface):
+    """Some storage item"""
+
+class SomeItem(Persistent, Contained):
+    implements(ISomeItem)
+    def __init__(self): 
+        pass
+
+class Storage(Persistent, Contained):
+
+    implements(IStorage)
+
+    def __setitem__(self, name, object):
+        if not isinstance(name, basestring):
+            raise TypeError("The key must be an ascii or a unicode string.")
+
+        if not name:
+            raise ValueError("The key must not be empty.")
+
+        if not ISomeItem.providedBy(object):
+            raise TypeError(
+                "The object %s cannot be added to this storage" % object)
+
+        provideUtility(component=object, provides=ISomeItem, name=name) 
+
+        object.__parent__ = self
+        object.__name__ = name
+
+    def __getitem__(self, name):
+        object = queryUtility(ISomeItem, name) 
+        if object is None:
+            raise KeyError("No such item %s." % name)
+        return object
+
+    def __delitem__(self, name):
+        object = self[name]
+
+    def __len__(self):
+        return len(self.keys())
+
+    def keys(self):
+        return list(getUtilitiesFor(ISomeItem))
+
+    def __iter__(self):
+        return iter([v for k, v in self.items()])
+
+    def get(self, name, default=None):
+        return queryUtility(ISomeItem, name, default=default) 
+
+    def items(self):
+        return list(getUtilitiesFor(ISomeItem))
+
+    def ___contains__(self, name):
+        return name in self.keys()
+
-- 
http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins

Reply via email to