entity.py
changeset 2968 0e3460341023
parent 2880 bfc8e1831290
parent 2942 77ebdbe93cf8
child 3023 7864fee8b4ec
equal deleted inserted replaced
2902:dd9f2dd02f85 2968:0e3460341023
    64     __select__ = yes()
    64     __select__ = yes()
    65 
    65 
    66     # class attributes that must be set in class definition
    66     # class attributes that must be set in class definition
    67     rest_attr = None
    67     rest_attr = None
    68     fetch_attrs = None
    68     fetch_attrs = None
    69     skip_copy_for = ()
    69     skip_copy_for = ('in_state',)
    70     # class attributes set automatically at registration time
    70     # class attributes set automatically at registration time
    71     e_schema = None
    71     e_schema = None
    72 
    72 
    73     @classmethod
    73     @classmethod
    74     def __initialize__(cls, schema):
    74     def __initialize__(cls, schema):
    81         for rschema, _ in eschema.attribute_definitions():
    81         for rschema, _ in eschema.attribute_definitions():
    82             if rschema.type == 'eid':
    82             if rschema.type == 'eid':
    83                 continue
    83                 continue
    84             setattr(cls, rschema.type, Attribute(rschema.type))
    84             setattr(cls, rschema.type, Attribute(rschema.type))
    85         mixins = []
    85         mixins = []
    86         for rschema, _, x in eschema.relation_definitions():
    86         for rschema, _, role in eschema.relation_definitions():
    87             if (rschema, x) in MI_REL_TRIGGERS:
    87             if (rschema, role) in MI_REL_TRIGGERS:
    88                 mixin = MI_REL_TRIGGERS[(rschema, x)]
    88                 mixin = MI_REL_TRIGGERS[(rschema, role)]
    89                 if not (issubclass(cls, mixin) or mixin in mixins): # already mixed ?
    89                 if not (issubclass(cls, mixin) or mixin in mixins): # already mixed ?
    90                     mixins.append(mixin)
    90                     mixins.append(mixin)
    91                 for iface in getattr(mixin, '__implements__', ()):
    91                 for iface in getattr(mixin, '__implements__', ()):
    92                     if not interface.implements(cls, iface):
    92                     if not interface.implements(cls, iface):
    93                         interface.extend(cls, iface)
    93                         interface.extend(cls, iface)
    94             if x == 'subject':
    94             if role == 'subject':
    95                 setattr(cls, rschema.type, SubjectRelation(rschema))
    95                 setattr(cls, rschema.type, SubjectRelation(rschema))
    96             else:
    96             else:
    97                 attr = 'reverse_%s' % rschema.type
    97                 attr = 'reverse_%s' % rschema.type
    98                 setattr(cls, attr, ObjectRelation(rschema))
    98                 setattr(cls, attr, ObjectRelation(rschema))
    99         if mixins:
    99         if mixins:
   150             if not rschema.is_final():
   150             if not rschema.is_final():
   151                 # XXX this does not handle several destination types
   151                 # XXX this does not handle several destination types
   152                 desttype = rschema.objects(eschema.type)[0]
   152                 desttype = rschema.objects(eschema.type)[0]
   153                 card = rschema.rproperty(eschema, desttype, 'cardinality')[0]
   153                 card = rschema.rproperty(eschema, desttype, 'cardinality')[0]
   154                 if card not in '?1':
   154                 if card not in '?1':
   155                     self.warning('bad relation %s specified in fetch attrs for %s',
   155                     cls.warning('bad relation %s specified in fetch attrs for %s',
   156                                  attr, self.__class__)
   156                                  attr, cls)
   157                     selection.pop()
   157                     selection.pop()
   158                     restrictions.pop()
   158                     restrictions.pop()
   159                     continue
   159                     continue
   160                 # XXX we need outer join in case the relation is not mandatory
   160                 # XXX we need outer join in case the relation is not mandatory
   161                 # (card == '?')  *or if the entity is being added*, since in
   161                 # (card == '?')  *or if the entity is being added*, since in
   377             # skip already defined relations
   377             # skip already defined relations
   378             if getattr(self, rschema.type):
   378             if getattr(self, rschema.type):
   379                 continue
   379                 continue
   380             if rschema.type in self.skip_copy_for:
   380             if rschema.type in self.skip_copy_for:
   381                 continue
   381                 continue
   382             if rschema.type == 'in_state':
       
   383                 # if the workflow is defining an initial state (XXX AND we are
       
   384                 # not in the managers group? not done to be more consistent)
       
   385                 # don't try to copy in_state
       
   386                 if execute('Any S WHERE S state_of ET, ET initial_state S,'
       
   387                            'ET name %(etype)s', {'etype': str(self.e_schema)}):
       
   388                     continue
       
   389             # skip composite relation
   382             # skip composite relation
   390             if self.e_schema.subjrproperty(rschema, 'composite'):
   383             if self.e_schema.subjrproperty(rschema, 'composite'):
   391                 continue
   384                 continue
   392             # skip relation with card in ?1 else we either change the copied
   385             # skip relation with card in ?1 else we either change the copied
   393             # object (inlined relation) or inserting some inconsistency
   386             # object (inlined relation) or inserting some inconsistency
   514             # handle attributes
   507             # handle attributes
   515             for i in xrange(1, lastattr):
   508             for i in xrange(1, lastattr):
   516                 self[str(selected[i-1][0])] = rset[i]
   509                 self[str(selected[i-1][0])] = rset[i]
   517             # handle relations
   510             # handle relations
   518             for i in xrange(lastattr, len(rset)):
   511             for i in xrange(lastattr, len(rset)):
   519                 rtype, x = selected[i-1][0]
   512                 rtype, role = selected[i-1][0]
   520                 value = rset[i]
   513                 value = rset[i]
   521                 if value is None:
   514                 if value is None:
   522                     rrset = ResultSet([], rql, {'x': self.eid})
   515                     rrset = ResultSet([], rql, {'x': self.eid})
   523                     self.req.decorate_rset(rrset)
   516                     self.req.decorate_rset(rrset)
   524                 else:
   517                 else:
   525                     rrset = self.req.eid_rset(value)
   518                     rrset = self.req.eid_rset(value)
   526                 self.set_related_cache(rtype, x, rrset)
   519                 self.set_related_cache(rtype, role, rrset)
   527 
   520 
   528     def get_value(self, name):
   521     def get_value(self, name):
   529         """get value for the attribute relation <name>, query the repository
   522         """get value for the attribute relation <name>, query the repository
   530         to get the value if necessary.
   523         to get the value if necessary.
   531 
   524 
   710             self._related_cache = {}
   703             self._related_cache = {}
   711         else:
   704         else:
   712             assert role
   705             assert role
   713             self._related_cache.pop('%s_%s' % (rtype, role), None)
   706             self._related_cache.pop('%s_%s' % (rtype, role), None)
   714 
   707 
       
   708     def clear_all_caches(self):
       
   709         self.clear()
       
   710         for rschema, _, role in self.e_schema.relation_definitions():
       
   711             self.clear_related_cache(rschema.type, role)
       
   712 
   715     # raw edition utilities ###################################################
   713     # raw edition utilities ###################################################
   716 
   714 
   717     def set_attributes(self, _cw_unsafe=False, **kwargs):
   715     def set_attributes(self, _cw_unsafe=False, **kwargs):
   718         assert kwargs
   716         assert kwargs
   719         relations = []
   717         relations = []