[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/OFS/Services/ServiceManager - ConfigurationManager.py:1.1.2.1 IConfigurationManager.py:1.1.2.1 IServiceConfiguration.py:1.1.2.1 ServiceConfiguration.py:1.1.2.1 IBindingAware.py:1.3.6.1 IServiceManager.py:1.4.6.3 Package.py:1.1.6.1 Packages.py:1.4.6.1 ServiceManager.py:1.8.6.7 configure.zcml:1.6.6.4 Configuration.py:NONE IConfiguration.py:NONE IServiceDirective.py:NONE ServiceDirective.py:NONE

Jim Fulton jim@zope.com
Sat, 30 Nov 2002 07:44:59 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Services/ServiceManager
In directory cvs.zope.org:/tmp/cvs-serv30047/lib/python/Zope/App/OFS/Services/ServiceManager

Modified Files:
      Tag: Zope3-Bangalore-TTW-Branch
	IBindingAware.py IServiceManager.py Package.py Packages.py 
	ServiceManager.py configure.zcml 
Added Files:
      Tag: Zope3-Bangalore-TTW-Branch
	ConfigurationManager.py IConfigurationManager.py 
	IServiceConfiguration.py ServiceConfiguration.py 
Removed Files:
      Tag: Zope3-Bangalore-TTW-Branch
	Configuration.py IConfiguration.py IServiceDirective.py 
	ServiceDirective.py 
Log Message:
Refactored the way TTW component registration is done.  There are now
separate registry objects that abstract the machinery for registering
multiple conflicting configurations and deciding which, if any are
active.  Also provided a new field and widget for the status
information.

Along the way, cleaned up and streamlined placeful testing
infrastructure a bit.

Now checking into branch. Will give file-by-file (or at least more
specific logs) when the changes are merged into the head.


=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/ConfigurationManager.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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: ConfigurationManager.py,v 1.1.2.1 2002/11/30 12:44:27 jim Exp $
"""

__metaclass__ = type

from Persistence import Persistent
from IConfigurationManager import IConfigurationManager

class ConfigurationManager(Persistent):
    """Configuration manager

    Manages configurations within a package.
    """
    
    __implements__ = IConfigurationManager

    def __init__(self):
        self._data = ()
        self._next = 0

    def __getitem__(self, key):
        "See Zope.App.OFS.Container.IContainer.IItemContainer"
        v = self.get(key)
        if v is None:
            raise KeyError, key
        return v

    def get(self, key, default=None):
        "See Interface.Common.Mapping.IReadMapping"
        for k, v in self._data:
            if k == key:
                return v
        return default

    def __contains__(self, key):
        "See Interface.Common.Mapping.IReadMapping"
        return self.get(key) is not None
    

    def keys(self):
        "See Interface.Common.Mapping.IEnumerableMapping"
        return [k for k, v in self._data]

    def values(self):
        "See Interface.Common.Mapping.IEnumerableMapping"
        return [v for k, v in self._data]
    
    def items(self):
        "See Interface.Common.Mapping.IEnumerableMapping"
        return self._data

    def __len__(self):
        "See Interface.Common.Mapping.IEnumerableMapping"
        return len(self._data)

    def setObject(self, key, object):
        "See Zope.App.OFS.Container.IContainer.IWriteContainer"
        self._next += 1
        key = str(self._next)
        self._data += ((key, object), )
        return key
        
    def __delitem__(self, key):
        "See Zope.App.OFS.Container.IContainer.IWriteContainer"
        if key not in self:
            raise KeyError, key
        self._data = tuple(
            [item
             for item in self._data
             if item[0] != key]
            )

    def moveTop(self, names):
        self._data = tuple(
            [item for item in self._data if (item[0] in names)]
            +
            [item for item in self._data if (item[0] not in names)]
            )

    def moveBottom(self, names):
        self._data = tuple(
            [item for item in self._data if (item[0] not in names)]
            +
            [item for item in self._data if (item[0] in names)]
            )

    def _moveUpOrDown(self, names, direction):
        # Move each named item by one position. Note that this
        # might require moving some unnamed objects by more than
        # one position.

        indexes = {}

        # Copy named items to positions one less than they currently have
        i = -1
        for item in self._data:
            i += 1
            if item[0] in names:
                j = max(i + direction, 0)
                while j in indexes:
                    j += 1
                
                indexes[j] = item

        # Fill in the rest where there's room.
        i = 0
        for item in self._data:
            if item[0] not in names:
                while i in indexes:
                    i += 1
                indexes[i] = item

        items = indexes.items()
        items.sort()

        self._data = tuple([item[1] for item in items])

    def moveUp(self, names):
        self._moveUpOrDown(names, -1)

    def moveDown(self, names):
        self._moveUpOrDown(names, 1)
        


__doc__ = ConfigurationManager.__doc__  + __doc__


=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IConfigurationManager.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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: IConfigurationManager.py,v 1.1.2.1 2002/11/30 12:44:27 jim Exp $
"""

from Zope.App.OFS.Container.IContainer  import IContainerNamesContainer

class IConfigurationManager(IContainerNamesContainer):
    """Manage Configuration Directives
    """

    def moveTop(names):
        """Move the objects corresponding to the given names to the top
        """

    def moveUp(names):
        """Move the objects corresponding to the given names up
        """

    def moveBottom(names):
        """Move the objects corresponding to the given names to the bottom
        """

    def moveDown(names):
        """Move the objects corresponding to the given names down
        """

__doc__ = IConfigurationManager.__doc__ + __doc__



=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IServiceConfiguration.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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: IServiceConfiguration.py,v 1.1.2.1 2002/11/30 12:44:27 jim Exp $
"""

from Interface.Attribute import Attribute
from Zope.App.OFS.Services.ConfigurationInterfaces import IConfiguration

class IServiceConfiguration(IConfiguration):
    """Service Configuration

    Service configurations are dependent on the components that they
    configure. They register themselves as component dependents.
    
    """

    serviceType = Attribute("The service type id")

    componentPath = Attribute("The physical path to the component")

    def getService(service_manager):
        """Return the service component named in the directive.
        """

__doc__ = IServiceConfiguration.__doc__ + __doc__



=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/ServiceConfiguration.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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: ServiceConfiguration.py,v 1.1.2.1 2002/11/30 12:44:27 jim Exp $
"""

__metaclass__ = type

from Persistence import Persistent
from Zope.Security.Checker import CheckerPublic, InterfaceChecker
from Zope.Security.Proxy import Proxy
from Zope.App.DependencyFramework.Exceptions import DependencyError
from Zope.App.Traversing import traverse
from IServiceConfiguration import IServiceConfiguration
from Zope.Proxy.ProxyIntrospection import removeAllProxies
from Zope.App.Traversing import getPhysicalRoot
from Zope.ComponentArchitecture import getService, getServiceManager
from Zope.App.Traversing import getPhysicalPathString
from ServiceManager import ServiceManager
from Zope.App.OFS.Container.IAddNotifiable import IAddNotifiable
from Zope.App.OFS.Container.IDeleteNotifiable import IDeleteNotifiable
from Zope.App.DependencyFramework.IDependable import IDependable
from Zope.ComponentArchitecture import getServiceManager, getAdapter
from Zope.ContextWrapper import ContextMethod
from Zope.App.OFS.Services.Configuration import ConfigurationStatusProperty
from Zope.ContextWrapper import ContextProperty
from IBindingAware import IBindingAware
from Zope.App.OFS.Services.ConfigurationInterfaces import Active
from Zope.App.OFS.Services.ConfigurationInterfaces import Registered
from Zope.App.OFS.Services.ConfigurationInterfaces import Unregistered

class ServiceConfiguration(Persistent):
    __doc__ = IServiceConfiguration.__doc__
    
    __implements__ = IServiceConfiguration, IAddNotifiable, IDeleteNotifiable

    status = ConfigurationStatusProperty('Services')

    def __init__(self, service_type, component_path, permission=None):
        self.serviceType = service_type
        self.componentPath = component_path
        if permission == 'Zope.Public':
            permission = CheckerPublic
            
        self.permission = permission

    def __repr__(self):
        return "service(%s, %s)" % (self.serviceType, self.componentPath)

    ############################################################
    # Implementation methods for interface
    # Zope.App.OFS.Services.ServiceManager.IServiceConfiguration.

    def getService(self):
        service_manager = getServiceManager(self)
        
        service = getattr(self, '_v_service', None)
        if service is None:
            
            # We have to be clever here. We need to do an honest to
            # god unrestricted traveral, which means we have to
            # traverse from an unproxies object. But, it's not enough
            # for the service manager to be unproxies, because the
            # path is an absolute path. When absolute paths are
            # traversed, the traverser finds the physical root and
            # traverses from there, so we need to make sure the
            # physical root isn;t proxied.

            # get the root and unproxy it.
            root = removeAllProxies(getPhysicalRoot(service_manager))            
            service = traverse(root, self.componentPath)

            if self.permission:
                if type(service) is Proxy:
                    # XXX what is this?
                    service = removeSecurityProxy(service)

                interface = service_manager.getInterfaceFor(self.serviceType)

                checker = InterfaceChecker(interface, self.permission)

                service = Proxy(service, checker)

            
            self._v_service = service


        return service

    getService.__doc__ = IServiceConfiguration['getService'].__doc__

    getService = ContextMethod(getService)

    ############################################################

    def activated(self):
        service = self.getService()
        if IBindingAware.isImplementedBy(service):
            service.bound(self.serviceType)

    activated = ContextMethod(activated)

    def deactivated(self):
        service = self.getService()
        if IBindingAware.isImplementedBy(service):
            service.unbound(self.serviceType)

    deactivated = ContextMethod(deactivated)

    def manage_afterAdd(self, configuration, container):
        "See Zope.App.OFS.Container.IAddNotifiable"
        sm = getServiceManager(configuration)
        service = configuration.getService()
        dependents = getAdapter(service, IDependable)
        objectpath = getPhysicalPathString(configuration)
        dependents.addDependent(objectpath)
        
    def manage_beforeDelete(self, configuration, container):
        "See Zope.App.OFS.Container.IDeleteNotifiable"
        assert self == configuration
        service_type = self.serviceType
        sm = getServiceManager(self)
        service = self.getService()
        objectstatus = self.status
        dependents = getAdapter(service, IDependable)
        objectpath = getPhysicalPathString(self)
        
        if objectstatus == Active:
            raise DependencyError("Can't delete active configurations")
        elif objectstatus == Registered:
            self.status = Unregistered

        dependents.removeDependent(objectpath)

    manage_beforeDelete = ContextMethod(manage_beforeDelete)
    
__doc__ = ServiceConfiguration.__doc__  + __doc__

            


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IBindingAware.py 1.3 => 1.3.6.1 ===
--- Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IBindingAware.py:1.3	Thu Jul 11 14:21:32 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IBindingAware.py	Sat Nov 30 07:44:27 2002
@@ -22,7 +22,7 @@
 class IBindingAware(Interface):
     
     def bound(name):
-        """
+        """Inform a service components that it's providing a service
 
         Called when an immediately-containing service manager binds
         this object to perform the named service.
@@ -30,7 +30,7 @@
         """
     
     def unbound(name):
-        """
+        """Inform a service components that it's no longer providing a service
 
         Called when an immediately-containing service manager unbinds
         this object from performing the named service.


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IServiceManager.py 1.4.6.2 => 1.4.6.3 ===
--- Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IServiceManager.py:1.4.6.2	Mon Oct 21 12:05:46 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IServiceManager.py	Sat Nov 30 07:44:27 2002
@@ -16,12 +16,11 @@
 $Id$
 """
 from Zope.ComponentArchitecture.IServiceService import IServiceService
-
+from Zope.App.OFS.Services.ConfigurationInterfaces import IConfigurable
 from IComponentManager import IComponentManager
-
 from Interface.Attribute import Attribute
 
-class IServiceManager(IServiceService, IComponentManager):
+class IServiceManager(IServiceService, IComponentManager, IConfigurable):
     """Service Managers act as containers for Services.
     
     If a Service Manager is asked for a service, it checks for those it
@@ -33,39 +32,12 @@
 
     Packages = Attribute("""Package container""")
     
-
-    def bindService(service_directive):
-        """Provide a service implementation.
-
-        If the named object implements IBindingAware, the wrapped object is
-        notified as per that interface.
-        """
-
-    def addService(service_directive):
-        """Add a registered service, but displace another active component
-
-        Register a service component, but don't make it active of
-        there is already a registered component providing the service.
-
+    def queryConfigurations(service_type):
+        """Return an IConfigurationRegistry for a service type
         """
 
-    def unbindService(service_directive):
-        """No longer provide a service implementation.
-
-        If the named object implements IBindingAware, the wrapped object is
-        notified as per that interface.
-        """
-
-    def disableService(service_type):
-        """Make the service type inactive in this service manager.
-
-        This doesn't unbind any services, but makes them all inactive.
-        """
-
-    def enableService(service_type, index):
-        """Make the service type inactive in this service manager.
-
-        This doesn't unbind any services, but makes them all inactive.
+    def createConfigurationsFor(configuration):
+        """Create and return an IConfigurationRegistry a service type
         """
 
     def getBoundService(name):
@@ -77,14 +49,6 @@
         None is returned if the named service isn't bound locally.
         """
 
-    def getDirectives(service_type):
-        """Get the directives registered for a service
-        """
-
     def getBoundServiceTypes():
         """Get a sequence of the bound service types"""
 
-
-    def getRegistrationState(service_directive, service_type):
-        """Get Registration status of the service directive
-        """


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/Package.py 1.1 => 1.1.6.1 ===
--- Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/Package.py:1.1	Thu Jul 11 14:21:32 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/Package.py	Sat Nov 30 07:44:27 2002
@@ -22,10 +22,14 @@
 from Zope.App.OFS.Container.BTreeContainer import BTreeContainer
 
 from IPackage import IPackage
+from ConfigurationManager import ConfigurationManager
 
 
 class Package(BTreeContainer):
     __implements__ = IPackage
 
-    
+    def __init__(self):
+        super(Package, self).__init__()
+        self.setObject('configure', ConfigurationManager())
+
     


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/Packages.py 1.4 => 1.4.6.1 ===
--- Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/Packages.py:1.4	Thu Sep  5 16:48:13 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/Packages.py	Sat Nov 30 07:44:27 2002
@@ -32,9 +32,14 @@
 
 from IPackages import IPackages
 from IPackage import IPackage
+from Package import Package
 
 class Packages(BTreeContainer):
     __implements__ = IPackages
+
+    def __init__(self):
+        super(Packages, self).__init__()
+        self.setObject('default', Package())
 
     def queryComponent(self, type=None, filter=None, all=0):
 


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/ServiceManager.py 1.8.6.6 => 1.8.6.7 ===
--- Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/ServiceManager.py:1.8.6.6	Thu Nov 14 09:15:39 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/ServiceManager.py	Sat Nov 30 07:44:27 2002
@@ -42,11 +42,11 @@
 from Zope.App.OFS.Container.BTreeContainer import BTreeContainer
 from Zope.Proxy.ProxyIntrospection import removeAllProxies
 
-from IBindingAware import IBindingAware
 from Packages import Packages
-from Package import Package
 from IServiceManager import IServiceManager
 
+from Zope.App.OFS.Services.Configuration import ConfigurationRegistry
+
 from Persistence.Module import PersistentModuleRegistry
 from Persistence.Module import PersistentModuleRegistry, PersistentModule
 from INameResolver import INameResolver
@@ -64,15 +64,13 @@
 
     def __init__(self):
         super(ServiceManager, self).__init__()
+
         self.__bindings = {}
         # Bindings is of the form:
         #
-        # {service_type -> [directives]}
-        #
-        # Where the first directive is always the active directive.
+        # {service_type -> ConfigurationRegistry}
 
         self.Packages = Packages()
-        self.Packages.setObject('default', Package())
 
 
     def getServiceDefinitions(self):
@@ -107,17 +105,17 @@
         # getting out getService to be called while looking up
         # services, so we'll
 
+        if name == 'Services':
+            return self # We are the service service
+
         if not getattr(self, '_v_calling', 0):
             
             self._v_calling = 1
             try:
-                service = self.__bindings.get(name)
-
+                service = self.getBoundService(name)
                 if service:
-                    service = service[0] # Get the active service directive
-                    if service is not None: # not disabled
-                        service = service.getService(self) # get the service
-                        return service
+                    return service
+                    
             finally:
                 self._v_calling = 0
 
@@ -126,17 +124,6 @@
     getService = ContextMethod(getService)
 
 
-    def getBoundService(self, name):
-        "See Zope.App.OFS.Services.ServiceManager.IServiceManager."
-
-        service = self.__bindings.get(name)
-        if service:
-            service = service[0] # Get the active service directive
-            service = service.getService(self) # get the service
-            return service
-
-        return None
-
     def getInterfaceFor(self, service_type):
         "See Zope.ComponentArchitecture.IServiceService.IServiceService"
         for type, interface in self.getServiceDefinitions():
@@ -147,160 +134,50 @@
 
     getInterfaceFor = ContextMethod(getInterfaceFor)
 
-    def disableService(self, service_type):
-        "See Zope.App.OFS.Services.ServiceManager.IServiceManager."
-        directives = self.__bindings.get(service_type)
-        if directives and directives[0] is not None:
-            service = directives[0].getService(self)
-            aware_service = queryAdapter(service, IBindingAware)
-            if aware_service is not None:
-                aware_service.unbound(service_type)
-            directives.insert(0, None)
-            self._p_changed = 1
-    
-    disableService = ContextMethod(disableService)
-
-    def enableService(self, service_type, index):
-        "See Zope.App.OFS.Services.ServiceManager.IServiceManager."
-        self._disableFirstBeforeEnable(service_type)
-
-        directives = self.__bindings.get(service_type)
-        directive = directives[index]
-        del directives[index]
-        directives.insert(0, directive)
-
-        self._p_changed = 1
-
-        service = directive.getService(self)
-        aware_service = queryAdapter(service, IBindingAware)
-        if aware_service is not None:
-            aware_service.bound(service_type)
-    
-    enableService = ContextMethod(enableService)
-
-
-    def _disableFirstBeforeEnable(self, service_type):
-        # Disable the first (active) service or remove the
-        # disabled marker prior to enabling a service.
-        directives = self.__bindings.get(service_type)
-
-        if directives:
-            if directives[0] is None:
-                # remove deactivation marker
-                del directives[0]
-            else:
-                
-                old_service = queryAdapter(
-                    directives[0].getService(self), IBindingAware)
-                if old_service is not None:
-                    # unbind old service, if necessary
-                    old_service.unbound(service_type)
-    
-    _disableFirstBeforeEnable = ContextMethod(
-        _disableFirstBeforeEnable)
-
-    def bindService(self, directive):
-        "See "
-        "Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
-
-        service = directive.getService(self)
-        service_type = directive.service_type
-
-        interface = self.getInterfaceFor(service_type)
-        
-        if not interface.isImplementedBy(service):
-            raise InvalidService(service_type, directive, interface)
+    def queryConfigurationsFor(self, configuration, default=None):
+        return self.queryConfigurations(configuration.serviceType, default)
 
-        self._disableFirstBeforeEnable(service_type)
+    queryConfigurationsFor = ContextMethod(queryConfigurationsFor)
 
-        bindings = self.__bindings
-        if service_type not in bindings:
-            bindings[service_type] = [directive]
-        else:
-            directives = bindings[service_type]
-            directives.insert(0, directive)
+    def queryConfigurations(self, service_type, default=None):
+        registry = self.__bindings.get(service_type, default)
+        return ContextWrapper(registry, self)
 
-        self._p_changed = 1
+    queryConfigurations = ContextMethod(queryConfigurations)
         
-        aware_service = queryAdapter(service, IBindingAware)
-        if aware_service is not None:
-            aware_service.bound(service_type)
-
-    bindService = ContextMethod(bindService)
 
-    def addService(self, directive):
-        "See "
-        "Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
-        service = directive.getService(self)
-        service_type = directive.service_type
-        interface = self.getInterfaceFor(service_type)
-        
-        if not interface.isImplementedBy(service):
-            raise InvalidService(service_type, directive, interface)
+    def createConfigurationsFor(self, configuration):
+        return self.createConfigurations(configuration.serviceType)
 
-        bindings = self.__bindings
-        
-        if service_type not in bindings:
-            bindings[service_type] = []
-        bindings[service_type].append(directive)
+    createConfigurationsFor = ContextMethod(createConfigurationsFor)
 
+    def createConfigurations(self, service_type):
+        registry = ConfigurationRegistry()
+        self.__bindings[service_type] = registry
         self._p_changed = 1
+        return registry
 
-        if len(bindings) == 1:
-            aware_service = queryAdapter(service, IBindingAware)
-            if aware_service is not None:
-                aware_service.bound(service_type)
-
-    addService = ContextMethod(addService)
-    
-    def unbindService(self, directive):
-        "See "
-        "Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
-
-        service = directive.getService(self) # must be before unwrapping self
-        self = removeAllProxies(self)  
-        service_type = directive.service_type
-
-        directives = self.__bindings[service_type]
-        if directive not in directives:
-            raise KeyError(directive)
-        
-        aware_service = queryAdapter(service, IBindingAware)
-        if aware_service is not None:
-            aware_service.unbound(service_type)
-
-        self.__bindings[service_type] = [d for d in directives
-                                         if d != directive]
+    createConfigurations = ContextMethod(createConfigurations)
 
-        self._p_changed = 1
+    def getBoundService(self, name):
+        "See Zope.App.OFS.Services.ServiceManager.IServiceManager."
 
-    unbindService = ContextMethod(unbindService)
+        registry = self.queryConfigurations(name)
+        if registry:
+            configuration = registry.active()
+            if configuration is not None:
+                service = configuration.getService()
+                return service
+            
+        return None
 
-    def getDirectives(self, service_type):
-        "See "
-        "Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
-        return self.__bindings[service_type]
+    getBoundService = ContextMethod(getBoundService)
 
     def getBoundServiceTypes(self):
         "See "
         "Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
         
         return  self.__bindings.keys()
-
-    def getRegistrationState(self, directive, service_type):
-        "See Zope.ComponentArchitecture.IServiceService.IServiceService"
-        
-        directives = self.__bindings[service_type]
-        if directives:
-            if directives[0] == directive:
-                return 'Active'
-            elif directive in directives:
-                return 'Registered'
-            else:
-                return 'UnRegistered'
-        else:
-            return 'UnRegistered'
-        
 
     ############################################################
     # Implementation methods for interface


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/configure.zcml 1.6.6.3 => 1.6.6.4 ===
--- Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/configure.zcml:1.6.6.3	Mon Nov 18 17:34:39 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/configure.zcml	Sat Nov 30 07:44:27 2002
@@ -36,7 +36,7 @@
 
   </content>
 
-   <content class=".Configuration.">
+   <content class=".ConfigurationManager.">
     <require
         permission="Zope.View"
         interface="Zope.App.OFS.Container.IContainer.IReadContainer" />
@@ -46,10 +46,10 @@
     <require
         permission="Zope.ManageServices"
     	attributes="arrange_object remove_objects" />
-
-    <factory id = "Zope.App.OFS.Services.Configuration" 
+    <factory 
+        id = "Zope.App.OFS.Services.ServiceManager.ConfigurationManager" 
 	permission = "Zope.ManageServices"
-	title = "Configuration" />
+	title = "Configuration Manager" />
   </content>
 
   <content class=".Module.Manager.">
@@ -60,22 +60,25 @@
    </content>
 
 
-  <content class=".ServiceDirective.">
-    <require
-        permission="Zope.ManageServices"
-        interface=".IServiceDirective." />
+  <content class=".ServiceConfiguration.">
     <require
         permission="Zope.ManageServices"
-        interface="Zope.App.OFS.Container.IAddNotifiable." />
+        interface=".IServiceConfiguration."
+        set_attributes="serviceType componentPath"
+        set_schema=
+            "Zope.App.OFS.Services.ConfigurationInterfaces.IConfiguration"
+        />
     <require
         permission="Zope.ManageServices"
-        interface="Zope.App.OFS.Container.IDeleteNotifiable." />
+        interface="Zope.App.OFS.Container.IAddNotifiable."
+        />
     <require
         permission="Zope.ManageServices"
-        set_attributes="service_type component_path" />
+        interface="Zope.App.OFS.Container.IDeleteNotifiable."
+        />
 
   </content>
   
-  <include package="Zope.App.OFS.Services.ServiceManager.Views" />
+  <include package="Zope.App.OFS.Services.ServiceManager.Browser" />
 
 </zopeConfigure>

=== Removed File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/Configuration.py ===

=== Removed File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IConfiguration.py ===

=== Removed File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IServiceDirective.py ===

=== Removed File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/ServiceDirective.py ===