# -*- coding: utf-8 -*- ############################################################################## # # Copyright (c) 2010 Nexedi SA and Contributors. All Rights Reserved. # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsibility 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 # guarantees 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # ############################################################################## import zope.interface from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions, interfaces class ExplainableMixin: """A mixin which provides common implementation of IExplainable to simulation movements and applied rules TODO: - extend it to support Delivery Lines / Cells """ # Declarative security security = ClassSecurityInfo() security.declareObjectProtected(Permissions.AccessContentsInformation) # Declarative interfaces zope.interface.implements(interfaces.IExplainable,) # IExplainable implementation security.declareProtected(Permissions.AccessContentsInformation,'getExplanationValueList') def getExplanationValueList(self): """Returns the list of deliveries of parent simulation movements. The first item in the list is the immediate explanation value. The last item in the list is the root explanation. """ return self._getExplanationValueList() def _getExplanationValueList(self, root=False, immediate=False, line=False): """Private implementation with some options to optimize and share code """ result = [] # This implementation does not take into account delivery lines / cells # Extension could be obtained by considering getDeliveryRelatedValueList document = self previous_delivery = None still_immediate = True # True if no immediate explanation found yet while document.getPortalType() != "Simulation Tool": if document.getPortalType() == "Simulation Movement": if (not root or (document.getParentValue().getParentValue().getPortalType() == "Simulation Tool"))\ and (not immediate or still_immediate): # Only make an effort to find root delivery if we need # to build a complete list of explanations else # or if we are at the root of the simulation tree (whenever applies) # or if we are at the immediate delivery (whenever applies) delivery_line = document.getDeliveryValue() if delivery_line is not None: if still_immediate: still_immediate = False if line: result.append(delivery_line) else: previous_delivery = delivery_line.getRootDeliveryValue() result.append(previous_delivery) elif document.getPortalType() == "Applied Rule": if (not root or (document.getParentValue().getPortalType() == "Simulation Tool"))\ and (not immediate or still_immediate) and not line: # Only make an effort to find root delivery if we need # to build a complete list of explanations else # or if we are at the root of the simulation tree (whenever applies) # or if we are at the immediate delivery (whenever applies) # If we collect lines, we do not care about applied rules delivery_or_item = document.getCausalityValue() if delivery_or_item is not None and delivery_or_item is not previous_delivery: if still_immediate: still_immediate = False # Make sure not to include same delivery twice result.append(delivery_or_item) return result security.declareProtected(Permissions.AccessContentsInformation,'getRootExplanationValue') def getRootExplanationValue(self): """Returns the delivery of the root simulation movement. """ return self._getExplanationValueList(root=True)[-1] security.declareProtected(Permissions.AccessContentsInformation,'getImmediateExplanationValue') def getImmediateExplanationValue(self): """Returns the delivery of the first parent simulation which has a delivery. """ return self._getExplanationValueList(immediate=True)[0] security.declareProtected(Permissions.AccessContentsInformation,'getExplanationLineValueList') def getExplanationLineValueList(self): """Returns the list of delivery lines of parent simulation movements. The first item in the list is the immediate explanation value. The last item in the list is the root explanation. """ return self._getExplanationValueList(line=True) security.declareProtected(Permissions.AccessContentsInformation,'getRootExplanationLineValue') def getRootExplanationLineValue(self): """Returns the delivery line of the root simulation movement. """ return self._getExplanationValueList(root=True, line=True)[-1] security.declareProtected(Permissions.AccessContentsInformation,'getImmediateExplanationLineValue') def getImmediateExplanationLineValue(self): """Returns the delivery line of the first parent simulation which has a delivery. """ return self._getExplanationValueList(immediate=True, line=True)[0] # Compatibility API security.declareProtected(Permissions.AccessContentsInformation,'getExplanationUid') def getExplanationUid(self): """Returns the UID of the root explanation """ return self.getRootExplanationValue().getUid()