############################################################################## # # Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved. # Jean-Paul Smets-Solanes <jp@nexedi.com> # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsability of assessing all potential # consequences resulting from its eventual inadequacies and bugs # End users who are looking for a ready-to-use solution with commercial # garantees and support are strongly adviced to contract a Free Software # Service Company # # This program is Free Software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## from Globals import InitializeClass from AccessControl import ClassSecurityInfo from Acquisition import aq_base, aq_inner from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface from Products.ERP5Type.Document.Folder import Folder from Products.ERP5Type.Document import newTempBase from Products.ERP5.Document.Predicate import Predicate from zLOG import LOG class PredicateGroup(Folder, Predicate): """ A predicate group allows to combine simple predicates """ meta_type = 'ERP5 Predicate Group' portal_type = 'Predicate Group' add_permission = Permissions.AddPortalContent isPortalContent = 1 isRADContent = 1 isPredicate = 1 _operators = ( { 'id': 'AND', 'title': 'And', 'description': 'All predicates must be true', 'sql_operator': '=', 'python_operator': '==', }, { 'id': 'OR', 'title': 'OR', 'description': 'Some predicate must be true', 'sql_operator': '<>', 'python_operator': '!=', }, { 'id': 'NOR', 'title': 'NOR', 'description': 'All predicates must be false', 'sql_operator': '>', 'python_operator': '>', }, { 'id': 'NAND', 'title': 'NAND', 'description': 'Some predicate must be false', 'sql_operator': '<', 'python_operator': '<', }, { 'id': 'XOR', 'title': 'XOR', 'description': 'Only one predicate can be true', 'sql_operator': '>=', 'python_operator': '>=', }, ) # Declarative security security = ClassSecurityInfo() security.declareObjectProtected(Permissions.View) # Declarative properties property_sheets = ( PropertySheet.Base , PropertySheet.Predicate , PropertySheet.SortIndex ) # Declarative interfaces __implements__ = ( Interface.Predicate ) # Factory Type Information factory_type_information = \ { 'id' : portal_type , 'meta_type' : meta_type , 'description' : """\ A bank account number holds a collection of numbers and codes (ex. SWIFT, RIB, etc.) which may be used to identify a bank account.""" , 'icon' : 'predicate_icon.gif' , 'product' : 'ERP5' , 'factory' : 'addPredicateGroup' , 'immediate_view' : 'predicate_view' , 'actions' : ( { 'id' : 'view' , 'name' : 'View' , 'category' : 'object_view' , 'action' : 'predicate_view' , 'permissions' : ( Permissions.View, ) } , ) } def test(self, context): """ A Predicate can be tested on a given context """ result = 1 if not hasattr(aq_base(self), '_identity_criterion'): self._identity_criterion = {} self._range_criterion = {} for property, value in self._identity_criterion.items(): result = result and (context.getProperty(property) == value) for property, (min, max) in self._range_criterion.items(): value = context.getProperty(property) if min is not None: result = result and (value >= min) if max is not None: result = result and (value < max) multimembership_criterion_base_category_list = self.getMultimembershipCriterionBaseCategoryList() membership_criterion_base_category_list = self.getMembershipCriterionBaseCategoryList() tested_base_category = {} for c in self.getMembershipCriterionCategoryList(): bc = c.split('/')[0] if not bc in tested_base_category.keys() : tested_base_category[bc] = 0 if bc in multimembership_criterion_base_category_list: tested_base_category[bc] = tested_base_category[bc] and context.isMemberOf(c) elif bc in membership_criterion_base_category_list: tested_base_category[bc] = tested_base_category[bc] or context.isMemberOf(c) result = result and (0 not in tested_base_category.values()) # Test method calls test_method_id = self.getTestMethodId() if test_method_id is not None and result: method = getattr(context,test_method_id) result = result and method() # XXX Add here additional method calls return result def asPythonExpression(): """ A Predicate can be rendered as a python expression. This is the preferred approach within Zope. """ pass def asSqlExpression(): """ A Predicate can be rendered as a python expression. This is the preferred approach within Zope. """ pass security.declareProtected( Permissions.AccessContentsInformation, 'getCriterionList' ) def getCriterionList(self, **kw): """ Returns a list of criterion """ if not hasattr(aq_base(self), '_identity_criterion'): self._identity_criterion = {} self._range_criterion = {} criterion_dict = {} for p in self.getCriterionPropertyList(): criterion_dict[p] = newTempBase(self, 'new_%s' % p) criterion_dict[p].identity = self._identity_criterion.get(p, None) criterion_dict[p].uid = 'new_%s' % p criterion_dict[p].property = p criterion_dict[p].min = self._range_criterion.get(p, (None, None))[0] criterion_dict[p].max = self._range_criterion.get(p, (None, None))[1] criterion_list = criterion_dict.values() criterion_list.sort() return criterion_list security.declareProtected( Permissions.ModifyPortalContent, 'setCriterion' ) def setCriterion(self, property, identity=None, min=None, max=None, **kw): if not hasattr(aq_base(self), '_identity_criterion'): self._identity_criterion = {} self._range_criterion = {} if identity != None : self._identity_criterion[property] = identity if min != '' or max != '' : self._range_criterion[property] = (min, max) self.reindexObject() security.declareProtected( Permissions.ModifyPortalContent, 'edit' ) def edit(self, **kwd) : if 'criterion_property_list' in kwd.keys() : criterion_property_list = kwd['criterion_property_list'] identity_criterion = {} range_criterion = {} for criterion in self._identity_criterion.keys() : if criterion in criterion_property_list : identity_criterion[criterion] = self._identity_criterion[criterion] for criterion in self._range_criterion.keys() : if criterion in criterion_property_list : range_criterion[criterion] = self._range_criterion[criterion] self._identity_criterion = identity_criterion self._range_criterion = range_criterion return self._edit(**kwd) # Predicate fusion method def setPredicateCategoryList(self, category_list): category_tool = aq_inner(self.portal_categories) base_category_id_list = category_tool.objectIds() membership_criterion_category_list = [] membership_criterion_base_category_list = [] multimembership_criterion_base_category_list = [] test_method_id_list = [] criterion_property_list = [] for c in category_list: bc = c.split('/')[0] if bc in base_category_id_list: # This is a category membership_criterion_category_list.append(c) membership_criterion_base_category_list.append(bc) else: predicate_value = category_tool.resolveCategory(c) if predicate_value is not None: criterion_property_list.extend(predicate_value.getCriterionPropertyList()) membership_criterion_category_list.extend( predicate_value.getMembershipCriterionCategoryList()) membership_criterion_base_category_list.extend( predicate_value.getMembershipCriterionBaseCategoryList()) multimembership_criterion_base_category_list.extend( predicate_value.getMultimembershipCriterionBaseCategoryList()) test_method_id_list += list(predicate_value.getTestMethodIdList() or []) for p in predicate_value.getCriterionList(): self.setCriterion(p.property, identity=p.identity, min=p.min, max=p.max) self.setCriterionPropertyList(criterion_property_list) self._setMembershipCriterionCategoryList(membership_criterion_category_list) self._setMembershipCriterionBaseCategoryList(membership_criterion_base_category_list) self._setMultimembershipCriterionBaseCategoryList(multimembership_criterion_base_category_list) self._setTestMethodIdList(test_method_id_list) self.reindexObject() # Predicate handling security.declareProtected(Permissions.AccessContentsInformation, 'asPredicate') def asPredicate(self): """ Returns a temporary Predicate based on the Resource properties """ return self