diff --git a/browser/common.py b/browser/common.py
index 2ef9181..2ba109d 100644
--- a/browser/common.py
+++ b/browser/common.py
@@ -27,7 +27,9 @@ from zope.app.dublincore.interfaces import ICMFDublinCore
from zope.app.form.browser.interfaces import ITerms
from zope.app.intid.interfaces import IIntIds
from zope.cachedescriptors.property import Lazy
+from zope.dottedname.resolve import resolve
from zope.interface import implements
+from zope.schema.vocabulary import SimpleTerm
from zope.security.proxy import removeSecurityProxy
from cybertools.typology.interfaces import IType
@@ -116,3 +118,21 @@ class LoopsTerms(object):
return self.loopsRoot.loopsTraverse(token)
+class InterfaceTerms(object):
+ """ Provide the ITerms interface for source list of interfaces.
+ """
+
+ implements(ITerms)
+
+ def __init__(self, source, request):
+ self.source = source
+ self.request = request
+
+ def getTerm(self, value):
+ token = '.'.join((value.__module__, value.__name__))
+ return SimpleTerm(value, token, token)
+
+ def getValue(self, token):
+ return resolve(token)
+
+
diff --git a/browser/concept.py b/browser/concept.py
index 52d8d01..fb5af05 100644
--- a/browser/concept.py
+++ b/browser/concept.py
@@ -39,7 +39,7 @@ from zope.publisher.interfaces.browser import IBrowserRequest
from zope import schema
from zope.schema.interfaces import IIterableSource
from zope.security.proxy import removeSecurityProxy
-from cybertools.typology.interfaces import ITypeManager
+from cybertools.typology.interfaces import IType, ITypeManager
from loops.interfaces import IConcept
from loops.concept import Concept, ConceptTypeSourceList, PredicateSourceList
from loops.browser.common import BaseView, LoopsTerms
@@ -48,9 +48,25 @@ from loops import util
class ConceptEditForm(EditForm):
- form_fields = FormFields(IConcept)
template = NamedTemplate('pageform')
+ @Lazy
+ def typeInterface(self):
+ print IType(self.context)
+ print IType(self.context).typeInterface
+ return IType(self.context).typeInterface
+
+ @property
+ def form_fields(self):
+ fields = FormFields(IConcept)
+ typeInterface = self.typeInterface
+ if typeInterface is not None:
+ fields = FormFields(fields, typeInterface)
+ #typeAdapter = zapi.queryAdapter(self.context, typeInterface)
+ #if typeAdapter is not None:
+ #...
+ return fields
+
class ConceptView(BaseView):
diff --git a/browser/configure.zcml b/browser/configure.zcml
index aeb3bdc..728c436 100644
--- a/browser/configure.zcml
+++ b/browser/configure.zcml
@@ -478,6 +478,10 @@
for="loops.concept.PredicateSourceList
zope.publisher.interfaces.browser.IBrowserRequest" />
+
+
+
+
>> sorted(t.token for t in types)
['loops.resource.Document', 'loops.resource.MediaAsset']
-Type-based interfaces
----------------------
+Type-based interfaces and adapters
+----------------------------------
+
+ >>> from loops.interfaces import ITypeConcept
+ >>> from loops.type import TypeConcept
+ >>> ztapi.provideAdapter(IConcept, ITypeConcept, TypeConcept)
A type has an optional typeInterface attribute that objects of this type
will be adaptable to. The default for this is None:
+ >>> cc1_type.typeInterface
>>> cc1_type.typeInterface is None
True
For concept objects that provide types (type providers) the value of
the typeInterface attribute is the ITypeConcept interface:
- >>> from loops.interfaces import ITypeConcept
>>> topic_type.typeInterface is ITypeConcept
True
-We now want to have a topic (i.e. a concept that has topic_type as its type)
-to provide the interface ITopic. This is done by assigning this interface
-to topic_type.typeProvider, i.e. the 'topic' concept, via an adapter:
-
- >>> from loops.type import TypeConcept
- >>> ztapi.provideAdapter(IConcept, ITypeConcept, TypeConcept)
+We now want to have a topic (i.e. a concept that has topic as its
+conceptType and thus topic_type as its type) to be adaptable to ITopic.
+This is done by assigning this interface to topic_type.typeProvider,
+i.e. the 'topic' concept, via an adapter:
>>> class ITopic(Interface): pass
>>> from zope.interface import implements
diff --git a/interfaces.py b/interfaces.py
index bfcb5d6..d59ea62 100644
--- a/interfaces.py
+++ b/interfaces.py
@@ -473,9 +473,14 @@ class IIndexAttributes(Interface):
# types stuff
class ITypeConcept(Interface):
- """ This interface should be provided by concepts of type 'type'.
+ """ Concepts of type 'type' should be adaptable to this interface.
"""
- typeInterface = Attribute('The interface provided by objects of this type')
-
+ typeInterface = schema.Choice(
+ title=_(u'Type Interface'),
+ description=_(u'An interface that objects of this type can '
+ 'be adapted to'),
+ default=None,
+ source="loops.TypeInterfaceSource",
+ required=False)
diff --git a/type.py b/type.py
index 2673534..84e20ba 100644
--- a/type.py
+++ b/type.py
@@ -27,6 +27,8 @@ from zope.component import adapts
from zope.interface import implements
from zope.cachedescriptors.property import Lazy
from zope.dottedname.resolve import resolve
+from zope import schema
+from zope.security.proxy import removeSecurityProxy
from cybertools.typology.type import BaseType, TypeManager
from loops.interfaces import ILoopsObject, IConcept, IResource
from loops.interfaces import ITypeConcept
@@ -58,7 +60,7 @@ class LoopsType(BaseType):
class ConceptType(LoopsType):
- """ The type adapter for concept objects.
+ """ The IType adapter for concept objects.
"""
adapts(IConcept)
@@ -77,11 +79,11 @@ class ConceptType(LoopsType):
@Lazy
def typeInterface(self):
adapter = zapi.queryAdapter(self.typeProvider, ITypeConcept)
- if adapter is not None:
+ if adapter is not None: # always gives TypeConcept
return adapter.typeInterface
else:
- conceptType = self.context.conceptType
- if conceptType is conceptType.getConceptManager().getTypeConcept():
+ conceptType = self.typeProvider
+ if conceptType is conceptType.getLoopsRoot().getConceptManager().getTypeConcept():
return ITypeConcept
return None
@@ -177,17 +179,39 @@ class LoopsTypeManager(TypeManager):
class TypeConcept(object):
+ """ typeInterface adapter for concepts of type 'type'.
+ """
implements(ITypeConcept)
adapts(IConcept)
def __init__(self, context):
- self.context = context
+ self.context = removeSecurityProxy(context)
def getTypeInterface(self):
- return getattr(self.context, '_typeInterface', None)
+ ti = getattr(self.context, '_typeInterface', None)
+ if ti is None:
+ conceptType = self.context
+ if conceptType == conceptType.getLoopsRoot().getConceptManager().getTypeConcept():
+ return ITypeConcept
+ return ti
def setTypeInterface(self, ifc):
self.context._typeInterface = ifc
typeInterface = property(getTypeInterface, setTypeInterface)
+class TypeInterfaceSourceList(object):
+
+ implements(schema.interfaces.IIterableSource)
+
+ typeInterfaces = (ITypeConcept,)
+
+ def __init__(self, context):
+ self.context = context
+
+ def __iter__(self):
+ return iter(self.typeInterfaces)
+
+ def __len__(self):
+ return len(self.typeInterfaces)
+