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
|
You may also like to read the file concepts.txt that gives you some more basic
|
||||||
ideas about the relation package.
|
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
|
>>> from zope.app.testing.placelesssetup import setUp
|
||||||
>>> setUp()
|
>>> setUp()
|
||||||
|
|
|
@ -38,6 +38,9 @@ class Relation(Persistent):
|
||||||
def getPredicateName(cls):
|
def getPredicateName(cls):
|
||||||
return '%s.%s' % (cls.__module__, cls.__name__)
|
return '%s.%s' % (cls.__module__, cls.__name__)
|
||||||
|
|
||||||
|
def validate(self, registry=None):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class DyadicRelation(Relation):
|
class DyadicRelation(Relation):
|
||||||
|
|
||||||
|
|
|
@ -28,17 +28,6 @@ from zope.app.event.interfaces import IObjectEvent
|
||||||
|
|
||||||
# relation interfaces
|
# 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):
|
class IRelation(Interface):
|
||||||
""" Base interface for relations.
|
""" Base interface for relations.
|
||||||
"""
|
"""
|
||||||
|
@ -47,6 +36,24 @@ class IRelation(Interface):
|
||||||
""" Return the predicate of this relation as a string that may be
|
""" Return the predicate of this relation as a string that may be
|
||||||
used for indexing.
|
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):
|
class IDyadicRelation(IRelation):
|
||||||
|
@ -64,6 +71,17 @@ class ITriadicRelation(IDyadicRelation):
|
||||||
third = Attribute('Third object that belongs to the relation.')
|
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
|
# event interfaces
|
||||||
|
|
||||||
class IRelationInvalidatedEvent(IObjectEvent):
|
class IRelationInvalidatedEvent(IObjectEvent):
|
||||||
|
@ -92,16 +110,22 @@ class IRelationsRegistryQuery(Interface):
|
||||||
""" Interface for querying a relations registry.
|
""" Interface for querying a relations registry.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def query(**kw):
|
def query(relation=None, **kw):
|
||||||
""" Return a sequence of relations that fulfill the criteria given.
|
""" Return a sequence of relations that fulfill the criteria given.
|
||||||
|
|
||||||
Example: rr.queryRelations(first=someObject, second=anotherObject,
|
You may provide a relation object as an example that specifies the
|
||||||
relationship=SomeRelationClass)
|
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):
|
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:
|
if relation in self.relations:
|
||||||
self.relations.remove(relation)
|
self.relations.remove(relation)
|
||||||
|
|
||||||
def query(self, **kw):
|
def query(self, example=None, **kw):
|
||||||
result = []
|
result = []
|
||||||
for r in self.relations:
|
for r in self.relations:
|
||||||
hit = True
|
hit = True
|
||||||
|
@ -89,7 +89,7 @@ class RelationsRegistry(Catalog):
|
||||||
def unregister(self, relation):
|
def unregister(self, relation):
|
||||||
self.unindex_doc(zapi.getUtility(IIntIds).getId(relation))
|
self.unindex_doc(zapi.getUtility(IIntIds).getId(relation))
|
||||||
|
|
||||||
def query(self, **kw):
|
def query(self, example=None, **kw):
|
||||||
for k in kw:
|
for k in kw:
|
||||||
if k == 'relationship':
|
if k == 'relationship':
|
||||||
quString = kw[k].getPredicateName()
|
quString = kw[k].getPredicateName()
|
||||||
|
|
Loading…
Add table
Reference in a new issue