use typology for type-related stuff on concepts and resources

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1124 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-03-13 14:15:26 +00:00
parent b39e7548b8
commit 072318ea06
13 changed files with 105 additions and 199 deletions

View file

@ -108,7 +108,14 @@ a special predicate 'hasType'.
>>> cc1.getConceptType().title
u'Topic'
We get a list of types using the ConceptTypeSourceList:
We get a list of types using the ConceptTypeSourceList.
In order for the type machinery to work we first have to provide a
type manager.
>>> from cybertools.typology.interfaces import ITypeManager
>>> from loops.interfaces import ILoopsObject
>>> from loops.type import LoopsTypeManager
>>> ztapi.provideAdapter(ILoopsObject, ITypeManager, LoopsTypeManager)
>>> from loops.concept import ConceptTypeSourceList
>>> types = ConceptTypeSourceList(cc1)
@ -167,10 +174,11 @@ underlying context object:
>>> sorted(c.title for c in cc1.getChildren())
[u'loops for Zope 3']
We can also create a new concept and assign it:
We can also create a new concept and assign it.
>>> params = {'action': 'create', 'create.name': 'cc4',
... 'create.title': u'New concept'}
... 'create.title': u'New concept',
... 'create.type': '.loops/concepts/topic'}
>>> view = ConceptConfigureView(cc1, TestRequest(**params))
>>> view.update()
True
@ -178,7 +186,7 @@ We can also create a new concept and assign it:
[u'New concept', u'loops for Zope 3']
The concept configuration view provides methods for displaying concept
types and predicates:
types and predicates.
>>> from zope.publisher.interfaces.browser import IBrowserRequest
>>> from loops.browser.common import LoopsTerms
@ -206,9 +214,6 @@ Index attributes adapter
>>> idx.title()
u'cc2 Zope 3'
>>> idx.type()
'loops:concept:unknown'
Resources and what they have to do with Concepts
================================================
@ -307,9 +312,6 @@ Index attributes adapter
>>> idx.title()
u'doc1 Zope Info'
>>> idx.type()
'loops:resource:Document'
Views/Nodes: Menus, Menu Items, Listings, Pages, etc
====================================================
@ -463,7 +465,8 @@ to the node's target: associate an existing one or create a new one.
... 'create.type': 'loops.resource.MediaAsset',}
>>> view = ConfigureView(m111, TestRequest(form = form))
>>> sorted((t.token, t.title) for t in view.targetTypes())
[('loops.concept.Concept', u'Concept'),
[('.loops/concepts/topic', u'Topic'), ('.loops/concepts/type', u'Type'),
('.loops/concepts/unknown', u'Unknown Type'),
('loops.resource.Document', u'Document'),
('loops.resource.MediaAsset', u'Media Asset')]
>>> view.update()

View file

@ -29,6 +29,7 @@ from zope.cachedescriptors.property import Lazy
from zope.interface import implements
from zope.security.proxy import removeSecurityProxy
from cybertools.typology.interfaces import IType
from loops import util
from loops.target import getTargetTypes
@ -69,14 +70,16 @@ class BaseView(object):
@Lazy
def typeTitle(self):
voc = util.KeywordVocabulary(getTargetTypes())
token = '.'.join((self.context.__module__,
self.context.__class__.__name__))
term = voc.getTermByToken(token)
return term.title
type = IType(self.context)
return type is not None and type.title or None
@Lazy
def typeUrl(self):
type = IType(self.context)
if type is not None:
provider = type.typeProvider
if provider is not None:
return zapi.absoluteURL(provider, self.request)
return None
def viewIterator(self, objs):

View file

@ -38,9 +38,9 @@ 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 loops.interfaces import IConcept
from loops.concept import Concept, ConceptTypeSourceList, PredicateSourceList
from loops.resource import getResourceTypes, getResourceTypesForSearch
from loops.target import getTargetTypes
from loops.browser.common import BaseView, LoopsTerms
from loops import util
@ -64,7 +64,7 @@ class ConceptView(BaseView):
def resources(self):
for r in self.context.getResourceRelations():
yield ConceptResourceRelationView(r, self.request, contextIsSecond=True)
yield ConceptRelationView(r, self.request, contextIsSecond=True)
class ConceptConfigureView(ConceptView):
@ -121,18 +121,14 @@ class ConceptConfigureView(ConceptView):
if not name:
raise(BadRequest, 'Empty name.')
title = request.get('create.title', u'')
conceptType = request.get('create.type')
if conceptType and conceptType.startswith('loops.resource.'):
factory = resolve(conceptType)
token = self.request.get('create.type')
type = ITypeManager(self.context).getType(token)
factory = type.factory
container = type.defaultContainer
concept = factory(title)
container = self.loopsRoot.getResourceManager()
else:
concept = Concept(title)
container = self.loopsRoot.getConceptManager()
container[name] = concept
if conceptType:
ctype = self.loopsRoot.loopsTraverse(conceptType)
concept.conceptType = ctype
if IConcept.providedBy(concept):
concept.conceptType = type.typeProvider
notify(ObjectCreatedEvent(removeSecurityProxy(concept)))
assignAs = self.request.get('assignAs', 'child')
predicate = request.get('create.predicate') or None
@ -176,44 +172,28 @@ class ConceptConfigureView(ConceptView):
result = [r for r in result if r.conceptType is None]
return self.viewIterator(result)
@Lazy
def typeTitle(self):
return self.context.conceptType.title
@Lazy
def typeUrl(self):
return zapi.absoluteURL(self.context.conceptType, self.request)
def viewIterator(self, objs):
request = self.request
for o in objs:
if IConcept.providedBy(o):
yield ConceptConfigureView(o, request)
else:
yield BaseView(o, request)
def conceptTypes(self):
types = ConceptTypeSourceList(self.context)
terms = zapi.getMultiAdapter((types, self.request), ITerms)
for type in types:
yield terms.getTerm(type)
return util.KeywordVocabulary([(t.token, t.title)
for t in ITypeManager(self.context).listTypes(('concept',))])
def conceptTypesForSearch(self):
types = ConceptTypeSourceList(self.context)
typesItems = [(':'.join(('loops:concept',
self.getConceptTypeTokenForSearch(t))), t.title)
for t in types]
return util.KeywordVocabulary(typesItems)
def getConceptTypeTokenForSearch(self, ct):
return ct is None and 'unknown' or zapi.getName(ct)
general = [('loops:concept:*', 'Any'),]
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
for t in ITypeManager(self.context).listTypes(('concept',))])
def resourceTypes(self):
return util.KeywordVocabulary(getResourceTypes())
return util.KeywordVocabulary([(t.token, t.title)
for t in ITypeManager(self.context).listTypes(('resource',))])
def resourceTypesForSearch(self):
return util.KeywordVocabulary(getResourceTypesForSearch())
general = [('loops:resource:*', 'Any'),]
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
for t in ITypeManager(self.context).listTypes(('resource',))])
def predicates(self):
preds = PredicateSourceList(self.context)
@ -222,7 +202,7 @@ class ConceptConfigureView(ConceptView):
yield terms.getTerm(pred)
class ConceptRelationView(object):
class ConceptRelationView(BaseView):
def __init__(self, relation, request, contextIsSecond=False):
if contextIsSecond:
@ -234,35 +214,11 @@ class ConceptRelationView(object):
self.predicate = relation.predicate
self.request = request
@Lazy
def loopsRoot(self):
return self.context.getLoopsRoot()
@Lazy
def url(self):
return zapi.absoluteURL(self.context, self.request)
@Lazy
def title(self):
return self.context.title
@Lazy
def token(self):
return ':'.join((self.loopsRoot.getLoopsUri(self.context),
self.loopsRoot.getLoopsUri(self.predicate)))
@Lazy
def conceptType(self):
return self.context.conceptType
@Lazy
def typeTitle(self):
return self.conceptType.title
@Lazy
def typeUrl(self):
return zapi.absoluteURL(self.conceptType, self.request)
@Lazy
def predicateTitle(self):
return self.predicate.title
@ -271,23 +227,3 @@ class ConceptRelationView(object):
def predicateUrl(self):
return zapi.absoluteURL(self.predicate, self.request)
class ConceptResourceRelationView(ConceptRelationView):
@Lazy
def conceptType(self):
return None
@Lazy
def typeTitle(self):
voc = util.KeywordVocabulary(getTargetTypes())
token = '.'.join((self.context.__module__,
self.context.__class__.__name__))
term = voc.getTermByToken(token)
return term.title
@Lazy
def typeUrl(self):
return ''

View file

@ -54,9 +54,6 @@
<metal:search fill-slot="topActions">
<metal:block use-macro="views/relation_macros/search">
<select name="searchType" metal:fill-slot="types">
<option value="loops:resource:*"
tal:attributes="selected python:
searchType == 'loops:resource:*'">Any</option>
<tal:types repeat="type view/resourceTypesForSearch">
<option value="loops:resource:Document"
i18n:translate=""

View file

@ -462,10 +462,6 @@
for="loops.concept.PredicateSourceList
zope.publisher.interfaces.browser.IBrowserRequest" />
<zope:adapter factory="loops.browser.common.LoopsTerms"
for="loops.target.TargetSourceList
zope.publisher.interfaces.browser.IBrowserRequest" />
<zope:view factory="loops.view.NodeTraverser"
for="loops.interfaces.INode"
type="zope.publisher.interfaces.browser.IBrowserRequest"

View file

@ -35,6 +35,7 @@ from zope.proxy import removeAllProxies
from zope.security import canAccess, canWrite
from zope.security.proxy import removeSecurityProxy
from cybertools.typology.interfaces import ITypeManager
from loops.interfaces import IConcept, IDocument, IMediaAsset
from loops.resource import MediaAsset
from loops.target import getTargetTypes, getTargetTypesForSearch
@ -183,13 +184,10 @@ class ConfigureView(BaseView):
def createAndAssign(self):
form = self.request.form
root = self.loopsRoot
type = self.request.form.get('create.type',
'loops.resource.MediaAsset')
factory = resolve(type)
if '.resource.' in type:
container = root.getResourceManager()
else:
container = root.getConceptManager()
token = form.get('create.type', 'loops.resource.MediaAsset')
type = ITypeManager(self.context).getType(token)
factory = type.factory
container = type.defaultContainer
name = form.get('create.name', '')
if not name:
viewManagerPath = zapi.getPath(root.getViewManager())
@ -204,15 +202,21 @@ class ConfigureView(BaseView):
container[name] = removeSecurityProxy(factory())
target = container[name]
target.title = form.get('create.title', u'')
if IConcept.providedBy(target):
target.conceptType = type.typeProvider
notify(ObjectCreatedEvent(target))
self.context.target = target
return True
def targetTypes(self):
return util.KeywordVocabulary(getTargetTypes())
return util.KeywordVocabulary([(t.token, t.title)
for t in ITypeManager(self.context).types])
def targetTypesForSearch(self):
return util.KeywordVocabulary(getTargetTypesForSearch())
general = [('loops:*', 'Any'), ('loops:concept:*', 'Any Concept'),
('loops:resource:*', 'Any Resource'),]
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
for t in ITypeManager(self.context).types])
@Lazy
def search(self):
@ -244,8 +248,9 @@ class ConfigureView(BaseView):
for o in objs:
if o == self.context.target:
continue
if IConcept.providedBy(o):
yield ConceptView(o, request)
else:
yield BaseView(o, request)
#if IConcept.providedBy(o):
# yield ConceptView(o, request)
#else:
# yield BaseView(o, request)

View file

@ -93,7 +93,6 @@
tal:attributes="value type/token"
tal:content="type/title">Topic</option>
</tal:types>
<option>None</option>
</select>
</div><br />
<div class="formControls">
@ -135,9 +134,6 @@
tal:attributes="value searchTerm" />
<span i18n:translate="">Type</span>
<select name="searchType" metal:define-slot="types">
<option value="loops:concept:*"
tal:attributes="selected python:
searchType == 'loops:concept:*'">Any</option>
<tal:types repeat="type view/conceptTypesForSearch">
<option value=".loops/concepts/topic"
i18n:translate=""

View file

@ -124,7 +124,6 @@
tal:attributes="value searchTerm" />
<span i18n:translate="">Type</span>
<select name="searchType">
<option>Any</option>
<tal:types repeat="type view/targetTypesForSearch">
<option value=".loops/concepts/topic"
i18n:translate=""

View file

@ -36,6 +36,7 @@ from cybertools.relation import DyadicRelation
from cybertools.relation.registry import getRelations
from cybertools.relation.registry import getRelationSingle, setRelationSingle
from cybertools.relation.interfaces import IRelationRegistry, IRelatable
from cybertools.typology.interfaces import ITypeManager
from interfaces import IConcept, IConceptRelation, IConceptView
from interfaces import IConceptManager, IConceptManagerContained
@ -237,27 +238,14 @@ class ConceptTypeSourceList(object):
def __init__(self, context):
self.context = context
#self.context = removeSecurityProxy(context)
root = self.context.getLoopsRoot()
self.concepts = root.getConceptManager()
def __iter__(self):
return iter(self.conceptTypes)
@Lazy
def conceptTypes(self):
result = []
cm = self.concepts
typeObject = cm.getTypeConcept()
unknownType = cm.get('unknown') # does this make sense?
if typeObject is not None:
types = typeObject.getChildren([cm.getTypePredicate()])
if typeObject not in types:
result.append(typeObject)
if unknownType is not None and unknownType not in types:
result.append(unknownType)
result.extend(types)
return result
types = ITypeManager(self.context).listTypes(include=('concept',))
return [t.typeProvider for t in types]
def __len__(self):
return len(self.conceptTypes)
@ -308,9 +296,3 @@ class IndexAttributes(object):
def title(self):
return self.text()
def type(self):
context = self.context
conceptType = context.conceptType
typeName = conceptType is None and 'unknown' or zapi.getName(conceptType)
return ':'.join(('loops:concept', typeName,))

View file

@ -264,10 +264,10 @@
name="loops.PredicateSource"
/>
<vocabulary
<!--<vocabulary
factory="loops.target.TargetSourceList"
name="loops.targetSource"
/>
/>-->
<!-- Register various browser related components, including all views -->
<include package=".browser" />

View file

@ -130,6 +130,10 @@ lazy properties, one should always get a new adapter:
True
>>> topic_type.qualifiers
('concept',)
>>> topic_type.defaultContainer
<loops.concept.ConceptManager object ...>
>>> topic_type.factory
<class 'loops.concept.Concept'>
Now let's have a look at resources.
@ -141,11 +145,15 @@ Now let's have a look at resources.
>>> doc1_type.title
u'Document'
>>> doc1_type.token
'.loops/resources/document'
'loops.resource.Document'
>>> doc1_type.tokenForSearch
'loops:resource:document'
>>> doc1_type.qualifiers
('resource',)
>>> doc1_type.defaultContainer
<loops.resource.ResourceManager object ...>
>>> doc1_type.factory
<class 'loops.resource.Document'>
>>> img1_type = IType(img1)
>>> img1_type.title
@ -167,7 +175,7 @@ get a type manager from all loops objects, always with the same context:
>>> types = typeManager.types
>>> sorted(t.token for t in types)
['.loops/concepts/topic', '.loops/concepts/type',
'.loops/resources/document', '.loops/resources/mediaasset']
'loops.resource.Document', 'loops.resource.MediaAsset']
>>> typeManager.getType('.loops/concepts/topic') == cc1_type
True
@ -180,18 +188,5 @@ condition:
['.loops/concepts/topic', '.loops/concepts/type']
>>> types = typeManager.listTypes(exclude=('concept',))
>>> sorted(t.token for t in types)
['.loops/resources/document', '.loops/resources/mediaasset']
Index attributes adapter
------------------------
>>> from loops.concept import IndexAttributes
>>> idx = IndexAttributes(cc2)
>>> idx.type()
'loops:concept:unknown'
>>> from loops.resource import IndexAttributes
>>> idx = IndexAttributes(doc1)
>>> idx.type()
'loops:resource:Document'
['loops.resource.Document', 'loops.resource.MediaAsset']

View file

@ -161,10 +161,6 @@ class IndexAttributes(object):
context = self.context
return ' '.join((zapi.getName(context), context.title,)).strip()
def type(self):
context = self.context
return ':'.join(('loops:resource', context.__class__.__name__))
class IndexableResource(object):
@ -180,15 +176,3 @@ class IndexableResource(object):
icc.addBinary(fields[0], context.data, context.contentType, language='de')
return icc
def getResourceTypes():
return (('loops.resource.Document', _(u'Document')),
('loops.resource.MediaAsset', _(u'Media Asset')),
)
def getResourceTypesForSearch():
return (('loops:resource:Document', _(u'Document')),
('loops:resource:MediaAsset', _(u'Media Asset')),
)

48
type.py
View file

@ -25,8 +25,10 @@ $Id$
from zope.app import zapi
from zope.component import adapts
from zope.cachedescriptors.property import Lazy
from zope.dottedname.resolve import resolve
from cybertools.typology.type import BaseType, TypeManager
from loops.interfaces import ILoopsObject, IConcept, IResource
from loops.concept import Concept
from loops.resource import Document, MediaAsset
@ -53,14 +55,6 @@ class LoopsType(BaseType):
return self.context.getLoopsRoot()
class LoopsTypeInfo(LoopsType):
""" A common class the instances of which are used as a generic type info.
"""
def __init__(self, typeProvider):
self.typeProvider = self.context = typeProvider
class ConceptType(LoopsType):
""" The type adapter for concept objects.
"""
@ -68,11 +62,16 @@ class ConceptType(LoopsType):
adapts(IConcept)
qualifiers = ('concept',)
factory = Concept
@Lazy
def typeProvider(self):
return self.context.conceptType
@Lazy
def defaultContainer(self):
return self.root.getConceptManager()
class ConceptTypeInfo(ConceptType):
@ -95,8 +94,9 @@ class ResourceType(LoopsType):
@Lazy
def token(self):
cn = self.className
return '/'.join(('.loops/resources', cn.lower(),))
return '.'.join((self.factory.__module__, self.className))
#cn = self.className
#return '/'.join(('.loops/resources', cn.lower(),))
@Lazy
def tokenForSearch(self):
@ -104,19 +104,23 @@ class ResourceType(LoopsType):
return ':'.join(('loops:resource', cn.lower(),))
@Lazy
def className(self):
return self.context.__class__.__name__
def defaultContainer(self):
return self.root.getResourceManager()
@Lazy
def factory(self):
return self.context.__class__
@Lazy
def className(self):
return self.factory.__name__
class ResourceTypeInfo(ResourceType):
def __init__(self, cls):
self.cls = cls
@Lazy
def className(self):
return self.cls.__name__
def __init__(self, context, factory):
self.context = context
self.factory = factory
class LoopsTypeManager(TypeManager):
@ -126,6 +130,11 @@ class LoopsTypeManager(TypeManager):
def __init__(self, context):
self.context = context.getLoopsRoot()
def getType(self, token):
if token.startswith('.loops'):
return ConceptTypeInfo(self.context.loopsTraverse(token))
return ResourceTypeInfo(self.context, resolve(token))
@property
def types(self):
return self.conceptTypes() + self.resourceTypes()
@ -150,4 +159,5 @@ class LoopsTypeManager(TypeManager):
return tuple([ConceptTypeInfo(c) for c in result])
def resourceTypes(self):
return tuple([ResourceTypeInfo(cls) for cls in (Document, MediaAsset)])
return tuple([ResourceTypeInfo(self.context, cls)
for cls in (Document, MediaAsset)])