1 // Copyright (C) 2006-2021 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "ComposedNode.hxx"
21 #include "LinkInfo.hxx"
22 #include "Container.hxx"
23 #include "InputPort.hxx"
24 #include "OutputPort.hxx"
25 #include "ServiceNode.hxx"
26 #include "InlineNode.hxx"
27 #include "DataFlowPort.hxx"
28 #include "DataStreamPort.hxx"
29 #include "ElementaryNode.hxx"
30 #include "ComponentInstance.hxx"
39 #include "YacsTrace.hxx"
41 using namespace YACS::ENGINE;
44 /*! \class YACS::ENGINE::ComposedNode
45 * \brief Base class for all composed nodes.
47 * This is an abstract class that must be specialized.
52 const char ComposedNode::SEP_CHAR_BTW_LEVEL[]=".";
54 ComposedNode::ComposedNode(const std::string& name):Node(name)
58 ComposedNode::ComposedNode(const ComposedNode& other, ComposedNode *father):Node(other,father)
62 ComposedNode::~ComposedNode()
66 void ComposedNode::performDuplicationOfPlacement(const Node& other)
68 const ComposedNode &otherC=*(dynamic_cast<const ComposedNode *>(&other));
69 DeploymentTree treeToDup=otherC.getDeploymentTree();
70 list< ElementaryNode * > clones=otherC.getRecursiveConstituents();
71 vector<Container *> conts=treeToDup.getAllContainers();
72 //iterate on all containers
73 for(vector<Container *>::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
75 vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
76 Container *contCloned=0;
78 contCloned=(*iterCt)->clone();
80 //iterate on all component instances linked to the container
81 for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
83 vector<Task *> tasks=treeToDup.getTasksLinkedToComponent(*iterCp);
84 ComponentInstance *curCloned=(*iterCp)->clone();
85 curCloned->setContainer(contCloned);
86 for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
88 //No risk for static cast : appendTask called by ComposedNode.
89 list< ElementaryNode * >::iterator res=find(clones.begin(),clones.end(),(ElementaryNode *)(*iterT));
90 //No risk here to because called only on cloning process...
91 ServiceNode *nodeC=(ServiceNode *)getChildByName(otherC.getChildName(*res));
92 nodeC->setComponent(curCloned);
97 // iterate on all tasks linked to the container
98 vector<Task *> tasks=treeToDup.getTasksLinkedToContainer(*iterCt);
99 for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
101 std::list< ElementaryNode * >::iterator res=find(clones.begin(),clones.end(),(ElementaryNode *)(*iterT));
102 InlineFuncNode *nodeC=(InlineFuncNode *)getChildByName(otherC.getChildName(*res));
103 nodeC->setContainer(contCloned);
106 // ended with current container
108 contCloned->decrRef();
112 void ComposedNode::performShallowDuplicationOfPlacement(const Node& other)
114 const ComposedNode &otherC=*(dynamic_cast<const ComposedNode *>(&other));
115 DeploymentTree treeToDup=otherC.getDeploymentTree();
116 list< ElementaryNode * > clones=otherC.getRecursiveConstituents();
117 vector<Container *> conts=treeToDup.getAllContainers();
118 //iterate on all containers
119 for(vector<Container *>::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
121 vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
122 Container *contCloned((*iterCt));
124 //iterate on all component instances linked to the container
125 for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
127 vector<Task *> tasks=treeToDup.getTasksLinkedToComponent(*iterCp);
128 ComponentInstance *curCloned((*iterCp));
129 curCloned->setContainer(contCloned);
130 for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
132 //No risk for static cast : appendTask called by ComposedNode.
133 list< ElementaryNode * >::iterator res=find(clones.begin(),clones.end(),(ElementaryNode *)(*iterT));
134 //No risk here to because called only on cloning process...
135 ServiceNode *nodeC=(ServiceNode *)getChildByName(otherC.getChildName(*res));
136 nodeC->setComponent(curCloned);
140 // iterate on all tasks linked to the container
141 vector<Task *> tasks=treeToDup.getTasksLinkedToContainer(*iterCt);
142 for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
144 std::list< ElementaryNode * >::iterator res=find(clones.begin(),clones.end(),(ElementaryNode *)(*iterT));
145 InlineFuncNode *nodeC=(InlineFuncNode *)getChildByName(otherC.getChildName(*res));
146 nodeC->setContainer(contCloned);
151 bool ComposedNode::isFinished()
153 if(_state==YACS::DONE)return true;
154 if(_state==YACS::ERROR)return true;
155 if(_state==YACS::FAILED)return true;
156 if(_state==YACS::DISABLED)return true;
160 void ComposedNode::init(bool start)
165 std::string ComposedNode::getName() const
167 return Node::getName();
170 std::string ComposedNode::getTaskName(Task *task) const
172 return getChildName(dynamic_cast<ElementaryNode *>(task));
175 //! Essentially for test. Use checkDeploymentTree instead to be sure that returned DeploymentTree is consistent.
176 DeploymentTree ComposedNode::getDeploymentTree() const
179 list< ElementaryNode * > tasks=getRecursiveConstituents();
180 for(list< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++)
181 ret.appendTask(*iter,(*iter)->getDynClonerIfExists(this));
185 //! Perform check of deployment consistency of the current graph.
187 * \param deep if \b true a deep check is perfomed. Typically has to be called by an executor before any attempt to launch an execution.
189 DeploymentTree ComposedNode::checkDeploymentTree(bool deep) const
192 list< ElementaryNode * > tasks=getRecursiveConstituents();
193 for(list< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++)
195 switch(ret.appendTask(*iter,(*iter)->getDynClonerIfExists(this)))
197 case DeploymentTree::DUP_TASK_NOT_COMPATIBLE_WITH_EXISTING_TREE:
199 string what("ComposedNode::checkDeploymentTree : ServiceNode with name \""); what+=(*iter)->getName();
200 what+="\" coexists in a component with an another Task which context is incompatible with it.";
201 throw Exception(what);
203 case DeploymentTree::DEPLOYABLE_BUT_NOT_SPECIFIED :
207 string what("ComposedNode::checkDeploymentTree : ServiceNode with name \""); what+=(*iter)->getName();
208 what+="\" is deployable but no component is specified on it.";
209 throw Exception(what);
217 std::vector<Task *> ComposedNode::getNextTasks(bool& isMore)
226 //! Notify the node a task has emitted an event
229 * \note Runtime called method. Overloads the Scheduler::notifyFrom abstract method.
230 * Typically Called in Executor (in a parallel thread or not) by the Task 'task'
231 * to inform the scheduler that an event coded 'event' (in Executor static const var) happened.
232 * Contrary to updateStateFrom several levels may exist between 'sender' and 'this'.
234 * \param sender : task emitting event
235 * \param event : event emitted
237 * Called by Executor::functionForTaskExecution on YACS::FINISH event
239 * Called by Executor::launchTask on YACS::START event
241 * Calls ComposedNode::updateStateFrom to update state from task to root node
243 void ComposedNode::notifyFrom(const Task *sender, //* I : task emitting event
244 YACS::Event event, //* I : event emitted
245 const Executor *execInst
248 DEBTRACE("ComposedNode::notifyFrom " << event);
249 ElementaryNode *taskTyped=dynamic_cast<ElementaryNode *>((Task *)sender);
250 YACS::Event curEvent=event;
251 Node *lminus1LevelNode=taskTyped;
252 ComposedNode *curLevelNode=taskTyped->_father;
253 if(!curLevelNode)//Specific case of loop when 0 turn is specified without any enclosing bloc.
255 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent,execInst);
256 while(curEvent!=YACS::NOEVENT && curLevelNode!=this)
258 lminus1LevelNode=curLevelNode;
259 curLevelNode=curLevelNode->_father;
260 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent,execInst);
264 //! Add a dataflow link between two data ports.
266 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
267 * \exception Exception : if incompatibility between input and output (type), or 'start'/'end'
268 * is/are NOT in/outputPort contained in a node in descendance
269 * of 'this', or a multiple link to an input not supporting it.
270 * \return true if a new link has been created, false otherwise.
273 bool ComposedNode::edAddLink(OutPort *start, InPort *end)
275 DEBTRACE("ComposedNode::edAddLink");
276 set<OutPort *> represented;
278 start->getAllRepresented(represented);
279 if(represented.size()!=1)
282 for(set<OutPort *>::iterator iter=represented.begin();iter!=represented.end();iter++)
283 ret|=edAddLink(*iter,end);
286 if(start->isAlreadyLinkedWith(end))
288 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
289 list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
290 list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
291 checkInMyDescendance(lwstCmnAnctr);
292 lwstCmnAnctr->checkLinkPossibility(start,allAscendanceOfNodeStart,end,allAscendanceOfNodeEnd);
294 if(dynamic_cast<ComposedNode *>(start->getNode()))
295 iterS=(ComposedNode *)start->getNode();
297 iterS=start->getNode()->_father;
298 pair<OutPort *, OutPort *> pO(start,start);
299 while(iterS!=lwstCmnAnctr)
301 iterS->buildDelegateOf(pO, end, allAscendanceOfNodeEnd);
302 iterS=iterS->_father;
304 if(dynamic_cast<ComposedNode *>(end->getNode()))
305 iterS=(ComposedNode *)end->getNode();
307 iterS=end->getNode()->_father;
309 InPort *currentPortI=end;
310 bool isLoopProofLink(true),isFirstTurn(true);
311 while(iterS!=lwstCmnAnctr)
313 if(!isFirstTurn && iterS->isLoop())// isFirstTurn is a way to filter special inputs like nbBranches, splitPort... These special inputs are loopProof -> they must not be realeased by ForEachLoop::exUpdateState
314 isLoopProofLink=false;
315 iterS->buildDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
316 iterS=iterS->_father;
319 bool ret=(pO.first)->addInPort(currentPortI);
320 end->edNotifyReferencedBy(pO.second,isLoopProofLink);
324 //! Connect an OutPort to an InPort and add the necessary control link
326 * Connect the ports with a data link (edAddLink) and add
327 * a control flow link between the children of the lowest common ancestor node.
329 * \param start : the OutPort to connect
330 * \param end : the InPort to connect
331 * \return true if a new link has been created, false otherwise.
333 bool ComposedNode::edAddDFLink(OutPort *start, InPort *end)
335 Node* n1=start->getNode();
336 Node* n2=end->getNode();
337 DEBTRACE( n1->getName() << ":" << n2->getName())
338 ComposedNode* father=getLowestCommonAncestor(n1,n2);
339 DEBTRACE( "ComposedNode::edAddDFLink: this="<<this->getName()
340 << " father=" << father->getName() )
341 DEBTRACE( "ComposedNode::edAddDFLink: OutPort=" << start->getName()
342 << " InPort=" << end->getName() )
345 bool ret = father->edAddDFLink(start,end); // special treatement for loop
349 throw Exception("Back link authorized only in special context (loop for example)");
351 bool ret= edAddLink(start,end);
354 //add a control link only if nodes are not in the same descendance
355 //if n1 == father (n2 is after n1) : the control link is not needed
356 //if n2 == father (n1 is after n2) : it's a back link authorized only in loop context
357 while(n1->getFather() != father)
359 while(n2->getFather() != father)
365 catch (Exception& ex)
367 // --- remove DF link already created in case of cycle dtection
368 DEBTRACE("Cycle detected, remove CF link");
369 if(start->isAlreadyLinkedWith(end))
370 edRemoveLink(start, end);
377 //! Add a controlflow link between two control ports.
379 * \note Precondition : 'start' AND 'end' are in/outGate contained in a node
380 * in DIRECT descendance of 'this'.
381 * \exception Exception : If a cycle has been detected, or incompatibility
382 * between input and output, or 'start'/'end' is/are NOT in/outputPort contained
383 * in a node in descendance of 'this', or a mutilple link to an input not
385 * \return true if a new link has been created, false otherwise.
387 bool ComposedNode::edAddLink(OutGate *start, InGate *end)
389 Node* n1=start->getNode();
390 Node* n2=end->getNode();
392 throw Exception("ComposedNode::edAddLink: can not add a control link to a node with itself",1);
393 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
395 throw Exception("ComposedNode::edAddLink: Trying to add CF link on orphan nodes.");
398 checkInMyDescendance(father);
399 return father->edAddLink(start,end);
401 bool ret=start->edAddInGate(end);
405 checkNoCyclePassingThrough(end->getNode());
407 catch (Exception& ex)
409 // --- remove created CF link in case of cycle detection
410 DEBTRACE("Cycle detected, remove CF link");
411 edRemoveCFLink(start->getNode(), end->getNode());
417 //! Add a controlflow link between two nodes.
419 * Add a controlflow link between two nodes by calling edAddLink on their control ports
421 bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE)
423 return edAddLink(nodeS->getOutGate(),nodeE->getInGate());
426 //! Remove a controlflow link.
427 void ComposedNode::edRemoveCFLink(Node *nodeS, Node *nodeE)
429 edRemoveLink(nodeS->getOutGate(),nodeE->getInGate());
432 //! Remove a dataflow link.
434 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
436 * \exception Exception : If the specified link does not exist. The content of Exception
437 * is different in accordance with the link from 'start' to 'end'
438 * implies DF/DS gateway.
441 void ComposedNode::edRemoveLink(OutPort *start, InPort *end)
443 if(!start->isAlreadyLinkedWith(end))
444 throw Exception("ComposedNode::edRemoveLink : unexisting link");
445 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
446 checkInMyDescendance(lwstCmnAnctr);
447 list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
448 list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
450 // --- Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created
452 ComposedNode *iterS=start->getNode()->_father;
453 pair<OutPort *,OutPort *> currentPortO(start,start);
454 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > > needsToDestroyO;
456 Node *nodeOTemp=start->getNode();
457 if(*nodeOTemp<*lwstCmnAnctr)
459 iterS=nodeOTemp->_father;
460 while(iterS!=lwstCmnAnctr)
465 what << "ComposedNode::edRemoveLink: "
466 << start->getNode()->getName() << "." <<start->getName() << "->"
467 << end->getNode()->getName() << "." << end->getName();
468 throw Exception(what.str());
470 OutPort *tmp=currentPortO.first;
471 iterS->getDelegateOf(currentPortO, end, allAscendanceOfNodeEnd);
472 needsToDestroyO.push_back(pair< ComposedNode * , pair < OutPort* , OutPort *> >(iterS,pair<OutPort* , OutPort *> (tmp,currentPortO.first)));
473 iterS=iterS->_father;
476 Node *nodeTemp=end->getNode();
477 InPort * currentPortI=end;
478 if(*nodeTemp<*lwstCmnAnctr)
480 iterS=nodeTemp->_father;
481 while(iterS!=lwstCmnAnctr)
486 what << "ComposedNode::edRemoveLink: "
487 << start->getNode()->getName() << "." <<start->getName() << "->"
488 << end->getNode()->getName() << "." << end->getName();
489 throw Exception(what.str());
491 iterS->getDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
492 iterS=iterS->_father;
495 // --- End of test for evt intermediate ports created
497 (currentPortO.first)->removeInPort(currentPortI,false);
499 (currentPortO.second)->getAllRepresented(repr);
501 end->edNotifyDereferencedBy(currentPortO.second);
503 // --- Performing deletion of intermediate ports
505 iterS=start->getNode()->_father;
506 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > >::reverse_iterator iter;
507 for(iter=needsToDestroyO.rbegin();iter!=needsToDestroyO.rend();iter++)
508 (*iter).first->releaseDelegateOf(((*iter).second).first, ((*iter).second).second, end,allAscendanceOfNodeEnd);
509 nodeTemp=end->getNode();
510 if(*nodeTemp<*lwstCmnAnctr)
512 iterS=end->getNode()->_father;
514 while(iterS!=lwstCmnAnctr)
516 iterS->releaseDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
517 iterS=iterS->_father;
522 //! Remove a controlflow link.
523 void ComposedNode::edRemoveLink(OutGate *start, InGate *end)
525 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
527 throw Exception("edRemoveLink : nodes not in direct descendance of this");
528 start->edRemoveInGate(end);
531 bool ComposedNode::edAddChild(Node *DISOWNnode)
533 return false; // --- reimplemented in derived classes
536 //! Remove a child node.
537 void ComposedNode::edRemoveChild(Node *node)
541 if (node->_father!=this)
543 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
544 throw Exception(what);
546 node->edDisconnectAllLinksWithMe();
548 //set _modified flag so edUpdateState() can refresh state
552 //! Splits name globalName in 2 parts using separator.
554 * \note 'priority' specifies if during search process of 'separator' the max part is
555 * for 'firstPart' (priority=true) or 'lastPart' (priority=false).
557 * \throw Exception : 'lastPart' or 'firstPart' is empty.
558 * \return true if split process succeeds false otherwise (typically when character
559 * separator was not found).
561 bool ComposedNode::splitNamesBySep(const std::string& globalName, const char separator[],
562 std::string& firstPart, std::string& lastPart, bool priority)
564 const string delims(separator);
565 string portName, nodeName;
566 string::size_type idx;
568 idx = globalName.find_last_of(delims);
570 idx = globalName.find_first_of(delims);
571 if (idx == string::npos)
573 firstPart=globalName;
577 firstPart = globalName.substr(0,idx);
578 lastPart = globalName.substr(idx+1);
579 if ((firstPart.empty()) || (lastPart.empty()))
581 string what("the name "); what+= globalName ; what+=" is not a valid port name";
582 throw Exception(what);
587 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfInternalLinks() const
589 vector< pair<OutPort *, InPort *> > ret;
590 list<OutPort *> temp=getSetOfOutPort();
591 for(list<OutPort *>::const_iterator iter2=temp.begin();iter2!=temp.end();iter2++)
593 set<InPort *> temp2=(*iter2)->edSetInPort();
594 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
595 if(isInMyDescendance((*iter3)->getNode()))
596 ret.push_back(pair<OutPort *, InPort *>((*iter2),(*iter3)));
601 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfLinksLeavingCurrentScope() const
603 vector< pair<OutPort *, InPort *> > ret;
604 std::set<OutPort *> ports=getAllOutPortsLeavingCurrentScope();
605 for(set<OutPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
607 set<InPort *> temp2=(*iter2)->edSetInPort();
608 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
609 if(!isInMyDescendance((*iter3)->getNode()))
610 ret.push_back(pair<OutPort *, InPort *>(*iter2,*iter3));
615 void ComposedNode::checkConsistency(LinkInfo& info) const
618 info.setPointOfView((ComposedNode *)this);
619 performCFComputations(info);
620 list<InputPort *> setOfInToTest=getSetOfInputPort();
621 for(list<InputPort *>::iterator iter1=setOfInToTest.begin();iter1!=setOfInToTest.end();iter1++)
623 vector<OutPort *> candidateForAdvCheck;
624 set<OutPort *> outPorts=(*iter1)->edSetOutPort();
625 //Filtering among outPorts, which of them, are candidates to fill *iter1 at the current scope.
626 for(set<OutPort *>::iterator iter2=outPorts.begin();iter2!=outPorts.end();iter2++)
628 (*iter2)->checkConsistency(info);
629 ComposedNode *manager=getLowestCommonAncestor((*iter2)->getNode(),(*iter1)->getNode());
630 if(isInMyDescendance(manager))
631 candidateForAdvCheck.push_back(*iter2);
633 if(!candidateForAdvCheck.empty())
634 //End of filtering. Now regarding CF constraints for the current InPutPort.
637 checkLinksCoherenceRegardingControl(candidateForAdvCheck,*iter1,info);
639 catch(YACS::Exception& ex)
641 std::string what=ex.what();
642 what += "\nfor input port: ";
643 what += (*iter1)->getNode()->getName();
645 what += (*iter1)->getName();
647 destructCFComputations(info);
648 throw YACS::Exception(what);
652 if(!(*iter1)->canBeNull() && !(*iter1)->edIsManuallyInitialized())
653 info.pushErrLink(0,*iter1,E_NEVER_SET_INPUTPORT);
655 destructCFComputations(info);
659 * This method check that G1 <- G2 <- G3 <- G1 does not happened.
660 * Typically called by methods that set a hierarchy (Bloc::edAddChild, Loop::edSetNode, ...).
662 void ComposedNode::checkNoCrossHierachyWith(Node *node) const
664 ComposedNode *nodeC=dynamic_cast<ComposedNode *>(node);
667 list<ComposedNode *> ascendants=getAllAscendanceOf();
668 if(find(ascendants.begin(),ascendants.end(),nodeC)!=ascendants.end())
670 const char what[]="ComposedNode::checkNoCrossHierachyWith : ComposedNode with name \"";
671 string stream(what); stream+=node->getName(); stream+="\" is already in hierarchy ascendance of node with name \"";
672 stream+=_name; stream+="\" ; So it can't be now in its descendance !";
673 throw Exception(stream);
677 //! perform \b recursively all CF computations.
678 void ComposedNode::performCFComputations(LinkInfo& info) const
680 list<Node *> nodes=edGetDirectDescendants();
681 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
682 if(dynamic_cast<ComposedNode *>(*iter))
683 ((ComposedNode *)(*iter))->performCFComputations(info);
686 //! destroy \b recursively all results of initial computations.
687 void ComposedNode::destructCFComputations(LinkInfo& info) const
689 list<Node *> nodes=edGetDirectDescendants();
690 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
691 if(dynamic_cast<ComposedNode *>(*iter))
692 ((ComposedNode *)(*iter))->destructCFComputations(info);
696 * Returns the lowest Node (Elementary or Composed) (is sense of hierachy level ( operator< ) ) containing all 'ports'.
697 * Typically use in consistency computation.
698 * Precondition : 'ports' \b must contain at least one element. All elements of 'ports' should be in descendance of 'this'.
700 Node *ComposedNode::getLowestNodeDealingAll(const std::list<OutPort *>& ports) const
702 list< OutPort *>::const_iterator iter=ports.begin();
703 Node *ret=(*iter)->getNode();
705 for(;iter!=ports.end();iter++)
707 Node *tmp=(*iter)->getNode();
715 * call it only for 'starts' to 'end' links \b DEALED by 'this'.
717 void ComposedNode::checkLinksCoherenceRegardingControl(const std::vector<OutPort *>& starts, InputPort *end, LinkInfo& info) const
719 map < ComposedNode *, list<OutPort *>, SortHierarc > outputs;//forward link classical
720 vector<OutPort *> outputsCross;//forward link cross
721 map < ComposedNode *, list<OutPort *>, SortHierarc > outputsBw;//backward
722 vector<OutPort *>::const_iterator iter1;
723 //vector<DataPort *> history=((*iter1).second)[0]->calculateHistoryOfLinkWith(end);
724 //DataPort *cross=DataPort::isCrossingType(history);
725 for(iter1=starts.begin();iter1!=starts.end();iter1++)
727 ComposedNode *manager=getLowestCommonAncestor((*iter1)->getNode(),end->getNode());
728 manager->checkControlDependancy((*iter1), end, false, outputs, outputsCross, outputsBw, info);
730 //Ok now let's regarding outputs all combinations : (outputs.size())*(outputs.size()-1)/2
731 unsigned char isAlreadyFed=FREE_ST;
732 //Dealing excusively with DS. Level is useless here because simultaneity is required for DS.
733 if(outputsCross.size()>0)
735 isAlreadyFed=FED_DS_ST;
736 if(outputsCross.size()>1)
737 for(vector< OutPort *>::const_iterator iter1=outputsCross.begin();iter1!=(outputsCross.end()-2);iter1++)
738 info.pushErrLink(*iter1,end,E_COLLAPSE_DS);
740 map < ComposedNode *, list<OutPort *>, SortHierarc >::iterator iter3=outputs.begin();
741 for(;iter3!=outputs.end();iter3++)
742 ((*iter3).first)->checkCFLinks((*iter3).second,end,isAlreadyFed,true,info);
743 if(isAlreadyFed==FREE_ST)
744 if(!end->edIsManuallyInitialized())
745 info.pushErrLink(0,end,E_ONLY_BACKWARD_DEFINED);
746 isAlreadyFed=FREE_ST;
748 map < ComposedNode *, list<OutPort *>, SortHierarc >::reverse_iterator iter5=outputsBw.rbegin();
749 for(;iter5!=outputsBw.rend();iter5++)
750 ((*iter5).first)->checkCFLinks((*iter5).second,end,isAlreadyFed,false,info);
754 * Internal method during CF links. This methode is in charge to statuate on links consistency in the case
755 * that no control flow defined by user is set.
757 void ComposedNode::solveObviousOrDelegateCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
759 static const char what[]="ComposedNode::solveObviousOrDelegateCFLinks : Internal error occured - uncorrect hierarchy detected !";
762 if(alreadyFed==FREE_ST)
765 info.pushInfoLink(*(starts.begin()),end,I_BACK);
768 else if(alreadyFed==FED_ST)
769 info.pushInfoLink(*(starts.begin()),end,direction ? I_USELESS : I_BACK_USELESS);
771 info.pushErrLink(*(starts.begin()),end,E_COLLAPSE_DFDS);
775 Node *levelOfDecision=getLowestNodeDealingAll(starts);
776 if(levelOfDecision==this)
777 throw Exception(what);
778 if(dynamic_cast<ElementaryNode *>(levelOfDecision))
781 if(alreadyFed==FREE_ST || alreadyFed==FED_ST)
783 if(alreadyFed==FREE_ST)
785 reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL;
789 reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS;
790 for(list< OutPort *>::const_iterator iter=starts.begin();iter!=starts.end();iter++)
791 info.pushWarnLink(*iter,end,reason);
795 ((ComposedNode *)levelOfDecision)->checkCFLinks(starts,end,alreadyFed,direction,info);
799 //! check control flow links
801 * \param starts If different of 0, must aggregate at leat \b 1 element.
803 * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
804 * \param direction If true : forward direction else backward direction.
805 * \param info : informations collectedduring the check
807 void ComposedNode::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
809 static const char what[]="ComposedNode::checkCFLinks : Internal error occured - uncorrect hierarchy detected !";
810 Node *nodeEnd=isInMyDescendance(end->getNode());
812 return solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
813 //This case is typically dedicated when direct son is ElementaryNode and self link is defined on this.
814 if(!dynamic_cast<ElementaryNode *>(nodeEnd))
815 throw Exception(what);
817 list< OutPort *>::const_iterator iter=starts.begin();
818 Node *nodeStart=(*iter)->getNode();
820 if(nodeEnd!=nodeStart)
821 throw Exception(what);
823 for(;iter!=starts.end();iter++)
824 if((*iter)->getNode()!=nodeStart)
825 throw Exception(what);
826 //Ok at this step we are sure that we have back links on the same elementary node.
828 for(iter=starts.begin();iter!=starts.end();iter++)
829 info.pushWarnLink(*iter,end,W_BACK_COLLAPSE_EL);
830 else//here no need to look at 'alreadyFed' var because it is waranteed to be equal to FREE_ST by construction.
831 info.pushInfoLink(*(starts.begin()),end,I_BACK);
835 std::vector< std::pair<InPort *, OutPort *> > ComposedNode::getSetOfLinksComingInCurrentScope() const
837 vector< pair<InPort *, OutPort *> > ret;
838 set<InPort *> ports=getAllInPortsComingFromOutsideOfCurrentScope();
839 for(set<InPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
841 set<OutPort *> temp2=(*iter2)->edSetOutPort();
842 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
844 if(isInMyDescendance((*iter3)->getNode()))continue;
845 std::set<OutPort *> trueOutPorts;
846 (*iter3)->getAllRepresented(trueOutPorts);
847 for(std::set<OutPort *>::iterator iter4=trueOutPorts.begin();iter4!=trueOutPorts.end();++iter4)
848 ret.push_back(pair<InPort *, OutPort *>(*iter2,*iter4));
854 //! List all output ports of children nodes that are linked to out of scope input ports
856 * \note List all output ports of nodes sons of 'this' that are linked to input ports
857 * of nodes not in descendance of 'this'.
858 * This method contrary to getAllInPortsComingFromOutsideOfCurrentScope is NOT virtual
859 * because for the moment all daughter classes have no more hidden YACS::ENGINE::OutPort.
861 std::set<OutPort *> ComposedNode::getAllOutPortsLeavingCurrentScope() const
864 list<OutPort *> temp=getSetOfOutPort();
865 for(list<OutPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
867 set<InPort *> temp2=(*iter2)->edSetInPort();
868 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
869 if(!isInMyDescendance((*iter3)->getNode()))
878 //! List all input ports that are linked to out of scope ports
881 * List all input ports of 'this' so that, for each it exists at least 1 link coming
882 * from outside to it.
885 std::set<InPort *> ComposedNode::getAllInPortsComingFromOutsideOfCurrentScope() const
888 list<InPort *> temp=getSetOfInPort();
889 for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
891 set<OutPort *> temp2=(*iter2)->edSetOutPort();
892 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
894 if(!isInMyDescendance((*iter3)->getNode()))
903 void ComposedNode::edDisconnectAllLinksWithMe()
907 Node::edDisconnectAllLinksWithMe();
910 vector< pair<OutPort *, InPort *> > linksToDestroy=getSetOfLinksLeavingCurrentScope();
911 vector< pair<OutPort *, InPort *> >::iterator iter;
912 for(iter=linksToDestroy.begin();iter!=linksToDestroy.end();iter++)
915 (*iter).first->removeInPort((*iter).second,true);
918 vector< pair<InPort *, OutPort *> > linksToDestroy2=getSetOfLinksComingInCurrentScope();
919 vector< pair<InPort *, OutPort *> >::iterator iter2;
920 for(iter2=linksToDestroy2.begin();iter2!=linksToDestroy2.end();iter2++)
923 (*iter2).second->removeInPort((*iter2).first,true);
927 ComposedNode *ComposedNode::getRootNode() const
930 return (ComposedNode *)this;
931 return Node::getRootNode();
934 //! Check that Node 'node' is already a direct son of this.
935 bool ComposedNode::isNodeAlreadyAggregated(const Node *node) const
937 list<ComposedNode *> nodeAncestors = node->getAllAscendanceOf();
938 return find(nodeAncestors.begin(),nodeAncestors.end(),(ComposedNode *)this)!=nodeAncestors.end();
941 //! Returns the parent of a node that is the direct child of this node
943 * \note if 'nodeToTest'=='this' this is returned. Else if 'nodeToTest' is in descendance of
944 * 'this' the direct son is returned.
945 * Else 0 is returned.
947 * \param nodeToTest : the node to check
949 Node *ComposedNode::isInMyDescendance(Node *nodeToTest) const
953 if((ComposedNode *)nodeToTest==this)
955 Node *iterBack=nodeToTest;
956 ComposedNode *iter=nodeToTest->_father;
957 while(iter!=0 && iter!=this)
968 string ComposedNode::getChildName(const Node* node) const
970 string nodeName=node->getQualifiedName();
971 if (!isNodeAlreadyAggregated(node))
973 if (node->getName() == "thisIsAFakeNode")
975 string child = node->getName()+".thisIsAFakeNode";
980 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
981 throw Exception(what);
985 const Node *father = node->_father;
986 while (father != this)
988 nodeName = father->getQualifiedName() + SEP_CHAR_BTW_LEVEL + nodeName;
989 father = father->_father;
994 std::string ComposedNode::getMyQualifiedName(const Node *directSon) const
996 return directSon->getName();
999 Node *ComposedNode::getChildByName(const std::string& name) const
1001 string potentiallyDirectSonName, remainsPath;
1002 bool forwardNeeded=ComposedNode::splitNamesBySep(name, SEP_CHAR_BTW_LEVEL,
1003 potentiallyDirectSonName,remainsPath,false);
1004 Node *child=getChildByShortName(potentiallyDirectSonName);
1008 return child->getChildByName(remainsPath);
1011 //! Check if a node is in the descendance of this node
1013 * \note Check that 'nodeToTest' is in descendance of 'this' OR equal to 'this'
1014 * \exception Exception : If 'nodeToTest' is NOT in descendance of 'this' AND not equal to 'this'
1015 * \param nodeToTest : the node to check
1017 void ComposedNode::checkInMyDescendance(Node *nodeToTest) const
1019 const char whatC[]=" is not the descendance of node ";
1022 string what("node "); what+= nodeToTest->getName(); what+=" ";
1023 what+=whatC; what+=_name;
1024 throw Exception(what);
1026 if((ComposedNode *)nodeToTest==this)
1028 ComposedNode *iter=nodeToTest->_father;
1029 while(iter!=0 && iter!=this)
1033 string what("node "); what+= nodeToTest->getName(); what+=" ";
1034 what+=whatC; what+=_name;
1035 throw Exception(what);
1039 //! Retrieves the lowest common ancestor of 2 nodes
1042 * \note Retrieves the lowest common ancestor of 'node1' AND 'node2'.
1043 * If 'node1' or 'node2' are both or indiscriminately instances of ComposedNode and that
1044 * 'node1' is in descendance of 'node2' (resp. 'node2' in descendance of 'node1')
1045 * 'node2' is returned (resp. 'node1').
1046 * \exception Exception : if 'node1' and 'node2' do not share the same genealogy.
1047 * \return The lowest common ancestor if it exists.
1050 ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2)
1052 const char what[]="The two nodes do not share the same genealogy";
1053 if(node1==0 || node2==0)
1054 throw Exception(what);
1056 if(dynamic_cast<ComposedNode *>(node1))
1057 temp=(ComposedNode *)node1;//->_father;
1059 temp=(ComposedNode *)node1->_father;
1060 set<ComposedNode *> s;
1067 if(dynamic_cast<ComposedNode *>(node2))
1068 temp=(ComposedNode *)node2;//->_father;
1070 temp=(ComposedNode *)node2->_father;
1071 set<ComposedNode *>::iterator iter=s.find(temp);
1072 while(temp && iter==s.end())
1078 throw Exception(what);
1083 * Same as getLowestCommonAncestor method except that absolute string representation is considered here instead of instances.
1085 std::string ComposedNode::getLowestCommonAncestorStr(const std::string& node1, const std::string& node2)
1088 std::size_t it1_b(0),it1_e(0),it2_b(0),it2_e(0);
1089 while(it1_b!=std::string::npos && it2_b!=std::string::npos)
1091 it1_e=node1.find(SEP_CHAR_BTW_LEVEL,it1_b);
1092 it2_e=node2.find(SEP_CHAR_BTW_LEVEL,it2_b);
1093 if(it1_e!=it2_e && it1_e!=std::string::npos && it2_e!=std::string::npos)
1095 std::string elt1(node1.substr(it1_b,it1_e-it1_b)),elt2(node2.substr(it2_b,it2_e-it2_b));
1099 ret+=SEP_CHAR_BTW_LEVEL;
1101 it1_b=node1.find_first_not_of(SEP_CHAR_BTW_LEVEL,it1_e);
1102 it2_b=node2.find_first_not_of(SEP_CHAR_BTW_LEVEL,it2_e);
1108 * This method recursively all redundant control links in this.
1110 void ComposedNode::removeRecursivelyRedundantCL()
1112 std::list<Node *> dd(edGetDirectDescendants());
1113 for(std::list<Node *>::const_iterator it=dd.begin();it!=dd.end();it++)
1115 ComposedNode *elt(dynamic_cast<ComposedNode *>(*it));
1117 elt->removeRecursivelyRedundantCL();
1121 list<ElementaryNode *> ComposedNode::getRecursiveConstituents() const
1123 list<ElementaryNode *> ret;
1124 list<Node *> setOfNode=edGetDirectDescendants();
1125 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1127 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1128 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1133 //! Idem getAllRecursiveNodes, but this node is NOT included.
1134 list<Node *> ComposedNode::getAllRecursiveConstituents()
1137 list<Node *> setOfNode=edGetDirectDescendants();
1138 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1140 if ( dynamic_cast<ComposedNode*> (*iter) )
1142 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveConstituents();
1143 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1144 ret.push_back(*iter);
1148 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1149 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1155 //! Get all children nodes elementary and composed including this node
1156 list<Node *> ComposedNode::getAllRecursiveNodes()
1159 list<Node *> setOfNode=edGetDirectDescendants();
1160 for(list<Node *>::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1162 if ( dynamic_cast<ElementaryNode*> (*iter) )
1164 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1165 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1169 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveNodes();
1170 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1173 ret.push_back(this);
1178 //! Get the progress weight for all elementary nodes
1180 * Only elementary nodes have weight. A simple composed node only sum up weight of all his descendants
1181 * (working is different for loop or switch nodes)
1183 list<ProgressWeight> ComposedNode::getProgressWeight() const
1185 list<ProgressWeight> ret;
1186 list<Node *> setOfNode=edGetDirectDescendants();
1187 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1189 list<ProgressWeight> myCurrentSet=((ComposedNode*)(*iter))->getProgressWeight();
1190 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1195 //! Get the input port name
1197 * get the input port name used by the current node, recursively built with children names.
1200 string ComposedNode::getInPortName(const InPort * inPort) const
1202 return getPortName<InPort>(inPort);
1205 string ComposedNode::getOutPortName(const OutPort *outPort) const
1207 return getPortName<OutPort>(outPort);
1210 int ComposedNode::getNumberOfInputPorts() const
1212 list<Node *> constituents=edGetDirectDescendants();
1214 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1215 ret+=(*iter)->getNumberOfInputPorts();
1219 int ComposedNode::getNumberOfOutputPorts() const
1221 list<Node *> constituents=edGetDirectDescendants();
1223 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1224 ret+=(*iter)->getNumberOfOutputPorts();
1228 list<InputPort *> ComposedNode::getSetOfInputPort() const
1230 list<Node *> constituents=edGetDirectDescendants();
1231 list<InputPort *> ret;
1232 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1234 list<InputPort *> currentsPorts=(*iter)->getSetOfInputPort();
1235 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1240 list<OutputPort *> ComposedNode::getSetOfOutputPort() const
1242 list<Node *> constituents=edGetDirectDescendants();
1243 list<OutputPort *> ret;
1244 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1246 list<OutputPort *> currentsPorts=(*iter)->getSetOfOutputPort();
1247 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1252 list<InputDataStreamPort *> ComposedNode::getSetOfInputDataStreamPort() const
1254 list<Node *> constituents=edGetDirectDescendants();
1255 list<InputDataStreamPort *> ret;
1256 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1258 list<InputDataStreamPort *> currentsPorts=(*iter)->getSetOfInputDataStreamPort();
1259 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1264 list<OutputDataStreamPort *> ComposedNode::getSetOfOutputDataStreamPort() const
1266 list<Node *> constituents=edGetDirectDescendants();
1267 list<OutputDataStreamPort *> ret;
1268 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1270 list<OutputDataStreamPort *> currentsPorts=(*iter)->getSetOfOutputDataStreamPort();
1271 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1276 OutPort *ComposedNode::getOutPort(const std::string& name) const
1278 string portName, nodeName;
1279 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1281 Node *child = getChildByShortName(nodeName);
1282 return child->getOutPort(portName);
1286 string what("ComposedNode::getOutPort : the port with name "); what+=name; what+=" does not exist on the current level";
1287 throw Exception(what);
1291 //! Get an input port given its name
1293 * Contrary to YACS::ENGINE::ComposedNode::getOutputPort, this method is \b NOT recursive
1294 * and so the leaf of type ElementaryNode aggregating
1295 * this InputPort is directly invoked.
1297 InputPort * ComposedNode::getInputPort(const std::string& name) const
1300 return Node::getInputPort(name);
1302 catch(Exception& e) {}
1304 string portName, nodeName;
1305 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1307 Node *child = getChildByName(nodeName);
1308 return child->getInputPort(portName);
1312 string what("ComposedNode::getInputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1313 throw Exception(what);
1317 //! Get an output port given its name
1319 * Contrary to YACS::ENGINE::ComposedNode::getInputPort, this method is recursive and go
1320 * down hierarchy step by step to complete its work.
1322 OutputPort * ComposedNode::getOutputPort(const std::string& name) const
1324 string portName, nodeName;
1325 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1327 Node *child = getChildByShortName(nodeName);
1328 return child->getOutputPort(portName);
1332 string what("ComposedNode::getOutputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1333 throw Exception(what);
1337 InputDataStreamPort *ComposedNode::getInputDataStreamPort(const std::string& name) const
1339 string portName, nodeName;
1340 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1342 Node *child = getChildByName(nodeName);
1343 return child->getInputDataStreamPort(portName);
1347 string what("ComposedNode::getInputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1348 throw Exception(what);
1352 OutputDataStreamPort *ComposedNode::getOutputDataStreamPort(const std::string& name) const
1354 string portName, nodeName;
1355 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1357 Node *child = getChildByName(nodeName);
1358 return child->getOutputDataStreamPort(portName);
1362 string what("ComposedNode::getOutputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1363 throw Exception(what);
1367 //! Update node state on receiving event from a node
1370 * \note Runtime called method. Perform, the state updating, from the son node 'node'
1371 * emitting the event 'event' (among Executor static const var).
1372 * WARNING Precondition : this == node->_father
1373 * \return The event (among Executor static const var) destinated to this->_father node
1374 * to perform eventually up level update.
1376 * Calls ComposedNode::updateStateOnStartEventFrom if event is YACS::START
1378 * Calls ComposedNode::updateStateOnFinishedEventFrom if event is YACS::FINISH
1380 * Called by ComposedNode::notifyFrom
1382 YACS::Event ComposedNode::updateStateFrom(Node *node, //* I : node emitting event
1383 YACS::Event event, //* I : event emitted
1384 const Executor *execInst
1387 DEBTRACE("updateStateFrom: " << node->getName() << " " << event);
1393 return updateStateOnStartEventFrom(node);
1396 return updateStateOnFinishedEventFrom(node);
1399 return updateStateOnFailedEventFrom(node,execInst);
1402 return YACS::NOEVENT;//TODO unexpected type of event
1406 catch(YACS::Exception& ex)
1408 //unexpected exception: probably a bug in engine
1409 //try to keep a consistent global state
1410 DEBTRACE( "updateStateFrom: " << ex.what() );
1411 _errorDetails="Internal error: ";
1412 _errorDetails=_errorDetails + ex.what();
1413 setState(YACS::ERROR);
1419 //unexpected exception: probably a bug in engine
1420 //try to keep a consistent global state
1421 setState(YACS::ERROR);
1427 //! Method used to notify the node that a child node has started
1429 * Update the ComposedNode state and return the ComposedNode change state
1431 * \param node : the child node that has started
1432 * \return the loop state change
1434 YACS::Event ComposedNode::updateStateOnStartEventFrom(Node *node)
1436 setState(YACS::ACTIVATED);
1440 //! Method used to notify the node that a child node has failed
1441 YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
1443 setState(YACS::FAILED);
1447 void ComposedNode::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
1448 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd)
1450 if((dynamic_cast<DataFlowPort *>(start) || dynamic_cast<DataFlowPort *>(end))
1451 && (dynamic_cast<DataStreamPort *>(start) || dynamic_cast<DataStreamPort *>(end)))
1452 {//cross protocol required : deeper check needed
1454 list<ComposedNode *>::const_iterator iter;
1455 for(iter=pointsOfViewStart.begin();iter!=pointsOfViewStart.end() && !isOK;iter++)
1456 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1457 for(iter=pointsOfViewEnd.begin();iter!=pointsOfViewEnd.end() && !isOK;iter++)
1458 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1460 throw Exception("ComposedNode::checkLinkPossibility : Request for cross protocol link impossible.");
1464 void ComposedNode::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
1468 void ComposedNode::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
1472 void ComposedNode::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
1476 void ComposedNode::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
1480 void ComposedNode::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
1484 void ComposedNode::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
1488 void ComposedNode::loaded()
1491 void ComposedNode::connected()
1495 void ComposedNode::accept(Visitor *visitor)
1497 list<Node *> constituents=edGetDirectDescendants();
1498 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1500 (*iter)->accept(visitor);
1504 void ComposedNode::setProperty(const std::string& name,const std::string& value)
1506 Node::setProperty(name, value);
1509 std::string ComposedNode::getProperty(const std::string& name)
1511 return Node::getProperty(name);
1515 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1516 std::list<InputPort *> ComposedNode::getLocalInputPorts() const
1518 std::list<InputPort *> lip; return lip; // empty list
1521 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1522 std::list<OutputPort *> ComposedNode::getLocalOutputPorts() const
1524 std::list<OutputPort *> lop; return lop; // empty list
1527 bool ComposedNode::isNameAlreadyUsed(const std::string& name) const
1532 void ComposedNode::edUpdateState()
1534 DEBTRACE("ComposedNode::edUpdateState(): " << _state << " " << _modified);
1535 YACS::StatesForNode state=YACS::READY;
1539 checkBasicConsistency();
1544 state=YACS::INVALID;
1545 _errorDetails=e.what();
1547 DEBTRACE("ComposedNode::edUpdateState: " << _errorDetails);
1549 //update children if needed
1550 list<Node *> constituents=edGetDirectDescendants();
1551 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1553 if(!(*iter)->isValid())
1554 state=YACS::INVALID;
1561 std::string ComposedNode::getErrorReport()
1563 DEBTRACE("ComposedNode::getErrorReport: " << getName() << " " << _state);
1564 YACS::StatesForNode effectiveState=getEffectiveState();
1566 if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
1569 std::string report="<error node= " + getName();
1570 switch(effectiveState)
1573 report=report+" state= INVALID";
1576 report=report+" state= ERROR";
1579 report=report+" state= FAILED";
1584 report=report + ">\n" ;
1585 if(_errorDetails != "")
1586 report=report+_errorDetails+"\n";
1588 list<Node *> constituents=edGetDirectDescendants();
1589 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1591 std::string rep=(*iter)->getErrorReport();
1594 report=report+rep+"\n";
1597 report=report+"</error>";
1603 void ComposedNode::checkBasicConsistency() const
1605 DEBTRACE("ComposedNode::checkBasicConsistency");
1606 std::list<InputPort *>::const_iterator iter;
1607 std::list<InputPort *> inports=getLocalInputPorts();
1608 for(iter=inports.begin();iter!=inports.end();iter++)
1609 (*iter)->checkBasicConsistency();
1612 //! Stop all pending activities of the composed node
1614 * This method should be called when a Proc is finished and must be deleted from the YACS server
1616 void ComposedNode::shutdown(int level)
1619 DEBTRACE("ComposedNode::shutdown");
1620 list<Node *> nodes=edGetDirectDescendants();
1621 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1622 (*iter)->shutdown(level);
1625 //! Clean the composed node in case of not clean exit
1627 * This method should be called on a control-c or sigterm
1629 void ComposedNode::cleanNodes()
1631 DEBTRACE("ComposedNode::cleanNodes");
1632 list<Node *> nodes=edGetDirectDescendants();
1633 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1634 (*iter)->cleanNodes();
1637 //! Reset the state of the node and its children depending on the parameter level
1638 void ComposedNode::resetState(int level)
1642 DEBTRACE("ComposedNode::resetState " << level << "," << _state);
1643 if( _state==YACS::ERROR || _state==YACS::FAILED || _state==YACS::ACTIVATED )
1645 Node::resetState(level);
1646 std::list<Node *> nodes=edGetDirectDescendants();
1647 for(std::list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1648 (*iter)->resetState(level);