diff --git a/common.py b/common.py index c4b866f..763c8ac 100644 --- a/common.py +++ b/common.py @@ -219,9 +219,11 @@ class NameChooser(BaseNameChooser): '\xdc': 'Ue', '\xfc': 'ue', '\xdf': 'ss'} -# virtual attributes +# virtual attributes/properties -class ContainerAttribute(object): +#class ContainerAttribute(object): +#class ContainedCollection(object): +class TypeInstances(object): """ Use objects within a ConceptManager object for a collection attribute. """ @@ -237,6 +239,14 @@ class ContainerAttribute(object): def typeConcept(self): return self.context[self.typeName] + @Lazy + def typeToken(self): + return 'loops:concept:' + self.typeName + + @Lazy + def typePredicate(self): + return self.context.getTypePredicate() + def create(self, id, **kw): from loops.concept import Concept from loops.setup import addAndConfigureObject @@ -250,11 +260,17 @@ class ContainerAttribute(object): del self.context[self.prefix + id] def get(self, id, default=None, langInfo=None): - return adapted(self.context.get(self.prefix + id, default), - langInfo=self.langInfo) + #return adapted(self.context.get(self.prefix + id, default), + # langInfo=self.langInfo) + from loops.expert import query + result = (query.Identifier(id) & query.Type(self.typeToken)).apply() + for obj in query.getObjects(result): + return adapted(obj, langInfo=self.langInfo) + else: + return default def __iter__(self): - for c in self.typeConcept.getChildren([self.context.getTypePredicate()]): + for c in self.typeConcept.getChildren([self.typePredicate]): yield adapted(c, langInfo=self.langInfo) @@ -318,6 +334,29 @@ class ChildRelationSet(RelationSet): yield adapted(c, langInfo=self.langInfo) +# property descriptors + +class RelationSetProperty(object): + + def __init__(self, predicateName): + self.predicateName = predicateName + + def __get__(self, inst, class_=None): + if inst is None: + return self + return self.factory(inst, self.predicateName) + + +class ParentRelationSetProperty(RelationSetProperty): + + factory = ParentRelationSet + + +class ChildRelationSetProperty(RelationSetProperty): + + factory = ChildRelationSet + + # caching (TBD) def cached(obj): diff --git a/concept.py b/concept.py index 4321f70..b41d691 100644 --- a/concept.py +++ b/concept.py @@ -397,13 +397,18 @@ class IndexAttributes(object): def __init__(self, context): self.context = context + @Lazy + def adapted(self): + return adapted(self.context) + def text(self): - ctx = self.context + #ctx = self.context #return ' '.join((getName(ctx), ctx.title,)) - description = ctx.description + description = self.context.description if isinstance(description, I18NValue): description = ' '.join(description.values()) - actx = adapted(ctx) + #actx = adapted(ctx) + actx = self.adapted indexAttrs = getattr(actx, '_textIndexAttributes', ()) #return ' '.join([getName(ctx), ctx.title, ctx.description] + return ' '.join([self.title(), description] + @@ -431,6 +436,12 @@ class IndexAttributes(object): creators.append(principal.title) return creators + def identifier(self): + id = getattr(self.adapted, 'identifier', None) + if id is None: + return getName(self) + return id + # events diff --git a/expert/query.py b/expert/query.py index f7a0cec..3519deb 100644 --- a/expert/query.py +++ b/expert/query.py @@ -41,6 +41,7 @@ from loops import util titleIndex = ('', 'loops_title') textIndex = ('', 'loops_text') typeIndex = ('', 'loops_type') +identifierIndex = ('', 'loops_identifier') stateIndex = ('', 'loops_state') @@ -54,6 +55,10 @@ def Title(value): def Text(value): return BaseText(textIndex, value) +@implementer(IQuery) +def Identifier(value): + return Eq(identifierIndex, value) + @implementer(IQuery) def Type(value): if value.endswith('*'): diff --git a/interfaces.py b/interfaces.py index b4fdeda..24eb26a 100644 --- a/interfaces.py +++ b/interfaces.py @@ -586,13 +586,13 @@ class IConceptRelation(IDyadicRelation): # interfaces for catalog indexes class IIndexAttributes(Interface): - """ Attributes odr methods providing index values. Typically provided + """ Attributes or methods providing index values. Typically provided by an adapter. """ def title(): """ Return a text containing title and similar attributes to be - indexed by a full-text index. + indexed by the title index. """ def text(): @@ -603,6 +603,11 @@ class IIndexAttributes(Interface): """ Return a string that identifies the type of the object. """ + def identifier(): + """ Returns a value that may be used for identifying an object within + a restricted range, e.g. the instances of a type. + """ + # types stuff diff --git a/resource.py b/resource.py index 1c05fc9..728554d 100644 --- a/resource.py +++ b/resource.py @@ -535,6 +535,9 @@ class IndexAttributes(object): creators.append(principal.title) return creators + def identifier(self): + return getName(self) + class ResourceTypeSourceList(object): diff --git a/tests/setup.py b/tests/setup.py index 2102d1d..d056dcb 100644 --- a/tests/setup.py +++ b/tests/setup.py @@ -157,6 +157,7 @@ class TestSite(object): component.provideUtility(catalog, ICatalog) catalog['loops_title'] = TextIndex('title', IIndexAttributes, True) catalog['loops_text'] = TextIndex('text', IIndexAttributes, True) + catalog['loops_identifier'] = FieldIndex('identifier', IIndexAttributes, True) catalog['loops_type'] = FieldIndex('tokenForSearch', IType, False) catalog['loops_state'] = KeywordIndex('tokens', IStatefulIndexInfo, False) component.provideAdapter(ConceptIndexAttributes)