def __init__(self, workflow_spec, **kwargs): """ Constructor. """ assert workflow_spec is not None self.spec = workflow_spec self.task_id_assigner = TaskIdAssigner() self.attributes = {} self.outer_workflow = kwargs.get('parent', self) self.locks = {} self.last_task = None self.task_tree = Task(self, specs.Simple(workflow_spec, 'Root')) self.success = True self.debug = False # Events. self.completed_event = Event() # Prevent the root task from being executed. self.task_tree.state = Task.COMPLETED start = self.task_tree._add_child(self.spec.start) self.spec.start._predict(start) if not kwargs.has_key('parent'): start.task_spec._update_state(start)
def _read_workflow(self, start_node): """ Reads the workflow specification from the given workflow node and returns a list of WorkflowSpec objects. start_node -- the xml structure (xml.dom.minidom.Node) """ name = start_node.getAttribute('name') assert name is not None workflow_spec = specs.WorkflowSpec(name) last_spec = workflow_spec.start for node in start_node.childNodes: if node.nodeType != minidom.Node.ELEMENT_NODE: continue if node.nodeName == 'description': pass elif node.nodeName.lower() in _spec_tags: (start, end) = self._read_spec(workflow_spec, node) last_spec.connect(start) last_spec = end else: print("Unknown type:", type) assert False # Unknown tag. last_spec.connect(specs.Simple(workflow_spec, 'End')) return workflow_spec
def _read_spec(self, workflow, start_node): """ Reads the task spec from the given node and returns a tuple (start, end) that contains the stream of objects that model the behavior. workflow -- the workflow with which the task spec is associated start_node -- the xml structure (xml.dom.minidom.Node) """ type = start_node.nodeName.lower() name = start_node.getAttribute('name').lower() assert type in _spec_tags if type == 'concurrence': return self._read_concurrence(workflow, start_node) elif type == 'if': return self._read_if(workflow, start_node) elif type == 'sequence': return self._read_sequence(workflow, start_node) elif type == 'task': spec = specs.Simple(workflow, name) return spec, spec else: print("Unknown type:", type) assert False # Unknown tag.
def __init__(self, workflow_spec, deserializing=False, task_class=None, **kwargs): """ Constructor. :param deserializing: set to true when deserializing to avoid generating tasks twice (and associated problems with multiple hierarchies of tasks) """ assert workflow_spec is not None LOG.debug("__init__ Workflow instance: %s" % self.__str__()) self.spec = workflow_spec self.data = {} self.outer_workflow = kwargs.get('parent', self) self.locks = {} self.last_task = None if task_class: self.task_class = task_class else: if 'parent' in kwargs: self.task_class = kwargs['parent'].task_class else: self.task_class = Task if deserializing: assert 'Root' in workflow_spec.task_specs root = workflow_spec.task_specs['Root'] # Probably deserialized else: if 'Root' in workflow_spec.task_specs: root = workflow_spec.task_specs['Root'] else: root = specs.Simple(workflow_spec, 'Root') self.task_tree = self.task_class(self, root) self.success = True self.debug = False # Events. self.completed_event = Event() # Prevent the root task from being executed. self.task_tree.state = Task.COMPLETED start = self.task_tree._add_child(self.spec.start, state=Task.FUTURE) self.spec.start._predict(start) if 'parent' not in kwargs: start.task_spec._update_state(start)
def _read_if(self, workflow, start_node): """ Reads the sequence from the given node. workflow -- the workflow with which the concurrence is associated start_node -- the xml structure (xml.dom.minidom.Node) """ assert start_node.nodeName.lower() == 'if' name = start_node.getAttribute('name').lower() # Collect all information. match = None nomatch = None condition = None for node in start_node.childNodes: if node.nodeType != minidom.Node.ELEMENT_NODE: continue if node.nodeName.lower() in _spec_tags: if match is None: match = self._read_spec(workflow, node) elif nomatch is None: nomatch = self._read_spec(workflow, node) else: assert False # Only two tasks in "if" allowed. elif node.nodeName.lower() in _op_map: if condition is None: condition = self._read_condition(node) else: assert False # Multiple conditions not yet supported. else: print("Unknown type:", type) assert False # Unknown tag. # Model the if statement. assert condition is not None assert match is not None choice = specs.ExclusiveChoice(workflow, name) end = specs.Simple(workflow, name + '_end') if nomatch is None: choice.connect(end) else: choice.connect(nomatch[0]) nomatch[1].connect(end) choice.connect_if(condition, match[0]) match[1].connect(end) return (choice, end)
def deserialize_workflow_spec(self, s_state, filename=None): """ Reads the workflow from the given XML structure and returns a WorkflowSpec instance. """ dom = minidom.parseString(s_state) node = dom.getElementsByTagName('process-definition')[0] name = node.getAttribute('name') if name == '': _exc('%s without a name attribute' % node.nodeName) # Read all task specs and create a list of successors. workflow_spec = specs.WorkflowSpec(name, filename) del workflow_spec.task_specs['Start'] end = specs.Simple(workflow_spec, 'End'), [] read_specs = dict(end=end) for child_node in node.childNodes: if child_node.nodeType != minidom.Node.ELEMENT_NODE: continue if child_node.nodeName == 'name': workflow_spec.name = child_node.firstChild.nodeValue elif child_node.nodeName == 'description': workflow_spec.description = child_node.firstChild.nodeValue elif _spec_map.has_key(child_node.nodeName.lower()): self._deserialize_task_spec(workflow_spec, child_node, read_specs) else: _exc('Unknown node: %s' % child_node.nodeName) # Remove the default start-task from the workflow. workflow_spec.start = read_specs['start'][0] # Connect all task specs. for name in read_specs: spec, successors = read_specs[name] for condition, successor_name in successors: if not read_specs.has_key(successor_name): _exc('Unknown successor: "%s"' % successor_name) successor, foo = read_specs[successor_name] if condition is None: spec.connect(successor) else: spec.connect_if(condition, successor) return workflow_spec