//TODO: containedEdge avec des ObjectFlow //Gerer diff entre ObjectFlow et ControlFlow public void addActivityEdge(XElement node, Activity activity) { string sourceid = node.Attribute("source").Value; string targetid = node.Attribute("target").Value; //MascaretApplication.Instance.logfile.WriteLine("sourceid : " + sourceid); MascaretApplication.Instance.logfile.Flush(); //MascaretApplication.Instance.logfile.WriteLine("targetid : " + targetid); MascaretApplication.Instance.logfile.Flush(); string type = ""; if (node.Attribute("{http://schema.omg.org/spec/XMI/2.1}type") != null) type = node.Attribute("{http://schema.omg.org/spec/XMI/2.1}type").Value;// "uml:ObjectFlow" "uml:ControlFlow" else type = node.Attribute("{http://www.omg.org/spec/XMI/20131001}type").Value; string id = ""; if (node.Attribute("{http://schema.omg.org/spec/XMI/2.1}id") != null) id = node.Attribute("{http://schema.omg.org/spec/XMI/2.1}id").Value; else id = node.Attribute("{http://www.omg.org/spec/XMI/20131001}id").Value; string name = ""; if (node.Attribute("name") != null) name = node.Attribute("name").Value; //Debug.Log(" ????????????????????????????????? " + type + " "+id); ActivityNode source = null; ActivityNode target = null; if (!_activityNodes.ContainsKey(sourceid)) { if (!_objectNodes.ContainsKey(sourceid)) { //MascaretApplication.Instance.logfile.WriteLine("erreur source"); MascaretApplication.Instance.logfile.Flush(); //Debug.Log("edge source not found : " + sourceid); return; } else source = _objectNodes[sourceid]; } else source = _activityNodes[sourceid]; if (!_activityNodes.ContainsKey(targetid)) { if (!_objectNodes.ContainsKey(targetid)) { //MascaretApplication.Instance.logfile.WriteLine("erreur cible"); MascaretApplication.Instance.logfile.Flush(); //Debug.Log("edge Target not found: " + targetid); return; } else target = _objectNodes[targetid]; } else target = _activityNodes[targetid]; ActivityEdge edge = null; if (type == "uml:ControlFlow") edge = new ControlFlow(name); else if (type == "uml:ObjectFlow") edge = new ObjectFlow(name); else edge = new ActivityEdge(name); source.Outgoing.Add(edge); target.Incoming.Add(edge); edge.Source = source; edge.Target = target; //Debug.Log("Source : " + source.name + " / Target : " + target.name); activity.addEdge(edge); edge.Description = getComment(node); edge.Summary = getSummary(node); edge.Tags = getTags(node); }
public void addEdge(ActivityEdge val) { val.Activity = this; edges.Add(val); }
protected bool tryToAdvanceToken(ActivityExecutionToken token, ActionNode doneAction, bool gotTicketToUseAction) { //TODO : current implementation will fail if the loop node has branches which are not joined together at the end //TODO : setup part of loop nodes not implemented //TODO : careful if the loop node contains only an initial node :: ENDLESS LOOP // Debug.Log(" current token : " + token.currentLocation.name); if (token.currentLocation.Kind == "action") { ActionNode aNode = (ActionNode)(token.currentLocation); if (actionIsCurrentlyRunning(aNode)) { System.Console.WriteLine(" ACTION is RUNNING : " + aNode.Action.name); //token busy... return(false); } } if (token.outgoingEdge == null) { //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "dbg Part1: edge null" << endl; //Debug.Log(" NO OUTGOING EDGES...."); //my work here is done *flies away* return(false); } //evaluate guard(s). Normal behavior for fork, but I treat decision nodes here, if there are more paths going out, I will take the first one. if (token.currentLocation.Kind == "fork") { //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "dbg Part1: fork" << endl; //normal behavior for fork (should not have guard, but hell... it doesn't hurt to check) if (token.outgoingEdge.Guard != null && (!(token.outgoingEdge.Guard.eval(procedure.Activity.Context)))) { return(false); //eval failed } } else { //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "dbg Part1: no fork" << endl; List <ActivityEdge> outgoingNormal = token.currentLocation.getOutgoingControlFlowEdges(); bool foundWayOut = false; for (int i = 0; i < outgoingNormal.Count; ++i) { //if <no guard> or <guard but evaluates ok> if ((outgoingNormal[i].Guard == null) || (outgoingNormal[i].Guard != null && (outgoingNormal[i].Guard.eval(procedure.Activity.Context)))) { foundWayOut = true; token.outgoingEdge = outgoingNormal[i]; //set new direction, we take the first possible one, remember ? } } if (!foundWayOut) { //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "dbg Part1: didn't find way out" << endl; return(false); //no way out... leave for later } } ActivityNode nextLocation = token.outgoingEdge.Target; //test allowed action if (nextLocation.Kind == "action") { if ((nextLocation != doneAction) || (!gotTicketToUseAction)) { //not allowed to advance to this action //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "dbg Part1: action not allowed" << endl; return(false); } gotTicketToUseAction = false; } //Debug.Log("Next Location : " + nextLocation); //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "adv tok from '" << token->currentLocation->getName() << "' to '" << nextLocation->getName() << "'" << endl; //Advance ActivityEdge dummyActivityEdge = null; token.currentLocation = nextLocation; token.outgoingEdge = dummyActivityEdge; List <ActivityEdge> outgoingAfterAdvance = token.currentLocation.getOutgoingControlFlowEdges(); List <ActivityExecutionToken> nextTokens = new List <ActivityExecutionToken>(); if (token.currentLocation.Kind == "fork") { //time to split token into pieces, in order to follow all fork branches token.forkStack.Add(token.currentLocation); //push this fork to the stack //remove this token from the active list for (int i = 0; i < activeTokens.Count; ++i) { if (activeTokens[i].ToString() == token.ToString()) { activeTokens.RemoveAt(i); break; } } for (int i = 0; i < outgoingAfterAdvance.Count; ++i) { ActivityExecutionToken tok = new ActivityExecutionToken(); tok.currentLocation = token.currentLocation; tok.forkStack = token.forkStack; tok.loopNodeStack = token.loopNodeStack; tok.outgoingEdge = outgoingAfterAdvance[i]; //set outgoing, to know which branch to follow //push to active list activeTokens.Add(tok); //save for further use nextTokens.Add(tok); } } else if (token.currentLocation.Kind == "join") { //we can only pass by a join, if all other branched tokens have arrived in this join //the point is that the number of tokens which have the same last fork as this one, should be the same as the nr of incoming links to this join //i hope i understand this next time i read it List <ActivityEdge> incoming = token.currentLocation.Incoming; //so get the incoming //see which is the last fork of this token ActivityNode lastFork = null; if (token.forkStack.Count > 0) { lastFork = token.forkStack[token.forkStack.Count - 1]; } if (lastFork != null) { //find all tokens that have this fork and see if they all finished their branch // TODO: remember that actually, the forkStacks should be identical for paired tokens... if they're not, we've got a problem.... List <ActivityExecutionToken> finishedTokens = new List <ActivityExecutionToken>(); for (int i = 0; i < activeTokens.Count; ++i) { //if found a token with this last fork if ((activeTokens[i].forkStack.Count > 0) && (activeTokens[i].forkStack[activeTokens[i].forkStack.Count - 1] == lastFork)) { //check to see if it's finished (arrived at the same join) if (activeTokens[i].currentLocation == token.currentLocation) { //add to finished tokens list finishedTokens.Add(activeTokens[i]); } } } //now check to see if the number of found tokens equals the number of incoming links to this join if (finishedTokens.Count == incoming.Count) { //then all should be great.... we can merge all tokens into a single one for (int i = 0; i < finishedTokens.Count; ++i) { //skip the current token, this one will remain if (finishedTokens[i].ToString() == token.ToString()) { continue; } //seek and destroy for (int j = 0; j < activeTokens.Count; ++j) { if (finishedTokens[i].ToString() == activeTokens[j].ToString()) { //destroy activeTokens.RemoveAt(j); } } } if (outgoingAfterAdvance.Count == 1) { token.outgoingEdge = outgoingAfterAdvance[0]; token.forkStack.RemoveAt(token.forkStack.Count - 1);//pop last fork nextTokens.Add(token); } else if (outgoingAfterAdvance.Count > 1) { } } } else { } } else if (token.currentLocation.Kind == "loop") { LoopNode loopNode = (LoopNode)(token.currentLocation); bool skipThisLoopNode = false; if (loopNode.TestedFirst) { if (loopNode.eval()) //thou shall pass { skipThisLoopNode = true; } } ActivityNode initLoop = loopNode.Initial; List <ActivityEdge> outgoingFromInitLoop = null; if (initLoop != null) { outgoingFromInitLoop = initLoop.getOutgoingControlFlowEdges(); } if (skipThisLoopNode || (initLoop == null) || (outgoingFromInitLoop.Count < 1)) { //I don't care which path to take, so I will just take the first one. In the advance part (see above) if it's a decision node, it will take the first possible path, if any if (outgoingAfterAdvance.Count >= 1) { token.outgoingEdge = outgoingAfterAdvance[0]; nextTokens.Add(token); } } else { //enter the loop node, we'll get the edge which exits the loopnode's initial node token.currentLocation = initLoop; token.outgoingEdge = outgoingFromInitLoop[0]; token.loopNodeStack.Add(loopNode); } } else { //I don't care which path to take, so I will just take the first one. In the advance part (see above) if it's a decision node, it will take the first possible path, if any if (outgoingAfterAdvance.Count >= 1) { token.outgoingEdge = outgoingAfterAdvance[0]; nextTokens.Add(token); } else if (token.loopNodeStack.Count != 0) //check if we're in a loop node { //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "dbg Part1: edge null, but in loop node" << endl; while (((token.outgoingEdge == null)) && (token.loopNodeStack.Count != 0)) //while we are still in a loopnode and it is finished { LoopNode lastLoop = token.loopNodeStack[token.loopNodeStack.Count - 1]; if (lastLoop.eval()) //test exit condition { //exiting loop node List <ActivityEdge> outgoingFromLoop = lastLoop.getOutgoingControlFlowEdges(); if (outgoingFromLoop.Count != 0) { token.currentLocation = lastLoop; token.outgoingEdge = outgoingFromLoop[0]; } token.loopNodeStack.RemoveAt(token.loopNodeStack.Count - 1); //remove last loop from stack (exit) } else { //restarting loop node ActivityNode initLoop = lastLoop.Initial; List <ActivityEdge> outgoingFromInitLoop = initLoop.getOutgoingControlFlowEdges(); token.currentLocation = initLoop; token.outgoingEdge = outgoingFromInitLoop[0]; //it should exist, given the fact that we've entered this loop node already } } if (token.outgoingEdge != null) { nextTokens.Add(token); } } } //continue to advance for (int i = 0; i < nextTokens.Count; ++i) { tryToAdvanceToken(nextTokens[i], doneAction, gotTicketToUseAction); } return(true); }