provide system qualifier for type type and predicate, check it when searching; + some minor refactorings
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1605 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
a2932828fb
commit
6e3e08c781
15 changed files with 146 additions and 88 deletions
|
@ -140,6 +140,13 @@ class BaseView(GenericView):
|
||||||
def value(self):
|
def value(self):
|
||||||
return self.context
|
return self.context
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def uniqueId(self):
|
||||||
|
return util.getUidForObject(self.context)
|
||||||
|
#return zapi.getUtility(IRelationRegistry).getUniqueIdForObject(self.context)
|
||||||
|
|
||||||
|
# type stuff
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def type(self):
|
def type(self):
|
||||||
return IType(self.context)
|
return IType(self.context)
|
||||||
|
@ -174,35 +181,47 @@ class BaseView(GenericView):
|
||||||
for o in objs:
|
for o in objs:
|
||||||
yield BaseView(o, request)
|
yield BaseView(o, request)
|
||||||
|
|
||||||
|
# type listings
|
||||||
|
|
||||||
|
def listTypes(self, include=None, exclude=None, sortOn='title'):
|
||||||
|
types = [dict(token=t.token, title=t.title)
|
||||||
|
for t in ITypeManager(self.context).listTypes(include, exclude)]
|
||||||
|
if sortOn:
|
||||||
|
types.sort(key=lambda x: x[sortOn])
|
||||||
|
return types
|
||||||
|
|
||||||
def resourceTypes(self):
|
def resourceTypes(self):
|
||||||
return util.KeywordVocabulary([(t.token, t.title)
|
return util.KeywordVocabulary(self.listTypes(('resource',) ('hidden',)))
|
||||||
for t in ITypeManager(self.context).listTypes(('resource',))
|
#if t.factory == Resource]) # ? if necessary -> type.qualifiers
|
||||||
if t.factory == Resource])
|
|
||||||
|
|
||||||
def conceptTypes(self):
|
def conceptTypes(self):
|
||||||
return util.KeywordVocabulary([(t.token, t.title)
|
return util.KeywordVocabulary(self.listTypes(('concept',), ('hidden',)))
|
||||||
for t in ITypeManager(self.context).listTypes(('concept',))])
|
|
||||||
|
def listTypesForSearch(self, include=None, exclude=None, sortOn='title'):
|
||||||
|
types = [dict(token=t.tokenForSearch, title=t.title)
|
||||||
|
for t in ITypeManager(self.context).listTypes(include, exclude)]
|
||||||
|
if sortOn:
|
||||||
|
types.sort(key=lambda x: x[sortOn])
|
||||||
|
return types
|
||||||
|
|
||||||
def typesForSearch(self):
|
def typesForSearch(self):
|
||||||
general = [('loops:resource:*', 'Any Resource'),
|
general = [('loops:resource:*', 'Any Resource'),
|
||||||
('loops:concept:*', 'Any Concept'),]
|
('loops:concept:*', 'Any Concept'),]
|
||||||
return util.KeywordVocabulary(general + sorted([(t.tokenForSearch, t.title)
|
return util.KeywordVocabulary(general
|
||||||
for t in ITypeManager(self.context).types])
|
+ self.listTypesForSearch(exclude=('system', 'hidden',))
|
||||||
+ [('loops:*', 'Any')])
|
+ [('loops:*', 'Any')])
|
||||||
|
|
||||||
def conceptTypesForSearch(self):
|
def conceptTypesForSearch(self):
|
||||||
general = [('loops:concept:*', 'Any Concept'),]
|
general = [('loops:concept:*', 'Any Concept'),]
|
||||||
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
|
return util.KeywordVocabulary(general
|
||||||
for t in ITypeManager(self.context).listTypes(('concept',))])
|
+ self.listTypesForSearch(('concept',), ('system', 'hidden',),))
|
||||||
|
|
||||||
def resourceTypesForSearch(self):
|
def resourceTypesForSearch(self):
|
||||||
general = [('loops:resource:*', 'Any Resource'),]
|
general = [('loops:resource:*', 'Any Resource'),]
|
||||||
return util.KeywordVocabulary(general + [(t.tokenForSearch, t.title)
|
return util.KeywordVocabulary(general
|
||||||
for t in ITypeManager(self.context).listTypes(('resource',))])
|
+ self.listTypesForSearch(('resource',), ('system', 'hidden'),))
|
||||||
|
|
||||||
@Lazy
|
# controllling editing
|
||||||
def uniqueId(self):
|
|
||||||
return zapi.getUtility(IRelationRegistry).getUniqueIdForObject(self.context)
|
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def editable(self):
|
def editable(self):
|
||||||
|
|
16
common.py
16
common.py
|
@ -42,29 +42,31 @@ class AdapterBase(object):
|
||||||
|
|
||||||
adapts(IConcept)
|
adapts(IConcept)
|
||||||
|
|
||||||
_attributes = ('context', '__parent__', )
|
_adapterAttributes = ('context', '__parent__', )
|
||||||
_schemas = list(IConcept)
|
_contextAttributes = list(IConcept)
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
self.context = context # to get the permission stuff right
|
self.context = context
|
||||||
self.__parent__ = context
|
self.__parent__ = context # to get the permission stuff right
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
self.checkAttr(attr)
|
self.checkAttr(attr)
|
||||||
return getattr(self.context, '_' + attr, None)
|
return getattr(self.context, '_' + attr, None)
|
||||||
|
|
||||||
def __setattr__(self, attr, value):
|
def __setattr__(self, attr, value):
|
||||||
if attr in self._attributes:
|
if attr in self._adapterAttributes:
|
||||||
object.__setattr__(self, attr, value)
|
object.__setattr__(self, attr, value)
|
||||||
else:
|
else:
|
||||||
self.checkAttr(attr)
|
self.checkAttr(attr)
|
||||||
setattr(self.context, '_' + attr, value)
|
setattr(self.context, '_' + attr, value)
|
||||||
|
|
||||||
def checkAttr(self, attr):
|
def checkAttr(self, attr):
|
||||||
if attr not in self._schemas:
|
if attr not in self._contextAttributes:
|
||||||
raise AttributeError(attr)
|
raise AttributeError(attr)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
|
if other is None:
|
||||||
|
return False
|
||||||
return self.context == other.context
|
return self.context == other.context
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,7 +74,7 @@ class ResourceAdapterBase(AdapterBase):
|
||||||
|
|
||||||
adapts(IResource)
|
adapts(IResource)
|
||||||
|
|
||||||
_schemas = list(IResourceAdapter)
|
_contextAttributes = list(IResourceAdapter)
|
||||||
|
|
||||||
|
|
||||||
# other adapters
|
# other adapters
|
||||||
|
|
19
concept.py
19
concept.py
|
@ -149,10 +149,6 @@ class Concept(Contained, Persistent):
|
||||||
|
|
||||||
def deassignChild(self, child, predicates=None):
|
def deassignChild(self, child, predicates=None):
|
||||||
registry = zapi.getUtility(IRelationRegistry)
|
registry = zapi.getUtility(IRelationRegistry)
|
||||||
#relations = []
|
|
||||||
#for rs in relationships:
|
|
||||||
# relations.extend(registry.query(first=self, second=concept,
|
|
||||||
# relationship=rs))
|
|
||||||
for rel in self.getChildRelations(predicates, child):
|
for rel in self.getChildRelations(predicates, child):
|
||||||
registry.unregister(rel)
|
registry.unregister(rel)
|
||||||
|
|
||||||
|
@ -192,6 +188,7 @@ class ConceptManager(BTreeContainer):
|
||||||
typeConcept = None
|
typeConcept = None
|
||||||
typePredicate = None
|
typePredicate = None
|
||||||
defaultPredicate = None
|
defaultPredicate = None
|
||||||
|
predicateType = None
|
||||||
|
|
||||||
def getLoopsRoot(self):
|
def getLoopsRoot(self):
|
||||||
return zapi.getParent(self)
|
return zapi.getParent(self)
|
||||||
|
@ -209,19 +206,27 @@ class ConceptManager(BTreeContainer):
|
||||||
self.defaultPredicate = self['standard']
|
self.defaultPredicate = self['standard']
|
||||||
return self.defaultPredicate
|
return self.defaultPredicate
|
||||||
|
|
||||||
|
def getPredicateType(self):
|
||||||
|
if self.predicateType is None:
|
||||||
|
dp = self.getDefaultPredicate()
|
||||||
|
self.predicateType = dp.conceptType
|
||||||
|
return self.predicateType
|
||||||
|
|
||||||
def getViewManager(self):
|
def getViewManager(self):
|
||||||
return self.getLoopsRoot().getViewManager()
|
return self.getLoopsRoot().getViewManager()
|
||||||
|
|
||||||
|
|
||||||
# adapters and similar components
|
# adapters and similar components
|
||||||
|
|
||||||
class ConceptSourceList(object):
|
class xxxConceptSourceList(object):
|
||||||
|
|
||||||
|
# seems to be obsolete
|
||||||
|
|
||||||
implements(schema.interfaces.IIterableSource)
|
implements(schema.interfaces.IIterableSource)
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
#self.context = context
|
self.context = context
|
||||||
self.context = removeSecurityProxy(context)
|
#self.context = removeSecurityProxy(context)
|
||||||
root = self.context.getLoopsRoot()
|
root = self.context.getLoopsRoot()
|
||||||
self.concepts = root.getConceptManager()
|
self.concepts = root.getConceptManager()
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,8 @@
|
||||||
|
|
||||||
<require
|
<require
|
||||||
permission="zope.View"
|
permission="zope.View"
|
||||||
attributes="getTypePredicate getDefaultPredicate getTypeConcept" />
|
attributes="getTypePredicate getDefaultPredicate getTypeConcept
|
||||||
|
getPredicateType" />
|
||||||
|
|
||||||
</class>
|
</class>
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ So let's check the type of the type object:
|
||||||
>>> type_type.tokenForSearch
|
>>> type_type.tokenForSearch
|
||||||
'loops:concept:type'
|
'loops:concept:type'
|
||||||
>>> type_type.qualifiers
|
>>> type_type.qualifiers
|
||||||
('concept',)
|
('concept', 'system')
|
||||||
|
|
||||||
Now we register another type ('topic') and assign it to cc1:
|
Now we register another type ('topic') and assign it to cc1:
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ lazy properties, one should always get a new adapter:
|
||||||
>>> cc1_type.typeProvider == topic
|
>>> cc1_type.typeProvider == topic
|
||||||
True
|
True
|
||||||
>>> topic_type.qualifiers
|
>>> topic_type.qualifiers
|
||||||
('concept',)
|
('concept', 'system')
|
||||||
>>> topic_type.defaultContainer
|
>>> topic_type.defaultContainer
|
||||||
<loops.concept.ConceptManager object ...>
|
<loops.concept.ConceptManager object ...>
|
||||||
>>> topic_type.factory
|
>>> topic_type.factory
|
||||||
|
|
|
@ -155,23 +155,30 @@ class IConceptView(Interface):
|
||||||
""" Used for accessing a concept via a node's target attribute"""
|
""" Used for accessing a concept via a node's target attribute"""
|
||||||
|
|
||||||
|
|
||||||
class IConceptManager(ILoopsObject, IContainer):
|
#class IConceptManager(ILoopsObject, IContainer):
|
||||||
|
class IConceptManager(ILoopsObject):
|
||||||
""" A manager/container for concepts.
|
""" A manager/container for concepts.
|
||||||
"""
|
"""
|
||||||
contains(IConcept)
|
contains(IConcept)
|
||||||
|
|
||||||
|
def getTypeConcept():
|
||||||
|
""" Return the concept that provides the type object,
|
||||||
|
i.e. the type of all types.
|
||||||
|
"""
|
||||||
|
|
||||||
def getTypePredicate():
|
def getTypePredicate():
|
||||||
""" Return the concept that provides the type predicate.
|
""" Return the concept that provides the type predicate.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def getTypeConcept():
|
|
||||||
""" Return the concept that provides the type object.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def getDefaultPredicate():
|
def getDefaultPredicate():
|
||||||
""" Return the concept that provides the default (standard) predicate.
|
""" Return the concept that provides the default (standard) predicate.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def getPredicateType():
|
||||||
|
""" Return the concept that provides the predicate type object,
|
||||||
|
i.e. the type of all predicates.
|
||||||
|
"""
|
||||||
|
|
||||||
class IConceptManagerContained(Interface):
|
class IConceptManagerContained(Interface):
|
||||||
containers(IConceptManager)
|
containers(IConceptManager)
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ class Topic(AdapterBase, KnowledgeAdapterMixin):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
implements(IKnowledgeElement)
|
implements(IKnowledgeElement)
|
||||||
_attributes = ('context', '__parent__', 'parent')
|
_adapterAttributes = ('context', '__parent__', 'parent')
|
||||||
|
|
||||||
def getParent(self):
|
def getParent(self):
|
||||||
parents = self.context.getParents((self.standardPred,))
|
parents = self.context.getParents((self.standardPred,))
|
||||||
|
|
|
@ -72,8 +72,8 @@ class Person(AdapterBase, BasePerson):
|
||||||
|
|
||||||
implements(IPerson)
|
implements(IPerson)
|
||||||
|
|
||||||
_attributes = ('context', '__parent__', 'userId', 'phoneNumbers')
|
_adapterAttributes = ('context', '__parent__', 'userId', 'phoneNumbers')
|
||||||
_schemas = list(IPerson) + list(IConcept)
|
_contextAttributes = list(IPerson) + list(IConcept)
|
||||||
|
|
||||||
def getUserId(self):
|
def getUserId(self):
|
||||||
return getattr(self.context, '_userId', None)
|
return getattr(self.context, '_userId', None)
|
||||||
|
@ -162,8 +162,8 @@ class Address(AdapterBase):
|
||||||
|
|
||||||
implements(IAddress)
|
implements(IAddress)
|
||||||
|
|
||||||
_attributes = ('context', '__parent__', 'lines')
|
_adapterAttributes = ('context', '__parent__', 'lines')
|
||||||
_schemas = list(IAddress) + list(IConcept)
|
_contextAttributes = list(IAddress) + list(IConcept)
|
||||||
|
|
||||||
def getLines(self):
|
def getLines(self):
|
||||||
return getattr(self.context, '_lines', [])
|
return getattr(self.context, '_lines', [])
|
||||||
|
|
|
@ -39,6 +39,6 @@ class Task(AdapterBase):
|
||||||
|
|
||||||
implements(ITask)
|
implements(ITask)
|
||||||
|
|
||||||
_attributes = ('context', '__parent__',)
|
_adapterAttributes = ('context', '__parent__',)
|
||||||
_schemas = list(ITask) + list(IConcept)
|
_contextAttributes = list(ITask) + list(IConcept)
|
||||||
|
|
||||||
|
|
22
query.py
22
query.py
|
@ -28,6 +28,7 @@ from zope import traversing
|
||||||
from zope.app.catalog.interfaces import ICatalog
|
from zope.app.catalog.interfaces import ICatalog
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
|
||||||
|
from cybertools.typology.interfaces import IType
|
||||||
from loops.interfaces import IConcept
|
from loops.interfaces import IConcept
|
||||||
from loops.common import AdapterBase
|
from loops.common import AdapterBase
|
||||||
from loops.type import TypeInterfaceSourceList
|
from loops.type import TypeInterfaceSourceList
|
||||||
|
@ -59,7 +60,7 @@ class BaseQuery(object):
|
||||||
def loopsRoot(self):
|
def loopsRoot(self):
|
||||||
return self.context.context.getLoopsRoot()
|
return self.context.context.getLoopsRoot()
|
||||||
|
|
||||||
def queryConcepts(self, title=None, type=None):
|
def queryConcepts(self, title=None, type=None, **kw):
|
||||||
if type.endswith('*'):
|
if type.endswith('*'):
|
||||||
start = type[:-1]
|
start = type[:-1]
|
||||||
end = start + '\x7f'
|
end = start + '\x7f'
|
||||||
|
@ -71,16 +72,23 @@ class BaseQuery(object):
|
||||||
else:
|
else:
|
||||||
result = cat.searchResults(loops_type=(start, end))
|
result = cat.searchResults(loops_type=(start, end))
|
||||||
result = set(r for r in result if r.getLoopsRoot() == self.loopsRoot)
|
result = set(r for r in result if r.getLoopsRoot() == self.loopsRoot)
|
||||||
|
if 'exclude' in kw:
|
||||||
|
r1 = set()
|
||||||
|
for r in result:
|
||||||
|
qur = IType(r).qualifiers
|
||||||
|
if not [qux for qux in kw['exclude'] if qux in qur]:
|
||||||
|
r1.add(r)
|
||||||
|
result = r1
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def queryConceptsWithChildren(self, title=None, type=None, uid=None):
|
def queryConceptsWithChildren(self, title=None, type=None, uid=None, **kw):
|
||||||
if title: # there are a few characters that the index doesn't like
|
if title: # there are a few characters that the index doesn't like
|
||||||
title = title.replace('(', ' ').replace(')', ' ')
|
title = title.replace('(', ' ').replace(')', ' ')
|
||||||
if not title and not uid and (type is None or '*' in type):
|
if not title and not uid and (type is None or '*' in type):
|
||||||
return None
|
return None
|
||||||
result = set()
|
result = set()
|
||||||
if not uid:
|
if not uid:
|
||||||
queue = list(self.queryConcepts(title=title, type=type))
|
queue = list(self.queryConcepts(title=title, type=type, **kw))
|
||||||
else:
|
else:
|
||||||
queue = [util.getObjectForUid(uid)]
|
queue = [util.getObjectForUid(uid)]
|
||||||
concepts = []
|
concepts = []
|
||||||
|
@ -100,7 +108,7 @@ class BaseQuery(object):
|
||||||
class FullQuery(BaseQuery):
|
class FullQuery(BaseQuery):
|
||||||
|
|
||||||
def query(self, text=None, type=None, useTitle=True, useFull=False,
|
def query(self, text=None, type=None, useTitle=True, useFull=False,
|
||||||
conceptTitle=None, conceptUid=None, conceptType=None):
|
conceptTitle=None, conceptUid=None, conceptType=None, **kw):
|
||||||
result = set()
|
result = set()
|
||||||
rc = self.queryConceptsWithChildren(title=conceptTitle, uid=conceptUid,
|
rc = self.queryConceptsWithChildren(title=conceptTitle, uid=conceptUid,
|
||||||
type=conceptType)
|
type=conceptType)
|
||||||
|
@ -136,10 +144,10 @@ class ConceptQuery(BaseQuery):
|
||||||
""" Find concepts of type `type` whose title starts with `title`.
|
""" Find concepts of type `type` whose title starts with `title`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def query(self, title=None, type=None):
|
def query(self, title=None, type=None, **kw):
|
||||||
if title and not title.endswith('*'):
|
if title and not title.endswith('*'):
|
||||||
title += '*'
|
title += '*'
|
||||||
return self.queryConcepts(title=title, type=type)
|
return self.queryConcepts(title=title, type=type, **kw)
|
||||||
|
|
||||||
|
|
||||||
# QueryConcept: concept objects that allow querying the database.
|
# QueryConcept: concept objects that allow querying the database.
|
||||||
|
@ -161,7 +169,7 @@ class QueryConcept(AdapterBase):
|
||||||
|
|
||||||
implements(IQueryConcept)
|
implements(IQueryConcept)
|
||||||
|
|
||||||
_schemas = list(IQueryConcept) + list(IConcept)
|
_contextAttributes = list(IQueryConcept) + list(IConcept)
|
||||||
|
|
||||||
|
|
||||||
TypeInterfaceSourceList.typeInterfaces += (IQueryConcept,)
|
TypeInterfaceSourceList.typeInterfaces += (IQueryConcept,)
|
||||||
|
|
11
resource.py
11
resource.py
|
@ -200,10 +200,9 @@ class FileAdapter(ResourceAdapterBase):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
implements(IFile)
|
implements(IFile)
|
||||||
_schemas = list(IFile) + list(IBaseResource)
|
|
||||||
|
|
||||||
# let the adapter handle the data attribute:
|
_contextAttributes = list(IFile) + list(IBaseResource)
|
||||||
_attributes = ResourceAdapterBase._attributes + ('data',)
|
_adapterAttributes = ResourceAdapterBase._adapterAttributes + ('data',)
|
||||||
|
|
||||||
def setData(self, data): self.context.data = data
|
def setData(self, data): self.context.data = data
|
||||||
def getData(self): return self.context.data
|
def getData(self): return self.context.data
|
||||||
|
@ -251,7 +250,7 @@ class DocumentAdapter(ResourceAdapterBase):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# let the adapter handle the data attribute:
|
# let the adapter handle the data attribute:
|
||||||
_attributes = ResourceAdapterBase._attributes + ('data',)
|
_adapterAttributes = ResourceAdapterBase._adapterAttributes + ('data',)
|
||||||
|
|
||||||
def setData(self, data): self.context._data = data.replace('\r', '')
|
def setData(self, data): self.context._data = data.replace('\r', '')
|
||||||
def getData(self): return self.context._data
|
def getData(self): return self.context._data
|
||||||
|
@ -263,7 +262,7 @@ class TextDocumentAdapter(DocumentAdapter):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
implements(IDocument)
|
implements(IDocument)
|
||||||
_schemas = list(IDocument) + list(IBaseResource)
|
_contextAttributes = list(IDocument) + list(IBaseResource)
|
||||||
|
|
||||||
|
|
||||||
class NoteAdapter(DocumentAdapter):
|
class NoteAdapter(DocumentAdapter):
|
||||||
|
@ -271,7 +270,7 @@ class NoteAdapter(DocumentAdapter):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
implements(INote)
|
implements(INote)
|
||||||
_schemas = list(INote) + list(IBaseResource)
|
_contextAttributes = list(INote) + list(IBaseResource)
|
||||||
|
|
||||||
|
|
||||||
# other adapters
|
# other adapters
|
||||||
|
|
|
@ -78,13 +78,13 @@ zcml in real life:
|
||||||
|
|
||||||
>>> t = searchView.typesForSearch()
|
>>> t = searchView.typesForSearch()
|
||||||
>>> len(t)
|
>>> len(t)
|
||||||
11
|
9
|
||||||
>>> t.getTermByToken('loops:resource:*').title
|
>>> t.getTermByToken('loops:resource:*').title
|
||||||
'Any Resource'
|
'Any Resource'
|
||||||
|
|
||||||
>>> t = searchView.conceptTypesForSearch()
|
>>> t = searchView.conceptTypesForSearch()
|
||||||
>>> len(t)
|
>>> len(t)
|
||||||
5
|
3
|
||||||
>>> t.getTermByToken('loops:concept:*').title
|
>>> t.getTermByToken('loops:concept:*').title
|
||||||
'Any Concept'
|
'Any Concept'
|
||||||
|
|
||||||
|
|
|
@ -77,11 +77,11 @@ class Search(BaseView):
|
||||||
request.response.setHeader('Content-Type', 'text/plain; charset=UTF-8')
|
request.response.setHeader('Content-Type', 'text/plain; charset=UTF-8')
|
||||||
title = request.get('searchString', '').replace('(', ' ').replace(')', ' ')
|
title = request.get('searchString', '').replace('(', ' ').replace(')', ' ')
|
||||||
type = request.get('searchType') or 'loops:concept:*'
|
type = request.get('searchType') or 'loops:concept:*'
|
||||||
result = ConceptQuery(self).query(title=title, type=type)
|
result = ConceptQuery(self).query(title=title, type=type, exclude=('system',))
|
||||||
registry = component.getUtility(IRelationRegistry)
|
#registry = component.getUtility(IRelationRegistry)
|
||||||
# simple way to provide JSON format:
|
# simple way to provide JSON format:
|
||||||
return str(sorted([[`o.title`[2:-1] + ' (%s)' % `o.conceptType.title`[2:-1],
|
return str(sorted([[`o.title`[2:-1] + ' (%s)' % `o.conceptType.title`[2:-1],
|
||||||
`registry.getUniqueIdForObject(o)`]
|
`int(util.getUidForObject(o))`]
|
||||||
for o in result
|
for o in result
|
||||||
if o.getLoopsRoot() == self.loopsRoot])).replace('\\\\x', '\\x')
|
if o.getLoopsRoot() == self.loopsRoot])).replace('\\\\x', '\\x')
|
||||||
#return str(sorted([[`o.title`[2:-1], `traversing.api.getName(o)`[2:-1]]
|
#return str(sorted([[`o.title`[2:-1], `traversing.api.getName(o)`[2:-1]]
|
||||||
|
|
57
type.py
57
type.py
|
@ -22,13 +22,14 @@ Type management stuff.
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.app import zapi
|
from zope import component, schema
|
||||||
from zope.component import adapts
|
from zope.component import adapts
|
||||||
from zope.interface import implements
|
from zope.interface import implements
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
from zope.dottedname.resolve import resolve
|
from zope.dottedname.resolve import resolve
|
||||||
from zope import schema
|
|
||||||
from zope.security.proxy import removeSecurityProxy
|
from zope.security.proxy import removeSecurityProxy
|
||||||
|
from zope.traversing.api import getName
|
||||||
|
|
||||||
from cybertools.typology.type import BaseType, TypeManager
|
from cybertools.typology.type import BaseType, TypeManager
|
||||||
from cybertools.typology.interfaces import ITypeManager
|
from cybertools.typology.interfaces import ITypeManager
|
||||||
from loops.interfaces import ILoopsObject, IConcept, IResource
|
from loops.interfaces import ILoopsObject, IConcept, IResource
|
||||||
|
@ -44,7 +45,8 @@ class LoopsType(BaseType):
|
||||||
|
|
||||||
adapts(ILoopsObject)
|
adapts(ILoopsObject)
|
||||||
|
|
||||||
factoryMapping = dict(concept=Concept, resource=Resource, document=Document)
|
factoryMapping = dict(concept=Concept, resource=Resource)
|
||||||
|
#document=Document)
|
||||||
containerMapping = dict(concept='concepts', resource='resources')
|
containerMapping = dict(concept='concepts', resource='resources')
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
|
@ -60,27 +62,31 @@ class LoopsType(BaseType):
|
||||||
@Lazy
|
@Lazy
|
||||||
def tokenForSearch(self):
|
def tokenForSearch(self):
|
||||||
tp = self.typeProvider
|
tp = self.typeProvider
|
||||||
typeName = tp is None and 'unknown' or str(zapi.getName(tp))
|
typeName = tp is None and 'unknown' or str(getName(tp))
|
||||||
return ':'.join(('loops', self.qualifiers[0], typeName,))
|
return ':'.join(('loops', self.qualifiers[0], typeName,))
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def typeInterface(self):
|
def typeInterface(self):
|
||||||
adapter = zapi.queryAdapter(self.typeProvider, ITypeConcept)
|
adapter = component.queryAdapter(self.typeProvider, ITypeConcept)
|
||||||
if adapter is not None:
|
if adapter is not None:
|
||||||
return removeSecurityProxy(adapter.typeInterface)
|
return removeSecurityProxy(adapter.typeInterface)
|
||||||
else:
|
else:
|
||||||
conceptType = self.typeProvider
|
if self.typeProvider is self.typeConcept:
|
||||||
typeConcept = self.root.getConceptManager().getTypeConcept()
|
return ITypeConcept # typeConcept always is a type concept
|
||||||
if conceptType is typeConcept:
|
|
||||||
return ITypeConcept
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def qualifiers(self):
|
def qualifiers(self):
|
||||||
ti = self.typeInterface
|
ti = self.typeInterface
|
||||||
if ti is None or not issubclass(ti, IResourceAdapter):
|
if ti is None or not issubclass(ti, IResourceAdapter):
|
||||||
return ('concept',)
|
qu = ['concept',]
|
||||||
return ('resource',)
|
else:
|
||||||
|
qu = ['resource',]
|
||||||
|
# check typeProvider for additional qualifiers:
|
||||||
|
if self.typeProvider in (self.typeConcept, self.predicateType,):
|
||||||
|
qu.append('system')
|
||||||
|
# how to set a type to 'hidden'?
|
||||||
|
return tuple(qu)
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def factory(self):
|
def factory(self):
|
||||||
|
@ -91,10 +97,6 @@ class LoopsType(BaseType):
|
||||||
def defaultContainer(self):
|
def defaultContainer(self):
|
||||||
return self.root[self.containerMapping.get(self.qualifiers[0], 'concept')]
|
return self.root[self.containerMapping.get(self.qualifiers[0], 'concept')]
|
||||||
|
|
||||||
@Lazy
|
|
||||||
def root(self):
|
|
||||||
return self.context.getLoopsRoot()
|
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def typeProvider(self):
|
def typeProvider(self):
|
||||||
# TODO: unify this type attribute naming...
|
# TODO: unify this type attribute naming...
|
||||||
|
@ -115,6 +117,20 @@ class LoopsType(BaseType):
|
||||||
result['default'].append(opt)
|
result['default'].append(opt)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
# general infos
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def root(self):
|
||||||
|
return self.context.getLoopsRoot()
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def typeConcept(self):
|
||||||
|
return self.root.getConceptManager().getTypeConcept()
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def predicateType(self):
|
||||||
|
return self.root.getConceptManager().getPredicateType()
|
||||||
|
|
||||||
|
|
||||||
class LoopsTypeInfo(LoopsType):
|
class LoopsTypeInfo(LoopsType):
|
||||||
""" The type info class used by the type manager for listing types.
|
""" The type info class used by the type manager for listing types.
|
||||||
|
@ -144,13 +160,10 @@ class ConceptTypeInfo(LoopsTypeInfo):
|
||||||
|
|
||||||
class ResourceType(LoopsType):
|
class ResourceType(LoopsType):
|
||||||
""" The 'old-style' resource type - different classes (Document, MediaAsset)
|
""" The 'old-style' resource type - different classes (Document, MediaAsset)
|
||||||
per type. Will be replaced by new style types that are governed by
|
per type. Are replaced by new style types that are governed by
|
||||||
type concepts as is already the case for concepts.
|
type concepts as is already the case for concepts.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#adapts(IResource)
|
|
||||||
|
|
||||||
#typeTitles = {'MediaAsset': u'Media Asset'}
|
|
||||||
typeTitles = {}
|
typeTitles = {}
|
||||||
|
|
||||||
typeInterface = None
|
typeInterface = None
|
||||||
|
@ -165,8 +178,6 @@ class ResourceType(LoopsType):
|
||||||
@Lazy
|
@Lazy
|
||||||
def token(self):
|
def token(self):
|
||||||
return '.'.join((self.factory.__module__, self.className))
|
return '.'.join((self.factory.__module__, self.className))
|
||||||
#cn = self.className
|
|
||||||
#return '/'.join(('.loops/resources', cn.lower(),))
|
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def tokenForSearch(self):
|
def tokenForSearch(self):
|
||||||
|
@ -240,7 +251,7 @@ class TypeConcept(AdapterBase):
|
||||||
|
|
||||||
implements(ITypeConcept)
|
implements(ITypeConcept)
|
||||||
|
|
||||||
_schemas = list(ITypeConcept) + list(IConcept)
|
_contextAttributes = list(ITypeConcept) + list(IConcept)
|
||||||
|
|
||||||
def getTypeInterface(self):
|
def getTypeInterface(self):
|
||||||
ti = getattr(self.context, '_typeInterface', None)
|
ti = getattr(self.context, '_typeInterface', None)
|
||||||
|
@ -255,10 +266,8 @@ class TypeConcept(AdapterBase):
|
||||||
|
|
||||||
def getOptions(self):
|
def getOptions(self):
|
||||||
return getattr(self.context, '_options', [])
|
return getattr(self.context, '_options', [])
|
||||||
#return super(TypeConcept, self).options or []
|
|
||||||
def setOptions(self, value):
|
def setOptions(self, value):
|
||||||
self.context._options = value
|
self.context._options = value
|
||||||
#super(TypeConcept, self).options = value
|
|
||||||
options = property(getOptions, setOptions)
|
options = property(getOptions, setOptions)
|
||||||
|
|
||||||
|
|
||||||
|
|
12
util.py
12
util.py
|
@ -36,8 +36,16 @@ _ = MessageFactory('zope') # it's easier not use a special i18n domain...
|
||||||
class KeywordVocabulary(vocabulary.SimpleVocabulary):
|
class KeywordVocabulary(vocabulary.SimpleVocabulary):
|
||||||
|
|
||||||
def __init__(self, items, *interfaces):
|
def __init__(self, items, *interfaces):
|
||||||
terms = [vocabulary.SimpleTerm(token, token, title)
|
""" ``items`` may be a tuple of (token, title) or a dictionary
|
||||||
for token, title in items]
|
with corresponding elements named 'token' and 'title'.
|
||||||
|
"""
|
||||||
|
terms = []
|
||||||
|
for t in items:
|
||||||
|
if type(t) is dict:
|
||||||
|
token, title = t['token'], t['title']
|
||||||
|
else:
|
||||||
|
token, title = t
|
||||||
|
terms.append(vocabulary.SimpleTerm(token, token, title))
|
||||||
super(KeywordVocabulary, self).__init__(terms, *interfaces)
|
super(KeywordVocabulary, self).__init__(terms, *interfaces)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue