Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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.
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
    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