public void addActivityNode(XNode node, LoopNode loopNode, Activity activity) { }
public void addActivityEdge(XNode node, LoopNode activity) { }
//TODO public void addActivityGroup(XElement node, Activity activity) { 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; else type = node.Attribute("{http://www.omg.org/spec/XMI/20131001}type").Value; if (type == "uml:ActivityPartition") { string name = node.Attribute("name").Value; ActivityPartition partition = new ActivityPartition(name); //Debug.Log(" ---> Partition : " + name); 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; _partitions.Add(id, partition); activity.addPartition(partition); } else if (type == "uml:LoopNode") { LoopNode loopNode = new LoopNode(node.Attribute("name").Value, "Loop"); loopNode.Description = getComment(node); activity.addNode(loopNode); string idPartition = node.Attribute("inPartition").Value; if (_partitions.ContainsKey(idPartition)) { loopNode.Partitions.Add(_partitions[idPartition]); _partitions[idPartition].Node.Add(loopNode); } /* string isTestedFirst = node.Attribute("isTestedFirst").Value; if (isTestedFirst == "true") { loopNode.setTestedFirst(true); } else { loopNode->setTestedFirst(false); }*/ _activityNodes.Add(node.Attribute("{http://schema.omg.org/spec/XMI/2.1}id").Value, loopNode); //string testId = node.Attribute("test").Value; /* map<string, shared_ptr<Expression> >::iterator it = _activityExpressions.find(testId); if (it != _activityExpressions.end()) { loopNode->setCondition(it->second); } else cerr << "Test for LoopNode : " << loopNode->getName() << " not found" << endl; */ foreach (XElement child in node.Elements()) { if (child.Name.LocalName == "node") { string inPart = node.Attribute("inPartition").Value; //child.->setProperty(string("inPartition"), inPart); //cerr << "././././././././././. transferring property: " << inPart << endl; addActivityNode(child, loopNode, activity); } } foreach (XElement child in node.Elements()) { if (child.Name.LocalName == "edge") addActivityEdge(child, loopNode); } } }
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); }