[Erp5-report] r33979 jp - /erp5/trunk/products/ERP5/Document/
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Mar 23 08:50:47 CET 2010
Author: jp
Date: Tue Mar 23 08:50:46 2010
New Revision: 33979
URL: http://svn.erp5.org?rev=33979&view=rev
Log:
Updated to support grouping even in very complex cases related to production or in universal solver cases.
Modified:
erp5/trunk/products/ERP5/Document/SolverProcess.py
erp5/trunk/products/ERP5/Document/SolverTypeInformation.py
Modified: erp5/trunk/products/ERP5/Document/SolverProcess.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/SolverProcess.py?rev=33979&r1=33978&r2=33979&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/SolverProcess.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/SolverProcess.py [utf8] Tue Mar 23 08:50:46 2010
@@ -82,64 +82,94 @@
"""
movement_dict = {}
types_tool = self.portal_types
+ message_list = []
# First create a mapping between delivery movements and solvers
# in order to know for each movements which solvers are needed
# and which parameters with
+ #
+ # movement_dict[movement] = {
+ # solver : [((c1, v1), (c2, v2 )),
+ # ((c1, v1), (c2, v2 )),
+ # ],
for decision in self.contentValues(portal_type="Solver Decision"):
solver = decision.getSolverValue()
# do nothing if solver is not yet set.
if solver is None:
continue
- solver_type = solver.getId() # ex. Postpone Production Solver
solver_conviguration_dict = decision.getConfigurationPropertyDict()
- solver_conviguration_key = tuple(solver_conviguration_dict.items())
+ configuration_mapping = solver_conviguration_dict.items()
+ configuration_mapping.sort() # Make sure the list is sorted in canonical way
+ configuration_mapping = tuple(configuration_mapping)
for movement in decision.getDeliveryValueList():
# Detect incompatibilities
- movement_solver_dict = movement_dict.setdefault(movement.getRelativeUrl(), {})
- movement_solver_configuration_list = movement_solver_dict.setdefault(solver_type, [])
- if solver_conviguration_key not in movement_solver_configuration_list:
- movement_solver_configuration_list.append(solver_conviguration_key)
-
- # Second, make sure solvers do not conflict and configuration is valid
- # Build a movement and configuration structure per solver type
+ movement_solver_dict = movement_dict.setdefault(movement, {})
+ movement_solver_configuration_list = movement_solver_dict.setdefault(solver, [])
+ if configuration_mapping not in movement_solver_configuration_list:
+ movement_solver_configuration_list.append(configuration_mapping)
+
+ # Second, create a mapping between solvers and movements
+ # and their configuration
+ #
+ # solver_dict[solver] = {
+ # movement : [((c1, v1), (c2, v2 )),
+ # ((c1, v1), (c2, v2 )),
+ # ],
+ # }
+ #
solver_dict = {}
- for movement_url, movement_solver_dict in movement_dict.items():
- for solver_type, movement_solver_configuration_list in movement_solver_dict.items():
- solver_movement_dict = solver_dict.setdefault(solver_type, {})
- configuration_list = solver_movement_dict.setdefault(movement_url, [])
- configuration_list.extend(movement_solver_configuration_list) # XXX-JPS WRONG
- # Then start the grouping procedure
- solver_dict = {}
- for movement_url, movement_solver_dict in movement_dict.items():
- for solver_type, movement_solver_configuration_list in movement_solver_dict.items():
- solver = types_tool[solver_type]
- for other_solver_type in movement_solver_dict.keys():
- if other_solver_type == solver_type:
- continue
- if solver.conflictsWithSolver(types_tool[other_solver_type]):
- # XXX6PJS REDO HERE
- raise ValueError, "Solver %s conflicts with solver %s on movement %s" % (solver_type, other_solver_type, movement_url)
- # Make sure multiple configuration are possible
- try:
- # Solver key contains only those properties which differentiate
- # solvers (ex. there should be only Production Reduction Solver)
- solver_key = solver.getSolverProcessGroupingKey(movement_url, movement_solver_configuration_list, movement_solver_dict)
- except: # Raise the exception generated by the solver in case of failure of grouping
- raise
- solver_key_dict = solver_dict.setdefault(solver_type, {})
- solver_movement_dict = solver_key_dict.setdefault(solver_key, {})
- solver_movement_dict[movement_url] = movement_solver_configuration_list
-
- # Third, build target solvers
- for solver_type, solver_key_dict in solver_dict.items():
+ for movement, movement_solver_dict in movement_dict.items():
+ for solver, movement_solver_configuration_list in movement_solver_dict.items():
+ solver_movement_dict = solver_dict.setdefault(solver, {})
+ solver_movement_dict[movement] = movement_solver_configuration_list
+
+ # Third, group solver configurations and make sure solvers do not conflict
+ # by creating a mapping between solvers and movement configuration grouped
+ # by a key which is used to aggregate multiple configurations
+ #
+ # grouped_solver_dict[solver] = {
+ # solver_key: {
+ # movement : [((c1, v1), (c2, v2 )),
+ # ((c1, v1), (c2, v2 )),
+ # ],
+ # }
+ # }
+ grouped_solver_dict = {}
+ for movement, movement_solver_dict in movement_dict.items():
+ for solver, movement_solver_configuration_list in movement_solver_dict.items():
+ for configuration_mapping in movement_solver_configuration_list:
+ solver_message_list = solver.getSolverConflictMessageList(movement, configuration_mapping, solver_dict)
+ if solver_message_list:
+ message_list.extend(solver_message_list)
+ continue # No need to keep on
+ # Make sure multiple configuration are possible
+ try:
+ # Solver key contains only those properties which differentiate
+ # solvers (ex. there should be only Production Reduction Solver)
+ solver_key = solver.getSolverProcessGroupingKey(movement, configuration_mapping, solver_dict)
+ except: # Raise the exception generated by the solver in case of failure of grouping
+ raise
+ solver_key_dict = grouped_solver_dict.setdefault(solver, {})
+ solver_movement_dict = solver_key_dict.setdefault(solver_key, {})
+ movement_solver_configuration_list = movement_solver_dict.setdefault(solver, [])
+ if configuration_mapping not in movement_solver_configuration_list:
+ movement_solver_configuration_list.append(configuration_mapping)
+
+ # Return empty list of conflicts
+ if message_list: return message_list
+
+ # Fourth, build target solvers
+ for solver, solver_key_dict in grouped_solver_dict.items():
for solver_key, solver_movement_dict in solver_key_dict.items():
- solver_instance = self.newContent(portal_type=solver_type)
- solver_instance._setDeliveryList(solver_movement_dict.keys())
- for movement_url, configuration_list in solver_movement_dict.iteritems():
- for configuration_kw in configuration_list:
- if len(configuration_kw):
- solver_instance.updateConfiguration(**dict(configuration_kw))
+ solver_instance = self.newContent(portal_type=solver.getId())
+ solver_instance._setDeliveryValueList(solver_movement_dict.keys())
+ for movement, configuration_list in solver_movement_dict.iteritems():
+ for configuration_mapping in configuration_list:
+ if len(configuration_mapping):
+ solver_instance.updateConfiguration(**dict(configuration_mapping))
+
+ # Return empty list of conflicts
+ return []
# ISolver implementation
# Solver Process Workflow Interface
Modified: erp5/trunk/products/ERP5/Document/SolverTypeInformation.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/SolverTypeInformation.py?rev=33979&r1=33978&r2=33979&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/SolverTypeInformation.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/SolverTypeInformation.py [utf8] Tue Mar 23 08:50:46 2010
@@ -52,31 +52,45 @@
, PropertySheet.Configurable
)
- def conflictsWithSolver(self, movement, configuration_dict, other_configuration_list):
+ def getSolverConflictMessageList(self, movement, configuration_mapping, solver_dict, movement_dict):
"""
- Returns True if the solver conflicts with other_solver. False else.
+ Returns the list of conflictings messgaes if the solver and configuration_mapping
+ conflicts with another solver
- movement -- a movement or a movement relative url
+ movement -- a movement
+
+ configuration_mapping -- a mapping of configuration parameters sorted in
+ canonical way. ((c1, v1), (c2, v2 ))
- configuration_dict -- a dictionary of configuration parameters to
- solve the current movement with self
-
- other_configuration_list -- a list of solvers and their configuration
- for the same movement
+ solver_dict -- a dictionary of configuration parameters for
+ each solver
+ solver_dict[solver] = {
+ movement : [((c1, v1), (c2, v2 )),
+ ((c1, v1), (c2, v2 )),
+ ],}
+
+ movement_dict -- a dictionary of solver and configuration parameters for
+ each movement
+ movement_dict[movement] = {
+ solver : [((c1, v1), (c2, v2 )),
+ ((c1, v1), (c2, v2 )),
+ ],}
"""
- method = self._getTypeBasedMethod('conflictsWithSolver')
+ method = self._getTypeBasedMethod('getSolverConflictMessageList')
if method is not None:
- return method(movement, configuration_dict, other_configuration_list)
+ return method(movement, configuration_mapping, solver_dict, movement_dict)
# Default Implementation (use categories and trivial case)
- for solver_type, configuration_dict in other_configuration_list:
- if solver.getTestedProperty() == self.getTestedProperty():
- return True
+ # this default implementation should be applicable to most
+ # solvers so that use of Type Based methods is very rare
+ for solver, configuration_list in movement_dict[movement].items():
+ if solver is not self and solver.getTestedProperty() == self.getTestedProperty():
+ return AppropriateUIMessage(whatever) # XXX-TODO
- # Return False by Default
- return False
+ # Return emtpty message list
+ return ()
- def getSolverProcessGroupingKey(self, movement, configuration_dict, other_configuration_list):
+ def getSolverProcessGroupingKey(self, movement, configuration_mapping, solver_dict, movement_dict):
"""
Returns a key which can be used to group solvers during the
process to build Targer Solver instances from Solver Decisions.
@@ -98,26 +112,34 @@
Adopt, Accept) which tested property is configurable, is the
tested property itself.
- movement -- a movement or a movement relative url
+ movement -- a movement
+
+ configuration_mapping -- a mapping of configuration parameters sorted in
+ canonical way. ((c1, v1), (c2, v2 ))
- configuration_dict -- a dictionary of configuration parameters
+ solver_dict -- a dictionary of configuration parameters for
+ each solver
+ solver_dict[solver] = {
+ movement : [((c1, v1), (c2, v2 )),
+ ((c1, v1), (c2, v2 )),
+ ],}
- other_configuration_list -- a list of movements and their configuration
- which are solved by the same solve type.
- [(m1, c1), (m2, c2), ...]
+ movement_dict -- a dictionary of solver and configuration parameters for
+ each movement
+ movement_dict[movement] = {
+ solver : [((c1, v1), (c2, v2 )),
+ ((c1, v1), (c2, v2 )),
+ ],}
"""
method = self._getTypeBasedMethod('getSolverProcessGroupingKey')
if method is not None:
- return method(movement, configuration_dict, other_configuration_list)
+ return method(movement, configuration_mapping, solver_dict, movement_dict)
- # Default Implementation (read properties and implement XXX)
+ # Default Implementation (read solver type properties and implement XXX-TODO)
if self.isLineGroupable():
return ()
- if isinstance(movement, str):
- return movement
- else:
- return movement.getRelativeUrl()
+ return movement.getRelativeUrl()
def getDefaultConfigurationPropertyDict(self, configurable):
"""
More information about the Erp5-report
mailing list