|
1 """schema definition related entities |
|
2 |
|
3 :organization: Logilab |
|
4 :copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
|
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
6 """ |
|
7 __docformat__ = "restructuredtext en" |
|
8 |
|
9 from logilab.common.decorators import cached |
|
10 |
|
11 from cubicweb import ValidationError |
|
12 from cubicweb.schema import ERQLExpression, RRQLExpression |
|
13 |
|
14 from cubicweb.entities import AnyEntity, fetch_config |
|
15 |
|
16 |
|
17 class EEType(AnyEntity): |
|
18 id = 'EEType' |
|
19 fetch_attrs, fetch_order = fetch_config(['name']) |
|
20 __rtags__ = { |
|
21 ('final', '*', 'subject'): 'generated', |
|
22 |
|
23 ('state_of', '*', 'object'): 'create', |
|
24 ('transition_of', '*', 'object'): 'create', |
|
25 ('from_entity', '*', 'object'): 'link', |
|
26 ('to_entity', '*', 'object'): 'link', |
|
27 } |
|
28 def dc_title(self): |
|
29 return self.req._(self.name) |
|
30 |
|
31 def dc_long_title(self): |
|
32 stereotypes = [] |
|
33 _ = self.req._ |
|
34 if self.meta: |
|
35 stereotypes.append(_('meta')) |
|
36 if self.final: |
|
37 stereotypes.append(_('final')) |
|
38 if stereotypes: |
|
39 return u'%s <<%s>>' % (self.dc_title(), ', '.join(stereotypes)) |
|
40 return self.dc_title() |
|
41 |
|
42 def db_key_name(self): |
|
43 """XXX goa specific""" |
|
44 return self.get('name') |
|
45 |
|
46 |
|
47 class ERType(AnyEntity): |
|
48 id = 'ERType' |
|
49 fetch_attrs, fetch_order = fetch_config(['name']) |
|
50 __rtags__ = { |
|
51 ('final', '*', 'subject'): 'generated', |
|
52 |
|
53 ('relation_type', '*', 'object') : 'create', |
|
54 } |
|
55 |
|
56 def dc_title(self): |
|
57 return self.req._(self.name) |
|
58 |
|
59 def dc_long_title(self): |
|
60 stereotypes = [] |
|
61 _ = self.req._ |
|
62 if self.meta: |
|
63 stereotypes.append(_('meta')) |
|
64 if self.symetric: |
|
65 stereotypes.append(_('symetric')) |
|
66 if self.inlined: |
|
67 stereotypes.append(_('inlined')) |
|
68 if self.final: |
|
69 stereotypes.append(_('final')) |
|
70 if stereotypes: |
|
71 return u'%s <<%s>>' % (self.dc_title(), ', '.join(stereotypes)) |
|
72 return self.dc_title() |
|
73 |
|
74 def inlined_changed(self, inlined): |
|
75 """check inlining is necessary and possible: |
|
76 |
|
77 * return False if nothing has changed |
|
78 * raise ValidationError if inlining is'nt possible |
|
79 * eventually return True |
|
80 """ |
|
81 rtype = self.name |
|
82 rschema = self.schema.rschema(rtype) |
|
83 if inlined == rschema.inlined: |
|
84 return False |
|
85 if inlined: |
|
86 for (stype, otype) in rschema.iter_rdefs(): |
|
87 card = rschema.rproperty(stype, otype, 'cardinality')[0] |
|
88 if not card in '?1': |
|
89 msg = self.req._("can't set inlined=%(inlined)s, " |
|
90 "%(stype)s %(rtype)s %(otype)s " |
|
91 "has cardinality=%(card)s") |
|
92 raise ValidationError(self.eid, {'inlined': msg % locals()}) |
|
93 return True |
|
94 |
|
95 def db_key_name(self): |
|
96 """XXX goa specific""" |
|
97 return self.get('name') |
|
98 |
|
99 |
|
100 class ENFRDef(AnyEntity): |
|
101 id = 'ENFRDef' |
|
102 fetch_attrs = fetch_config(['cardinality'])[0] |
|
103 __rtags__ = { |
|
104 ('relation_type', 'ERType', 'subject') : 'inlineview', |
|
105 ('from_entity', 'EEType', 'subject') : 'inlineview', |
|
106 ('to_entity', 'EEType', 'subject') : 'inlineview', |
|
107 } |
|
108 |
|
109 def dc_title(self): |
|
110 return u'%s %s %s' % ( |
|
111 self.from_entity[0].name, |
|
112 self.relation_type[0].name, |
|
113 self.to_entity[0].name) |
|
114 |
|
115 def dc_long_title(self): |
|
116 card = self.cardinality |
|
117 scard, ocard = u'', u'' |
|
118 if card[0] != '1': |
|
119 scard = '[%s]' % card[0] |
|
120 if card[1] != '1': |
|
121 ocard = '[%s]' % card[1] |
|
122 return u'%s %s%s%s %s' % ( |
|
123 self.from_entity[0].name, |
|
124 scard, self.relation_type[0].name, ocard, |
|
125 self.to_entity[0].name) |
|
126 |
|
127 def after_deletion_path(self): |
|
128 """return (path, parameters) which should be used as redirect |
|
129 information when this entity is being deleted |
|
130 """ |
|
131 if self.relation_type: |
|
132 return self.relation_type[0].rest_path(), {} |
|
133 return super(ENFRDef, self).after_deletion_path() |
|
134 |
|
135 |
|
136 class EFRDef(ENFRDef): |
|
137 id = 'EFRDef' |
|
138 |
|
139 def dc_long_title(self): |
|
140 card = self.cardinality |
|
141 scard = u'' |
|
142 if card[0] == '1': |
|
143 scard = '+' |
|
144 return u'%s %s%s %s' % ( |
|
145 self.from_entity[0].name, |
|
146 scard, self.relation_type[0].name, |
|
147 self.to_entity[0].name) |
|
148 |
|
149 |
|
150 class EConstraint(AnyEntity): |
|
151 id = 'EConstraint' |
|
152 fetch_attrs, fetch_order = fetch_config(['value']) |
|
153 |
|
154 def dc_title(self): |
|
155 return '%s(%s)' % (self.cstrtype[0].name, self.value or u'') |
|
156 |
|
157 def after_deletion_path(self): |
|
158 """return (path, parameters) which should be used as redirect |
|
159 information when this entity is being deleted |
|
160 """ |
|
161 if self.reverse_constrained_by: |
|
162 return self.reverse_constrained_by[0].rest_path(), {} |
|
163 return super(EConstraint, self).after_deletion_path() |
|
164 |
|
165 @property |
|
166 def type(self): |
|
167 return self.cstrtype[0].name |
|
168 |
|
169 |
|
170 class RQLExpression(AnyEntity): |
|
171 id = 'RQLExpression' |
|
172 fetch_attrs, fetch_order = fetch_config(['exprtype', 'mainvars', 'expression']) |
|
173 |
|
174 widgets = { |
|
175 'expression' : "StringWidget", |
|
176 } |
|
177 |
|
178 def dc_title(self): |
|
179 return '%s(%s)' % (self.exprtype, self.expression or u'') |
|
180 |
|
181 @property |
|
182 def expression_of(self): |
|
183 for rel in ('read_permission', 'add_permission', 'delete_permission', |
|
184 'update_permission', 'condition'): |
|
185 values = getattr(self, 'reverse_%s' % rel) |
|
186 if values: |
|
187 return values[0] |
|
188 |
|
189 @cached |
|
190 def _rqlexpr(self): |
|
191 if self.exprtype == 'ERQLExpression': |
|
192 return ERQLExpression(self.expression, self.mainvars, self.eid) |
|
193 #if self.exprtype == 'RRQLExpression': |
|
194 return RRQLExpression(self.expression, self.mainvars, self.eid) |
|
195 |
|
196 def check_expression(self, *args, **kwargs): |
|
197 return self._rqlexpr().check(*args, **kwargs) |
|
198 |
|
199 def after_deletion_path(self): |
|
200 """return (path, parameters) which should be used as redirect |
|
201 information when this entity is being deleted |
|
202 """ |
|
203 if self.expression_of: |
|
204 return self.expression_of.rest_path(), {} |
|
205 return super(RQLExpression, self).after_deletion_path() |
|
206 |
|
207 |
|
208 class EPermission(AnyEntity): |
|
209 id = 'EPermission' |
|
210 fetch_attrs, fetch_order = fetch_config(['name', 'label']) |
|
211 |
|
212 |
|
213 __rtags__ = { |
|
214 'require_group' : 'primary', |
|
215 } |
|
216 |
|
217 def dc_title(self): |
|
218 if self.label: |
|
219 return '%s (%s)' % (self.req._(self.name), self.label) |
|
220 return self.req._(self.name) |
|
221 |
|
222 def after_deletion_path(self): |
|
223 """return (path, parameters) which should be used as redirect |
|
224 information when this entity is being deleted |
|
225 """ |
|
226 permissionof = getattr(self, 'reverse_require_permission', ()) |
|
227 if len(permissionof) == 1: |
|
228 return permissionof[0].rest_path(), {} |
|
229 return super(EPermission, self).after_deletion_path() |