provide State query and fix bug in state event notification
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2561 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
883656bd1e
commit
45efbd3c6f
5 changed files with 71 additions and 24 deletions
|
@ -27,7 +27,7 @@ configuration):
|
||||||
>>> concepts, resources, views = t.setup()
|
>>> concepts, resources, views = t.setup()
|
||||||
|
|
||||||
>>> len(concepts) + len(resources)
|
>>> len(concepts) + len(resources)
|
||||||
36
|
32
|
||||||
|
|
||||||
>>> loopsRoot = site['loops']
|
>>> loopsRoot = site['loops']
|
||||||
|
|
||||||
|
@ -47,11 +47,11 @@ Type- and text-based queries
|
||||||
>>> from loops.expert import query
|
>>> from loops.expert import query
|
||||||
>>> qu = query.Title('ty*')
|
>>> qu = query.Title('ty*')
|
||||||
>>> list(qu.apply())
|
>>> list(qu.apply())
|
||||||
[0, 1, 47]
|
[0, 1, 45]
|
||||||
|
|
||||||
>>> qu = query.Type('loops:*')
|
>>> qu = query.Type('loops:*')
|
||||||
>>> len(list(qu.apply()))
|
>>> len(list(qu.apply()))
|
||||||
36
|
32
|
||||||
|
|
||||||
>>> qu = query.Type('loops:concept:predicate')
|
>>> qu = query.Type('loops:concept:predicate')
|
||||||
>>> len(list(qu.apply()))
|
>>> len(list(qu.apply()))
|
||||||
|
@ -61,6 +61,53 @@ Type- and text-based queries
|
||||||
>>> list(qu.apply())
|
>>> list(qu.apply())
|
||||||
[1]
|
[1]
|
||||||
|
|
||||||
|
State-based queries
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
>>> qu = query.State('loops.classification_quality', 'new')
|
||||||
|
>>> list(qu.apply())
|
||||||
|
[]
|
||||||
|
|
||||||
|
>>> from cybertools.stateful.publishing import simplePublishing
|
||||||
|
>>> component.provideUtility(simplePublishing(), name='loops.simple_publishing')
|
||||||
|
>>> from loops.organize.stateful.base import SimplePublishable
|
||||||
|
>>> component.provideAdapter(SimplePublishable, name='loops.simple_publishing')
|
||||||
|
>>> from loops.organize.stateful.quality import classificationQuality
|
||||||
|
>>> component.provideUtility(classificationQuality(),
|
||||||
|
... name='loops.classification_quality')
|
||||||
|
>>> from loops.organize.stateful.quality import ClassificationQualityCheckable
|
||||||
|
>>> component.provideAdapter(ClassificationQualityCheckable,
|
||||||
|
... name='loops.classification_quality')
|
||||||
|
|
||||||
|
>>> loopsRoot.options = ['organize.stateful.resource:'
|
||||||
|
... 'loops.classification_quality,loops.simple_publishing']
|
||||||
|
|
||||||
|
>>> from zope.app.catalog.interfaces import ICatalog
|
||||||
|
>>> catalog = component.getUtility(ICatalog)
|
||||||
|
>>> from loops import util
|
||||||
|
|
||||||
|
>>> for r in resources.values():
|
||||||
|
... catalog.index_doc(int(util.getUidForObject(r)), r)
|
||||||
|
|
||||||
|
>>> qu = query.State('loops.classification_quality', 'new')
|
||||||
|
>>> list(qu.apply())
|
||||||
|
[23, 25, 27]
|
||||||
|
|
||||||
|
>>> from cybertools.stateful.interfaces import IStateful
|
||||||
|
>>> statefulD001 = component.getAdapter(resources['d001.txt'], IStateful,
|
||||||
|
... name='loops.classification_quality')
|
||||||
|
|
||||||
|
>>> from loops.organize.stateful.base import handleTransition
|
||||||
|
>>> component.provideHandler(handleTransition)
|
||||||
|
|
||||||
|
>>> statefulD001.doTransition('classify')
|
||||||
|
>>> list(qu.apply())
|
||||||
|
[25, 27]
|
||||||
|
|
||||||
|
>>> qu = query.State('loops.classification_quality', 'classified')
|
||||||
|
>>> list(qu.apply())
|
||||||
|
[23]
|
||||||
|
|
||||||
Relationship-based queries
|
Relationship-based queries
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
|
@ -69,10 +116,10 @@ relations to other objects the expert package provides methods
|
||||||
for selecting and filtering related objects using our basic querying
|
for selecting and filtering related objects using our basic querying
|
||||||
syntax (that in turn is based on hurry.query).
|
syntax (that in turn is based on hurry.query).
|
||||||
|
|
||||||
>>> stateNew = concepts['new']
|
>>> cust1 = concepts['cust1']
|
||||||
>>> qu = query.Resources(stateNew)
|
>>> qu = query.Resources(cust1)
|
||||||
>>> list(qu.apply())
|
>>> list(qu.apply())
|
||||||
[25, 27]
|
[23, 27]
|
||||||
|
|
||||||
Getting objects
|
Getting objects
|
||||||
---------------
|
---------------
|
||||||
|
@ -136,7 +183,7 @@ Organizing Queries and Filters with Query Instances
|
||||||
A query instance consists of
|
A query instance consists of
|
||||||
|
|
||||||
- a base query (a composition of terms)
|
- a base query (a composition of terms)
|
||||||
- one or more query filter that will be joined with the base query
|
- one or more query filters that will be joined with the base query
|
||||||
- a result filter that will be applied to the result set of the
|
- a result filter that will be applied to the result set of the
|
||||||
preceding steps
|
preceding steps
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ $Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from BTrees.IIBTree import IITreeSet
|
from BTrees.IIBTree import IITreeSet
|
||||||
from BTrees.IFBTree import IFBTree, IFTreeSet
|
from BTrees.IFBTree import IFBucket, IFBTree, IFTreeSet
|
||||||
from BTrees.IOBTree import IOBTree
|
from BTrees.IOBTree import IOBucket, IOBTree
|
||||||
from zope import interface, component
|
from zope import interface, component
|
||||||
from zope.app.intid.interfaces import IIntIds
|
from zope.app.intid.interfaces import IIntIds
|
||||||
from zope.component import adapts
|
from zope.component import adapts
|
||||||
|
@ -33,6 +33,7 @@ from zope.cachedescriptors.property import Lazy
|
||||||
|
|
||||||
from cybertools.catalog.query import Term, Eq, Between
|
from cybertools.catalog.query import Term, Eq, Between
|
||||||
from cybertools.catalog.query import Text as BaseText
|
from cybertools.catalog.query import Text as BaseText
|
||||||
|
from cybertools.catalog.query import AnyOf
|
||||||
from loops.expert.interfaces import IQuery
|
from loops.expert.interfaces import IQuery
|
||||||
from loops.security.common import canListObject
|
from loops.security.common import canListObject
|
||||||
from loops import util
|
from loops import util
|
||||||
|
@ -40,8 +41,11 @@ from loops import util
|
||||||
titleIndex = ('', 'loops_title')
|
titleIndex = ('', 'loops_title')
|
||||||
textIndex = ('', 'loops_text')
|
textIndex = ('', 'loops_text')
|
||||||
typeIndex = ('', 'loops_type')
|
typeIndex = ('', 'loops_type')
|
||||||
|
stateIndex = ('', 'loops_state')
|
||||||
|
|
||||||
|
|
||||||
|
# standard text/field/keyword index queries
|
||||||
|
|
||||||
@implementer(IQuery)
|
@implementer(IQuery)
|
||||||
def Title(value):
|
def Title(value):
|
||||||
return BaseText(titleIndex, value)
|
return BaseText(titleIndex, value)
|
||||||
|
@ -58,6 +62,12 @@ def Type(value):
|
||||||
return Between(typeIndex, v1, v2)
|
return Between(typeIndex, v1, v2)
|
||||||
return Eq(typeIndex, value)
|
return Eq(typeIndex, value)
|
||||||
|
|
||||||
|
@implementer(IQuery)
|
||||||
|
def State(statesDefinition, value):
|
||||||
|
return AnyOf(stateIndex, ':'.join((statesDefinition, value)))
|
||||||
|
|
||||||
|
|
||||||
|
# concept map queries
|
||||||
|
|
||||||
class ConceptMapTerm(Term):
|
class ConceptMapTerm(Term):
|
||||||
|
|
||||||
|
@ -105,6 +115,8 @@ class Children(ConceptMapTerm):
|
||||||
self.getRecursive(c, result)
|
self.getRecursive(c, result)
|
||||||
|
|
||||||
|
|
||||||
|
# utility functions
|
||||||
|
|
||||||
def getObjects(uids, root=None, checkPermission=canListObject):
|
def getObjects(uids, root=None, checkPermission=canListObject):
|
||||||
intIds = component.getUtility(IIntIds)
|
intIds = component.getUtility(IIntIds)
|
||||||
for uid in uids:
|
for uid in uids:
|
||||||
|
|
|
@ -44,8 +44,6 @@ class TestSite(BaseTestSite):
|
||||||
type=tType)
|
type=tType)
|
||||||
tCustomer = addObject(concepts, Concept, 'customer', title=u'Customer',
|
tCustomer = addObject(concepts, Concept, 'customer', title=u'Customer',
|
||||||
type=tType)
|
type=tType)
|
||||||
tState = addObject(concepts, Concept, 'state', title=u'State',
|
|
||||||
type=tType)
|
|
||||||
tDocumentType = addObject(concepts, Concept, 'documenttype',
|
tDocumentType = addObject(concepts, Concept, 'documenttype',
|
||||||
title=u'Document Type', type=tType)
|
title=u'Document Type', type=tType)
|
||||||
dGeneral = addObject(concepts, Concept, 'general',
|
dGeneral = addObject(concepts, Concept, 'general',
|
||||||
|
@ -53,7 +51,6 @@ class TestSite(BaseTestSite):
|
||||||
dProjects = addObject(concepts, Concept, 'projects',
|
dProjects = addObject(concepts, Concept, 'projects',
|
||||||
title=u'Project Domain', type=tDomain)
|
title=u'Project Domain', type=tDomain)
|
||||||
tCountry.assignParent(dGeneral)
|
tCountry.assignParent(dGeneral)
|
||||||
tState.assignParent(dGeneral)
|
|
||||||
tCustomer.assignParent(dProjects)
|
tCustomer.assignParent(dProjects)
|
||||||
tDocumentType.assignParent(dProjects)
|
tDocumentType.assignParent(dProjects)
|
||||||
|
|
||||||
|
@ -70,12 +67,6 @@ class TestSite(BaseTestSite):
|
||||||
cust1.assignParent(countryDe)
|
cust1.assignParent(countryDe)
|
||||||
cust2.assignParent(countryDe)
|
cust2.assignParent(countryDe)
|
||||||
cust3.assignParent(countryUs)
|
cust3.assignParent(countryUs)
|
||||||
stateNew = addObject(concepts, Concept, 'new',
|
|
||||||
title=u'New', type=tState)
|
|
||||||
stateReleased = addObject(concepts, Concept, 'released',
|
|
||||||
title=u'Released', type=tState)
|
|
||||||
stateObsolete = addObject(concepts, Concept, 'obsolete',
|
|
||||||
title=u'Obsolete', type=tState)
|
|
||||||
dtStudy = addObject(concepts, Concept, 'dt_study',
|
dtStudy = addObject(concepts, Concept, 'dt_study',
|
||||||
title=u'Study', type=tDocumentType)
|
title=u'Study', type=tDocumentType)
|
||||||
dtNote = addObject(concepts, Concept, 'dt_note',
|
dtNote = addObject(concepts, Concept, 'dt_note',
|
||||||
|
@ -86,15 +77,12 @@ class TestSite(BaseTestSite):
|
||||||
|
|
||||||
d001 = resources['d001.txt']
|
d001 = resources['d001.txt']
|
||||||
d001.assignConcept(cust1)
|
d001.assignConcept(cust1)
|
||||||
d001.assignConcept(stateReleased)
|
|
||||||
d001.assignConcept(dtNote)
|
d001.assignConcept(dtNote)
|
||||||
d002 = resources['d002.txt']
|
d002 = resources['d002.txt']
|
||||||
d002.assignConcept(cust3)
|
d002.assignConcept(cust3)
|
||||||
d002.assignConcept(stateNew)
|
|
||||||
d002.assignConcept(dtNote)
|
d002.assignConcept(dtNote)
|
||||||
d003 = resources['d003.txt']
|
d003 = resources['d003.txt']
|
||||||
d003.assignConcept(cust1)
|
d003.assignConcept(cust1)
|
||||||
d003.assignConcept(stateNew)
|
|
||||||
d003.assignConcept(dtStudy)
|
d003.assignConcept(dtStudy)
|
||||||
|
|
||||||
catalog = component.getUtility(ICatalog)
|
catalog = component.getUtility(ICatalog)
|
||||||
|
|
|
@ -95,7 +95,7 @@ later.
|
||||||
... title='DocFive')
|
... title='DocFive')
|
||||||
|
|
||||||
When we change the concept assignments of the resource - i.e. its classification
|
When we change the concept assignments of the resource - i.e. its classification
|
||||||
- the classification quality state changes automaticalls
|
- the classification quality state changes automatically
|
||||||
|
|
||||||
>>> c01.assignResource(doc01)
|
>>> c01.assignResource(doc01)
|
||||||
>>> qcheckedDoc01 = component.getAdapter(doc01, IStateful,
|
>>> qcheckedDoc01 = component.getAdapter(doc01, IStateful,
|
||||||
|
|
|
@ -61,9 +61,9 @@ class StatefulResourceIndexInfo(IndexInfo):
|
||||||
|
|
||||||
|
|
||||||
@adapter(IResource, ITransitionEvent)
|
@adapter(IResource, ITransitionEvent)
|
||||||
def handleTransition(self, obj, event):
|
def handleTransition(obj, event):
|
||||||
previous = event.previousState
|
previous = event.previousState
|
||||||
next = event.transition.targetState
|
next = event.transition.targetState
|
||||||
if next != previous:
|
if next != previous:
|
||||||
cat = getUtility(ICatalog)
|
cat = component.getUtility(ICatalog)
|
||||||
cat.index_doc(int(util.getUidForObject(obj)), obj)
|
cat.index_doc(int(util.getUidForObject(obj)), obj)
|
||||||
|
|
Loading…
Add table
Reference in a new issue