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:
helmutm 2005-11-14 07:39:25 +00:00
parent d3aba77217
commit bc4a012b4f
4 changed files with 100 additions and 21 deletions

View file

@ -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()

View file

@ -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):

View file

@ -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 .
"""

View file

@ -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()