def fork_has_more_incomings(self, activity):
        ''' if a fork has more than one incoming. if yes, create one merge before the fork.
        yes: return True
        no:  return False
        '''
        nodes_dict = activity.nodes_dict
        ret = False
        ids = []
        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            if node.xmi_type == uml_element.Types.FORK_NODE:
                incomings = node.incomings
                num = len(incomings)
                if num > 1:
                    # parallel = self.is_parallel(incomings, activity)
                    # if not parallel:
                    ids.append(node_id)
                    log.show_warn("the fork " + "name:" + str(node.name) + \
                                  " id:" + node.xmi_id + " has " + \
                                   str(num) + " incomings")
                    ret = True
        if ret:
            for node_id in ids:
                self._create_merge(node_id, activity,
                                   uml_element.Types.CONTROL_FLOW)

        return ids
    def get_tokens_num(self, merge, activity):
        """first, judge if the incomings of the merge from the different parallel_num,
        if yes set the tokens to the number of the incomings.
        """
        edges_dict = activity.edges_dict
        # the number of the place's tokens
        tokens_num = 1
        # the number of the parallel
        parallel_num = 0

        # for the edge, which edge.parallel is True
        edges = []
        for incoming in merge.incomings:
            edge_id = incoming.xmi_idref
            edge = edges_dict[edge_id]
            if edge.parallel:
                edges.append(edge)
            else:
                log.show_warn(
                    "the merge in the fork has a incoming,"
                    + "but the incoming is not from the fork, the incoming comes from the outside"
                )

        if len(edges) > 1:
            first_edge = edges[0]
            parallel_num = first_edge.parallel_num

        for edge in edges:
            # the edges come from the same fork, but different parallels
            if edge.parallel_num != parallel_num:
                tokens_num += 1

        if tokens_num > 1:
            self.set_tokens(merge, tokens_num)
            log.show_info("the merge has %d tokens. name:%s, id:%s" % (tokens_num, str(merge.name), str(merge.xmi_id)))
    def fork_has_more_incomings(self, activity):
        """ if a fork has more than one incoming. if yes, create one merge before the fork.
        yes: return True
        no:  return False
        """
        nodes_dict = activity.nodes_dict
        ret = False
        ids = []
        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            if node.xmi_type == uml_element.Types.FORK_NODE:
                incomings = node.incomings
                num = len(incomings)
                if num > 1:
                    # parallel = self.is_parallel(incomings, activity)
                    # if not parallel:
                    ids.append(node_id)
                    log.show_warn(
                        "the fork "
                        + "name:"
                        + str(node.name)
                        + " id:"
                        + node.xmi_id
                        + " has "
                        + str(num)
                        + " incomings"
                    )
                    ret = True
        if ret:
            for node_id in ids:
                self._create_merge(node_id, activity, uml_element.Types.CONTROL_FLOW)

        return ids
 def _analyse_nodes(self, node1, node2, activity):
     """for example:
     situation:
     1. action1(with(out) pout)-->action2 (with(out) pin)
     2. action1-->object-->action2(or control)
     3. action1 with pin-->control node #pass
     4. control node(fork,decision,merge)-->action2 with pin #pass
     5. control node(fork,decision,merge)-->object-->action2(or control)
     6. control node-->control node #pass
     7. object node-->... #pass
     if action1 has no control flow, add one control flow between action1 and action2.
     """
     # if node1 and node2 are actions
     # 1.situation
     if isinstance(node1, uml_element.ExecutableNode) and isinstance(node2, uml_element.ExecutableNode):
         log.show_info("1.situation: action to action")
         # if node1 has no control flow
         if not self._has_outgoing_control_flow(node1, activity):
             # add one control flow from action1 to action2
             self._add_control_flow(node1, node2, activity)
     # if node1 is a action, and node2 is a object_node
     # 2.situation
     elif isinstance(node1, uml_element.ExecutableNode) and isinstance(node2, uml_element.ObjectNode):
         log.show_info("2.situation: action to object node")
         # if node1 has no control flow
         if not self._has_outgoing_control_flow(node1, activity):
             node3 = self._get_object_next_node(node2, activity)
             # if node3 not None
             if node3:
                 self._add_control_flow(node1, node3, activity)
     # if node1 is a action with pout, and node2 is a control
     # 3.situation
     elif isinstance(node1, uml_element.ExecutableNode) and isinstance(node2, uml_element.ControlNode):
         log.show_info("3.situation: action to control node")
         # pass
     # if node1 is control_node, node2 is a action with pin
     # 4.situation
     elif isinstance(node1, uml_element.ControlNode) and isinstance(node2, uml_element.ExecutableNode):
         log.show_info("4.situation: control node to action")
         # pass
     # if node1 is control_node, node2 is object_node
     # 5.situation
     elif isinstance(node1, uml_element.ControlNode) and isinstance(node2, uml_element.ObjectNode):
         log.show_info("5.situation: control node to object node")
         node3 = self._get_object_next_node(node2, activity)
         if node3:
             # add one control flow from node1 to node3
             self._add_control_flow(node1, node3, activity)
     # if node1 is control_node, node2 is control_node
     # 6.situation
     elif isinstance(node1, uml_element.ControlNode) and isinstance(node2, uml_element.ControlNode):
         log.show_info("6.situation: control node to control node")
         # TODO
         # pass
     # if node1 is object node
     # 7.situation
     elif isinstance(node1, uml_element.ObjectNode):
         pass
     else:
         log.show_warn("a object flow from node1 to node2," "but the 2 nodes's situation are not defined")
Example #5
0
def object_node_has_more_incomings(self, activity):
        ''' if a object node has more than one incoming.
        if yes, create one merge before the object node.
        yes: return True
        no:  return False
        @see: example/document
        '''
        nodes_dict = activity.nodes_dict
        ret = False
        ids = []
        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            if isinstance(node, uml_element.ObjectNode):
                incomings = node.incomings
                num = len(incomings)
                if  num > 1:
                    ids.append(node_id)
                    log.show_warn("the object node " + "name:" + str(node.name) + \
                                  " id:" + node.xmi_id + " has " + str(num) + " incomings")
                    ret = True
        if ret:
            for node_id in ids:
                self._create_merge(node_id, activity, uml_element.Types.OBJECT_FLOW)

        return ret
    def get_tokens_num(self, merge, activity):
        '''first, judge if the incomings of the merge from the different parallel_num,
        if yes set the tokens to the number of the incomings.
        '''
        edges_dict = activity.edges_dict
        # the number of the place's tokens
        tokens_num = 1
        # the number of the parallel
        parallel_num = 0

        # for the edge, which edge.parallel is True
        edges = []
        for incoming in merge.incomings:
            edge_id = incoming.xmi_idref
            edge = edges_dict[edge_id]
            if edge.parallel:
                edges.append(edge)
            else:
                log.show_warn("the merge in the fork has a incoming," + \
                "but the incoming is not from the fork, the incoming comes from the outside")

        if len(edges) > 1:
            first_edge = edges[0]
            parallel_num = first_edge.parallel_num

        for edge in edges:
            # the edges come from the same fork, but different parallels
            if edge.parallel_num != parallel_num:
                tokens_num += 1

        if tokens_num > 1:
            self.set_tokens(merge, tokens_num)
            log.show_info("the merge has %d tokens. name:%s, id:%s" %
                          (tokens_num, str(merge.name), str(merge.xmi_id)))
Example #7
0
 def create_node_object(self, nodes_dict, xmi_id, xmi_type, name, \
                       incomings, outgoings, results, arguments, behavior):
     '''create instance of uml_activity_diagram_element.ActivityNode
     from the xmi_type
     '''
     if xmi_type == uml_element.Types.INITIAL_NODE:
         initial_node = uml_element.InitialNode(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = initial_node
     elif xmi_type == uml_element.Types.CALLBEHAVIOR_ACTION:
         action_node = uml_element.Action(xmi_id, xmi_type, name, \
                                          incomings, outgoings, results, arguments)
         action_node.behavior = behavior
         nodes_dict[xmi_id] = action_node
     elif xmi_type == uml_element.Types.ACTION:
         action_node = uml_element.Action(xmi_id, xmi_type, name, \
                                          incomings, outgoings, results, arguments)
         action_node.behavior = None
         nodes_dict[xmi_id] = action_node
     elif xmi_type == uml_element.Types.SEND_SIGNAL_ACTION:
         send_signal_action = uml_element.SendSignalAction(xmi_id, xmi_type, name, \
                                                 incomings, outgoings, results, arguments)
         nodes_dict[xmi_id] = send_signal_action
     elif xmi_type == uml_element.Types.ACCEPT_EVENT_ACTION:
         accept_event_action = uml_element.AcceptEventAction(xmi_id, xmi_type, name, \
                                                 incomings, outgoings, results, arguments)
         nodes_dict[xmi_id] = accept_event_action
     elif xmi_type == uml_element.Types.FORK_NODE:
         # for EA
         if len(outgoings) == 1 and len(incomings) > 1:
             join_node = uml_element.Join(xmi_id, uml_element.Types.JOIN_NODE, name, \
                                          incomings, outgoings)
             nodes_dict[xmi_id] = join_node
         else:
             fork_node = uml_element.Fork(xmi_id, xmi_type, name, incomings, outgoings)
             nodes_dict[xmi_id] = fork_node
     elif xmi_type == uml_element.Types.JOIN_NODE:
         join_node = uml_element.Join(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = join_node
     elif xmi_type == uml_element.Types.ACTIVITY_FINAL_NODE:
         final_node = uml_element.ActivityFinal(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = final_node
     elif xmi_type == uml_element.Types.FLOW_FINAL_NODE:
         flow_final_node = uml_element.FlowFinal(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = flow_final_node
     elif xmi_type == uml_element.Types.MERGE_NODE:
         merge = uml_element.Merge(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = merge
     elif xmi_type == uml_element.Types.DECISION_NODE:
         decision = uml_element.Decision(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = decision
     # ObjectNode
     elif xmi_type == uml_element.Types.OBJECT_NODE:
         object_node = uml_element.ObjectNode(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = object_node
     elif xmi_type == uml_element.Types.DATA_STORE_NODE:
         data_store_node = uml_element.DataStore(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = data_store_node
     else:
         log.show_warn("the type of the node is not defined " + xmi_type)
Example #8
0
 def create_node_object(
     self, nodes_dict, xmi_id, xmi_type, name, incomings, outgoings, results, arguments, behavior
 ):
     """create instance of uml_activity_diagram_element.ActivityNode
     from the xmi_type
     """
     if xmi_type == uml_element.Types.INITIAL_NODE:
         initial_node = uml_element.InitialNode(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = initial_node
     elif xmi_type == uml_element.Types.CALLBEHAVIOR_ACTION:
         action_node = uml_element.Action(xmi_id, xmi_type, name, incomings, outgoings, results, arguments)
         action_node.behavior = behavior
         nodes_dict[xmi_id] = action_node
     elif xmi_type == uml_element.Types.ACTION:
         action_node = uml_element.Action(xmi_id, xmi_type, name, incomings, outgoings, results, arguments)
         action_node.behavior = None
         nodes_dict[xmi_id] = action_node
     elif xmi_type == uml_element.Types.SEND_SIGNAL_ACTION:
         send_signal_action = uml_element.SendSignalAction(
             xmi_id, xmi_type, name, incomings, outgoings, results, arguments
         )
         nodes_dict[xmi_id] = send_signal_action
     elif xmi_type == uml_element.Types.ACCEPT_EVENT_ACTION:
         accept_event_action = uml_element.AcceptEventAction(
             xmi_id, xmi_type, name, incomings, outgoings, results, arguments
         )
         nodes_dict[xmi_id] = accept_event_action
     elif xmi_type == uml_element.Types.FORK_NODE:
         # for EA
         if len(outgoings) == 1 and len(incomings) > 1:
             join_node = uml_element.Join(xmi_id, uml_element.Types.JOIN_NODE, name, incomings, outgoings)
             nodes_dict[xmi_id] = join_node
         else:
             fork_node = uml_element.Fork(xmi_id, xmi_type, name, incomings, outgoings)
             nodes_dict[xmi_id] = fork_node
     elif xmi_type == uml_element.Types.JOIN_NODE:
         join_node = uml_element.Join(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = join_node
     elif xmi_type == uml_element.Types.ACTIVITY_FINAL_NODE:
         final_node = uml_element.ActivityFinal(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = final_node
     elif xmi_type == uml_element.Types.FLOW_FINAL_NODE:
         flow_final_node = uml_element.FlowFinal(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = flow_final_node
     elif xmi_type == uml_element.Types.MERGE_NODE:
         merge = uml_element.Merge(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = merge
     elif xmi_type == uml_element.Types.DECISION_NODE:
         decision = uml_element.Decision(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = decision
     # ObjectNode
     elif xmi_type == uml_element.Types.OBJECT_NODE:
         object_node = uml_element.ObjectNode(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = object_node
     elif xmi_type == uml_element.Types.DATA_STORE_NODE:
         data_store_node = uml_element.DataStore(xmi_id, xmi_type, name, incomings, outgoings)
         nodes_dict[xmi_id] = data_store_node
     else:
         log.show_warn("the type of the node is not defined " + xmi_type)
Example #9
0
 def get_id_name_type(self, node):
     """get the attribute--xmi:id, name,xmi:type
     @param node: xml node
     @type node: xml.dom.Node (attention: it is not a instance of
         uml_activity_diagram_element.ActivityNode)
     @return: xmi_id,name,xmi_type
     @rtype: xmi_id--str, name--str, xmi_type--str
     """
     xmi_id = None
     name = None
     xmi_type = None
     if node.hasAttribute("xmi:id"):
         # Return the value of the attribute named by name as a string.
         # If no such attribute exists, an empty string is returned,
         # as if the attribute had no value.
         xmi_id = node.getAttribute("xmi:id")
     # it is a error, if node has no xmi:id
     else:
         if node.nodeName == "edge":
             log.show_warn("edge has no xmi:id attribute")
         else:
             log.show_warn("node has no xmi:id attribute")
     # get the name of the node
     if node.hasAttribute("name"):
         name = node.getAttribute("name")
     # get the type of the node
     if node.hasAttribute("xmi:type"):
         xmi_type = node.getAttribute("xmi:type")
     # it is a error, if node has no xmi:type
     else:
         if node.nodeName == "edge":
             log.show_warn("edge has no xmi:type attribute")
         else:
             log.show_warn("node has no xmi:type attribute")
     return xmi_id, name, xmi_type
Example #10
0
 def get_id_name_type(self, node):
     '''get the attribute--xmi:id, name,xmi:type
     @param node: xml node
     @type node: xml.dom.Node (attention: it is not a instance of
         uml_activity_diagram_element.ActivityNode)
     @return: xmi_id,name,xmi_type
     @rtype: xmi_id--str, name--str, xmi_type--str
     '''
     xmi_id = None
     name = None
     xmi_type = None
     if node.hasAttribute("xmi:id"):
         # Return the value of the attribute named by name as a string.
         # If no such attribute exists, an empty string is returned,
         # as if the attribute had no value.
         xmi_id = node.getAttribute("xmi:id")
     # it is a error, if node has no xmi:id
     else:
         if node.nodeName == "edge":
             log.show_warn("edge has no xmi:id attribute")
         else:
             log.show_warn("node has no xmi:id attribute")
     # get the name of the node
     if node.hasAttribute("name"):
         name = node.getAttribute("name")
     # get the type of the node
     if node.hasAttribute("xmi:type"):
         xmi_type = node.getAttribute("xmi:type")
     # it is a error, if node has no xmi:type
     else:
         if node.nodeName == "edge":
             log.show_warn("edge has no xmi:type attribute")
         else:
             log.show_warn("node has no xmi:type attribute")
     return xmi_id, name, xmi_type
Example #11
0
    def create_edge_object(self, edges_dict, xmi_id, xmi_type, name, target, source, guard):
        """create instance of uml_activity_diagram_element.ActivityEdge
        from the xmi_type
        """
        if xmi_type == uml_element.Types.CONTROL_FLOW:
            edge = uml_element.ControlFlow(xmi_id, xmi_type, name, target, source, guard)
            edges_dict[xmi_id] = edge
            # get the probability from the guard of the control flow(edge)
            cf_prob = self._get_cf_prob_from_text(guard)
            edge.prob = cf_prob

        elif xmi_type == uml_element.Types.OBJECT_FLOW:
            edge = uml_element.ObjectFlow(xmi_id, xmi_type, name, target, source, guard)
            edges_dict[xmi_id] = edge
        else:
            log.show_warn("the edge is not control flow, neither object flow")
Example #12
0
    def create_edge_object(self, edges_dict, xmi_id, xmi_type, name, target, source, guard):
        '''create instance of uml_activity_diagram_element.ActivityEdge
        from the xmi_type
        '''
        if xmi_type == uml_element.Types.CONTROL_FLOW:
            edge = uml_element.ControlFlow(xmi_id, xmi_type, name, target, source, guard)
            edges_dict[xmi_id] = edge
            # get the probability from the guard of the control flow(edge)
            cf_prob = self._get_cf_prob_from_text(guard)
            edge.prob = cf_prob

        elif xmi_type == uml_element.Types.OBJECT_FLOW:
            edge = uml_element.ObjectFlow(xmi_id, xmi_type, name, target, source, guard)
            edges_dict[xmi_id] = edge
        else:
            log.show_warn("the edge is not control flow, neither object flow")
 def _get_data_flow(self, object_node_ids, action_ids, activity):
     '''get the data flow in activity diagram.
     also action1 to object, object to action2
     @type object_node_ids: list
     @type action_ids: list
     @return: data_flows,[(from,to),(from,to)...]
     @rtype: list
     '''
     # it is a list: [(from,to),(from,to)..]
     data_flows = []
     nodes_dict = activity.nodes_dict
     edges_dict = activity.edges_dict
     for node_id in object_node_ids:
         object_node = nodes_dict[node_id]
         incomings = object_node.incomings
         outgoings = object_node.outgoings
         # get name
         data_name = object_node.name
         # from element to object node(data)
         for incoming in incomings:
             edge_id = incoming.xmi_idref
             edge = edges_dict[edge_id]
             source = edge.source
             source_node = nodes_dict[source]
             if source in action_ids:
                 element_name = source_node.name
                 data_flows.append((element_name, data_name))
             else:
                 log.show_warn(
                     "the source of the object node is not a element")
         # from object node(data) to element
         for outgoing in outgoings:
             edge_id = outgoing.xmi_idref
             edge = edges_dict[edge_id]
             target = edge.target
             target_node = nodes_dict[target]
             if target in action_ids:
                 element_name = target_node.name
                 data_flows.append((data_name, element_name))
             else:
                 log.show_warn(
                     "the target of the object node is not a element")
     return data_flows
    def get_next_nodes(self, node, fork_num, parallel_num, activity, merges):
        """get the next activity nodes(s)
        @param fork_num: the number of the fork,from 1 to...
        @type fork_num: int
        @param parallel_num: the number of the parallel
        @type parallel_num: int
        """

        nodes_dict = activity.nodes_dict
        edges_dict = activity.edges_dict

        # join, fork, activity final, flow final
        stop_types = [
            uml_element.Types.JOIN_NODE,
            uml_element.Types.FORK_NODE,
            uml_element.Types.ACTIVITY_FINAL_NODE,
            uml_element.Types.FLOW_FINAL_NODE,
        ]

        node_type = node.xmi_type

        if node_type in stop_types:
            return
        else:
            # if it is merge, put it in the merges list
            if node_type == uml_element.Types.MERGE_NODE:
                if node not in merges:
                    merges.append(node)
            else:
                outgoings = node.outgoings
                for outgoing in outgoings:
                    edge_id = outgoing.xmi_idref
                    edge = edges_dict[edge_id]
                    if edge.xmi_type == uml_element.Types.CONTROL_FLOW:
                        if edge.parallel is False:
                            edge.parallel = True
                            edge.fork_num = fork_num
                            edge.parallel_num = parallel_num
                            target = edge.target
                            next_node = nodes_dict[target]
                            self.get_next_nodes(next_node, fork_num, parallel_num, activity, merges)
                        else:
                            log.show_warn("the edge is Already in parallel")
    def get_parallel_edges(self, activity):
        '''get the parallel edges in the fork.
        for example, fork1 has 2 parallel edge, the first edge's fork_num =1, parallel_num =1
        the second edge's fork_num =1, parallel_num =2
        fork2 has 2 parallel edge, the first edge's fork_num =2, parallel_num =1
        the second edge's fork_num =2, parallel_num =2
        '''

        nodes_dict = activity.nodes_dict
        edges_dict = activity.edges_dict

        # the merges list
        # see the example payOrder
        merges = []
        # the number of the fork,from 1 to...
        fork_num = 0

        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            # if it is fork
            if node.xmi_type == uml_element.Types.FORK_NODE:
                fork_num += 1
                # the number of the parallel
                parallel_num = 0
                outgoings = node.outgoings
                for outgoing in outgoings:
                    parallel_num += 1
                    edge_id = outgoing.xmi_idref
                    edge = edges_dict[edge_id]
                    if edge.xmi_type == uml_element.Types.CONTROL_FLOW:
                        if edge.parallel is False:
                            edge.parallel = True
                            edge.fork_num = fork_num
                            edge.parallel_num = parallel_num
                            target = edge.target
                            next_node = nodes_dict[target]
                            self.get_next_nodes(next_node, fork_num,
                                                parallel_num, activity, merges)
                        else:
                            log.show_warn("the edge is Already in parallel")
        for merge in merges:
            self.get_tokens_num(merge, activity)
Example #16
0
 def get_target_source(self, edge):
     '''get the target, source of the edge (xml.dom.Node)
     @param edge: xml.dom.Node---<edge...../>
     @type edge: (xml.dom.Node)
     @return: target,source
     @rtype: str
     '''
     target = None
     source = None
     # get the target of the edge
     if edge.hasAttribute("target"):
         target = edge.getAttribute("target")
     else:
         log.show_warn("edge has no target....")
     # get the target of the edge
     if edge.hasAttribute("source"):
         source = edge.getAttribute("source")
     else:
         log.show_warn("edge has no source....")
     return target, source
Example #17
0
 def get_target_source(self, edge):
     """get the target, source of the edge (xml.dom.Node)
     @param edge: xml.dom.Node---<edge...../>
     @type edge: (xml.dom.Node)
     @return: target,source
     @rtype: str
     """
     target = None
     source = None
     # get the target of the edge
     if edge.hasAttribute("target"):
         target = edge.getAttribute("target")
     else:
         log.show_warn("edge has no target....")
     # get the target of the edge
     if edge.hasAttribute("source"):
         source = edge.getAttribute("source")
     else:
         log.show_warn("edge has no source....")
     return target, source
 def _get_data_flow(self, object_node_ids, action_ids, activity):
     '''get the data flow in activity diagram.
     also action1 to object, object to action2
     @type object_node_ids: list
     @type action_ids: list
     @return: data_flows,[(from,to),(from,to)...]
     @rtype: list
     '''
     # it is a list: [(from,to),(from,to)..]
     data_flows = []
     nodes_dict = activity.nodes_dict
     edges_dict = activity.edges_dict
     for node_id in object_node_ids:
         object_node = nodes_dict[node_id]
         incomings = object_node.incomings
         outgoings = object_node.outgoings
         # get name
         data_name = object_node.name
         # from element to object node(data)
         for incoming in incomings:
             edge_id = incoming.xmi_idref
             edge = edges_dict[edge_id]
             source = edge.source
             source_node = nodes_dict[source]
             if source in action_ids:
                 element_name = source_node.name
                 data_flows.append((element_name, data_name))
             else:
                 log.show_warn("the source of the object node is not a element")
         # from object node(data) to element
         for outgoing in outgoings:
             edge_id = outgoing.xmi_idref
             edge = edges_dict[edge_id]
             target = edge.target
             target_node = nodes_dict[target]
             if target in action_ids:
                 element_name = target_node.name
                 data_flows.append((data_name, element_name))
             else:
                 log.show_warn("the target of the object node is not a element")
     return data_flows
    def get_parallel_edges(self, activity):
        """get the parallel edges in the fork.
        for example, fork1 has 2 parallel edge, the first edge's fork_num =1, parallel_num =1
        the second edge's fork_num =1, parallel_num =2
        fork2 has 2 parallel edge, the first edge's fork_num =2, parallel_num =1
        the second edge's fork_num =2, parallel_num =2
        """

        nodes_dict = activity.nodes_dict
        edges_dict = activity.edges_dict

        # the merges list
        # see the example payOrder
        merges = []
        # the number of the fork,from 1 to...
        fork_num = 0

        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            # if it is fork
            if node.xmi_type == uml_element.Types.FORK_NODE:
                fork_num += 1
                # the number of the parallel
                parallel_num = 0
                outgoings = node.outgoings
                for outgoing in outgoings:
                    parallel_num += 1
                    edge_id = outgoing.xmi_idref
                    edge = edges_dict[edge_id]
                    if edge.xmi_type == uml_element.Types.CONTROL_FLOW:
                        if edge.parallel is False:
                            edge.parallel = True
                            edge.fork_num = fork_num
                            edge.parallel_num = parallel_num
                            target = edge.target
                            next_node = nodes_dict[target]
                            self.get_next_nodes(next_node, fork_num, parallel_num, activity, merges)
                        else:
                            log.show_warn("the edge is Already in parallel")
        for merge in merges:
            self.get_tokens_num(merge, activity)
    def get_next_nodes(self, node, fork_num, parallel_num, activity, merges):
        '''get the next activity nodes(s)
        @param fork_num: the number of the fork,from 1 to...
        @type fork_num: int
        @param parallel_num: the number of the parallel
        @type parallel_num: int
        '''

        nodes_dict = activity.nodes_dict
        edges_dict = activity.edges_dict

        # join, fork, activity final, flow final
        stop_types = [uml_element.Types.JOIN_NODE, uml_element.Types.FORK_NODE, \
                      uml_element.Types.ACTIVITY_FINAL_NODE, uml_element.Types.FLOW_FINAL_NODE]

        node_type = node.xmi_type

        if node_type in stop_types:
            return
        else:
            # if it is merge, put it in the merges list
            if node_type == uml_element.Types.MERGE_NODE:
                if node not in merges:
                    merges.append(node)
            else:
                outgoings = node.outgoings
                for outgoing in outgoings:
                    edge_id = outgoing.xmi_idref
                    edge = edges_dict[edge_id]
                    if edge.xmi_type == uml_element.Types.CONTROL_FLOW:
                        if edge.parallel is False:
                            edge.parallel = True
                            edge.fork_num = fork_num
                            edge.parallel_num = parallel_num
                            target = edge.target
                            next_node = nodes_dict[target]
                            self.get_next_nodes(next_node, fork_num,
                                                parallel_num, activity, merges)
                        else:
                            log.show_warn("the edge is Already in parallel")
    def _get_control_flows(self, action_ids, activity):
        '''get the control flow in activity diagram.
        also action1 to action2
        @return: control_flows,[(from,to,prob),(from,to,prob)...]
        '''
        control_flows = []
        nodes_dict = activity.nodes_dict
        for node_id in action_ids:
            temp = False
            node1 = nodes_dict[node_id]
            # no control flow from fork, just control flow from join
            # no control flow to join, just control flow to fork
            if node1.xmi_type == uml_element.Types.FORK_NODE:
                pass
            else:
                # get the next nodes from node1, also node1-->nodes....
                nodes, probs = self._get_next_actions(node1, action_ids,
                                                      activity, 1)
                # the probs is more than 1
                if sum(probs) > 1:
                    temp = True
                    log.show_warn(
                        "the sum of edge probabilitys after the node:%s is more than 1"
                        % node1.name)
                for index in range(len(nodes)):
                    node2 = nodes[index]
                    # no control flow to join
                    if node2.xmi_type == uml_element.Types.JOIN_NODE:
                        pass
                    else:
                        # the prob
                        prob = probs[index]
                        if temp:
                            prob = 1.0 / len(nodes)
                        # get corrected name
                        name1 = node1.name
                        name2 = node2.name
                        control_flows.append((name1, name2, prob))

        return control_flows
    def find_deadlock(self, petri_net):
        '''find the deadlock.1)the place can never be marked.2)the transition can never fire
        also if the id_changed is False.
        '''
        # put the deadlock id to the list
        place_ids = []
        transition_ids = []

        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        for place in places_dict.values():
            if place.id_changed is False:
                place_ids.append(place.pt_id)
                log.show_warn("the place can never be marked "\
                              + "name:" + str(place.name) + " id:" + place.pt_id)
        for transition in transitions_dict.values():
            if transition.id_changed is False:
                transition_ids.append(transition.pt_id)
                log.show_warn("the transition can never fire "\
                              + "name:" + str(transition.name) + " id:" + transition.pt_id)

        return place_ids + transition_ids
 def _has_outgoing_control_flow(self, node, activity):
     """if the node has control flow,
     yes return True , no return False
     @param node: action, and so on
     @type node: uml_activity_diagram_element.Node... here Action
     """
     edges_dict = activity.edges_dict
     # has no control flow
     has_control_flow = False
     for outgoing in node.outgoings:
         idref = outgoing.xmi_idref
         edge = edges_dict[idref]
         # if action1 has a ControlFlow,
         # we can't accept it as the ControlFlow from action1 to action2
         if edge.xmi_type == uml_element.Types.CONTROL_FLOW:
             # one flow is control flow, also the node has control flow
             has_control_flow = True
             break
     if has_control_flow is False:
         # show a warn message
         log.show_warn("the node has no outgoing ControlFlow,name:%s,id:%s" % (node.name, node.xmi_id))
     return has_control_flow
 def _get_object_next_node(self, object_node, activity):
     """get the action or control node after the object node.
     """
     nodes_dict = activity.nodes_dict
     edges_dict = activity.edges_dict
     node = None
     outgoings = object_node.outgoings
     num = len(outgoings)
     if num == 0:
         log.show_warn("the object node has no ougoings")
     elif num == 1:
         outgoing = outgoings[0]
         edge_id = outgoing.xmi_idref
         edge = edges_dict[edge_id]
         node_id = edge.target
         node = nodes_dict[node_id]
     elif num > 1:
         log.show_error("the object node has more ougoings")
     # if the node after the object node is also object node.show error
     if isinstance(node, uml_element.ObjectNode):
         log.show_error("the node after the object node:%s is object node" % str(object_node.name))
     return node
Example #25
0
 def set_time(self, str_time, base_element, time_type, model):
     '''set the time property of action
     '''
     for activity_id in model.activitys_dict:
         activity = model.activitys_dict[activity_id]
         nodes_dict = activity.nodes_dict
         if base_element in nodes_dict:
             node = nodes_dict[base_element]
             time = self.get_time(str_time)
             # it is not immediate
             node.immediate = False
             if time_type == "const":
                 node.deterministic = True
             elif time_type == "exp":
                 node.exponential = True
             else:
                 log.show_warn("the type of the time is not defined.type:%s" % time_type)
                 # set it to default deterministic
                 node.deterministic = True
             node.time = time
             log.show_info("the action has time property.name:%s,id:%s,time:%s" % 
                           (str(node.name), node.xmi_id, str_time))
             break
 def _get_object_next_node(self, object_node, activity):
     '''get the action or control node after the object node.
     '''
     nodes_dict = activity.nodes_dict
     edges_dict = activity.edges_dict
     node = None
     outgoings = object_node.outgoings
     num = len(outgoings)
     if num == 0:
         log.show_warn("the object node has no ougoings")
     elif num == 1:
         outgoing = outgoings[0]
         edge_id = outgoing.xmi_idref
         edge = edges_dict[edge_id]
         node_id = edge.target
         node = nodes_dict[node_id]
     elif num > 1:
         log.show_error("the object node has more ougoings")
     # if the node after the object node is also object node.show error
     if isinstance(node, uml_element.ObjectNode):
         log.show_error("the node after the object node:%s is object node" %
                        str(object_node.name))
     return node
    def _get_control_flows(self, action_ids, activity):
        '''get the control flow in activity diagram.
        also action1 to action2
        @return: control_flows,[(from,to,prob),(from,to,prob)...]
        '''
        control_flows = []
        nodes_dict = activity.nodes_dict
        for node_id in action_ids:
            temp = False
            node1 = nodes_dict[node_id]
            # no control flow from fork, just control flow from join
            # no control flow to join, just control flow to fork
            if node1.xmi_type == uml_element.Types.FORK_NODE:
                pass
            else:
                # get the next nodes from node1, also node1-->nodes....
                nodes, probs = self._get_next_actions(node1, action_ids, activity, 1)
                # the probs is more than 1
                if sum(probs) > 1:
                    temp = True
                    log.show_warn("the sum of edge probabilitys after the node:%s is more than 1" % node1.name)
                for index in range(len(nodes)):
                    node2 = nodes[index]
                    # no control flow to join
                    if node2.xmi_type == uml_element.Types.JOIN_NODE:
                        pass
                    else:
                        # the prob
                        prob = probs[index]
                        if temp:
                            prob = 1.0 / len(nodes)
                        # get corrected name
                        name1 = node1.name
                        name2 = node2.name
                        control_flows.append((name1, name2, prob))

        return control_flows
Example #28
0
    def find_self_loop(self, petri_net):
        '''A Petri Net without any self loop is called "Pure Petri Net".
        A self-loop occurs when a place p is at same time input and output to a transition t.
        A Petri Net is said to be ordinary if the weight of all its arcs is 1.
        auf deutsch: reines PN ohne Selbstschleifen,Schlingen--> eliminieren
        '''
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict

        self_loop_places = []
        self_loop_arcs = []
        # the number of the self_loops
        num = 0

        # place->arc1->transition->arc2->place
        for place_id in places_dict:
            place = places_dict[place_id]
            for place_outgoing in place.outgoings:
                arc1 = arcs_dict[place_outgoing]
                transiton_id = arc1.target
                transition = transitions_dict[transiton_id]
                for transition_outgoing in transition.outgoings:
                    arc2 = arcs_dict[transition_outgoing]
                    next_place_id = arc2.target
                    # place p is at same time input and output to a transition t.
                    if next_place_id == place_id:
                        num += 1
                        self_loop_places.append(place)
                        self_loop_arcs.append(arc2)
        if num > 0:
            log.show_warn("the petri net has " + str(num) + " self-loop.")
            for index in range(num):
                place = self_loop_places[index]
                arc = self_loop_arcs[index]
                self.eliminate_self_loop(place, arc, petri_net)
        return num
Example #29
0
    def find_self_loop(self, petri_net):
        '''A Petri Net without any self loop is called "Pure Petri Net".
        A self-loop occurs when a place p is at same time input and output to a transition t.
        A Petri Net is said to be ordinary if the weight of all its arcs is 1.
        auf deutsch: reines PN ohne Selbstschleifen,Schlingen--> eliminieren
        '''
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict

        self_loop_places = []
        self_loop_arcs = []
        # the number of the self_loops
        num = 0

        # place->arc1->transition->arc2->place
        for place_id in places_dict:
            place = places_dict[place_id]
            for place_outgoing in place.outgoings:
                arc1 = arcs_dict[place_outgoing]
                transiton_id = arc1.target
                transition = transitions_dict[transiton_id]
                for transition_outgoing in transition.outgoings:
                    arc2 = arcs_dict[transition_outgoing]
                    next_place_id = arc2.target
                    # place p is at same time input and output to a transition t.
                    if next_place_id == place_id:
                        num += 1
                        self_loop_places.append(place)
                        self_loop_arcs.append(arc2)
        if num > 0:
            log.show_warn("the petri net has " + str(num) + " self-loop.")
            for index in range(num):
                place = self_loop_places[index]
                arc = self_loop_arcs[index]
                self.eliminate_self_loop(place, arc, petri_net)
        return num
 def _has_outgoing_control_flow(self, node, activity):
     '''if the node has control flow,
     yes return True , no return False
     @param node: action, and so on
     @type node: uml_activity_diagram_element.Node... here Action
     '''
     edges_dict = activity.edges_dict
     # has no control flow
     has_control_flow = False
     for outgoing in node.outgoings:
         idref = outgoing.xmi_idref
         edge = edges_dict[idref]
         # if action1 has a ControlFlow,
         # we can't accept it as the ControlFlow from action1 to action2
         if edge.xmi_type == uml_element.Types.CONTROL_FLOW:
             # one flow is control flow, also the node has control flow
             has_control_flow = True
             break
     if has_control_flow is False:
         # show a warn message
         log.show_warn(
             "the node has no outgoing ControlFlow,name:%s,id:%s" %
             (node.name, node.xmi_id))
     return has_control_flow
Example #31
0
 def set_time(self, str_time, base_element, time_type, model):
     """set the time property of action
     """
     for activity_id in model.activitys_dict:
         activity = model.activitys_dict[activity_id]
         nodes_dict = activity.nodes_dict
         if base_element in nodes_dict:
             node = nodes_dict[base_element]
             time = self.get_time(str_time)
             # it is not immediate
             node.immediate = False
             if time_type == "const":
                 node.deterministic = True
             elif time_type == "exp":
                 node.exponential = True
             else:
                 log.show_warn("the type of the time is not defined.type:%s" % time_type)
                 # set it to default deterministic
                 node.deterministic = True
             node.time = time
             log.show_info(
                 "the action has time property.name:%s,id:%s,time:%s" % (str(node.name), node.xmi_id, str_time)
             )
             break
    def transform_to_petri_net(self, activity):
        '''
        transform the UmlActivityDiagramElemnt objects to the petri_net_element objects
        '''
        # the activity elements
        activity_name = activity.name
        nodes_dict = activity.nodes_dict
        edges_dict = activity.edges_dict

        # the Petri net elements
        # name:Place (class petri_net_element.Place)
        places_dict = {}
        # name:Transition (class petri_net_element.Transition)
        transitions_dict = {}
        # name:Arc (class petri_net_element.Arc)
        arcs_dict = {}
        # create a petri net object
        petri_net = pt_element.PetriNet(places_dict, transitions_dict,
                                        arcs_dict, activity_name)

        # create Place,Transition objects from the nodes, if node.petri=True
        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            # nodes_dict[node_id].petri = True
            if node.petri:
                # get the id, name, incomings, outgoings
                pt_id = node.xmi_id
                name = node.name
                incomings = []  # list
                outgoings = []
                # new Place object, and put it in the places_dict
                if node.place:
                    # initial Node is "s1" and start:True
                    if node.xmi_type == uml_element.Types.INITIAL_NODE:
                        place = pt_element.Place(pt_id, name, incomings,
                                                 outgoings)
                        place.start = True
                        place.tokens = 1
                        places_dict[pt_id] = place
                    elif node.xmi_type == uml_element.Types.ACTIVITY_FINAL_NODE:
                        place = pt_element.Place(pt_id, name, incomings,
                                                 outgoings)
                        place.final = True
                        places_dict[pt_id] = place
                    elif node.xmi_type == uml_element.Types.MERGE_NODE:
                        place = pt_element.Place(pt_id, name, incomings,
                                                 outgoings)
                        places_dict[pt_id] = place
                        # if the max_tokens of the merge is not 1
                        # see example:payOrder
                        if node.max_tokens != 1:
                            place.max_tokens = node.max_tokens
                    else:
                        place = pt_element.Place(pt_id, name, incomings,
                                                 outgoings)
                        places_dict[pt_id] = place
                # new Transition object, and put it in the transitions_dict
                elif node.transition:
                    # fork,join,action without <<Time>> stereotyping
                    if node.immediate:
                        transition = pt_element.ImmediateTransition(
                            pt_id, name, incomings, outgoings)
                        # transition.delay =0
                    # action with <<Time>> stereotyping and property time and "const"
                    elif node.deterministic:
                        transition = pt_element.DeterministicTransition(
                            pt_id, name, incomings, outgoings)
                        transition.delay = node.time
                    # action with <<Time>> stereotyping and property time and "exp"
                    elif node.exponential:
                        transition = pt_element.ExponentialTransition(
                            pt_id, name, incomings, outgoings)
                        transition.delay = node.time
                    transitions_dict[pt_id] = transition
        # edge--> arc
        for edge_id in edges_dict:
            # get the source, target of the edge
            edge = edges_dict[edge_id]
            # if it is control flows
            if edge.xmi_type == uml_element.Types.CONTROL_FLOW:
                source = edge.source
                target = edge.target
                # get the body of the guard.
                # arc_label = ""
                guard = edge.guard
                if guard is not None:
                    pass
                    # arc_label = guard.body
                # get the node in nodes_dict from the ID
                if source in nodes_dict:
                    node1_id = source
                    node1 = nodes_dict[node1_id]
                # pin,pout
                else:
                    log.show_warn("the source is not a node")
                # get the node in nodes_dict from the ID
                if target in nodes_dict:
                    node2_id = target
                    node2 = nodes_dict[node2_id]
                else:
                    log.show_warn("the target is not a node")
                if node1.petri and node2.petri:  # node1 , node2 -- P(merge...) or T(action...)
                    self.create_pt_object(node1, node2, edge.prob, petri_net)
                else:
                    log.show_warn("node1 and node2 are not both petri")
            # object flow, pass
            else:
                pass
        return petri_net
 def create_pt_object(self, node1, node2, prob, petri_net):
     '''create p or t object
     '''
     places_dict = petri_net.places_dict
     transitions_dict = petri_net.transitions_dict
     arcs_dict = petri_net.arcs_dict
     # the id is nodeId of the umlActivityElement , also the pt_id of the petri_net_element
     id1 = node1.xmi_id
     id2 = node2.xmi_id
     # the 2 nodes are place
     if node1.place and node2.place:
         # create a transition and put it in the transitionsDict
         # place1 -(arc1)-> transition -(arc2)-> place2
         pt_id = id1 + id2
         if pt_id not in transitions_dict:
             # create one immediate transition
             transition = pt_element.ImmediateTransition(pt_id,
                                                         name=None,
                                                         incomings=[],
                                                         outgoings=[])
             transitions_dict[pt_id] = transition
             # place1
             place1 = places_dict[id1]
             # place2
             place2 = places_dict[id2]
             # create one arc, place1 -(arc1)-> transition,
             # and put it in the arcs_dict
             self.create_arc(arcs_dict, place1, transition, prob)
             # create the other arc, transition -(arc2)-> place2,
             # and put it in the arcs_dict
             self.create_arc(arcs_dict, transition, place2)
         else:
             log.show_warn("id1-->id2 has more than one connection")
     # the 2 nodes are transition
     elif node1.transition and node2.transition:
         # create a place and put it in the placesDict
         # transition1 -(arc1)-> place -(arc2)-> transition2
         pt_id = id1 + id2
         if pt_id not in places_dict:
             # create one place
             place = pt_element.Place(pt_id,
                                      name=None,
                                      incomings=[],
                                      outgoings=[])
             places_dict[pt_id] = place
             # transition1
             transition1 = transitions_dict[id1]
             # transition2
             transition2 = transitions_dict[id2]
             # create one arc, transition1 -(arc1)-> place,
             # and put it in the arcs_dict
             self.create_arc(arcs_dict, transition1, place)
             # create the other arc, place -(arc2)-> transition2,
             # and put it in the arcs_dict
             self.create_arc(arcs_dict, place, transition2)
         else:
             log.show_warn("id1-->id2 has more than one connection")
     # p --> t    #TODO more than one connection
     elif node1.place and node2.transition:
         # just create one arc, p -(arc)-> t
         place = places_dict[id1]
         transition = transitions_dict[id2]
         self.create_arc(arcs_dict, place, transition, prob)
     # t --> p
     elif node1.transition and node2.place:
         # just create one arc, t -(arc)-> p
         transition = transitions_dict[id1]
         place = places_dict[id2]
         self.create_arc(arcs_dict, transition, place)
     else:
         # Error
         print "type error +create_pt_object():", node1.xmi_type, node2.xmi_type
    def get_init_final_num(self, activity):
        """ verify, if the uml activity diagram has just(genau)
        one Initial Node, and one or more ActivityFinal. if a node has no incoming or no outgoing,
        it is a error, except init node and final node and flow final.
        """
        nodes_dict = activity.nodes_dict
        initial_num = 0
        final_num = 0
        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            incomings = node.incomings
            outgoings = node.outgoings
            in_num = len(incomings)
            out_num = len(outgoings)
            # initial node, just one and it must have outgoing
            if node.xmi_type == uml_element.Types.INITIAL_NODE:
                initial_num += 1
                if out_num == 0:
                    log.show_error(
                        "the Initial Node has no outgoing." + "name:" + str(node.name) + " id:" + node.xmi_id
                    )
            # final node, one or more, and it must have incoming
            elif node.xmi_type == uml_element.Types.ACTIVITY_FINAL_NODE:
                final_num += 1
                if in_num == 0:
                    log.show_error("the final Node has no incoming." + "name:" + str(node.name) + " id:" + node.xmi_id)
            # flow final, it must have incoming
            elif node.xmi_type == uml_element.Types.FLOW_FINAL_NODE:
                if len(incomings) == 0:
                    log.show_error("the final Node has no incoming." + "name:" + str(node.name) + " id:" + node.xmi_id)
            elif isinstance(node, uml_element.ObjectNode):
                if not isinstance(node, uml_element.InstanceSpecification_node):
                    if len(incomings) == 0:
                        # @see example Order
                        # show warn info, not error info
                        log.show_warn("the object Node has no incoming.name:%s,id:%s" % (str(node.name), node.xmi_id))
                    if len(outgoings) == 0:
                        # @see example Order
                        # show warn info, not error info
                        log.show_warn("the object Node has no outgoins.name:%s,id:%s" % (str(node.name), node.xmi_id))
            # if the node has no incoming or no outgoing
            # it is a error(except initial,final,object node)
            else:
                # incoming and outgoing of a node
                if in_num == 0:
                    # action has no incoming, but it has argument, and the argument has incoming
                    if isinstance(node, uml_element.ExecutableNode):
                        arguments = node.arguments
                        for argument in arguments:
                            # if the argument has no incoming
                            if len(argument.incomings) == 0:
                                log.show_error(
                                    "the action node's argument in "
                                    + "uml activity diagram has no incoming."
                                    + "name:"
                                    + str(node.name)
                                    + " id:"
                                    + node.xmi_id
                                )
                    # it is not a action
                    else:
                        log.show_error(
                            "the node in uml activity diagram has no incoming."
                            + "name:"
                            + str(node.name)
                            + " id:"
                            + node.xmi_id
                        )
                if out_num == 0:
                    # action has no outgoing, but it has result, and the result has outgoing
                    if isinstance(node, uml_element.ExecutableNode):
                        results = node.results
                        for result in results:
                            # if the result has no outgoing
                            if len(result.outgoings) == 0:
                                log.show_error(
                                    "the action node's result in "
                                    + "uml activity diagram has no incoming."
                                    + +"name:"
                                    + str(node.name)
                                    + " id:"
                                    + node.xmi_id
                                )
                    # it is not a action
                    else:
                        log.show_error(
                            "the node in uml activity diagram has no outgoing."
                            + "name:"
                            + str(node.name)
                            + " id:"
                            + node.xmi_id
                        )
        # initial node just one
        if initial_num == 0:
            log.show_error("the uml activity diagram has no Initial Node")
        elif initial_num > 1:
            log.show_error("the uml activity diagram has " + str(initial_num) + " Initial Nodes")
        # final node one or more than one
        if final_num == 0:
            log.show_warn("the uml activity diagram has no final Node")

        return initial_num, final_num
    def find_enabled_transitions(self, places, petri_net, rg_graph,
                                 unreach_list, reach):
        ''' first,get the next following transition from the current marked places,
        second, see if it can be enabled(see function-is_transition_enabled),
        and save the transitions in one list, for example [s1,s2]
        @param places: the current marked places,pre-places
        @type places: list
        @param reach: True, for the reachability_graph diagram.
        False, unreach_list=[],for the unreachability_graph.
        @type reach: Boolean
        @see: algorithm- step1
        '''
        # [t1,t2,t3...]
        transitions = []
        # [[t1],[t2,t3]...]
        # t1 fire from place1, t2,t3 fire from place2(decision)
        transitions_slices = []
        # the probs to fire the transition
        # [prob1,prob2,prob3...], the sum must be 1
        probs = []
        # [[prob1],[prob2,prob3]...]
        # prob1 is 1, sum of prob2 and prob3 is 1
        probs_slices = []
        # petri_net
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict

        # get the next transition from the place, and see if it can be enabled
        for place in places:
            # [t1] or [t2,t3]
            transitions_slice = []
            # [1] or [0.3,0.7]
            probs_slice = []
            outgoings = place.outgoings
            for outgoing in outgoings:
                arc = arcs_dict[outgoing]
                target = arc.target
                transition = transitions_dict[target]
                # if the transition can be enabled
                if self.is_transition_enabled(transition, places, places_dict,
                                              arcs_dict):
                    # get the prob from the arc
                    prob = arc.prob
                    # put the transition in the transitions_slice
                    if transition not in transitions_slice:
                        transitions_slice.append(transition)
                        # put the prob in the probs_slice
                        probs_slice.append(prob)
                    else:
                        # show error
                        log.show_error(
                            "more than 1 arcs between the place and the transition:find_enabled_transitions()"
                        )
                    # put it in the transitions
                    if transition not in transitions:
                        transitions.append(transition)
                        probs.append(prob)
                    # change the id of transition,which can be enabled
                    if not transition.id_changed:
                        self.change_pt_id(transition, transitions_dict,
                                          arcs_dict, petri_net)
            # if it is not []
            if transitions_slice:
                transitions_slices.append(transitions_slice)
                probs_slices.append(probs_slice)
        if reach:
            # parallel find the min(delay),
            # if just decision len(transitions) > 1 and len(transitions_slices)=1
            # if len(transitions_slices) > 1, but len(transitions) = 1-->join:
            # len(transitions_slices) >1 ,-->parallel
            if len(transitions) > 1 and len(transitions_slices) > 1:
                # delete the same type
                types_set = set(
                    [transition.transition_type for transition in transitions])
                types_list = list(types_set)
                # TODO
                if len(types_list) == 1:
                    # get the type of the transitions
                    transition_type = types_list[0]

                    # all are immediate transition
                    if transition_type == petri_net_element.TransitionTypes.IMMEDIATE_TRANSITION:
                        pass
                    # all are DeterministicTransition
                    elif transition_type == petri_net_element.TransitionTypes.DETERMINISTIC_TRANSITION:
                        execute_transition = self.get_execute_transition(
                            transitions)

                        transitions.remove(execute_transition)
                        #
                        tokens_list = [place.tokens for place in places]
                        unreach_list.append(places)
                        unreach_list.append(tokens_list)
                        unreach_list.append(transitions)
                        #
                        transitions = [execute_transition]
                    # all are EXPONENTIAL_TRANSITION
                    elif transition_type == petri_net_element.TransitionTypes.EXPONENTIAL_TRANSITION:
                        if len(transitions_slices) == 2:
                            self._calculate_probability(
                                transitions_slices, probs_slices, transitions,
                                probs)
                        else:
                            log.show_error(
                                "the code can not analyse 3 parallel exp distribution process"
                            )
                    else:
                        log.show_error(
                            "the type of the transition is not defined")

                # all are ExponentialTransition
                else:
                    log.show_warn(
                        "the types of the enabled transitions are not the same"
                    )

        # see algorithm- step1a)
        if len(transitions) > 0:
            # fire t and determine the marking m' after firing.
            self.get_next_state(places, transitions, petri_net, rg_graph,
                                unreach_list, reach, probs)
 def _analyse_nodes(self, node1, node2, activity):
     '''for example:
     situation:
     1. action1(with(out) pout)-->action2 (with(out) pin)
     2. action1-->object-->action2(or control)
     3. action1 with pin-->control node #pass
     4. control node(fork,decision,merge)-->action2 with pin #pass
     5. control node(fork,decision,merge)-->object-->action2(or control)
     6. control node-->control node #pass
     7. object node-->... #pass
     if action1 has no control flow, add one control flow between action1 and action2.
     '''
     # if node1 and node2 are actions
     # 1.situation
     if (isinstance(node1, uml_element.ExecutableNode) and \
         isinstance(node2, uml_element.ExecutableNode)):
         log.show_info("1.situation: action to action")
         # if node1 has no control flow
         if not self._has_outgoing_control_flow(node1, activity):
             # add one control flow from action1 to action2
             self._add_control_flow(node1, node2, activity)
     # if node1 is a action, and node2 is a object_node
     # 2.situation
     elif (isinstance(node1, uml_element.ExecutableNode)
           and isinstance(node2, uml_element.ObjectNode)):
         log.show_info("2.situation: action to object node")
         # if node1 has no control flow
         if not self._has_outgoing_control_flow(node1, activity):
             node3 = self._get_object_next_node(node2, activity)
             # if node3 not None
             if node3:
                 self._add_control_flow(node1, node3, activity)
     # if node1 is a action with pout, and node2 is a control
     # 3.situation
     elif (isinstance(node1, uml_element.ExecutableNode)
           and isinstance(node2, uml_element.ControlNode)):
         log.show_info("3.situation: action to control node")
         # pass
     # if node1 is control_node, node2 is a action with pin
     # 4.situation
     elif (isinstance(node1, uml_element.ControlNode)
           and isinstance(node2, uml_element.ExecutableNode)):
         log.show_info("4.situation: control node to action")
         # pass
     # if node1 is control_node, node2 is object_node
     # 5.situation
     elif (isinstance(node1, uml_element.ControlNode)
           and isinstance(node2, uml_element.ObjectNode)):
         log.show_info("5.situation: control node to object node")
         node3 = self._get_object_next_node(node2, activity)
         if node3:
             # add one control flow from node1 to node3
             self._add_control_flow(node1, node3, activity)
     # if node1 is control_node, node2 is control_node
     # 6.situation
     elif (isinstance(node1, uml_element.ControlNode)
           and isinstance(node2, uml_element.ControlNode)):
         log.show_info("6.situation: control node to control node")
         # TODO
         # pass
     # if node1 is object node
     # 7.situation
     elif isinstance(node1, uml_element.ObjectNode):
         pass
     else:
         log.show_warn("a object flow from node1 to node2,"
                       "but the 2 nodes's situation are not defined")
    def transform_to_petri_net(self, activity):
        '''
        transform the UmlActivityDiagramElemnt objects to the petri_net_element objects
        '''
        # the activity elements
        activity_name = activity.name
        nodes_dict = activity.nodes_dict
        edges_dict = activity.edges_dict

        # the Petri net elements
        # name:Place (class petri_net_element.Place)
        places_dict = {}
        # name:Transition (class petri_net_element.Transition)
        transitions_dict = {}
        # name:Arc (class petri_net_element.Arc)
        arcs_dict = {}
        # create a petri net object
        petri_net = pt_element.PetriNet(places_dict, transitions_dict, arcs_dict, activity_name)

        # create Place,Transition objects from the nodes, if node.petri=True
        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            # nodes_dict[node_id].petri = True
            if node.petri:
                # get the id, name, incomings, outgoings
                pt_id = node.xmi_id
                name = node.name
                incomings = []  # list
                outgoings = []
                # new Place object, and put it in the places_dict
                if node.place:
                    # initial Node is "s1" and start:True
                    if node.xmi_type == uml_element.Types.INITIAL_NODE:
                        place = pt_element.Place(pt_id, name, incomings, outgoings)
                        place.start = True
                        place.tokens = 1
                        places_dict[pt_id] = place
                    elif node.xmi_type == uml_element.Types.ACTIVITY_FINAL_NODE:
                        place = pt_element.Place(pt_id, name, incomings, outgoings)
                        place.final = True
                        places_dict[pt_id] = place
                    elif node.xmi_type == uml_element.Types.MERGE_NODE:
                        place = pt_element.Place(pt_id, name, incomings, outgoings)
                        places_dict[pt_id] = place
                        # if the max_tokens of the merge is not 1
                        # see example:payOrder
                        if node.max_tokens != 1:
                            place.max_tokens = node.max_tokens
                    else:
                        place = pt_element.Place(pt_id, name, incomings, outgoings)
                        places_dict[pt_id] = place
                # new Transition object, and put it in the transitions_dict
                elif node.transition:
                    # fork,join,action without <<Time>> stereotyping
                    if node.immediate:
                        transition = pt_element.ImmediateTransition(pt_id,
                                                                    name,
                                                                    incomings,
                                                                    outgoings)
                        # transition.delay =0
                    # action with <<Time>> stereotyping and property time and "const"
                    elif node.deterministic:
                        transition = pt_element.DeterministicTransition(pt_id,
                                                                        name,
                                                                        incomings,
                                                                        outgoings)
                        transition.delay = node.time
                    # action with <<Time>> stereotyping and property time and "exp"
                    elif node.exponential:
                        transition = pt_element.ExponentialTransition(pt_id,
                                                                        name,
                                                                        incomings,
                                                                        outgoings)
                        transition.delay = node.time
                    transitions_dict[pt_id] = transition
        # edge--> arc
        for edge_id in edges_dict:
            # get the source, target of the edge
            edge = edges_dict[edge_id]
            # if it is control flows
            if edge.xmi_type == uml_element.Types.CONTROL_FLOW:
                source = edge.source
                target = edge.target
                # get the body of the guard.
                # arc_label = ""
                guard = edge.guard
                if guard is not None:
                    pass
                    # arc_label = guard.body
                # get the node in nodes_dict from the ID
                if source in nodes_dict:
                    node1_id = source
                    node1 = nodes_dict[node1_id]
                # pin,pout
                else:
                    log.show_warn("the source is not a node")
                # get the node in nodes_dict from the ID
                if target in nodes_dict:
                    node2_id = target
                    node2 = nodes_dict[node2_id]
                else:
                    log.show_warn("the target is not a node")
                if node1.petri and node2.petri:  # node1 , node2 -- P(merge...) or T(action...)
                    self.create_pt_object(node1, node2, edge.prob, petri_net)
                else:
                    log.show_warn("node1 and node2 are not both petri")
            # object flow, pass
            else:
                pass
        return petri_net
    def transform_to_epf(self, activity, model):
        '''transform the activity diagram to error model.
        return: model
        '''
        # clear the epf model
        model.clear()
        # get the name
        model.name = activity.name

        nodes_dict = activity.nodes_dict
        pins_dict = activity.pins_dict
        edges_dict = activity.edges_dict

        # save the id of actions
        action_ids = []
        # save the id of the object_node
        object_node_ids = []

        elements, datas = self._get_elements_datas(action_ids, object_node_ids, activity, model)
        control_flows = self._get_control_flows(action_ids, activity)
        data_flows = self._get_data_flow(object_node_ids, action_ids, activity)

        # add control flow
        for cf_from, cf_to, prob in control_flows:
            model.add_cf_arc(cf_from, cf_to, prob)

        # add data flow
        for df_from, df_to  in data_flows:
            model.add_df_arc(df_from, df_to)
        
        # pout--> pin, the two elements come in together
        for pin_id in pins_dict:
            # action with pout
            pout = pins_dict[pin_id]
            if isinstance(pout, uml_element.Result):
                name = pout.name
                node1_id = pout.host
                node1 = nodes_dict[node1_id]
                # add data, pout.name
                model.add_data(name)
                # add data flow from node1 to pout
                model.add_df_arc(node1.name, name)
                outgoings = pout.outgoings
                for outgoing in outgoings:
                    edge_id = outgoing.xmi_idref
                    edge = edges_dict[edge_id]
                    target = edge.target
                    if target in nodes_dict:
                        node2 = nodes_dict[target]
                        model.add_df_arc(name, node2.name)
                        log.show_warn("pout has a outgoing node")
                    elif target in pins_dict:
                        # action with pin
                        pin = pins_dict[target]
                        node2_id = pin.host
                        node2 = nodes_dict[node2_id]
                        model.add_df_arc(name, node2.name)
        
        '''
        print model.elements  # key = element name
        print model.data  # key = data name
        print model.cf_probs  # key =  "(from,to)", value = prob
        print model.subsystems  # key = host, value = {intial_element, elements, data}
        '''
        model.xml.save(activity.name + "_epf.xml")
        # model.checking.check()
        # model.acknowledge_all_conditions()
        #model.xml.load(activity.name + "_epf.xml")
        
        
        model.drawing.draw_system(activity.name + "_epf.png")

        return model
    def transform_to_epf(self, activity, model):
        '''transform the activity diagram to error model.
        return: model
        '''
        # clear the epf model
        model.clear()
        # get the name
        model.name = activity.name

        nodes_dict = activity.nodes_dict
        pins_dict = activity.pins_dict
        edges_dict = activity.edges_dict

        # save the id of actions
        action_ids = []
        # save the id of the object_node
        object_node_ids = []

        elements, datas = self._get_elements_datas(action_ids, object_node_ids,
                                                   activity, model)
        control_flows = self._get_control_flows(action_ids, activity)
        data_flows = self._get_data_flow(object_node_ids, action_ids, activity)

        # add control flow
        for cf_from, cf_to, prob in control_flows:
            model.add_cf_arc(cf_from, cf_to, prob)

        # add data flow
        for df_from, df_to in data_flows:
            model.add_df_arc(df_from, df_to)

        # pout--> pin, the two elements come in together
        for pin_id in pins_dict:
            # action with pout
            pout = pins_dict[pin_id]
            if isinstance(pout, uml_element.Result):
                name = pout.name
                node1_id = pout.host
                node1 = nodes_dict[node1_id]
                # add data, pout.name
                model.add_data(name)
                # add data flow from node1 to pout
                model.add_df_arc(node1.name, name)
                outgoings = pout.outgoings
                for outgoing in outgoings:
                    edge_id = outgoing.xmi_idref
                    edge = edges_dict[edge_id]
                    target = edge.target
                    if target in nodes_dict:
                        node2 = nodes_dict[target]
                        model.add_df_arc(name, node2.name)
                        log.show_warn("pout has a outgoing node")
                    elif target in pins_dict:
                        # action with pin
                        pin = pins_dict[target]
                        node2_id = pin.host
                        node2 = nodes_dict[node2_id]
                        model.add_df_arc(name, node2.name)
        '''
        print model.elements  # key = element name
        print model.data  # key = data name
        print model.cf_probs  # key =  "(from,to)", value = prob
        print model.subsystems  # key = host, value = {intial_element, elements, data}
        '''
        model.xml.save(activity.name + "_epf.xml")
        # model.checking.check()
        # model.acknowledge_all_conditions()
        #model.xml.load(activity.name + "_epf.xml")

        model.drawing.draw_system(activity.name + "_epf.png")

        return model
    def check_names(self, activity):
        """check the name of action and object.
        1.if it is None or "",it will cause a error when it transforms to epf.
        set the name "node1","node2"
        2.if two nodes(action or object) have the same name, it will also cause a error
        when it transforms to epf. for example "get info" and "get_info"
        3.change the name to the corrected name
        # TODO check the name of pin
        @return: check_ok, if checks ok
        @rtype: boolean
        """
        check_ok = True
        names = []
        nodes_dict = activity.nodes_dict
        pins_dict = activity.pins_dict

        # action, object, initial, final
        node_types = (
            uml_element.ExecutableNode,
            uml_element.ObjectNode,
            uml_element.InitialNode,
            uml_element.FinalNode,
            uml_element.Fork,
            uml_element.Join,
        )
        # for node
        num1 = 0
        # for pin,pout
        num2 = 0
        # it checks the name of pout, do not need to check the name of pin
        for pin_id in pins_dict:
            pin = pins_dict[pin_id]
            # if it is a pout(Result)
            if isinstance(pin, uml_element.Result):
                name = pin.name
                # if it has no name, see condition1
                if name is None or name.strip() == "":
                    # if the pin has no name, set the name "pin1","pin2"...
                    num2 += 1
                    pin.name = "pin" + str(num2)
                    log.show_warn("the pin has no name.id:%s" % pin.xmi_id)
                else:
                    corrected_name = self.__get_corrected_name(name)
                    # change the name of node to corrected name
                    pin.name = corrected_name
                    # see condition2
                    if corrected_name in names:
                        check_ok = False
                        log.show_error("the pin has the same name.name:%s" % name)
                    else:
                        names.append(corrected_name)

        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            # if it is a action or object,initial,final
            # The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
            # isinstance(x, A) or isinstance(x, B) or ... (etc.).
            if isinstance(node, node_types):
                name = node.name
                # if it has no name, see condition1
                if name is None or name.strip() == "":
                    # if the node has no name, set the name "node1","node2"...
                    num1 += 1
                    node.name = "node" + str(num1)
                    log.show_warn("the node has no name.id:%s" % node.xmi_id)
                else:
                    corrected_name = self.__get_corrected_name(name)
                    # change the name of node to corrected name
                    node.name = corrected_name
                    # see condition2
                    if corrected_name in names:
                        check_ok = False
                        log.show_error("the nodes has the same name.name:%s" % name)
                    else:
                        names.append(corrected_name)
        return check_ok
    def get_init_final_num(self, activity):
        ''' verify, if the uml activity diagram has just(genau)
        one Initial Node, and one or more ActivityFinal. if a node has no incoming or no outgoing,
        it is a error, except init node and final node and flow final.
        '''
        nodes_dict = activity.nodes_dict
        initial_num = 0
        final_num = 0
        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            incomings = node.incomings
            outgoings = node.outgoings
            in_num = len(incomings)
            out_num = len(outgoings)
            # initial node, just one and it must have outgoing
            if node.xmi_type == uml_element.Types.INITIAL_NODE:
                initial_num += 1
                if out_num == 0:
                    log.show_error("the Initial Node has no outgoing." + \
                                   "name:" + str(node.name) + " id:" + node.xmi_id)
            # final node, one or more, and it must have incoming
            elif node.xmi_type == uml_element.Types.ACTIVITY_FINAL_NODE:
                final_num += 1
                if in_num == 0:
                    log.show_error("the final Node has no incoming." + \
                                   "name:" + str(node.name) + " id:" + node.xmi_id)
            # flow final, it must have incoming
            elif node.xmi_type == uml_element.Types.FLOW_FINAL_NODE:
                if len(incomings) == 0:
                    log.show_error("the final Node has no incoming." + \
                                   "name:" + str(node.name) + " id:" + node.xmi_id)
            elif isinstance(node, uml_element.ObjectNode):
                if not isinstance(node,
                                  uml_element.InstanceSpecification_node):
                    if len(incomings) == 0:
                        # @see example Order
                        # show warn info, not error info
                        log.show_warn(
                            "the object Node has no incoming.name:%s,id:%s" %
                            (str(node.name), node.xmi_id))
                    if len(outgoings) == 0:
                        # @see example Order
                        # show warn info, not error info
                        log.show_warn(
                            "the object Node has no outgoins.name:%s,id:%s" %
                            (str(node.name), node.xmi_id))
            # if the node has no incoming or no outgoing
            # it is a error(except initial,final,object node)
            else:
                # incoming and outgoing of a node
                if in_num == 0:
                    # action has no incoming, but it has argument, and the argument has incoming
                    if isinstance(node, uml_element.ExecutableNode):
                        arguments = node.arguments
                        for argument in arguments:
                            # if the argument has no incoming
                            if len(argument.incomings) == 0:
                                log.show_error("the action node's argument in " + \
                                                "uml activity diagram has no incoming." + \
                                                "name:" + str(node.name) + \
                                                " id:" + node.xmi_id)
                    # it is not a action
                    else:
                        log.show_error("the node in uml activity diagram has no incoming."\
                                       + "name:" + str(node.name) + " id:" + node.xmi_id)
                if out_num == 0:
                    # action has no outgoing, but it has result, and the result has outgoing
                    if isinstance(node, uml_element.ExecutableNode):
                        results = node.results
                        for result in results:
                            # if the result has no outgoing
                            if len(result.outgoings) == 0:
                                log.show_error("the action node's result in " + \
                                                "uml activity diagram has no incoming." + \
                                                + "name:" + str(node.name) + " id:" + node.xmi_id)
                    # it is not a action
                    else:
                        log.show_error("the node in uml activity diagram has no outgoing."\
                                       + "name:" + str(node.name) \
                                        + " id:" + node.xmi_id)
        # initial node just one
        if initial_num == 0:
            log.show_error("the uml activity diagram has no Initial Node")
        elif initial_num > 1:
            log.show_error("the uml activity diagram has " + str(initial_num) +
                           " Initial Nodes")
        # final node one or more than one
        if final_num == 0:
            log.show_warn("the uml activity diagram has no final Node")

        return initial_num, final_num
    def find_enabled_transitions(self, places, petri_net, rg_graph, unreach_list, reach):
        ''' first,get the next following transition from the current marked places,
        second, see if it can be enabled(see function-is_transition_enabled),
        and save the transitions in one list, for example [s1,s2]
        @param places: the current marked places,pre-places
        @type places: list
        @param reach: True, for the reachability_graph diagram.
        False, unreach_list=[],for the unreachability_graph.
        @type reach: Boolean
        @see: algorithm- step1
        '''
        # [t1,t2,t3...]
        transitions = []
        # [[t1],[t2,t3]...]
        # t1 fire from place1, t2,t3 fire from place2(decision)
        transitions_slices = []
        # the probs to fire the transition
        # [prob1,prob2,prob3...], the sum must be 1
        probs = []
        # [[prob1],[prob2,prob3]...]
        # prob1 is 1, sum of prob2 and prob3 is 1
        probs_slices = []
        # petri_net
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict

        # get the next transition from the place, and see if it can be enabled
        for place in places:
            # [t1] or [t2,t3]
            transitions_slice = []
            # [1] or [0.3,0.7]
            probs_slice = []
            outgoings = place.outgoings
            for outgoing in outgoings:
                arc = arcs_dict[outgoing]
                target = arc.target
                transition = transitions_dict[target]
                # if the transition can be enabled
                if self.is_transition_enabled(transition, places, places_dict, arcs_dict):
                    # get the prob from the arc
                    prob = arc.prob
                    # put the transition in the transitions_slice
                    if transition not in transitions_slice:
                        transitions_slice.append(transition)
                        # put the prob in the probs_slice
                        probs_slice.append(prob)
                    else:
                        # show error
                        log.show_error("more than 1 arcs between the place and the transition:find_enabled_transitions()")
                    # put it in the transitions
                    if transition not in transitions:
                        transitions.append(transition)
                        probs.append(prob)
                    # change the id of transition,which can be enabled
                    if not transition.id_changed:
                        self.change_pt_id(transition, transitions_dict, arcs_dict, petri_net)
            # if it is not []
            if transitions_slice:
                transitions_slices.append(transitions_slice)
                probs_slices.append(probs_slice)
        if reach:
            # parallel find the min(delay), 
            # if just decision len(transitions) > 1 and len(transitions_slices)=1
            # if len(transitions_slices) > 1, but len(transitions) = 1-->join:
            # len(transitions_slices) >1 ,-->parallel
            if len(transitions) > 1 and len(transitions_slices) > 1:
                # delete the same type
                types_set = set([transition.transition_type for transition in transitions])
                types_list = list(types_set)
                # TODO
                if len(types_list) == 1:
                    # get the type of the transitions
                    transition_type = types_list[0]

                    # all are immediate transition
                    if transition_type == petri_net_element.TransitionTypes.IMMEDIATE_TRANSITION:
                        pass
                    # all are DeterministicTransition
                    elif transition_type == petri_net_element.TransitionTypes.DETERMINISTIC_TRANSITION:
                        execute_transition = self.get_execute_transition(transitions)

                        transitions.remove(execute_transition)
                        #
                        tokens_list = [place.tokens for place in places]
                        unreach_list.append(places)
                        unreach_list.append(tokens_list)
                        unreach_list.append(transitions)
                        #
                        transitions = [execute_transition]
                    # all are EXPONENTIAL_TRANSITION
                    elif transition_type == petri_net_element.TransitionTypes.EXPONENTIAL_TRANSITION:
                        if len(transitions_slices) == 2:
                            self._calculate_probability(transitions_slices, probs_slices, transitions, probs)
                        else:
                            log.show_error("the code can not analyse 3 parallel exp distribution process")
                    else:
                        log.show_error("the type of the transition is not defined")

                # all are ExponentialTransition
                else:
                    log.show_warn("the types of the enabled transitions are not the same")

        # see algorithm- step1a)
        if len(transitions) > 0:
            # fire t and determine the marking m' after firing.
            self.get_next_state(places, transitions, petri_net, rg_graph, unreach_list, reach, probs)
 def create_pt_object(self, node1, node2, prob, petri_net):
     '''create p or t object
     '''
     places_dict = petri_net.places_dict
     transitions_dict = petri_net.transitions_dict
     arcs_dict = petri_net.arcs_dict
     # the id is nodeId of the umlActivityElement , also the pt_id of the petri_net_element
     id1 = node1.xmi_id
     id2 = node2.xmi_id
     # the 2 nodes are place
     if node1.place and node2.place:
         # create a transition and put it in the transitionsDict
         # place1 -(arc1)-> transition -(arc2)-> place2
         pt_id = id1 + id2
         if pt_id not in transitions_dict:
             # create one immediate transition
             transition = pt_element.ImmediateTransition(pt_id,
                                                         name=None,
                                                         incomings=[],
                                                         outgoings=[])
             transitions_dict[pt_id] = transition
             # place1
             place1 = places_dict[id1]
             # place2
             place2 = places_dict[id2]
             # create one arc, place1 -(arc1)-> transition,
             # and put it in the arcs_dict
             self.create_arc(arcs_dict, place1, transition, prob)
             # create the other arc, transition -(arc2)-> place2,
             # and put it in the arcs_dict
             self.create_arc(arcs_dict, transition, place2)
         else:
             log.show_warn("id1-->id2 has more than one connection")
     # the 2 nodes are transition
     elif node1.transition and node2.transition:
         # create a place and put it in the placesDict
         # transition1 -(arc1)-> place -(arc2)-> transition2
         pt_id = id1 + id2
         if pt_id not in places_dict:
             # create one place
             place = pt_element.Place(pt_id, name=None,
                                      incomings=[], outgoings=[])
             places_dict[pt_id] = place
             # transition1
             transition1 = transitions_dict[id1]
             # transition2
             transition2 = transitions_dict[id2]
             # create one arc, transition1 -(arc1)-> place,
             # and put it in the arcs_dict
             self.create_arc(arcs_dict, transition1, place)
             # create the other arc, place -(arc2)-> transition2,
             # and put it in the arcs_dict
             self.create_arc(arcs_dict, place, transition2)
         else:
             log.show_warn("id1-->id2 has more than one connection")
     # p --> t    #TODO more than one connection
     elif node1.place and node2.transition:
         # just create one arc, p -(arc)-> t
         place = places_dict[id1]
         transition = transitions_dict[id2]
         self.create_arc(arcs_dict, place, transition, prob)
     # t --> p
     elif node1.transition and node2.place:
         # just create one arc, t -(arc)-> p
         transition = transitions_dict[id1]
         place = places_dict[id2]
         self.create_arc(arcs_dict, transition, place)
     else:
         # Error
         print "type error +create_pt_object():", node1.xmi_type, node2.xmi_type
    def check_names(self, activity):
        '''check the name of action and object.
        1.if it is None or "",it will cause a error when it transforms to epf.
        set the name "node1","node2"
        2.if two nodes(action or object) have the same name, it will also cause a error
        when it transforms to epf. for example "get info" and "get_info"
        3.change the name to the corrected name
        # TODO check the name of pin
        @return: check_ok, if checks ok
        @rtype: boolean
        '''
        check_ok = True
        names = []
        nodes_dict = activity.nodes_dict
        pins_dict = activity.pins_dict

        # action, object, initial, final
        node_types = (uml_element.ExecutableNode, uml_element.ObjectNode,
                      uml_element.InitialNode, uml_element.FinalNode,
                      uml_element.Fork, uml_element.Join)
        # for node
        num1 = 0
        # for pin,pout
        num2 = 0
        # it checks the name of pout, do not need to check the name of pin
        for pin_id in pins_dict:
            pin = pins_dict[pin_id]
            # if it is a pout(Result)
            if isinstance(pin, uml_element.Result):
                name = pin.name
                # if it has no name, see condition1
                if name is None or name.strip() == "":
                    # if the pin has no name, set the name "pin1","pin2"...
                    num2 += 1
                    pin.name = "pin" + str(num2)
                    log.show_warn("the pin has no name.id:%s" % pin.xmi_id)
                else:
                    corrected_name = self.__get_corrected_name(name)
                    # change the name of node to corrected name
                    pin.name = corrected_name
                    # see condition2
                    if corrected_name in names:
                        check_ok = False
                        log.show_error("the pin has the same name.name:%s" %
                                       name)
                    else:
                        names.append(corrected_name)

        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            # if it is a action or object,initial,final
            # The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
            # isinstance(x, A) or isinstance(x, B) or ... (etc.).
            if isinstance(node, node_types):
                name = node.name
                # if it has no name, see condition1
                if name is None or name.strip() == "":
                    # if the node has no name, set the name "node1","node2"...
                    num1 += 1
                    node.name = "node" + str(num1)
                    log.show_warn("the node has no name.id:%s" % node.xmi_id)
                else:
                    corrected_name = self.__get_corrected_name(name)
                    # change the name of node to corrected name
                    node.name = corrected_name
                    # see condition2
                    if corrected_name in names:
                        check_ok = False
                        log.show_error("the nodes has the same name.name:%s" %
                                       name)
                    else:
                        names.append(corrected_name)
        return check_ok