entity.py
changeset 3890 d7a270f50f54
parent 3777 3ef8cdb5fb1c
parent 3877 7ca53fc72a0a
child 3998 94cc7cad3d2d
--- a/entity.py	Sun Nov 08 21:53:18 2009 +0100
+++ b/entity.py	Fri Nov 20 19:35:54 2009 +0100
@@ -34,7 +34,7 @@
 def greater_card(rschema, subjtypes, objtypes, index):
     for subjtype in subjtypes:
         for objtype in objtypes:
-            card = rschema.rproperty(subjtype, objtype, 'cardinality')[index]
+            card = rschema.rdef(subjtype, objtype).cardinality[index]
             if card in '+*':
                 return card
     return '1'
@@ -144,7 +144,8 @@
                 cls.warning('skipping fetch_attr %s defined in %s (not found in schema)',
                             attr, cls.__regid__)
                 continue
-            if not user.matching_groups(rschema.get_groups('read')):
+            rdef = eschema.rdef(attr)
+            if not user.matching_groups(rdef.get_groups('read')):
                 continue
             var = varmaker.next()
             selection.append(var)
@@ -153,7 +154,7 @@
             if not rschema.final:
                 # XXX this does not handle several destination types
                 desttype = rschema.objects(eschema.type)[0]
-                card = rschema.rproperty(eschema, desttype, 'cardinality')[0]
+                card = rdef.cardinality[0]
                 if card not in '?1':
                     cls.warning('bad relation %s specified in fetch attrs for %s',
                                  attr, cls)
@@ -256,10 +257,10 @@
             self._cw.local_perm_cache.pop((rqlexpr.eid, (('x', self.eid),)), None)
 
     def check_perm(self, action):
-        self.e_schema.check_perm(self._cw, action, self.eid)
+        self.e_schema.check_perm(self._cw, action, eid=self.eid)
 
     def has_perm(self, action):
-        return self.e_schema.has_perm(self._cw, action, self.eid)
+        return self.e_schema.has_perm(self._cw, action, eid=self.eid)
 
     def view(self, vid, __registry='views', **kwargs):
         """shortcut to apply a view on this entity"""
@@ -339,11 +340,11 @@
             return u''
         if attrtype is None:
             attrtype = self.e_schema.destination(attr)
-        props = self.e_schema.rproperties(attr)
+        props = self.e_schema.rdef(attr)
         if attrtype == 'String':
             # internalinalized *and* formatted string such as schema
             # description...
-            if props.get('internationalizable'):
+            if props.internationalizable:
                 value = self._cw._(value)
             attrformat = self.attr_metadata(attr, 'format')
             if attrformat:
@@ -391,11 +392,12 @@
             if rschema.type in self.skip_copy_for:
                 continue
             # skip composite relation
-            if self.e_schema.subjrproperty(rschema, 'composite'):
+            rdef = self.e_schema.rdef(rschema)
+            if rdef.composite:
                 continue
             # skip relation with card in ?1 else we either change the copied
             # object (inlined relation) or inserting some inconsistency
-            if self.e_schema.subjrproperty(rschema, 'cardinality')[1] in '?1':
+            if rdef.cardinality[1] in '?1':
                 continue
             rql = 'SET X %s V WHERE X eid %%(x)s, Y eid %%(y)s, Y %s V' % (
                 rschema.type, rschema.type)
@@ -405,14 +407,15 @@
             if rschema.meta:
                 continue
             # skip already defined relations
-            if getattr(self, 'reverse_%s' % rschema.type):
+            if self.related(rschema.type, 'object'):
                 continue
+            rdef = self.e_schema.rdef(rschema, 'object')
             # skip composite relation
-            if self.e_schema.objrproperty(rschema, 'composite'):
+            if rdef.composite:
                 continue
             # skip relation with card in ?1 else we either change the copied
             # object (inlined relation) or inserting some inconsistency
-            if self.e_schema.objrproperty(rschema, 'cardinality')[0] in '?1':
+            if rdef.cardinality[0] in '?1':
                 continue
             rql = 'SET V %s X WHERE X eid %%(x)s, Y eid %%(y)s, V %s Y' % (
                 rschema.type, rschema.type)
@@ -433,15 +436,16 @@
         for rschema in self.e_schema.subject_relations():
             if rschema.final:
                 continue
-            if len(rschema.objects(self.e_schema)) > 1:
+            targets = rschema.objects(self.e_schema)
+            if len(targets) > 1:
                 # ambigous relations, the querier doesn't handle
                 # outer join correctly in this case
                 continue
             if rschema.inlined:
                 matching_groups = self._cw.user.matching_groups
-                if matching_groups(rschema.get_groups('read')) and \
-                   all(matching_groups(es.get_groups('read'))
-                       for es in rschema.objects(self.e_schema)):
+                rdef = rschema.rdef(self.e_schema, targets[0])
+                if matching_groups(rdef.get_groups('read')) and \
+                   all(matching_groups(e.get_groups('read')) for e in targets):
                     yield rschema, 'subject'
 
     def to_complete_attributes(self, skip_bytes=True):
@@ -453,7 +457,8 @@
             if attr == 'eid':
                 continue
             # password retreival is blocked at the repository server level
-            if not self._cw.user.matching_groups(rschema.get_groups('read')) \
+            rdef = rschema.rdef(self.e_schema, attrschema)
+            if not self._cw.user.matching_groups(rdef.get_groups('read')) \
                    or attrschema.type == 'Password':
                 self[attr] = None
                 continue
@@ -489,24 +494,21 @@
                 if self.relation_cached(rtype, role):
                     continue
                 var = varmaker.next()
+                targettype = rschema.targets(self.e_schema, role)[0]
+                rdef = rschema.role_rdef(self.e_schema, targettype, role)
+                card = rdef.role_cardinality(role)
+                assert card in '1?', '%s %s %s %s' % (self.e_schema, rtype,
+                                                      role, card)
                 if role == 'subject':
-                    targettype = rschema.objects(self.e_schema)[0]
-                    card = rschema.rproperty(self.e_schema, targettype,
-                                             'cardinality')[0]
                     if card == '1':
                         rql.append('%s %s %s' % (V, rtype, var))
-                    else: # '?"
+                    else:
                         rql.append('%s %s %s?' % (V, rtype, var))
                 else:
-                    targettype = rschema.subjects(self.e_schema)[1]
-                    card = rschema.rproperty(self.e_schema, targettype,
-                                             'cardinality')[1]
                     if card == '1':
                         rql.append('%s %s %s' % (var, rtype, V))
-                    else: # '?"
+                    else:
                         rql.append('%s? %s %s' % (var, rtype, V))
-                assert card in '1?', '%s %s %s %s' % (self.e_schema, rtype,
-                                                      role, card)
                 selected.append(((rtype, role), var))
         if selected:
             # select V, we need it as the left most selected variable
@@ -652,16 +654,16 @@
             restriction = []
             args = {}
             securitycheck_args = {}
-        insertsecurity = (rtype.has_local_role('add') and not
-                          rtype.has_perm(self._cw, 'add', **securitycheck_args))
-        constraints = rtype.rproperty(subjtype, objtype, 'constraints')
+        rdef = rtype.role_rdef(self.e_schema, targettype, role)
+        insertsecurity = (rdef.has_local_role('add') and not
+                          rdef.has_perm(self._cw, 'add', **securitycheck_args))
         if vocabconstraints:
             # RQLConstraint is a subclass for RQLVocabularyConstraint, so they
             # will be included as well
-            restriction += [cstr.restriction for cstr in constraints
+            restriction += [cstr.restriction for cstr in rdef.constraints
                             if isinstance(cstr, RQLVocabularyConstraint)]
         else:
-            restriction += [cstr.restriction for cstr in constraints
+            restriction += [cstr.restriction for cstr in rdef.constraints
                             if isinstance(cstr, RQLConstraint)]
         etypecls = self._cw.vreg['etypes'].etype_class(targettype)
         rql = etypecls.fetch_rql(self._cw.user, restriction,
@@ -671,12 +673,16 @@
             before, after = rql.split(' WHERE ', 1)
             rql = '%s ORDERBY %s WHERE %s' % (before, searchedvar, after)
         if insertsecurity:
-            rqlexprs = rtype.get_rqlexprs('add')
+            rqlexprs = rdef.get_rqlexprs('add')
             rewriter = RQLRewriter(self._cw)
             rqlst = self._cw.vreg.parse(self._cw, rql, args)
+            if not self.has_eid():
+                existant = searchedvar
+            else:
+                existant = None # instead of 'SO', improve perfs
             for select in rqlst.children:
                 rewriter.rewrite(select, [((searchedvar, searchedvar), rqlexprs)],
-                                 select.solutions, args)
+                                 select.solutions, args, existant)
             rql = rqlst.as_string()
         return rql, args
 
@@ -719,12 +725,10 @@
             related = list(rset.entities(col))
             rschema = self._cw.vreg.schema.rschema(rtype)
             if role == 'subject':
-                rcard = rschema.rproperty(self.e_schema, related[0].e_schema,
-                                          'cardinality')[1]
+                rcard = rschema.rdef(self.e_schema, related[0].e_schema).cardinality[1]
                 target = 'object'
             else:
-                rcard = rschema.rproperty(related[0].e_schema, self.e_schema,
-                                          'cardinality')[0]
+                rcard = rschema.rdef(related[0].e_schema, self.e_schema).cardinality[0]
                 target = 'subject'
             if rcard in '?1':
                 for rentity in related: