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")
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)))
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)
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)
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
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
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 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)
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_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
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
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
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 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 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