public ActionNode getActionByNameFor(AID agent, string action)
        {
            //assuming only one action exists by that name !

            List <ActionNode> allActionNodes = getAllActions();

            ActionNode found = null;

            for (int i = 0; i < allActionNodes.Count; ++i)
            {
                //agentToPartition.getMap(agent.toString()).name;

                if ((allActionNodes[i].Partitions[0].name == agentToPartition[agent.toString()].name) && (action == clean(allActionNodes[i].name)))
                {
                    found = allActionNodes[i];
                    break;
                }
            }

            return(found);
        }
        public List <ActionNode> getAllActions()
        {
            List <ActivityNode> allNodes    = procedure.Activity.Nodes;
            List <ActionNode>   actionNodes = new List <ActionNode>();

            for (int i = 0; i < allNodes.Count; ++i)
            {
                if (allNodes[i].Kind == "LoopNode")
                {
                    continue;
                }

                if (allNodes[i].Kind == "action")
                {
                    ActionNode aNode = (ActionNode)(allNodes[i]);
                    actionNodes.Add(aNode);
                    continue;
                }
            }

            return(actionNodes);
        }
Beispiel #3
0
        //FinalNode, Merge et Decision devraent �tre des activityNode !!
        public void addActivityNode(XElement node, Activity activity)
        {
            MascaretApplication.Instance.VRComponentFactory.Log("New activity node");
            string type = "";
            string id = "";
            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;

            MascaretApplication.Instance.VRComponentFactory.Log(" Type : " + type);

            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;
            MascaretApplication.Instance.VRComponentFactory.Log(" ID : " + id);

            string name = "";
            if (node.Attribute("name") != null)
                name = node.Attribute("name").Value;
            else name = id;
            MascaretApplication.Instance.VRComponentFactory.Log(" Name : " + name);

            string idPartition = "";
            if (node.Attribute("inPartition") != null)
                idPartition = node.Attribute("inPartition").Value;

            MascaretApplication.Instance.VRComponentFactory.Log(id);
            MascaretApplication.Instance.VRComponentFactory.Log(type);
            MascaretApplication.Instance.VRComponentFactory.Log(name);
            MascaretApplication.Instance.VRComponentFactory.Log(idPartition);

            ActivityNode actNode = null;

            //Debug.Log(" TYPE NODE : " + type);

            if (type == "uml:InitialNode")
            {
                actNode = new InitialNode();
                activity.Initial = actNode;
                actNode.name = "Initial";
            }
            else if (type == "uml:FinalNode" || type == "uml:ActivityFinalNode")
            {
                actNode = new FinalNode();
            }
            else if (type == "uml:LoopNode")
            {
                addActivityGroup(node, activity);
            }
            else if (type == "uml:ForkNode")
            {
                actNode = new ForkNode();
            }
            else if (type == "uml:JoinNode")
            {
                actNode = new JoinNode();
            }
            else if (type == "uml:MergeNode")
            {
                actNode = new MergeNode();
            }
            /*else if (type == "uml:DecisionNode")
            {
                actNode = new DecisionNode();
            }*/
            else if (type == "uml:ObjectNode" || type == "uml:CentralBufferNode")
            {

                ObjectNode objNode = new ObjectNode(name);
                Classifier ressourceType = getObjectNodeType(node);
                if (ressourceType != null)
                    objNode.ResourceType = ressourceType;
                actNode = objNode;
                string type2 = node.Attribute("{http://schema.omg.org/spec/XMI/2.1}type").Value;
                if (_idClass.ContainsKey(type2))
                    ((ObjectNode)actNode).ResourceType = _idClass[type2];
            }
            else if (type == "uml:ValueSpecificationAction")
            {
                /*
                shared_ptr<XmlNode> valueNode = node->getChildByName("value");
                string expressionValue = valueNode->getProperty("value");
                shared_ptr<Expression> expression = make_shared<Expression>(expressionValue, _model->getBasicType("boolean"));
                _activityExpressions[node->getProperty("id")] = expression;
                */
            }
            else if (type == "uml:OpaqueAction")
            {
                if (isStereotypedPlayAnimation(node))
                {
                    string animationName = getAnimName(node);
                    MascaretApplication.Instance.VRComponentFactory.Log("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% NEW PLAY ANIMATION : " + name + "    " + animationName);

                    ActionNode an = new ActionNode(name, "action");
                    PlayAnimationAction ap = new PlayAnimationAction();
                    ap.Description = getComment(node);
                    ap.name = name;
                    ap.Owner = activity;
                    ap.animationName = animationName;

                    an.Action = ap;
                    addPins(an, node);
                    actNode = an;
                }
            }
            else if (type == "uml:CallBehaviorAction")
            {

                ActionNode an = new ActionNode(name, "action");
                CallBehaviorAction cb = new CallBehaviorAction();
                cb.Description = getComment(node);
                cb.name = name;
                cb.Owner = activity;
                XElement beNode = node.Element("behavior");

                string opid;

                if (beNode != null) opid = beNode.Attribute("idref").Value;
                else opid = node.Attribute("behavior").Value;

                if (_idBehaviors.ContainsKey(opid))
                {
                    cb.Behavior = _idBehaviors[opid];
                }
                else
                {
                    // Debug.Log("[ModelLoader2 Info] Behavior " + opid
                    //           + " not yet found for ActionNode " + name + ". Postbone...");
                    _callBehaviors.Add(cb, opid);
                }

                an.Action = cb;
                addPins(an, node);
                actNode = an;

            }
            else if (type == "uml:CallOperationAction")
            {

                ActionNode an = new ActionNode(name, "action");
                //Debug.Log("Action Node : " +name);
                CallOperationAction act = new CallOperationAction();
                act.Description = getComment(node);
                an.Fml = getFML(node);

                act.name = name;

                act.Owner = activity;

                XElement opNode = node.Element("operation");
                if (opNode != null)
                {
                    string opid;
                    opid = opNode.Attribute("idref").Value;
                    //MascaretApplication.Instance.logfile.WriteLine("Operation ID : " + opid); MascaretApplication.Instance.logfile.Flush();
                    string stereo = getStereotype(opid);
                    MascaretApplication.Instance.VRComponentFactory.Log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + name + " : " + opid + " " + stereo);
                    if (stereo != "")
                    {

                        an.Stereotype = stereo;
                    }

                    if (_idOperations.ContainsKey(opid))
                        act.Operation = _idOperations[opid];
                    else
                    {
                        //cerr << "ERREUR PAS OPERATION... " << opid<< endl;
                        _callOperations.Add(act, opid);
                    }
                }
                else
                {
                    string opid;
                    opid = node.Attribute("operation").Value;
                    // MascaretApplication.Instance.logfile.WriteLine("Operation ID : " + opid); MascaretApplication.Instance.logfile.Flush();
                    string stereo = getStereotype(opid);
                    MascaretApplication.Instance.VRComponentFactory.Log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + name + " : " + opid + " " + stereo);
                    if (stereo != "")
                    {

                        an.Stereotype = stereo;
                    }

                    // MascaretApplication.Instance.logfile.WriteLine("Operation ID : " + opid); MascaretApplication.Instance.logfile.Flush();

                    if (_idOperations.ContainsKey(opid))
                    {
                        act.Operation = _idOperations[opid];
                        // MascaretApplication.Instance.logfile.WriteLine("Operation Name : " + act.Operation); MascaretApplication.Instance.logfile.Flush();

                    }
                    else
                        _callOperations.Add(act, opid);
                }
                an.Action = act;
                addPins(an, node);
                actNode = an;
            }
            else if (type == "uml:SendSignalAction")
            {
                MascaretApplication.Instance.VRComponentFactory.Log("SendSignalAction");
                ActionNode an = new ActionNode(name, "action");
                SendSignalAction act = new SendSignalAction();
                XElement sigNode = node.Element("signal");
                if (sigNode != null)
                {
                    string signame = sigNode.Attribute("name").Value;
                    if (!_signals.ContainsKey(signame))
                    {
                        Signal ns = new Signal(signame);
                        _signals.Add(signame, ns);
                    }
                    act.SignalClass = _signals[signame];
                }
                else
                {
                    string signame = "";
                    if (node.Attribute("signal") != null)
                        signame = node.Attribute("signal").Value;
                    if (!_signals.ContainsKey(signame))
                    {
                        Signal ns = new Signal(signame);
                        _signals.Add(signame, ns);
                    }

                    act.SignalClass = _signals[signame];
                }

                XElement targetNode = node.Element("argument");
                if (targetNode != null)
                {
                    string targetName = targetNode.Attribute("name").Value;
                    XElement typeNode = targetNode.Element("type");
                    string classid = "";
                    if (typeNode != null)
                        classid = typeNode.Attribute("idref").Value;
                    else
                        classid = targetNode.Attribute("type").Value;
                    act.Target = new SendSignalTarget();
                    act.Target.targetName = targetName;
                    act.Target.targetClass = _idClass[classid];
                }
                else
                {
                    targetNode = node.Element("target");
                    if (targetNode != null)
                    {
                        MascaretApplication.Instance.VRComponentFactory.Log("SendSignal Target");
                        string targetName = targetNode.Attribute("name").Value;
                        string classid = targetNode.Attribute("type").Value;
                        MascaretApplication.Instance.VRComponentFactory.Log("name : " + targetName);
                        MascaretApplication.Instance.VRComponentFactory.Log("name : " + targetName + " : " + _idClass[classid]);

                        act.Target = new SendSignalTarget();
                        act.Target.targetName = targetName;
                        act.Target.targetClass = _idClass[classid];

                    }
                    else MascaretApplication.Instance.VRComponentFactory.Log("No target");
                }
                an.Action = act;
                addPins(an, node);
                actNode = an;
            }
            else if (type == "uml:AddStructuralFeatureValueAction")
            {
                //cerr << " ############# Found a AddStructuralFeatureValueAction : " << endl;
                /*
                shared_ptr<ActionNode> an = make_shared<ActionNode>(name);
                shared_ptr<Classifier> type;
                shared_ptr<XmlNode> pinNode = node->getChildByName("object");

                string attrName = pinNode->getProperty("name");

                cerr << " Name == " << attrName << endl;

                shared_ptr<XmlNode> typeNode = pinNode->getChildByName("type");
                if (typeNode && typeNode->getProperty("type") == "uml:PrimitiveType")
                {
                    string href = typeNode->getProperty("href");
                    string strType = href.substr(href.rfind('#') + 1);
                    boost::to_lower(strType);
                    type = _model->getBasicType(strType);
                }

                shared_ptr<XmlNode> valueNode = pinNode->getChildByName("value");
                if (valueNode)
                {
                    string value = valueNode->getProperty("value");
                    cerr << "    VALUE : " << value << endl;
                    shared_ptr<Expression> expression = make_shared<Expression>(value, type);
                    shared_ptr<AddStructuralFeatureValueAction> act =
                        make_shared<AddStructuralFeatureValueAction>();
                    act->setValue(expression);
                    act->setProperty(attrName);
                    an->setAction(act);
                }
                actNode = an;
                */

            }
            else if (type == "uml:AcceptEventAction")
            {
                MascaretApplication.Instance.VRComponentFactory.Log("New uml:AcceptEventAction");
                ActionNode an = new ActionNode(name, "action");
                AcceptEventAction act = new AcceptEventAction();

                XElement triggerNode = node.Element("trigger");
                if (triggerNode != null)
                {
                    MascaretApplication.Instance.VRComponentFactory.Log("trigger node found");

                    Trigger trigger = new Trigger(name);
                    MascaretApplication.Instance.VRComponentFactory.Log("Debug : " + name);
                    string idT = "";
                    if (triggerNode.Attribute("{http://schema.omg.org/spec/XMI/2.1}id") != null)
                        idT = triggerNode.Attribute("{http://schema.omg.org/spec/XMI/2.1}id").Value;
                    else
                        idT = triggerNode.Attribute("{http://www.omg.org/spec/XMI/20131001}id").Value;

                    trigger.Id = idT;
                    MascaretApplication.Instance.VRComponentFactory.Log(trigger.Id);

                    if (triggerNode.Attribute("event") != null)
                    {
                        string idEvent = triggerNode.Attribute("event").Value;

                        if (_events.ContainsKey(idEvent))
                        {
                            trigger.MEvent = _events[idEvent];
                            act.setTrigger(trigger);
                        }
                        else
                            MascaretApplication.Instance.VRComponentFactory.Log("Could not find event : " + idEvent);
                    }
                }
                an.Action = act;
                addPins(an, node);
                actNode = an;

                MascaretApplication.Instance.VRComponentFactory.Log(" Fin AcceptEventAction");

            }
            // ...
            else
            {
                //Debug.Log("Unknown state: " + type);
            }

            if (actNode != null)
            {
                _activityNodes.Add(id, actNode);
                activity.addNode(actNode);
                //cerr << "searching _partitions for '" << idPartition << "'" << endl;
                if (_partitions.ContainsKey(idPartition))
                {
                    actNode.Partitions.Add(_partitions[idPartition]);
                    _partitions[idPartition].Node.Add(actNode);
                }
                actNode.Summary = getSummary(node);
                actNode.Description = getComment(node);
                actNode.Tags = getTags(node);
            }
        }
Beispiel #4
0
        public void addPins(ActionNode an, XElement node)
        {
            foreach (XElement pins in node.Elements())
            {
                if (pins.Name.LocalName == "argument")
                {
                    MascaretApplication.Instance.VRComponentFactory.Log("ARGUMENT PIN ################################");

                    XAttribute att = pins.Attribute("{http://www.omg.org/spec/XMI/20131001}type");
                    if (att == null)
                        att = pins.Attribute("{http://schema.omg.org/spec/XMI/2.1}type");

                    if (att != null)
                        MascaretApplication.Instance.VRComponentFactory.Log(att.Value);
                    if (att != null && att.Value == "uml:ValuePin")
                    {
                        ValuePin valuePin = new ValuePin();
                        XAttribute attID = pins.Attribute("{http://schema.omg.org/spec/XMI/2.1}id");
                        if (attID == null)
                            attID = pins.Attribute("{http://www.omg.org/spec/XMI/20131001}id");

                        string id = attID.Value;
                        string name = pins.Attribute("name").Value;
                        MascaretApplication.Instance.VRComponentFactory.Log("Pin Name : " + name);
                        valuePin.Id = id;
                        valuePin.name = name;

                        string strType = "";
                        XElement typeNode = pins.Element("type");
                        if (typeNode == null)
                        {
                            // Check if it's an attribute
                            string typeId = pins.Attribute("type").Value;
                            if (_primitiveTypes.ContainsKey(typeId))
                                strType = _primitiveTypes[typeId];
                        }
                        else
                        {
                            XAttribute attr = (XAttribute)typeNode.Attribute("href");
                            if (attr != null)
                                strType = attr.Value.Substring(attr.Value.IndexOf("#") + 1);
                        }
                        MascaretPrimitiveType attributeType = model.getBasicType(strType.ToLower());

                        valuePin.ResourceType = attributeType;

                        string strValue = "";
                        XElement valueNode = pins.Element("value");
                        XAttribute attrV = (XAttribute)valueNode.Attribute("value");
                        if (attrV != null) strValue = attrV.Value;

                        MascaretApplication.Instance.VRComponentFactory.Log("Valeur : " + strValue);
                        valuePin.ValueSpec = attributeType.createValueFromString(strValue);

                        /*Classifier ressourceType = getObjectNodeType(pins);
                        if(ressourceType != null)
                            valuePin.ResourceType = ressourceType;*/

                        an.Action.ValuePins.Add(valuePin);
                        _objectNodes.Add(valuePin.Id, valuePin);
                    }
                    else
                    {
                        InputPin inputPin = new InputPin();
                        inputPin.Id = pins.Attribute("{http://schema.omg.org/spec/XMI/2.1}id").Value;
                        if (inputPin.Id == null) inputPin.Id = pins.Attribute("{http://www.omg.org/spec/XMI/20131001}id").Value;

                        inputPin.name = pins.Attribute("name").Value;
                        Classifier ressourceType = getObjectNodeType(pins);
                        if (ressourceType != null)
                            inputPin.ResourceType = ressourceType;

                        //Debug.Log(" AN : " + an);

                        an.Action.InputPins.Add(inputPin);
                        _objectNodes.Add(inputPin.Id, inputPin);
                    }
                }
                else if (pins.Name.LocalName == "result")
                {
                    OutputPin outputPin = new OutputPin();
                    outputPin.Id = pins.Attribute("id").Value;
                    outputPin.name = pins.Attribute("name").Value;
                    Classifier ressourceType = getObjectNodeType(pins);
                    if (ressourceType != null)
                        outputPin.ResourceType = ressourceType;
                    an.Action.OutputPins.Add(outputPin);
                    _objectNodes.Add(outputPin.Id, outputPin);
                }
            }
        }
 bool IsBehaviourFinished(ActionNode node)
 {
     bool result = true;
     Dictionary<string, Agent> agents = MascaretApplication.Instance.AgentPlateform.Agents;
     foreach (KeyValuePair<string, Agent> agt in agents)
     {
         AgentBehaviorExecution pbehavior = agt.Value.getBehaviorExecutingByName("ProceduralBehavior");
         // MascaretApplication.Instance.VRComponentFactory.Log ("++++++++++++++++++++++++checking ++++++++++" +node.name);
         if (pbehavior != null)
         {
             ProceduralBehavior procBehave = (ProceduralBehavior)(pbehavior);
             foreach (ProcedureExecution pe in procBehave.runningProcedures)
             {
                 //MascaretApplication.Instance.VRComponentFactory.Log ("+++++++++++++++++++++++++Running++++++++++" +pe.procedure.name + "  : " +  pe.isFinished());
                 if (pe.procedure.name == node.Action.name)
                     result = pe.isFinished();
                 if (!result)
                     break;
             }
         }
         if (!result)
             break;
     }
     return result;
 }
        void CallProceduralBehaviourExecution(ActionNode action)
        {
            MascaretApplication.Instance.VRComponentFactory.Log(Host.name + "+++++++++++++++++++++++++++########################################### CallProceduralBehaviourExecution  " + action.name);

            MascaretApplication appli = MascaretApplication.Instance;
            //bool found = false;
            OrganisationalEntity askedOrg = null;
            Procedure askedProc = null;
            Role askedRole = null;

            List<OrganisationalEntity> orgs = appli.AgentPlateform.Organisations;

            appli.VRComponentFactory.Log("ProceduralBehaviourExecution");

            for (int iOrg = 0; iOrg < orgs.Count; iOrg++)
            {
                appli.VRComponentFactory.Log("------ Org " + orgs[iOrg].name + " ?");
                if (orgs[iOrg].name == parameters["orgEntity"].getStringFromValue())
                {
                    appli.VRComponentFactory.Log("----------Org : " + orgs[iOrg].name + " found");
                    OrganisationalStructure os = orgs[iOrg].Structure;
                    List<Procedure> procs = os.Procedures;
                    askedOrg = orgs[iOrg];

                    for (int iP = 0; iP < procs.Count; iP++)
                    {
                        if (procs[iP].name == action.Action.name)
                        {
                            appli.VRComponentFactory.Log("Procedure " + procs[iP].name + " found");
                            askedProc = procs[iP];
                            List<RoleAssignement> assigns = orgs[iOrg].RoleAssignement;

                            appli.VRComponentFactory.Log("Assigns : " + assigns.Count);
                            for (int iAss = 0; iAss < assigns.Count; iAss++)
                            {
                                agt = appli.AgentPlateform.Agents[assigns[iAss].Agent.toString()];
                                askedRole = assigns[iAss].Role;
                                if (agt.name == Host.name)
                                {
                                    appli.VRComponentFactory.Log("Role : " + assigns[iAss].Role.name + " == " + agt.name);

                                    AgentBehaviorExecution pbehavior = agt.getBehaviorExecutingByName("ProceduralBehavior");

                                    if (pbehavior != null)
                                    {
                                        appli.VRComponentFactory.Log("Procedure " + askedProc.name + " launched for " + agt.name);
                                        ProceduralBehavior procBehave = (ProceduralBehavior)(pbehavior);

                                        Dictionary<string, ValueSpecification> procParams = new Dictionary<string, ValueSpecification>();

                                        procBehave.pushProcedureToDo(askedProc, askedOrg, askedRole, procParams);

                                    }
                                }
                            }
                        }

                    }
                }
            }
        }
        void CallGlobalActivityBehaviourExecution(ActionNode action)
        {
            MascaretApplication.Instance.VRComponentFactory.Log(Host.name + "+++++++++++++++++++++++++++########################################### CallGlobalActivityBehaviourExecution  " + action.name);

            string orgEntity = null;

            List<OrganisationalStructure> structs = VRApplication.Instance.AgentPlateform.Structures;
            foreach (OrganisationalStructure s in structs)
            {
                List<Procedure> procs = s.Procedures;
                foreach (Procedure p in procs)
                {
                    if (p.name == action.Action.name)
                    {
                        orgEntity = s.Entities[0].name;
                    }
                }
            }

            List<Entity> entities = MascaretApplication.Instance.getEnvironment().getEntities();
            Entity entity = entities[0];
            Action action2 = null;
            /*     action2 = new CallProcedureAction();
            ((CallProcedureAction)(action2)).Procedure = procedure;
            ((CallProcedureAction)(action2)).OrganisationalEntity = orgEntity;
            BehaviorScheduler.Instance.executeBehavior(action2, entity, new Dictionary<string, ValueSpecification>(), false);

            */
            action2 = new CallGlobalActivityAction();
            ((CallGlobalActivityAction)(action2)).Procedure = action.Action.name;
            ((CallGlobalActivityAction)(action2)).OrganisationalEntity = orgEntity;
            BehaviorExecution be = BehaviorScheduler.Instance.executeBehavior(action2, entity, new Dictionary<string, ValueSpecification>(), false);
            behaviorToNode.Add(be, action);
        }
        public ProcedureExecution(Procedure procedure, OrganisationalEntity organisation, Agent agent)
        {
            this.procedure    = procedure;
            this.organisation = organisation;
            this.agent        = agent;

            agentToPartition         = new Dictionary <string, ActivityPartition>();
            partitionToAgent         = new Dictionary <ActivityPartition, AID>();
            activeTokens             = new List <ActivityExecutionToken>();
            affectations             = new Dictionary <string, InstanceSpecification>();
            activityParams           = new Dictionary <string, ValueSpecification>();
            actionsRunning           = new List <KeyValuePair <string, ActionNode> >();
            actionsDone              = new List <ActionNode>();
            allActionsDone           = new Dictionary <string, List <ActionNode> >(); // key: AID
            allActionsDoneTimestamps = new Dictionary <string, List <TimeExpression> >();

            for (int i = 0; i < procedure.Activity.Partitions.Count; i++)
            {
                ActivityPartition      partition    = procedure.Activity.Partitions[i];
                List <RoleAssignement> assignements = organisation.RoleAssignement;
                for (int j = 0; j < assignements.Count; j++)
                {
                    if (partition.name == assignements[j].Role.name)
                    {
                        agentToPartition.Add(assignements[j].Agent.toString(), partition);
                        partitionToAgent.Add(partition, assignements[j].Agent);
                        Agent agt = MascaretApplication.Instance.AgentPlateform.Agents[assignements[j].Agent.toString()];
                        if (agt == null)
                        {
                            MascaretApplication.Instance.VRComponentFactory.Log("CA VA TRANCHER");
                        }
                        affectations.Add(partition.name, agt);
                    }
                }
            }

            ActivityExecutionToken initialToken = new ActivityExecutionToken();

            initialToken.currentLocation = procedure.Activity.Initial;

            if (initialToken.currentLocation == null)
            {
                System.Console.WriteLine("ERROR: no initial node found, not allowed");
                System.Console.WriteLine("Procedure will not start.");
                return;
            }

            List <ActivityEdge> controlFlows = procedure.Activity.Initial.getOutgoingControlFlowEdges();

            if (controlFlows.Count == 1)
            {
                initialToken.outgoingEdge = controlFlows[0];
                activeTokens.Add(initialToken);

                ActionNode dummyActionVariable = null;
                tryToAdvanceToken(initialToken, dummyActionVariable, true); //first advancement
            }
            else
            {
                if (controlFlows.Count == 0)
                {
                    System.Console.WriteLine("WARNING: initial node has no outgoing edges");
                }
                else
                {
                    System.Console.WriteLine("ERROR: multiple outgoing edges for the initial node, not allowed");
                }
                System.Console.WriteLine("Procedure will not start.");
            }
        }
        protected bool actionIsCurrentlyRunning(ActionNode action)
        {
            //remove already running nodes :: TODO : check if we should allow this or not....
            for (int i = 0; i < actionsRunning.Count; ++i)
            {
                if (actionsRunning[i].Value == action)
                {
                    return true;
                }
            }

            return false;
        }
        public void onActionDone(AID agent, ActionNode action)
        {
            for (int iP = 0; iP < runningProcedures.Count; iP++)
            {
                ProcedureExecution procInfo = runningProcedures[iP];

                procInfo.informActionDone(agent, action);
            }
            ispause = false;
        }
        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);
        }
        public void informActionDone(AID agent, string actionName)
        {
            ActionNode action = getActionByNameFor(agent, actionName);

            informActionDone(agent, action);
        }
        public void informActionRunning(AID agent, ActionNode action)
        {
            //check if procedure will advance if this action is made
            bool canAdvance = true;

            ActionNode actionToRun = null;

            MascaretApplication.Instance.VRComponentFactory.Log("Start : " + action.getFullName());

            // Test if action owned by agent
            if (action.Partitions[0].name == agentToPartition[agent.toString()].name)
            {
                actionToRun = action;
            }
            else
            {
                MascaretApplication.Instance.VRComponentFactory.Log("This action " + action.getFullName() + " doesn't belong to agent " + agent.toString());
            }
            if (actionToRun != null)
            {
                //check if procedure can advance (action is reachable from the previous done actions)
                List <ActionNode> possibleNextActions = getActionToExecuteFor(agent);

                for (int i = 0; i < possibleNextActions.Count; ++i)
                {
                    if (actionToRun == possibleNextActions[i])
                    {
                        canAdvance = true;
                        break;
                    }
                }
            }

            if (canAdvance)
            {
                //save the running action in the list
                actionsRunning.Add(new KeyValuePair <string, ActionNode>(agent.toString(), action));

                //TODO: appologise because the hack is not so beautiful. the good part is that it works fine :)
                //update next reachable nodes list, if their current location is not a dead end (this caused problems with loopnodes for example...)
                //-- the problem was that loopnodes must not be restarted/skipped until the effect of its actions is understood. this is not the case with decision nodes for example
                ActionNode doneAction = action;

                if (doneAction != null)
                {
                    bool advancedToken = false;
                    for (int i = 0; i < activeTokens.Count; ++i)
                    {
                        if ((activeTokens[i].outgoingEdge == null) ||
                            (activeTokens[i].outgoingEdge.Target.getOutgoingControlFlowEdges().Count == 0))
                        {
                            continue; //skip deadends
                        }
                        //try to advance
                        //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "> trying to advance token " << (i+1) << "/" << _activeTokens.size() << " from " << _activeTokens[i]->currentLocation->getName() << endl;

                        ActivityExecutionToken token = activeTokens[i];
                        if (tryToAdvanceToken(token, doneAction, true))
                        {
                            //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "   >>  advanced token " << (i+1) << "/" << _activeTokens.size() << " to " << _activeTokens[i]->currentLocation->getName() << endl;

                            activeTokens[i] = token;
                            advancedToken   = true;
                        }
                    }

                    if (advancedToken)
                    {
                        //add to "done" list
                        actionsDone.Add(doneAction);

                        MascaretApplication.Instance.VRComponentFactory.Log("AllActionsDone : " + agent.toString());
                        if (!allActionsDone.ContainsKey(agent.toString()))
                        {
                            allActionsDone.Add(agent.toString(), new List <ActionNode>());
                        }
                        allActionsDone[agent.toString()].Add(doneAction);

                        MascaretApplication.Instance.VRComponentFactory.Log("allActionsDoneTimestamps : " + agent.toString());
                        if (!allActionsDoneTimestamps.ContainsKey(agent.toString()))
                        {
                            allActionsDoneTimestamps.Add(agent.toString(), new List <TimeExpression>());
                        }
                        allActionsDoneTimestamps[agent.toString()].Add(doneAction.CurrentExecution.Finish);
                        MascaretApplication.Instance.VRComponentFactory.Log("Done");
                    }
                    else
                    {
                        //if (ACTIVATE_GENERAL_DEBUG) cerr << "HUSTON, WE'VE GOT A PROBLEM... no token was advanced for " << doneAction->getName() << endl;
                    }
                }
            }
        }
        public List <ActionNode> getActionToExecuteForAll()
        {
            //this function simulates token advancement to provide the list of actions that can be executed
            //an action can be executed if it makes a difference in the procedure (if it enables a token to advance)

            //prepare output vector
            List <ActionNode> toExec = new List <ActionNode>();
            // StreamWriter file = MascaretApplication.Instance.logfile;

            //build list of all reachable actions (this list is a super-set which includes the actions to execute). we will filter this list
            List <ActionNode> allPossibleActionsToExecute = getAllActions();

            //backup current activeTokens
            List <ActivityExecutionToken> activeTokensBackup = new List <ActivityExecutionToken>();

            for (int i = 0; i < activeTokens.Count; i++)
            {
                activeTokensBackup.Add(activeTokens[i]);
            }


            //now filter the list by creating dummy tokens and simulate their advancement
            for (int i = 0; i < allPossibleActionsToExecute.Count; ++i)
            {
                //create dummy list
                activeTokens.Clear();

                for (int j = 0; j < activeTokensBackup.Count; ++j)
                {
                    //copy the token into a dummy
                    ActivityExecutionToken dummyToken = new ActivityExecutionToken();
                    dummyToken.currentLocation = activeTokensBackup[j].currentLocation;
                    dummyToken.forkStack       = activeTokensBackup[j].forkStack;
                    dummyToken.loopNodeStack   = activeTokensBackup[j].loopNodeStack;
                    dummyToken.outgoingEdge    = activeTokensBackup[j].outgoingEdge;

                    activeTokens.Add(dummyToken);
                }

                //test to see if this action is able to advance a token
                //file.WriteLine(" NB ACTIVE TOKENS : " + activeTokens.Count); file.Flush();

                for (int j = 0; j < activeTokens.Count; ++j)
                {
                    // file.WriteLine(activeTokens[j].currentLocation.name); file.Flush();
                    //advance token without the action (just to be sure we don't get fooled into thinking it advanced because of the action when it advances because of some other conditions that came true)
                    //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "advancing with dummy action" << endl;
                    ActionNode dummyActionNode = null;
                    tryToAdvanceToken(activeTokens[j], dummyActionNode, true); //care not about the result //TODO .... check this out

                    //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "advancing dummy token" << endl;

                    //see if the dummy advances with the current action
                    ActivityExecutionToken token = activeTokens[j];
                    //Debug.Log("CURRENT ACTIVE TOKEN : " + token.currentLocation.name);
                    if (tryToAdvanceToken(token, allPossibleActionsToExecute[i], true))
                    {
                        //dummy token advanced, so this action is an action to execute
                        activeTokens[j] = token;

                        toExec.Add(allPossibleActionsToExecute[i]);
                        //Debug.Log("New Current Location : " + activeTokens[j].currentLocation.name);
                        //if (ACTIVATE_GENERAL_DEBUG) cerr << "allPossibleActionsToExecute[" << i << "] = " << allPossibleActionsToExecute[i]->getName() << endl;
                        //break;
                    }
                }
            }

            //reinstate backed up activeTokens
            activeTokens.Clear();
            for (int i = 0; i < activeTokensBackup.Count; i++)
            {
                activeTokens.Add(activeTokensBackup[i]);
            }

            //remove already running nodes :: TODO : check if we should allow this or not....
            // file.WriteLine("Action Running : " + actionsRunning.Count); file.Flush();
            for (int i = 0; i < actionsRunning.Count; ++i)
            {
                for (int j = 0; j < toExec.Count; ++j)
                {
                    if (actionsRunning[i].Value == toExec[j])
                    {
                        toExec.RemoveAt(j);
                        j--;
                    }
                }
            }

            return(toExec);
        }
        public void informActionDone(AID agent, ActionNode action)
        {
            bool foundAndRemoved = false;
            //remove from "running" list
            for (int i = 0; i < actionsRunning.Count; ++i)
            {
                if ((actionsRunning[i].Key == agent.toString()) && (actionsRunning[i].Value.getFullName() == action.getFullName()))
                {
                    actionsRunning.RemoveAt(i);
                    foundAndRemoved = true;
                    break;
                }
            }

            //Debug.Log(" IAD : " + activeTokens.Count);
            if (foundAndRemoved)
            {
                ActionNode doneAction = action;
                if (doneAction != null)
                {
                    bool advancedToken = false;

                    for (int i = 0; i < activeTokens.Count; i++)
                    {
                        ActivityExecutionToken token = activeTokens[i];
                       	if (tryToAdvanceToken(token, doneAction, true))
                        {
                            advancedToken = true;
                        }
                    }

                    if (advancedToken)
                    {

                        //add to "done" list
                        actionsDone.Add(doneAction);
                        allActionsDone[agent.toString()].Add(doneAction);
                        allActionsDoneTimestamps[agent.toString()].Add(doneAction.CurrentExecution.Finish);
                    }
                    else
                    {
                        //if (ACTIVATE_GENERAL_DEBUG) cerr << "HUSTON, WE'VE GOT A PROBLEM... no token was advanced for " << doneAction->getName() << endl;
                    }
                }
            }
        }
        public void informActionRunning(AID agent, ActionNode action)
        {
            //check if procedure will advance if this action is made
            bool canAdvance = true;

            ActionNode actionToRun = null;
            MascaretApplication.Instance.VRComponentFactory.Log("Start : " + action.getFullName());

            // Test if action owned by agent
            if (action.Partitions[0].name == agentToPartition[agent.toString()].name)
                actionToRun = action;
            else
                MascaretApplication.Instance.VRComponentFactory.Log( "This action " + action.getFullName() + " doesn't belong to agent " + agent.toString());
             if (actionToRun != null)
             {
                 //check if procedure can advance (action is reachable from the previous done actions)
                 List<ActionNode> possibleNextActions = getActionToExecuteFor(agent);

                 for (int i=0; i<possibleNextActions.Count; ++i)
                 {
                     if (actionToRun == possibleNextActions[i])
                     {
                        canAdvance = true;
                        break;
                     }
                 }
            }

            if (canAdvance)
            {
                //save the running action in the list
                actionsRunning.Add(new KeyValuePair<string, ActionNode>(agent.toString(), action));

                //TODO: appologise because the hack is not so beautiful. the good part is that it works fine :)
                //update next reachable nodes list, if their current location is not a dead end (this caused problems with loopnodes for example...)
                //-- the problem was that loopnodes must not be restarted/skipped until the effect of its actions is understood. this is not the case with decision nodes for example
                ActionNode doneAction = action;

                if (doneAction != null)
                {
                    bool advancedToken = false;
                    for (int i = 0; i < activeTokens.Count; ++i)
                    {
                        if ((activeTokens[i].outgoingEdge == null) ||
                                (activeTokens[i].outgoingEdge.Target.getOutgoingControlFlowEdges().Count == 0))
                        {
                            continue; //skip deadends
                        }
                        //try to advance
                        //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "> trying to advance token " << (i+1) << "/" << _activeTokens.size() << " from " << _activeTokens[i]->currentLocation->getName() << endl;

                        ActivityExecutionToken token = activeTokens[i];
                        if (tryToAdvanceToken(token, doneAction, true))
                        {
                            //if (ACTIVATE_DEBUG_CONSOLE_OUTPUT_TOKENS) cerr << "   >>  advanced token " << (i+1) << "/" << _activeTokens.size() << " to " << _activeTokens[i]->currentLocation->getName() << endl;

                            activeTokens[i] = token;
                            advancedToken = true;
                        }

                    }

                    if (advancedToken)
                    {

                        //add to "done" list
                        actionsDone.Add(doneAction);

                        MascaretApplication.Instance.VRComponentFactory.Log("AllActionsDone : " + agent.toString());
                        if (!allActionsDone.ContainsKey(agent.toString()))
                            allActionsDone.Add(agent.toString(), new List<ActionNode>());
                        allActionsDone[agent.toString()].Add(doneAction);

                        MascaretApplication.Instance.VRComponentFactory.Log("allActionsDoneTimestamps : " + agent.toString());
                        if (!allActionsDoneTimestamps.ContainsKey(agent.toString()))
                            allActionsDoneTimestamps.Add(agent.toString(),new List<TimeExpression>());
                        allActionsDoneTimestamps[agent.toString()].Add( doneAction.CurrentExecution.Finish);
                        MascaretApplication.Instance.VRComponentFactory.Log("Done");
                    }
                    else
                    {
                        //if (ACTIVATE_GENERAL_DEBUG) cerr << "HUSTON, WE'VE GOT A PROBLEM... no token was advanced for " << doneAction->getName() << endl;
                    }
                }
            }
        }
        public void sendActionDoneMessage(ActionNode action, ProcedureExecution procInfo)
        {
            Agent agt = (Agent)(this.Host);

            ACLMessage procMsg = new ACLMessage(ACLPerformative.INFORM);

            //we inform at wich time the action finished
            TimeExpression timestamp = action.CurrentExecution.Finish;

            procMsg.Timestamp = timestamp;

            //set ACLMessage content
            string content = "((done (action ";
            content += agt.name;
            content += " ";
            content += "(" + clean(action.name) + ")";
            content += ")))";
            procMsg.Content = content;
            //MascaretApplication.Instance.VRComponentFactory.Log(content);

            //send message to other agents
            List<AID> agents = procInfo.getOtherAgents();

            for (int iA = 0; iA < agents.Count; iA++)
            {
                procMsg.Receivers.Add(agents[iA]);
            }
            agt.send(procMsg);
        }
        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;
        }
        public void sendActionRealisationMessage(ActionNode action, ProcedureExecution procInfo)
        {
            Agent agt = (Agent)(this.Host);

            ACLMessage procMsg = new ACLMessage(ACLPerformative.INFORM);

            //we inform at wich time the action start
            TimeExpression timestamp = action.CurrentExecution.Start;

            procMsg.Timestamp = timestamp;

            //set ACLMessage content
            string content = "((action ";
            content += agt.name;
            content += " ";
            content += "(" + clean(action.name) + ")";
            content += "))";
            procMsg.Content = content;

            //send message to other agents
            List<AID> agents = procInfo.getOtherAgents();

            for (int iA = 0; iA < agents.Count; iA++)
            {
                procMsg.Receivers.Add(agents[iA]);
            }
            agt.send(procMsg);
        }