Commit 4d594631 authored by Sylvain's avatar Sylvain
Browse files

support for entities whose fulltext content should be indexed on a related

entity, using new fulltext_container attribute on RelationSchema instance
and new fulltext_relations and fulltext_containers methods on EntitySchema
parent 3c4b362d8c5f
......@@ -4,6 +4,9 @@ ChangeLog for yams
--
* fix a bug in entity validation : should convert value to the correct
python type before checking constraints
* support for entities whose fulltext content should be indexed on a related
entity, using new fulltext_container attribute on RelationSchema instance
and new fulltext_relations and fulltext_containers methods on EntitySchema
2008-02-15 -- 0.16.0
* nicer schema image view
......
......@@ -24,7 +24,7 @@ __all__ = ('ObjectRelation', 'SubjectRelation', 'BothWayRelation',
ETYPE_PROPERTIES = ('meta', 'description', 'permissions')
# don't put description inside, handled "manually"
RTYPE_PROPERTIES = ('meta', 'symetric', 'inlined', 'permissions')
RTYPE_PROPERTIES = ('meta', 'symetric', 'inlined', 'fulltext_container', 'permissions')
RDEF_PROPERTIES = ('cardinality', 'constraints', 'composite',
'order', 'default', 'uid', 'indexed', 'uid',
'fulltextindexed', 'internationalizable')
......@@ -229,6 +229,7 @@ class EntityType(Definition):
class RelationType(Definition):
symetric = MARKER
inlined = MARKER
fulltext_container = MARKER
def __init__(self, name=None, **kwargs):
super(RelationType, self).__init__(name)
......
......@@ -356,24 +356,42 @@ class EntitySchema(ERSchema):
for rschema in self.object_relations():
yield rschema, rschema.subjects(self), 'object'
def main_attribute(self):
"""convenience method that returns the *main* (i.e. the first non meta)
attribute defined in the entity schema
"""
for rschema, _ in self.attribute_definitions():
if not rschema.meta:
# XXX return rschema.type for bw compat ?
return rschema
def indexable_attributes(self):
"""return the name of relations to index"""
"""return the (name, role) of relations to index"""
assert not self.is_final()
for rschema in self.subject_relations():
if rschema.is_final():
if self.rproperty(rschema, 'fulltextindexed'):
# XXX return rschema.type for bw compat ?
yield rschema
def fulltext_relations(self):
"""return the (name, role) of relations to index"""
assert not self.is_final()
for rschema in self.subject_relations():
if not rschema.is_final() and rschema.fulltext_container == 'subject':
yield rschema, 'subject'
for rschema in self.object_relations():
if rschema.fulltext_container == 'object':
yield rschema, 'object'
def fulltext_containers(self):
"""return relations whose extremity points to an entity that should
contains the full text index content of entities of this type
"""
for rschema in self.subject_relations():
if rschema.fulltext_container == 'object':
yield rschema, 'object'
for rschema in self.object_relations():
if rschema.fulltext_container == 'subject':
yield rschema, 'subject'
def defaults(self):
"""return an iterator on (attribute name, default value)"""
......@@ -382,7 +400,6 @@ class EntitySchema(ERSchema):
if rschema.is_final():
value = self.default(rschema)
if value is not None:
# XXX return rschema.type for bw compat ?
yield rschema, value
def default(self, rtype):
......@@ -531,6 +548,9 @@ class RelationSchema(ERSchema):
# if this relation is symetric/inlined
self.symetric = rdef.symetric or False
self.inlined = rdef.inlined or False
# if full text content of subject/object entity should be added
# to other side entity (the container)
self.fulltext_container = rdef.fulltext_container or None
# if this relation is an attribute relation
self.final = False
# mapping to subject/object with schema as key
......@@ -685,7 +705,7 @@ class RelationSchema(ERSchema):
raise KeyError('%s %s %s' % (subject, self, object))
def rproperty(self, subject, object, property):
"""return the properties dictionary of a relation"""
"""return the property for a relation definition"""
return self.rproperties(subject, object).get(property)
def set_rproperty(self, subject, object, pname, value):
......@@ -696,7 +716,7 @@ class RelationSchema(ERSchema):
def init_rproperties(self, subject, object, rdef):
key = subject, object
if key in self._rproperties:
msg = '%s already defined for %s' % (key, self)
msg = '(%s, %s) already defined for %s' % (subject, object, self)
raise BadSchemaDefinition(msg)
self._rproperties[key] = {}
for prop, default in self.rproperty_defs(key[1]).iteritems():
......
......@@ -11,6 +11,7 @@ class require_permission(RelationType):
"""link a permission to the entity. This permission should be used in the
security definition of the entity's type to be useful.
"""
fulltext_container = 'subject'
permissions = {
'read': ('managers', 'users', 'guests'),
'add': ('managers',),
......@@ -26,5 +27,6 @@ class missing_require_permission(RelationDefinition):
class EPermission(MetaEntityType):
"""entity type that may be used to construct some advanced security configuration
"""
name = String(required=True, indexed=True, internationalizable=True, maxsize=100,
name = String(required=True, indexed=True, internationalizable=True,
fulltextindexed=True, maxsize=100,
description=_('name or identifier of the permission'))
......@@ -125,6 +125,23 @@ class SchemaLoaderTC(TestCase):
self.assert_(not eschema.rproperty('sexe', 'fulltextindexed'))
indexable = sorted(eschema.indexable_attributes())
self.assertEquals(['nom', 'prenom', 'titre'], indexable)
self.assertEquals(schema.rschema('works_for').fulltext_container, None)
self.assertEquals(schema.rschema('require_permission').fulltext_container,
'subject')
eschema = schema.eschema('Company')
indexable = sorted(eschema.indexable_attributes())
self.assertEquals([], indexable)
indexable = sorted(eschema.fulltext_relations())
self.assertEquals([('require_permission', 'subject')], indexable)
containers = sorted(eschema.fulltext_containers())
self.assertEquals([], containers)
eschema = schema.eschema('EPermission')
indexable = sorted(eschema.indexable_attributes())
self.assertEquals(['name'], indexable)
indexable = sorted(eschema.fulltext_relations())
self.assertEquals([], indexable)
containers = sorted(eschema.fulltext_containers())
self.assertEquals([('require_permission', 'subject')], containers)
def test_internationalizable(self):
eschema = schema.eschema('Eetype')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment