diff --git a/common.py b/common.py
index 6584907..202a2e4 100644
--- a/common.py
+++ b/common.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
+# Copyright (c) 2008 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -88,6 +88,9 @@ class AdapterBase(object):
return False
return self.context == other.context
+ def getLoopsRoot(self):
+ return self.context.getLoopsRoot()
+
class ResourceAdapterBase(AdapterBase):
diff --git a/concept.py b/concept.py
index ce59774..6428da7 100644
--- a/concept.py
+++ b/concept.py
@@ -29,7 +29,7 @@ from zope.cachedescriptors.property import Lazy
from zope.component import adapts
from zope.interface import implements
from zope.interface import alsoProvides, directlyProvides, directlyProvidedBy
-from zope.security.proxy import removeSecurityProxy
+from zope.security.proxy import removeSecurityProxy, isinstance
from zope.traversing.api import getName, getParent
from persistent import Persistent
@@ -41,6 +41,7 @@ from cybertools.typology.interfaces import IType, ITypeManager
from cybertools.util.jeep import Jeep
from loops.base import ParentInfo
+from loops.common import AdapterBase
from loops.interfaces import IConcept, IConceptRelation, IConceptView
from loops.interfaces import IConceptManager, IConceptManagerContained
from loops.interfaces import ILoopsContained
@@ -286,6 +287,9 @@ class ConceptTypeSourceList(object):
def __init__(self, context):
self.context = context
+ if isinstance(context, AdapterBase):
+ self.context = self.context.context
+
def __iter__(self):
return iter(self.conceptTypes)
@@ -326,7 +330,7 @@ class PredicateSourceList(object):
return result
def __len__(self):
- return len(self.conceptTypes)
+ return len(self.predicates)
class IndexAttributes(object):
diff --git a/configure.zcml b/configure.zcml
index 07defea..cfd60dc 100644
--- a/configure.zcml
+++ b/configure.zcml
@@ -467,41 +467,28 @@
component="loops.resource.ResourceTypeSourceList"
name="loops.resourceTypeSource" />
+
+
-
-
-
-
-
-
+
+
-
diff --git a/constraint/README.txt b/constraint/README.txt
index 2300efd..726d8e8 100644
--- a/constraint/README.txt
+++ b/constraint/README.txt
@@ -4,3 +4,22 @@ loops - Linked Objects for Organization and Processing Services
($Id$)
+ >>> from zope import component
+ >>> from zope.traversing.api import getName
+
+Let's set up a loops site with basic and example concepts and resources.
+
+ >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
+ >>> site = placefulSetUp(True)
+
+ >>> from loops.tests.setup import TestSite
+ >>> t = TestSite(site)
+ >>> concepts, resources, views = t.setup()
+
+
+Constraints - Restrict Predicates and Types for Concept and Resource Assignments
+================================================================================
+
+ >>> from loops.constraint.base import StaticConstraint
+ >>> component.provideAdapter(StaticConstraint)
+
diff --git a/constraint/base.py b/constraint/base.py
index 38f3c88..b4568c9 100644
--- a/constraint/base.py
+++ b/constraint/base.py
@@ -23,3 +23,33 @@ for assignment as children or as concepts to resources.
$Id$
"""
+from zope.cachedescriptors.property import Lazy
+from zope.interface import implements
+from zope.traversing.api import getName
+
+from loops.common import AdapterBase
+from loops.constraint.interfaces import IStaticConstraint
+from loops.type import TypeInterfaceSourceList
+
+
+TypeInterfaceSourceList.typeInterfaces += (IStaticConstraint,)
+
+
+class StaticConstraint(AdapterBase):
+
+ _contextAttributes = AdapterBase._contextAttributes + ['relationType', 'cardinality']
+ _adapterAttributes = AdapterBase._adapterAttributes + ('predicates', 'types',)
+
+ implements(IStaticConstraint)
+
+ def getPredicates(self):
+ return getattr(self.context, '_predicates', [])
+ def setPredicates(self, value):
+ self.context._predicates = value
+ predicates = property(getPredicates, setPredicates)
+
+ def getTypes(self):
+ return getattr(self.context, '_types', [])
+ def setTypes(self, value):
+ self.context._types = value
+ types = property(getTypes, setTypes)
diff --git a/constraint/configure.zcml b/constraint/configure.zcml
new file mode 100644
index 0000000..6e46b30
--- /dev/null
+++ b/constraint/configure.zcml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/constraint/interfaces.py b/constraint/interfaces.py
index a9d0552..cf127da 100644
--- a/constraint/interfaces.py
+++ b/constraint/interfaces.py
@@ -29,6 +29,8 @@ $Id$
from zope.interface import Interface, Attribute
from zope import interface, component, schema
+from loops.concept import Concept
+from loops.interfaces import IConceptSchema
from loops.util import _
@@ -38,10 +40,10 @@ class IConstraint(Interface):
client object.
When the client object is a concept the constraint checks
- for child relations, if it is a resource it checks for concept
- relations. In order to check for allowed parent relations (on
- a concept only) you may specify ``relationType=parent``
- on the method calls.
+ parent relations, if it is a resource it checks concept
+ relations. In order to check for allowed child relations
+ on a concept only you may specify a relation type of ``child``
+ as an additional argument for the method calls.
"""
client = Attribute('Object that will be checked for allowed relations.')
@@ -68,7 +70,7 @@ class IConstraint(Interface):
"""
-class IStaticConstraint(IConstraint):
+class IStaticConstraint(IConceptSchema, IConstraint):
""" Provides a statically assigned contstraint setting.
Typically used as a concept adapter for a persistent constraint
@@ -76,11 +78,40 @@ class IStaticConstraint(IConstraint):
of allowed relationships.
"""
- relationType = schema.TextLine()
+ relationType = schema.Choice(
+ title=_(u'Relation type'),
+ description=_(u'Select the type of the relation for '
+ 'which this constraint should be checked, '
+ '"default" meaning parent relations for concepts '
+ 'and resource/concept relations for resources.'),
+ values=('default', 'child'),
+ default='default',
+ required=True,)
- predicates = schema.List()
+ predicates = schema.List(
+ title=_(u'Predicates'),
+ description=_(u'Select the predicates that this '
+ 'constraint should allow.'),
+ value_type=schema.Choice(
+ title=_(u'Predicate'),
+ source='loops.predicateSource'),
+ required=False,)
- types = schema.List()
+ types = schema.List(
+ title=_(u'Target types'),
+ description=_(u'Select the types of the objects '
+ 'that this constraints should allow.'),
+ value_type=schema.Choice(
+ title=_(u'Type'),
+ source='loops.conceptTypeSource'),
+ required=False,)
- cardinality = schema.List()
+ cardinality = schema.Choice(
+ title=_(u'Cardinality'),
+ description=_(u'Select an entry that represents the '
+ 'allowed number of assigned items as specified '
+ 'by this constraint.'),
+ values=('0,*', '0,1', '1,*', '1,1'),
+ default='0,*',
+ required=True,)
diff --git a/knowledge/interfaces.py b/knowledge/interfaces.py
index 1a76984..0c89a1b 100644
--- a/knowledge/interfaces.py
+++ b/knowledge/interfaces.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
+# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -24,7 +24,6 @@ $Id$
from zope.interface import Interface, Attribute
from zope import interface, component, schema
-from zope.app import zapi
from zope.i18nmessageid import MessageFactory
from zope.security.proxy import removeSecurityProxy
diff --git a/organize/interfaces.py b/organize/interfaces.py
index 1139739..84bf6e1 100644
--- a/organize/interfaces.py
+++ b/organize/interfaces.py
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
+# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by