Extended interfaces for IRelation and IRelationsRegistry (still without real implementation); added IMonadicRelation
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@677 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
d3aba77217
commit
bc4a012b4f
4 changed files with 100 additions and 21 deletions
|
@ -21,10 +21,62 @@ You are now ready to retrieve relations by using the relations registry's
|
|||
|
||||
You may also like to read the file concepts.txt that gives you some more basic
|
||||
ideas about the relation package.
|
||||
|
||||
|
||||
Relations Management: create - register - query
|
||||
===============================================
|
||||
|
||||
A Basic API for Relation Management
|
||||
===================================
|
||||
|
||||
In object-oriented programming you usually don't care explicitly about
|
||||
relations: you just assign an object to an attribute of another object
|
||||
and you have created a relation beween these two objects.
|
||||
|
||||
An example: Let's have two classes, Person and City, and we want to store the
|
||||
fact that a person lives in a certain city. So if ``clark`` is an instance
|
||||
of Person and ``washington`` an instance of City we can just say:
|
||||
``clark.city = washington``.
|
||||
|
||||
This works fine (even when you are dealing with persistent objects in Zope)
|
||||
and is the standard way of establishing a relation in an object-oriented
|
||||
programming language.
|
||||
|
||||
But there are scenarios where this is not sufficient and you have to
|
||||
care explicitly about relations.
|
||||
|
||||
One would be the requirement to get all inhabitants of Washington: You could
|
||||
of course do this by collecting all persons and check which ones have
|
||||
set it's ``city`` attribute to ``washington``. This approach poses (at least)
|
||||
two problems:
|
||||
|
||||
- how can I find all instances of the Person class?
|
||||
|
||||
- depending on the numbers of persons in my system checking all might take a
|
||||
tremendous long time.
|
||||
|
||||
You can easiliy resolve these problems by providing a corresponding attribute
|
||||
on the City class, something like ``washington.inhabitants = [clark]`` and add
|
||||
a person to this list every time you assign ``washington`` to a person's
|
||||
``city`` attribute.
|
||||
|
||||
Of course there are other things to consider, e.g. how to handle deletions
|
||||
of objects.
|
||||
|
||||
But for this simple kind of relationships just connecting two objects you
|
||||
could in fact solve all this problems without the need for a special
|
||||
relation management framework. Nevertheless, as this is a common pattern,
|
||||
it would be helpful to have an ageed-upon standard how to handle such
|
||||
cases; this might deal with the automatic housekeeping of redundant
|
||||
assignments as well as with the deletion problem.
|
||||
|
||||
Such a standard - and a corresponding relation management framework - is
|
||||
getting really important when we deal with more complex use cases - involving
|
||||
e.g. triadic relations (connecting three objects) like in
|
||||
"kirk is the child of audrey and clark" or if we want the relation to carry
|
||||
additional information, e.g. like in
|
||||
"clark lived in washington from 1999 to 2003".
|
||||
|
||||
|
||||
Relation Management at Work: create - register - query
|
||||
======================================================
|
||||
|
||||
>>> from zope.app.testing.placelesssetup import setUp
|
||||
>>> setUp()
|
||||
|
|
|
@ -38,6 +38,9 @@ class Relation(Persistent):
|
|||
def getPredicateName(cls):
|
||||
return '%s.%s' % (cls.__module__, cls.__name__)
|
||||
|
||||
def validate(self, registry=None):
|
||||
return True
|
||||
|
||||
|
||||
class DyadicRelation(Relation):
|
||||
|
||||
|
|
|
@ -28,17 +28,6 @@ from zope.app.event.interfaces import IObjectEvent
|
|||
|
||||
# relation interfaces
|
||||
|
||||
class IPredicate(Interface):
|
||||
""" A predicate signifies a relationship. This may be implemented
|
||||
directly as a relation class, or the relation object may
|
||||
hold the predicate as an attribute.
|
||||
"""
|
||||
|
||||
def getPredicateName():
|
||||
""" Return this predicate as a string that may be used for indexing.
|
||||
"""
|
||||
|
||||
|
||||
class IRelation(Interface):
|
||||
""" Base interface for relations.
|
||||
"""
|
||||
|
@ -47,6 +36,24 @@ class IRelation(Interface):
|
|||
""" Return the predicate of this relation as a string that may be
|
||||
used for indexing.
|
||||
"""
|
||||
|
||||
def validate(registry=None):
|
||||
""" Return True if this relation is valid.
|
||||
|
||||
If the registry argument is provided the check should be done
|
||||
with respect to this relation registry, e.g. to
|
||||
"""
|
||||
|
||||
|
||||
class IMonadicRelation(IRelation):
|
||||
""" Relation with just one object.
|
||||
|
||||
While a monadic relation could be easily represented by an attribute
|
||||
or an annotation, monadic relations are e.g. useful when working with
|
||||
an ontology-driven higher-level relation framework.
|
||||
"""
|
||||
|
||||
first = Attribute('First and only object that belongs to the relation.')
|
||||
|
||||
|
||||
class IDyadicRelation(IRelation):
|
||||
|
@ -64,6 +71,17 @@ class ITriadicRelation(IDyadicRelation):
|
|||
third = Attribute('Third object that belongs to the relation.')
|
||||
|
||||
|
||||
class IPredicate(Interface):
|
||||
""" A predicate signifies a relationship. This may be implemented
|
||||
directly as a relation class, or the relation object may
|
||||
hold the predicate as an attribute.
|
||||
"""
|
||||
|
||||
def getPredicateName():
|
||||
""" Return this predicate as a string that may be used for indexing.
|
||||
"""
|
||||
|
||||
|
||||
# event interfaces
|
||||
|
||||
class IRelationInvalidatedEvent(IObjectEvent):
|
||||
|
@ -92,16 +110,22 @@ class IRelationsRegistryQuery(Interface):
|
|||
""" Interface for querying a relations registry.
|
||||
"""
|
||||
|
||||
def query(**kw):
|
||||
def query(relation=None, **kw):
|
||||
""" Return a sequence of relations that fulfill the criteria given.
|
||||
|
||||
Example: rr.queryRelations(first=someObject, second=anotherObject,
|
||||
relationship=SomeRelationClass)
|
||||
You may provide a relation object as an example that specifies the
|
||||
search criteria, i.e. its predicate and first, second or third
|
||||
attribute will be used for searching, or explicit criteria
|
||||
via keyword arguments.
|
||||
|
||||
Example for using keyword criteria:
|
||||
rr.queryRelations(first=someObject, second=anotherObject,
|
||||
relationship=SomeRelationClass)
|
||||
"""
|
||||
|
||||
|
||||
class IRelationsRegistry(IRelationsRegistryUpdate, IRelationsRegistryQuery):
|
||||
""" Local utility for registering (cataloguing) and searching relations.
|
||||
""" A registry for registering and searching relations typically
|
||||
implemented as a local utility .
|
||||
"""
|
||||
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class DummyRelationsRegistry(object):
|
|||
if relation in self.relations:
|
||||
self.relations.remove(relation)
|
||||
|
||||
def query(self, **kw):
|
||||
def query(self, example=None, **kw):
|
||||
result = []
|
||||
for r in self.relations:
|
||||
hit = True
|
||||
|
@ -89,7 +89,7 @@ class RelationsRegistry(Catalog):
|
|||
def unregister(self, relation):
|
||||
self.unindex_doc(zapi.getUtility(IIntIds).getId(relation))
|
||||
|
||||
def query(self, **kw):
|
||||
def query(self, example=None, **kw):
|
||||
for k in kw:
|
||||
if k == 'relationship':
|
||||
quString = kw[k].getPredicateName()
|
||||
|
|
Loading…
Add table
Reference in a new issue