232 for each entity's class in the result set. If any score is 0, |
232 for each entity's class in the result set. If any score is 0, |
233 return 0. |
233 return 0. |
234 * if row is specified, return the value returned by the method with |
234 * if row is specified, return the value returned by the method with |
235 the entity's class of this row |
235 the entity's class of this row |
236 """ |
236 """ |
|
237 # XXX this selector can be refactored : extract the code testing |
|
238 # for entity schema / interface compliance |
237 score = 0 |
239 score = 0 |
238 # check 'accepts' to give priority to more specific classes |
240 # check 'accepts' to give priority to more specific classes |
239 if row is None: |
241 if row is None: |
240 for etype in rset.column_types(col or 0): |
242 for etype in rset.column_types(col or 0): |
241 eclass = cls.vreg.etype_class(etype) |
243 eclass = cls.vreg.etype_class(etype) |
243 for iface in cls.accepts_interfaces: |
245 for iface in cls.accepts_interfaces: |
244 escore += iface.is_implemented_by(eclass) |
246 escore += iface.is_implemented_by(eclass) |
245 if not escore: |
247 if not escore: |
246 return 0 |
248 return 0 |
247 score += escore |
249 score += escore |
248 if eclass.id in getattr(cls, 'accepts', ()): |
250 accepts = set(getattr(cls, 'accepts', ())) |
249 score += 2 |
251 # if accepts is defined on the vobject, eclass must match |
|
252 if accepts: |
|
253 eschema = eclass.e_schema |
|
254 etypes = set([eschema] + eschema.ancestors()) |
|
255 if accepts & etypes: |
|
256 score += 2 |
|
257 elif 'Any' not in accepts: |
|
258 return 0 |
250 return score + 1 |
259 return score + 1 |
251 etype = rset.description[row][col or 0] |
260 etype = rset.description[row][col or 0] |
252 if etype is None: # outer join |
261 if etype is None: # outer join |
253 return 0 |
262 return 0 |
254 eclass = cls.vreg.etype_class(etype) |
263 eclass = cls.vreg.etype_class(etype) |
255 for iface in cls.accepts_interfaces: |
264 for iface in cls.accepts_interfaces: |
256 score += iface.is_implemented_by(eclass) |
265 score += iface.is_implemented_by(eclass) |
257 if score: |
266 if score: |
258 if eclass.id in getattr(cls, 'accepts', ()): |
267 accepts = set(getattr(cls, 'accepts', ())) |
259 score += 2 |
268 # if accepts is defined on the vobject, eclass must match |
260 else: |
269 if accepts: |
261 score += 1 |
270 eschema = eclass.e_schema |
|
271 etypes = set([eschema] + eschema.ancestors()) |
|
272 if accepts & etypes: |
|
273 score += 1 |
|
274 elif 'Any' not in accepts: |
|
275 return 0 |
|
276 score += 1 |
262 return score |
277 return score |
263 |
278 |
264 @lltrace |
279 @lltrace |
265 def score_entity_selector(cls, req, rset, row=None, col=None, **kwargs): |
280 def score_entity_selector(cls, req, rset, row=None, col=None, **kwargs): |
266 if row is None: |
281 if row is None: |