Commit 42625ce0 authored by Vincent Pelletier's avatar Vincent Pelletier

Factorise code for auto-generated related keys.

Also, in RelatedBaseCategory, move most computation cost from call-time to
construction-time.
parent 3510a2b1
...@@ -61,8 +61,12 @@ from Persistence import Persistent ...@@ -61,8 +61,12 @@ from Persistence import Persistent
from Acquisition import Implicit from Acquisition import Implicit
DYNAMIC_METHOD_NAME = 'z_related_' DYNAMIC_METHOD_NAME = 'z_related_'
DYNAMIC_METHOD_NAME_LEN = len(DYNAMIC_METHOD_NAME)
STRICT_DYNAMIC_METHOD_NAME = DYNAMIC_METHOD_NAME + 'strict_' STRICT_DYNAMIC_METHOD_NAME = DYNAMIC_METHOD_NAME + 'strict_'
STRICT_DYNAMIC_METHOD_NAME_LEN = len(STRICT_DYNAMIC_METHOD_NAME)
RELATED_DYNAMIC_METHOD_NAME = '_related' RELATED_DYNAMIC_METHOD_NAME = '_related'
# Negative as it's used as a slice end offset
RELATED_DYNAMIC_METHOD_NAME_LEN = -len(RELATED_DYNAMIC_METHOD_NAME)
ZOPE_SECURITY_SUFFIX = '__roles__' ZOPE_SECURITY_SUFFIX = '__roles__'
class IndexableObjectWrapper(object): class IndexableObjectWrapper(object):
...@@ -190,27 +194,39 @@ class RelatedBaseCategory(Method): ...@@ -190,27 +194,39 @@ class RelatedBaseCategory(Method):
""" """
def __init__(self, id, strict_membership=0, related=0): def __init__(self, id, strict_membership=0, related=0):
self._id = id self._id = id
self.strict_membership=strict_membership if strict_membership:
self.related = related strict = 'AND %(category_table)s.category_strict_membership = 1\n'
else:
strict = ''
# From the point of view of query_table, we are looking up objects...
if related:
# ... which have a relation toward us
from_table = 'related'
to_table = 'relation_holder'
else:
# ... toward which we have a relation
from_table = 'relation_holder'
to_table = 'related'
self._template = """\
%%(category_table)s.base_category_uid = %%(base_category_uid)s
%(strict)sAND %%(%(to_table)s)s.uid = %%(category_table)s.category_uid
AND %%(category_table)s.uid = %%(%(from_table)s)s.uid""" % {
'strict': strict,
'from_table': from_table,
'to_table': to_table,
}
def __call__(self, instance, table_0, table_1, query_table='catalog', **kw): def __call__(self, instance, table_0, table_1, query_table='catalog', **kw):
"""Create the sql code for this related key.""" """Create the sql code for this related key."""
base_category_uid = instance.portal_categories._getOb(self._id).getUid() # Note: in normal conditions, our category's uid will not change from
expression_list = [] # one invocation to the next.
append = expression_list.append return self._template % {
if self.related: 'base_category_uid': instance.getPortalObject().portal_categories.\
append('%s.uid = %s.uid' % (table_1,table_0)) _getOb(self._id).getUid(),
if self.strict_membership: 'category_table': table_0,
append('AND %s.category_strict_membership = 1' % table_0) 'relation_holder': query_table,
append('AND %s.base_category_uid = %s' % (table_0,base_category_uid)) 'related': table_1,
append('AND %s.category_uid = %s.uid' % (table_0,query_table)) }
else:
append('%s.uid = %s.category_uid' % (table_1,table_0))
if self.strict_membership:
append('AND %s.category_strict_membership = 1' % table_0)
append('AND %s.base_category_uid = %s' % (table_0,base_category_uid))
append('AND %s.uid = %s.uid' % (table_0,query_table))
return ' '.join(expression_list)
class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
""" """
...@@ -889,31 +905,19 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): ...@@ -889,31 +905,19 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
if end_key.startswith('related_'): if end_key.startswith('related_'):
end_key = end_key[len('related_'):] end_key = end_key[len('related_'):]
# accept only some catalog columns suffix = '_related'
if end_key in ('title', 'uid', 'description', 'reference',
'relative_url', 'id', 'portal_type',
'simulation_state'):
if strict:
related_key_list.append(
'%s%s | category,catalog/%s/z_related_strict_%s_related' %
(prefix, key, end_key, expected_base_cat_id))
else:
related_key_list.append(
'%s%s | category,catalog/%s/z_related_%s_related' %
(prefix, key, end_key, expected_base_cat_id))
else: else:
# accept only some catalog columns suffix = ''
if end_key in ('title', 'uid', 'description', 'reference', # accept only some catalog columns
'relative_url', 'id', 'portal_type', if end_key in ('title', 'uid', 'description', 'reference',
'simulation_state'): 'relative_url', 'id', 'portal_type',
if strict: 'simulation_state'):
related_key_list.append( if strict:
'%s%s | category,catalog/%s/z_related_strict_%s' % pattern = '%s%s | category,catalog/%s/z_related_strict_%s%s'
(prefix, key, end_key, expected_base_cat_id)) else:
else: pattern = '%s%s | category,catalog/%s/z_related_%s%s'
related_key_list.append( related_key_list.append(pattern %
'%s%s | category,catalog/%s/z_related_%s' % (prefix, key, end_key, expected_base_cat_id, suffix))
(prefix, key, end_key, expected_base_cat_id))
return related_key_list return related_key_list
...@@ -925,23 +929,18 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): ...@@ -925,23 +929,18 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
result = None result = None
if name.startswith(DYNAMIC_METHOD_NAME) and \ if name.startswith(DYNAMIC_METHOD_NAME) and \
not name.endswith(ZOPE_SECURITY_SUFFIX): not name.endswith(ZOPE_SECURITY_SUFFIX):
kw = {}
if name.endswith(RELATED_DYNAMIC_METHOD_NAME): if name.endswith(RELATED_DYNAMIC_METHOD_NAME):
if name.startswith(STRICT_DYNAMIC_METHOD_NAME): end_offset = RELATED_DYNAMIC_METHOD_NAME_LEN
base_category_id = name[len(STRICT_DYNAMIC_METHOD_NAME):-len('_related')] kw['related'] = 1
method = RelatedBaseCategory(base_category_id,
strict_membership=1, related=1)
else:
base_category_id = name[len(DYNAMIC_METHOD_NAME):-len('_related')]
method = RelatedBaseCategory(base_category_id, related=1)
else: else:
if name.startswith(STRICT_DYNAMIC_METHOD_NAME): end_offset = None
base_category_id = name[len(STRICT_DYNAMIC_METHOD_NAME):] if name.startswith(STRICT_DYNAMIC_METHOD_NAME):
method = RelatedBaseCategory(base_category_id, strict_membership=1) start_offset = STRICT_DYNAMIC_METHOD_NAME_LEN
else: kw['strict_membership'] = 1
base_category_id = name[len(DYNAMIC_METHOD_NAME):] else:
method = RelatedBaseCategory(base_category_id) start_offset = DYNAMIC_METHOD_NAME_LEN
method = RelatedBaseCategory(name[start_offset:end_offset], **kw)
setattr(self.__class__, name, method) setattr(self.__class__, name, method)
# This getattr has 2 purposes: # This getattr has 2 purposes:
# - wrap in acquisition context # - wrap in acquisition context
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment