Commit 5261079a authored by Nicolas Dumazet's avatar Nicolas Dumazet

do not explore the whole subtree recursively: exit if there's an unbuilt

movement at some point


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@36658 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent c29c9d6d
...@@ -571,8 +571,13 @@ class SimulationMovement(Movement, PropertyRecordableMixin): ...@@ -571,8 +571,13 @@ class SimulationMovement(Movement, PropertyRecordableMixin):
# has predecessors: check movements related to those predecessors! # has predecessors: check movements related to those predecessors!
predecessor_path_list = predecessor_state.getSuccessorRelatedValueList() predecessor_path_list = predecessor_state.getSuccessorRelatedValueList()
def isBuiltAndCompleted(simulation, path):
return simulation.getCausalityValue() is not None and \
simulation.getSimulationState() in path.getCompletedStateList()
### Step 1: ### Step 1:
## Explore ancestors in ZODB (cheap) ## Explore ancestors in ZODB (cheap)
#
# store a causality -> causality_related_movement_list mapping # store a causality -> causality_related_movement_list mapping
causality_dict = dict() causality_dict = dict()
...@@ -587,25 +592,22 @@ class SimulationMovement(Movement, PropertyRecordableMixin): ...@@ -587,25 +592,22 @@ class SimulationMovement(Movement, PropertyRecordableMixin):
# XXX or maybe directly go up by two levels? # XXX or maybe directly go up by two levels?
current = current.getParentValue() current = current.getParentValue()
remaining_path_list = [] remaining_path_set = set()
for path in predecessor_path_list: for path in predecessor_path_list:
related_simulation = causality_dict.get(path.getRelativeUrl()) related_simulation = causality_dict.get(path.getRelativeUrl())
if related_simulation is None: if related_simulation is None:
remaining_path_list.append(path) remaining_path_set.add(path)
continue continue
# XXX assumption is made here that if we find ONE completed ancestor # XXX assumption is made here that if we find ONE completed ancestor
# movement of self that is related to a predecessor path, then # movement of self that is related to a predecessor path, then
# that predecessor path is completed. Is it True? (aka when # that predecessor path is completed. Is it True? (aka when
# Business Process goes downwards, is the maximum movements per # Business Process goes downwards, is the maximum movements per
# predecessor 1 or can we have more?) # predecessor 1 or can we have more?)
if related_simulation.getDeliveryValue() is None: if not isBuiltAndCompleted(related_simulation, path):
return False # related movement is not delivered yet
if related_simulation.getSimulationState() not in \
path.getCompletedStateList():
return False return False
# in 90% of cases, Business Path goes downward and this is enough # in 90% of cases, Business Path goes downward and this is enough
if not remaining_path_list: if not remaining_path_set:
return True return True
# But sometimes we have to dig deeper # But sometimes we have to dig deeper
...@@ -613,38 +615,38 @@ class SimulationMovement(Movement, PropertyRecordableMixin): ...@@ -613,38 +615,38 @@ class SimulationMovement(Movement, PropertyRecordableMixin):
### Step 2: ### Step 2:
## Try catalog to find descendant movements, knowing ## Try catalog to find descendant movements, knowing
# that it can be incomplete # that it can be incomplete
uid_list = [p.getUid() for p in remaining_path_list]
# That list might be incomplete if catalog is lagging behind
portal_catalog = self.getPortalObject().portal_catalog portal_catalog = self.getPortalObject().portal_catalog
catalog_simulation_movement_list = portal_catalog( catalog_simulation_movement_list = portal_catalog(
portal_type='Simulation Movement', portal_type='Simulation Movement',
causality_uid=uid_list, causality_uid=[p.getUid() for p in remaining_path_set],
path='%s/%%' % self.getPath()) path='%s/%%' % self.getPath())
for simulation in catalog_simulation_movement_list: for simulation in catalog_simulation_movement_list:
path = simulation.getCausalityValue() if not isBuiltAndCompleted(simulation, simulation.getCausalityValue()):
if simulation.getDeliveryValue() is None or \
simulation.getSimulationState() not in path.getCompletedStateList():
return False return False
### Step 3: ### Step 3:
## We had no luck, we have to explore descendant movements in ZODB ## We had no luck, we have to explore descendant movements in ZODB
#
# reset dict def _recurseGetValueList(document):
causality_dict = dict() """
generator yielding Simulation Movement descendants of document.
# and explore descendants It does _not_ explore the whole subtree if iteration is stopped.
# XXX: _recurseGetValueList fetches _all_ descendants, but we can bail """
# out early if one movement is not built subdocument_list = document.contentValues()
for descendant in business_path._recurseGetValueList(self, 'Simulation Movement'): for subdocument in subdocument_list:
causality_dict.setdefault(descendant.getCausality(), []).append(descendant) if subdocument.getPortalType() == "Simulation Movement":
for path in remaining_path_list: yield subdocument
completed_state_list = path.getCompletedStateList() for subdocument in subdocument_list:
for simulation in causality_dict.get(path.getRelativeUrl(), []): for d in _recurseGetValueList(subdocument):
if simulation.getDeliveryValue() is None: yield d
return False
if simulation.getSimulationState() not in completed_state_list: for descendant in _recurseGetValueList(self):
path = descendant.getCausalityValue()
if path not in remaining_path_set:
continue
if not isBuiltAndCompleted(descendant, path):
return False return False
return True return True
......
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