entity.py
changeset 5556 9ab2b4c74baf
parent 5522 6be95896d49e
child 5557 1a534c596bff
--- a/entity.py	Thu May 20 20:47:13 2010 +0200
+++ b/entity.py	Thu May 20 20:47:55 2010 +0200
@@ -107,10 +107,10 @@
                     if not interface.implements(cls, iface):
                         interface.extend(cls, iface)
             if role == 'subject':
-                setattr(cls, rschema.type, SubjectRelation(rschema))
+                attr = rschema.type
             else:
                 attr = 'reverse_%s' % rschema.type
-                setattr(cls, attr, ObjectRelation(rschema))
+            setattr(cls, attr, Relation(rschema, role))
         if mixins:
             # see etype class instantation in cwvreg.ETypeRegistry.etype_class method:
             # due to class dumping, cls is the generated top level class with actual
@@ -125,6 +125,24 @@
             cls.__bases__ = tuple(mixins)
             cls.info('plugged %s mixins on %s', mixins, cls)
 
+    fetch_attrs = ('modification_date',)
+    @classmethod
+    def fetch_order(cls, attr, var):
+        """class method used to control sort order when multiple entities of
+        this type are fetched
+        """
+        return cls.fetch_unrelated_order(attr, var)
+
+    @classmethod
+    def fetch_unrelated_order(cls, attr, var):
+        """class method used to control sort order when multiple entities of
+        this type are fetched to use in edition (eg propose them to create a
+        new relation on an edited entity).
+        """
+        if attr == 'modification_date':
+            return '%s DESC' % var
+        return None
+
     @classmethod
     def fetch_rql(cls, user, restriction=None, fetchattrs=None, mainvar='X',
                   settype=True, ordermethod='fetch_order'):
@@ -378,6 +396,23 @@
         for attr, value in values.items():
             self[attr] = value # use self.__setitem__ implementation
 
+    def cw_adapt_to(self, interface):
+        """return an adapter the entity to the given interface name.
+
+        return None if it can not be adapted.
+        """
+        try:
+            cache = self._cw_adapters_cache
+        except AttributeError:
+            self._cw_adapters_cache = cache = {}
+        try:
+            return cache[interface]
+        except KeyError:
+            adapter = self._cw.vreg['adapters'].select_or_none(
+                interface, self._cw, entity=self)
+            cache[interface] = adapter
+            return adapter
+
     def rql_set_value(self, attr, value):
         """call by rql execution plan when some attribute is modified
 
@@ -949,6 +984,10 @@
             del self.__unique
         except AttributeError:
             pass
+        try:
+            del self._cw_adapters_cache
+        except AttributeError:
+            pass
 
     # raw edition utilities ###################################################
 
@@ -1038,61 +1077,6 @@
         self.e_schema.check(self, creation=creation, _=_,
                             relations=relations)
 
-    def fti_containers(self, _done=None):
-        if _done is None:
-            _done = set()
-        _done.add(self.eid)
-        containers = tuple(self.e_schema.fulltext_containers())
-        if containers:
-            for rschema, target in containers:
-                if target == 'object':
-                    targets = getattr(self, rschema.type)
-                else:
-                    targets = getattr(self, 'reverse_%s' % rschema)
-                for entity in targets:
-                    if entity.eid in _done:
-                        continue
-                    for container in entity.fti_containers(_done):
-                        yield container
-                        yielded = True
-        else:
-            yield self
-
-    def get_words(self):
-        """used by the full text indexer to get words to index
-
-        this method should only be used on the repository side since it depends
-        on the logilab.database package
-
-        :rtype: list
-        :return: the list of indexable word of this entity
-        """
-        from logilab.database.fti import tokenize
-        # take care to cases where we're modyfying the schema
-        pending = self._cw.transaction_data.setdefault('pendingrdefs', set())
-        words = []
-        for rschema in self.e_schema.indexable_attributes():
-            if (self.e_schema, rschema) in pending:
-                continue
-            try:
-                value = self.printable_value(rschema, format='text/plain')
-            except TransformError:
-                continue
-            except:
-                self.exception("can't add value of %s to text index for entity %s",
-                               rschema, self.eid)
-                continue
-            if value:
-                words += tokenize(value)
-        for rschema, role in self.e_schema.fulltext_relations():
-            if role == 'subject':
-                for entity in getattr(self, rschema.type):
-                    words += entity.get_words()
-            else: # if role == 'object':
-                for entity in getattr(self, 'reverse_%s' % rschema.type):
-                    words += entity.get_words()
-        return words
-
 
 # attribute and relation descriptors ##########################################
 
@@ -1111,13 +1095,13 @@
     def __set__(self, eobj, value):
         eobj[self._attrname] = value
 
+
 class Relation(object):
     """descriptor that controls schema relation access"""
-    _role = None # for pylint
 
-    def __init__(self, rschema):
-        self._rschema = rschema
+    def __init__(self, rschema, role):
         self._rtype = rschema.type
+        self._role = role
 
     def __get__(self, eobj, eclass):
         if eobj is None:
@@ -1129,14 +1113,6 @@
         raise NotImplementedError
 
 
-class SubjectRelation(Relation):
-    """descriptor that controls schema relation access"""
-    _role = 'subject'
-
-class ObjectRelation(Relation):
-    """descriptor that controls schema relation access"""
-    _role = 'object'
-
 from logging import getLogger
 from cubicweb import set_log_methods
 set_log_methods(Entity, getLogger('cubicweb.entity'))