From e6e73ab46dbcfbf4c8da3ec42f761a48d496b66c Mon Sep 17 00:00:00 2001 From: helmutm Date: Tue, 31 Jul 2007 09:15:48 +0000 Subject: [PATCH] work in progress: service managment with composer.schema for tumsm git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1851 fd906abe-77d9-0310-91a1-e0d9ade77398 --- composer/schema/browser/base.py | 49 +++++++++++++++++++++++++++- composer/schema/client.py | 5 +-- composer/schema/instance.py | 49 ++++++++++++++++++++-------- composer/schema/interfaces.py | 57 +++++++++++++++++++-------------- composer/schema/schema.py | 6 +++- organize/interfaces.py | 40 ++++++++--------------- organize/service.py | 3 ++ 7 files changed, 142 insertions(+), 67 deletions(-) diff --git a/composer/schema/browser/base.py b/composer/schema/browser/base.py index 442a152..ad4c95e 100644 --- a/composer/schema/browser/base.py +++ b/composer/schema/browser/base.py @@ -22,13 +22,60 @@ Basic browser view classes for composer.schema. $Id$ """ +from zope import component from zope.cachedescriptors.property import Lazy +from zope.traversing.browser import absoluteURL -from cybertools.composer.instance import Instance +from cybertools.composer.interfaces import IInstance +from cybertools.composer.schema.interfaces import IClientFactory class SchemaView(object): + def __init__(self, context, request): + self.context = context + self.request = request + self.clientName = None + @Lazy def fields(self): return self.context.fields + + @Lazy + def data(self): + form = self.request.form + clientName = self.clientName = form.get('id') + if not clientName: + return {} + manager = self.context.manager + client = manager.clients.get(clientName) + if client is None: + return {} + instance = IInstance(client) + instance.template = self.context + return instance.applyTemplate() + + def update(self): + form = self.request.form + if not form.get('action'): + return True + manager = self.context.manager + clientName = form.get('id') + if clientName: + client = manager.clients.get(clientName) + if client is None: + # TODO: provide error message (?) + return True + else: + client = IClientFactory(manager)() + clientName = self.clientName = manager.addClient(client) + instance = component.getAdapter(client, IInstance, name='editor') + instance.template = self.context + instance.applyTemplate(form) + self.request.response.redirect(self.nextUrl) + return False + + @Lazy + def nextUrl(self): + url = absoluteURL(self.context, self.request) + return '%s/thank_you?id=%s' % (url, self.clientName) diff --git a/composer/schema/client.py b/composer/schema/client.py index b769fd9..57a8d2a 100644 --- a/composer/schema/client.py +++ b/composer/schema/client.py @@ -22,6 +22,7 @@ Client implementations. $Id$ """ +from persistent import Persistent from zope.component import adapts from zope.interface import implements @@ -29,11 +30,11 @@ from cybertools.composer.schema.interfaces import IClient from cybertools.composer.schema.interfaces import IClientManager, IClientFactory -class Client(object): +class Client(Persistent): implements(IClient) - def __init__(self, manager): + def __init__(self, manager=None): self.manager = manager diff --git a/composer/schema/instance.py b/composer/schema/instance.py index 5d25db0..ba034b2 100644 --- a/composer/schema/instance.py +++ b/composer/schema/instance.py @@ -44,33 +44,56 @@ class Editor(Instance): print c.name, getattr(self.context, c.name, '-') -class ClientInstanceAdapter(object): +class ClientInstance(object): implements(IInstance) adapts(IClient) + attrsName = '__schema_attributes__' + + template = None baseAspect = 'schema.client.' - schema = 'default' @property def aspect(self): - return self.baseAspect + self.schema - - @property - def template(self): - return self.context.manager.clientSchemas.get(self.schema, None) + return self.baseAspect + self.template.name def __init__(self, context): self.context = context - def applyTemplate(self, data={}, schema='default', **kw): - if getattr(self.context, 'attributes', None) is None: - self.context.attributes = OOBTree() - self.schema = schema + def applyTemplate(self, **kw): + """ Return a mapping of field names from self.template (a schema) + to the corresponding values from the context object. + """ + result = {} + attrs = getattr(self.context, self.attrsName, None) + if attrs is None: + return result template = self.template - attributes = self.context.attributes.setdefault(self.aspect, OOBTree()) + values = attrs.setdefault(self.aspect, {}) if template is not None: for c in template.components: name = c.name - attributes[name] = data.get(name, u'') + result[name] = values.get(name, u'') + result['__name__'] = self.context.__name__ + return result + + +class ClientInstanceEditor(ClientInstance): + + def applyTemplate(self, data={}, **kw): + """ Store the attributes described by self.template (a schema) + using corresponding values from the data argument. + """ + attrs = getattr(self.context, self.attrsName, None) + if attrs is None: + attrs = OOBTree() + setattr(self.context, self.attrsName, attrs) + template = self.template + values = attrs.setdefault(self.aspect, OOBTree()) + if template is not None: + for c in template.components: + name = c.name + if name in data: + values[name] = data[name] diff --git a/composer/schema/interfaces.py b/composer/schema/interfaces.py index 467b0e3..a56b0c2 100644 --- a/composer/schema/interfaces.py +++ b/composer/schema/interfaces.py @@ -35,11 +35,14 @@ class ISchema(ITemplate): """ Represents an ordered sequence of fields. """ + name = Attribute('An internal name of the schema; will be used ' + 'to identify data fields of instance objects that ' + 'are associated with this schema.') fields = Attribute('The components the schema is built up of. ' 'Should be a sequence of IField objects.') - manager = Attribute('A manager object that may provide special ' - 'features, e.g. a factory of o') + 'features, e.g. a factory for objects to be associated ' + 'with this schema.') class IField(IComponent): @@ -47,31 +50,31 @@ class IField(IComponent): """ name = schema.ASCII( - title=_(u'Fieldname'), - description=_(u'The internal name of the field'), - required=True,) + title=_(u'Fieldname'), + description=_(u'The internal name of the field'), + required=True,) title = schema.TextLine( - title=_(u'Title'), - description=_(u'The title or label of the field'), - required=True,) + title=_(u'Title'), + description=_(u'The title or label of the field'), + required=True,) description = schema.Text( - title=_(u'Description'), - description=_(u'A more lengthy description of the field'), - required=False,) + title=_(u'Description'), + description=_(u'A more lengthy description of the field'), + required=False,) fieldType = schema.Choice( - title=_(u'Field type'), - description=_(u'The type of the field'), - required=True, - default='textline', - values=('textline', 'textarea', 'date')) + title=_(u'Field type'), + description=_(u'The type of the field'), + required=True, + default='textline', + values=('textline', 'textarea', 'date')) defaultValue = schema.TextLine( - title=_(u'Default'), - description=_(u'Value with which to pre-set the field contents'), - required=False,) + title=_(u'Default'), + description=_(u'Value with which to pre-set the field contents'), + required=False,) required = schema.Bool( - title=_(u'Required'), - description=_(u'Must a value been entered into this field?'), - required=False,) + title=_(u'Required'), + description=_(u'Must a value been entered into this field?'), + required=False,) # clients @@ -97,8 +100,14 @@ class IClientManager(Interface): """ Cares for a client typically providing schemas. """ + clients = Attribute('A collection of client objects (e.g. persons) ' + 'associated with this client manager.') clientSchemas = Attribute('A collection of schema objects ' - 'that describe the data fields of the client ' - 'objects.') + 'that describe the data fields of the client ' + 'objects.') + + def addClient(client): + """ Add the client object given to the collection of clients. + """ diff --git a/composer/schema/schema.py b/composer/schema/schema.py index fe8ac59..cd58c39 100644 --- a/composer/schema/schema.py +++ b/composer/schema/schema.py @@ -38,7 +38,7 @@ class Schema(Template): def __init__(self, *fields, **kw): self.name = kw.get('name', u'') - self.manager = kw.get('manager', None) + self.manager = self.__parent__ = kw.get('manager', None) super(Schema, self).__init__() for f in fields: self.components.append(f) @@ -46,3 +46,7 @@ class Schema(Template): @property def fields(self): return self.components + + @property + def __name__(self): + return self.name diff --git a/organize/interfaces.py b/organize/interfaces.py index 3c4105d..cb38df2 100644 --- a/organize/interfaces.py +++ b/organize/interfaces.py @@ -128,43 +128,32 @@ class IServiceManager(Interface): services = Attribute('A collection of services managed by this object.') - clients = Attribute('A collection of client objects (e.g. persons) ' - 'that have registered or want to register for ' - 'services managed by this service manager.') - - def addClient(client): - """ Add the client object given to the collection of clients. - """ - class IServiceGroup(Interface): """ A group of related services or a general service definition, e.g. a regular bus service or a series of trainings. """ + services = Attribute('A collection of services belonging to this object.') + class IService(Interface): """ A service that clients may register with. """ serviceGroup = Attribute('The service group this object is an instance of.') - capacity = schema.Int( - title=_(u'Capacity'), - description=_(u'The capacity (maximum number of clients) ' + title=_(u'Capacity'), + description=_(u'The capacity (maximum number of clients) ' 'of this service; a negative number means: ' 'no restriction, i.e. unlimited capacity.'), - required=False,) - + required=False,) availableCapacity = Attribute('Available capacity, i.e. number of seats ' - 'still available; a negative number means: ' - 'no restriction, i.e. unlimited capacity; ' - 'read-only') - + 'still available; a negative number means: ' + 'no restriction, i.e. unlimited capacity; ' + 'read-only') serviceProviders = Attribute('A collection of one or more service providers.') - resources = Attribute('A collection of one or more resources.') - registrations = Attribute('A collection of client registrations.') def register(client): @@ -180,14 +169,13 @@ class IScheduledService(IService): """ start = schema.Date( - title=_(u'Start date/time'), - description=_(u'The date/time when the service starts'), - required=False,) + title=_(u'Start date/time'), + description=_(u'The date/time when the service starts'), + required=False,) end = schema.Date( - title=_(u'End date/time'), - description=_(u'The date/time when the service ends'), - required=False,) - + title=_(u'End date/time'), + description=_(u'The date/time when the service ends'), + required=False,) duration = Attribute('Time delta between start and end date/time.') diff --git a/organize/service.py b/organize/service.py index 5d08a46..74faf9c 100644 --- a/organize/service.py +++ b/organize/service.py @@ -57,6 +57,9 @@ class ServiceManager(object): def addClient(self, client): name = self.generateClientName(client) self.clients[name] = client + client.__name__ = name + client.__parent__ = self + return name def generateClientName(self, client): self.clientNum += 1