1 // Copyright (C) 2006-2016 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 throw(YACS::Exception)
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) throw(YACS::Exception)
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 while(iterS!=lwstCmnAnctr)
312 iterS->buildDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
313 iterS=iterS->_father;
315 bool ret=(pO.first)->addInPort(currentPortI);
316 end->edNotifyReferencedBy(pO.second);
320 //! Connect an OutPort to an InPort and add the necessary control link
322 * Connect the ports with a data link (edAddLink) and add
323 * a control flow link between the children of the lowest common ancestor node.
325 * \param start : the OutPort to connect
326 * \param end : the InPort to connect
327 * \return true if a new link has been created, false otherwise.
329 bool ComposedNode::edAddDFLink(OutPort *start, InPort *end) throw(YACS::Exception)
331 Node* n1=start->getNode();
332 Node* n2=end->getNode();
333 DEBTRACE( n1->getName() << ":" << n2->getName())
334 ComposedNode* father=getLowestCommonAncestor(n1,n2);
335 DEBTRACE( "ComposedNode::edAddDFLink: this="<<this->getName()
336 << " father=" << father->getName() )
337 DEBTRACE( "ComposedNode::edAddDFLink: OutPort=" << start->getName()
338 << " InPort=" << end->getName() )
341 bool ret = father->edAddDFLink(start,end); // special treatement for loop
345 throw Exception("Back link authorized only in special context (loop for example)");
347 bool ret= edAddLink(start,end);
350 //add a control link only if nodes are not in the same descendance
351 //if n1 == father (n2 is after n1) : the control link is not needed
352 //if n2 == father (n1 is after n2) : it's a back link authorized only in loop context
353 while(n1->getFather() != father)
355 while(n2->getFather() != father)
361 catch (Exception& ex)
363 // --- remove DF link already created in case of cycle dtection
364 DEBTRACE("Cycle detected, remove CF link");
365 if(start->isAlreadyLinkedWith(end))
366 edRemoveLink(start, end);
373 //! Add a controlflow link between two control ports.
375 * \note Precondition : 'start' AND 'end' are in/outGate contained in a node
376 * in DIRECT descendance of 'this'.
377 * \exception Exception : If a cycle has been detected, or incompatibility
378 * between input and output, or 'start'/'end' is/are NOT in/outputPort contained
379 * in a node in descendance of 'this', or a mutilple link to an input not
381 * \return true if a new link has been created, false otherwise.
383 bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(YACS::Exception)
385 Node* n1=start->getNode();
386 Node* n2=end->getNode();
388 throw Exception("ComposedNode::edAddLink: can not add a control link to a node with itself",1);
389 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
391 throw Exception("ComposedNode::edAddLink: Trying to add CF link on orphan nodes.");
394 checkInMyDescendance(father);
395 return father->edAddLink(start,end);
397 bool ret=start->edAddInGate(end);
401 checkNoCyclePassingThrough(end->getNode());
403 catch (Exception& ex)
405 // --- remove created CF link in case of cycle detection
406 DEBTRACE("Cycle detected, remove CF link");
407 edRemoveCFLink(start->getNode(), end->getNode());
413 //! Add a controlflow link between two nodes.
415 * Add a controlflow link between two nodes by calling edAddLink on their control ports
417 bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE) throw(YACS::Exception)
419 return edAddLink(nodeS->getOutGate(),nodeE->getInGate());
422 //! Remove a controlflow link.
423 void ComposedNode::edRemoveCFLink(Node *nodeS, Node *nodeE) throw(YACS::Exception)
425 edRemoveLink(nodeS->getOutGate(),nodeE->getInGate());
428 //! Remove a dataflow link.
430 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
432 * \exception Exception : If the specified link does not exist. The content of Exception
433 * is different in accordance with the link from 'start' to 'end'
434 * implies DF/DS gateway.
437 void ComposedNode::edRemoveLink(OutPort *start, InPort *end) throw(YACS::Exception)
439 if(!start->isAlreadyLinkedWith(end))
440 throw Exception("ComposedNode::edRemoveLink : unexisting link");
441 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
442 checkInMyDescendance(lwstCmnAnctr);
443 list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
444 list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
446 // --- Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created
448 ComposedNode *iterS=start->getNode()->_father;
449 pair<OutPort *,OutPort *> currentPortO(start,start);
450 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > > needsToDestroyO;
452 Node *nodeOTemp=start->getNode();
453 if(*nodeOTemp<*lwstCmnAnctr)
455 iterS=nodeOTemp->_father;
456 while(iterS!=lwstCmnAnctr)
461 what << "ComposedNode::edRemoveLink: "
462 << start->getNode()->getName() << "." <<start->getName() << "->"
463 << end->getNode()->getName() << "." << end->getName();
464 throw Exception(what.str());
466 OutPort *tmp=currentPortO.first;
467 iterS->getDelegateOf(currentPortO, end, allAscendanceOfNodeEnd);
468 needsToDestroyO.push_back(pair< ComposedNode * , pair < OutPort* , OutPort *> >(iterS,pair<OutPort* , OutPort *> (tmp,currentPortO.first)));
469 iterS=iterS->_father;
472 Node *nodeTemp=end->getNode();
473 InPort * currentPortI=end;
474 if(*nodeTemp<*lwstCmnAnctr)
476 iterS=nodeTemp->_father;
477 while(iterS!=lwstCmnAnctr)
482 what << "ComposedNode::edRemoveLink: "
483 << start->getNode()->getName() << "." <<start->getName() << "->"
484 << end->getNode()->getName() << "." << end->getName();
485 throw Exception(what.str());
487 iterS->getDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
488 iterS=iterS->_father;
491 // --- End of test for evt intermediate ports created
493 (currentPortO.first)->removeInPort(currentPortI,false);
495 (currentPortO.second)->getAllRepresented(repr);
497 end->edNotifyDereferencedBy(currentPortO.second);
499 // --- Performing deletion of intermediate ports
501 iterS=start->getNode()->_father;
502 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > >::reverse_iterator iter;
503 for(iter=needsToDestroyO.rbegin();iter!=needsToDestroyO.rend();iter++)
504 (*iter).first->releaseDelegateOf(((*iter).second).first, ((*iter).second).second, end,allAscendanceOfNodeEnd);
505 nodeTemp=end->getNode();
506 if(*nodeTemp<*lwstCmnAnctr)
508 iterS=end->getNode()->_father;
510 while(iterS!=lwstCmnAnctr)
512 iterS->releaseDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
513 iterS=iterS->_father;
518 //! Remove a controlflow link.
519 void ComposedNode::edRemoveLink(OutGate *start, InGate *end) throw(YACS::Exception)
521 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
523 throw Exception("edRemoveLink : nodes not in direct descendance of this");
524 start->edRemoveInGate(end);
527 bool ComposedNode::edAddChild(Node *DISOWNnode) throw(YACS::Exception)
529 return false; // --- reimplemented in derived classes
532 //! Remove a child node.
533 void ComposedNode::edRemoveChild(Node *node) throw(YACS::Exception)
537 if (node->_father!=this)
539 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
540 throw Exception(what);
542 node->edDisconnectAllLinksWithMe();
544 //set _modified flag so edUpdateState() can refresh state
548 //! Splits name globalName in 2 parts using separator.
550 * \note 'priority' specifies if during search process of 'separator' the max part is
551 * for 'firstPart' (priority=true) or 'lastPart' (priority=false).
553 * \throw Exception : 'lastPart' or 'firstPart' is empty.
554 * \return true if split process succeeds false otherwise (typically when character
555 * separator was not found).
557 bool ComposedNode::splitNamesBySep(const std::string& globalName, const char separator[],
558 std::string& firstPart, std::string& lastPart, bool priority) throw(YACS::Exception)
560 const string delims(separator);
561 string portName, nodeName;
562 string::size_type idx;
564 idx = globalName.find_last_of(delims);
566 idx = globalName.find_first_of(delims);
567 if (idx == string::npos)
569 firstPart=globalName;
573 firstPart = globalName.substr(0,idx);
574 lastPart = globalName.substr(idx+1);
575 if ((firstPart.empty()) || (lastPart.empty()))
577 string what("the name "); what+= globalName ; what+=" is not a valid port name";
578 throw Exception(what);
583 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfInternalLinks() const
585 vector< pair<OutPort *, InPort *> > ret;
586 list<OutPort *> temp=getSetOfOutPort();
587 for(list<OutPort *>::const_iterator iter2=temp.begin();iter2!=temp.end();iter2++)
589 set<InPort *> temp2=(*iter2)->edSetInPort();
590 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
591 if(isInMyDescendance((*iter3)->getNode()))
592 ret.push_back(pair<OutPort *, InPort *>((*iter2),(*iter3)));
597 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfLinksLeavingCurrentScope() const
599 vector< pair<OutPort *, InPort *> > ret;
600 std::set<OutPort *> ports=getAllOutPortsLeavingCurrentScope();
601 for(set<OutPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
603 set<InPort *> temp2=(*iter2)->edSetInPort();
604 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
605 if(!isInMyDescendance((*iter3)->getNode()))
606 ret.push_back(pair<OutPort *, InPort *>(*iter2,*iter3));
611 void ComposedNode::checkConsistency(LinkInfo& info) const throw(YACS::Exception)
614 info.setPointOfView((ComposedNode *)this);
615 performCFComputations(info);
616 list<InputPort *> setOfInToTest=getSetOfInputPort();
617 for(list<InputPort *>::iterator iter1=setOfInToTest.begin();iter1!=setOfInToTest.end();iter1++)
619 vector<OutPort *> candidateForAdvCheck;
620 set<OutPort *> outPorts=(*iter1)->edSetOutPort();
621 //Filtering among outPorts, which of them, are candidates to fill *iter1 at the current scope.
622 for(set<OutPort *>::iterator iter2=outPorts.begin();iter2!=outPorts.end();iter2++)
624 (*iter2)->checkConsistency(info);
625 ComposedNode *manager=getLowestCommonAncestor((*iter2)->getNode(),(*iter1)->getNode());
626 if(isInMyDescendance(manager))
627 candidateForAdvCheck.push_back(*iter2);
629 if(!candidateForAdvCheck.empty())
630 //End of filtering. Now regarding CF constraints for the current InPutPort.
633 checkLinksCoherenceRegardingControl(candidateForAdvCheck,*iter1,info);
635 catch(YACS::Exception& ex)
637 std::string what=ex.what();
638 what += "\nfor input port: ";
639 what += (*iter1)->getNode()->getName();
641 what += (*iter1)->getName();
643 destructCFComputations(info);
644 throw YACS::Exception(what);
648 if(!(*iter1)->canBeNull() && !(*iter1)->edIsManuallyInitialized())
649 info.pushErrLink(0,*iter1,E_NEVER_SET_INPUTPORT);
651 destructCFComputations(info);
655 * This method check that G1 <- G2 <- G3 <- G1 does not happened.
656 * Typically called by methods that set a hierarchy (Bloc::edAddChild, Loop::edSetNode, ...).
658 void ComposedNode::checkNoCrossHierachyWith(Node *node) const throw(YACS::Exception)
660 ComposedNode *nodeC=dynamic_cast<ComposedNode *>(node);
663 list<ComposedNode *> ascendants=getAllAscendanceOf();
664 if(find(ascendants.begin(),ascendants.end(),nodeC)!=ascendants.end())
666 const char what[]="ComposedNode::checkNoCrossHierachyWith : ComposedNode with name \"";
667 string stream(what); stream+=node->getName(); stream+="\" is already in hierarchy ascendance of node with name \"";
668 stream+=_name; stream+="\" ; So it can't be now in its descendance !";
669 throw Exception(stream);
673 //! perform \b recursively all CF computations.
674 void ComposedNode::performCFComputations(LinkInfo& info) const
676 list<Node *> nodes=edGetDirectDescendants();
677 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
678 if(dynamic_cast<ComposedNode *>(*iter))
679 ((ComposedNode *)(*iter))->performCFComputations(info);
682 //! destroy \b recursively all results of initial computations.
683 void ComposedNode::destructCFComputations(LinkInfo& info) const
685 list<Node *> nodes=edGetDirectDescendants();
686 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
687 if(dynamic_cast<ComposedNode *>(*iter))
688 ((ComposedNode *)(*iter))->destructCFComputations(info);
692 * Returns the lowest Node (Elementary or Composed) (is sense of hierachy level ( operator< ) ) containing all 'ports'.
693 * Typically use in consistency computation.
694 * Precondition : 'ports' \b must contain at least one element. All elements of 'ports' should be in descendance of 'this'.
696 Node *ComposedNode::getLowestNodeDealingAll(const std::list<OutPort *>& ports) const
698 list< OutPort *>::const_iterator iter=ports.begin();
699 Node *ret=(*iter)->getNode();
701 for(;iter!=ports.end();iter++)
703 Node *tmp=(*iter)->getNode();
711 * call it only for 'starts' to 'end' links \b DEALED by 'this'.
713 void ComposedNode::checkLinksCoherenceRegardingControl(const std::vector<OutPort *>& starts, InputPort *end, LinkInfo& info) const throw(YACS::Exception)
715 map < ComposedNode *, list<OutPort *>, SortHierarc > outputs;//forward link classical
716 vector<OutPort *> outputsCross;//forward link cross
717 map < ComposedNode *, list<OutPort *>, SortHierarc > outputsBw;//backward
718 vector<OutPort *>::const_iterator iter1;
719 //vector<DataPort *> history=((*iter1).second)[0]->calculateHistoryOfLinkWith(end);
720 //DataPort *cross=DataPort::isCrossingType(history);
721 for(iter1=starts.begin();iter1!=starts.end();iter1++)
723 ComposedNode *manager=getLowestCommonAncestor((*iter1)->getNode(),end->getNode());
724 manager->checkControlDependancy((*iter1), end, false, outputs, outputsCross, outputsBw, info);
726 //Ok now let's regarding outputs all combinations : (outputs.size())*(outputs.size()-1)/2
727 unsigned char isAlreadyFed=FREE_ST;
728 //Dealing excusively with DS. Level is useless here because simultaneity is required for DS.
729 if(outputsCross.size()>0)
731 isAlreadyFed=FED_DS_ST;
732 if(outputsCross.size()>1)
733 for(vector< OutPort *>::const_iterator iter1=outputsCross.begin();iter1!=(outputsCross.end()-2);iter1++)
734 info.pushErrLink(*iter1,end,E_COLLAPSE_DS);
736 map < ComposedNode *, list<OutPort *>, SortHierarc >::iterator iter3=outputs.begin();
737 for(;iter3!=outputs.end();iter3++)
738 ((*iter3).first)->checkCFLinks((*iter3).second,end,isAlreadyFed,true,info);
739 if(isAlreadyFed==FREE_ST)
740 if(!end->edIsManuallyInitialized())
741 info.pushErrLink(0,end,E_ONLY_BACKWARD_DEFINED);
742 isAlreadyFed=FREE_ST;
744 map < ComposedNode *, list<OutPort *>, SortHierarc >::reverse_iterator iter5=outputsBw.rbegin();
745 for(;iter5!=outputsBw.rend();iter5++)
746 ((*iter5).first)->checkCFLinks((*iter5).second,end,isAlreadyFed,false,info);
750 * Internal method during CF links. This methode is in charge to statuate on links consistency in the case
751 * that no control flow defined by user is set.
753 void ComposedNode::solveObviousOrDelegateCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
755 static const char what[]="ComposedNode::solveObviousOrDelegateCFLinks : Internal error occured - uncorrect hierarchy detected !";
758 if(alreadyFed==FREE_ST)
761 info.pushInfoLink(*(starts.begin()),end,I_BACK);
764 else if(alreadyFed==FED_ST)
765 info.pushInfoLink(*(starts.begin()),end,direction ? I_USELESS : I_BACK_USELESS);
767 info.pushErrLink(*(starts.begin()),end,E_COLLAPSE_DFDS);
771 Node *levelOfDecision=getLowestNodeDealingAll(starts);
772 if(levelOfDecision==this)
773 throw Exception(what);
774 if(dynamic_cast<ElementaryNode *>(levelOfDecision))
777 if(alreadyFed==FREE_ST || alreadyFed==FED_ST)
779 if(alreadyFed==FREE_ST)
781 reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL;
785 reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS;
786 for(list< OutPort *>::const_iterator iter=starts.begin();iter!=starts.end();iter++)
787 info.pushWarnLink(*iter,end,reason);
791 ((ComposedNode *)levelOfDecision)->checkCFLinks(starts,end,alreadyFed,direction,info);
795 //! check control flow links
797 * \param starts If different of 0, must aggregate at leat \b 1 element.
799 * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
800 * \param direction If true : forward direction else backward direction.
801 * \param info : informations collectedduring the check
803 void ComposedNode::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
805 static const char what[]="ComposedNode::checkCFLinks : Internal error occured - uncorrect hierarchy detected !";
806 Node *nodeEnd=isInMyDescendance(end->getNode());
808 return solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
809 //This case is typically dedicated when direct son is ElementaryNode and self link is defined on this.
810 if(!dynamic_cast<ElementaryNode *>(nodeEnd))
811 throw Exception(what);
813 list< OutPort *>::const_iterator iter=starts.begin();
814 Node *nodeStart=(*iter)->getNode();
816 if(nodeEnd!=nodeStart)
817 throw Exception(what);
819 for(;iter!=starts.end();iter++)
820 if((*iter)->getNode()!=nodeStart)
821 throw Exception(what);
822 //Ok at this step we are sure that we have back links on the same elementary node.
824 for(iter=starts.begin();iter!=starts.end();iter++)
825 info.pushWarnLink(*iter,end,W_BACK_COLLAPSE_EL);
826 else//here no need to look at 'alreadyFed' var because it is waranteed to be equal to FREE_ST by construction.
827 info.pushInfoLink(*(starts.begin()),end,I_BACK);
831 std::vector< std::pair<InPort *, OutPort *> > ComposedNode::getSetOfLinksComingInCurrentScope() const
833 vector< pair<InPort *, OutPort *> > ret;
834 set<InPort *> ports=getAllInPortsComingFromOutsideOfCurrentScope();
835 for(set<InPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
837 set<OutPort *> temp2=(*iter2)->edSetOutPort();
838 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
840 if(isInMyDescendance((*iter3)->getNode()))continue;
841 std::set<OutPort *> trueOutPorts;
842 (*iter3)->getAllRepresented(trueOutPorts);
843 for(std::set<OutPort *>::iterator iter4=trueOutPorts.begin();iter4!=trueOutPorts.end();++iter4)
844 ret.push_back(pair<InPort *, OutPort *>(*iter2,*iter4));
850 //! List all output ports of children nodes that are linked to out of scope input ports
852 * \note List all output ports of nodes sons of 'this' that are linked to input ports
853 * of nodes not in descendance of 'this'.
854 * This method contrary to getAllInPortsComingFromOutsideOfCurrentScope is NOT virtual
855 * because for the moment all daughter classes have no more hidden YACS::ENGINE::OutPort.
857 std::set<OutPort *> ComposedNode::getAllOutPortsLeavingCurrentScope() const
860 list<OutPort *> temp=getSetOfOutPort();
861 for(list<OutPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
863 set<InPort *> temp2=(*iter2)->edSetInPort();
864 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
865 if(!isInMyDescendance((*iter3)->getNode()))
874 //! List all input ports that are linked to out of scope ports
877 * List all input ports of 'this' so that, for each it exists at least 1 link coming
878 * from outside to it.
881 std::set<InPort *> ComposedNode::getAllInPortsComingFromOutsideOfCurrentScope() const
884 list<InPort *> temp=getSetOfInPort();
885 for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
887 set<OutPort *> temp2=(*iter2)->edSetOutPort();
888 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
890 if(!isInMyDescendance((*iter3)->getNode()))
899 void ComposedNode::edDisconnectAllLinksWithMe()
903 Node::edDisconnectAllLinksWithMe();
906 vector< pair<OutPort *, InPort *> > linksToDestroy=getSetOfLinksLeavingCurrentScope();
907 vector< pair<OutPort *, InPort *> >::iterator iter;
908 for(iter=linksToDestroy.begin();iter!=linksToDestroy.end();iter++)
911 (*iter).first->removeInPort((*iter).second,true);
914 vector< pair<InPort *, OutPort *> > linksToDestroy2=getSetOfLinksComingInCurrentScope();
915 vector< pair<InPort *, OutPort *> >::iterator iter2;
916 for(iter2=linksToDestroy2.begin();iter2!=linksToDestroy2.end();iter2++)
919 (*iter2).second->removeInPort((*iter2).first,true);
923 ComposedNode *ComposedNode::getRootNode() const throw(YACS::Exception)
926 return (ComposedNode *)this;
927 return Node::getRootNode();
930 //! Check that Node 'node' is already a direct son of this.
931 bool ComposedNode::isNodeAlreadyAggregated(const Node *node) const
933 list<ComposedNode *> nodeAncestors = node->getAllAscendanceOf();
934 return find(nodeAncestors.begin(),nodeAncestors.end(),(ComposedNode *)this)!=nodeAncestors.end();
937 //! Returns the parent of a node that is the direct child of this node
939 * \note if 'nodeToTest'=='this' this is returned. Else if 'nodeToTest' is in descendance of
940 * 'this' the direct son is returned.
941 * Else 0 is returned.
943 * \param nodeToTest : the node to check
945 Node *ComposedNode::isInMyDescendance(Node *nodeToTest) const
949 if((ComposedNode *)nodeToTest==this)
951 Node *iterBack=nodeToTest;
952 ComposedNode *iter=nodeToTest->_father;
953 while(iter!=0 && iter!=this)
964 string ComposedNode::getChildName(const Node* node) const throw(YACS::Exception)
966 string nodeName=node->getQualifiedName();
967 if (!isNodeAlreadyAggregated(node))
969 if (node->getName() == "thisIsAFakeNode")
971 string child = node->getName()+".thisIsAFakeNode";
976 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
977 throw Exception(what);
981 const Node *father = node->_father;
982 while (father != this)
984 nodeName = father->getQualifiedName() + SEP_CHAR_BTW_LEVEL + nodeName;
985 father = father->_father;
990 std::string ComposedNode::getMyQualifiedName(const Node *directSon) const
992 return directSon->getName();
995 Node *ComposedNode::getChildByName(const std::string& name) const throw(YACS::Exception)
997 string potentiallyDirectSonName, remainsPath;
998 bool forwardNeeded=ComposedNode::splitNamesBySep(name, SEP_CHAR_BTW_LEVEL,
999 potentiallyDirectSonName,remainsPath,false);
1000 Node *child=getChildByShortName(potentiallyDirectSonName);
1004 return child->getChildByName(remainsPath);
1007 //! Check if a node is in the descendance of this node
1009 * \note Check that 'nodeToTest' is in descendance of 'this' OR equal to 'this'
1010 * \exception Exception : If 'nodeToTest' is NOT in descendance of 'this' AND not equal to 'this'
1011 * \param nodeToTest : the node to check
1013 void ComposedNode::checkInMyDescendance(Node *nodeToTest) const throw(YACS::Exception)
1015 const char whatC[]=" is not the descendance of node ";
1018 string what("node "); what+= nodeToTest->getName(); what+=" ";
1019 what+=whatC; what+=_name;
1020 throw Exception(what);
1022 if((ComposedNode *)nodeToTest==this)
1024 ComposedNode *iter=nodeToTest->_father;
1025 while(iter!=0 && iter!=this)
1029 string what("node "); what+= nodeToTest->getName(); what+=" ";
1030 what+=whatC; what+=_name;
1031 throw Exception(what);
1035 //! Retrieves the lowest common ancestor of 2 nodes
1038 * \note Retrieves the lowest common ancestor of 'node1' AND 'node2'.
1039 * If 'node1' or 'node2' are both or indiscriminately instances of ComposedNode and that
1040 * 'node1' is in descendance of 'node2' (resp. 'node2' in descendance of 'node1')
1041 * 'node2' is returned (resp. 'node1').
1042 * \exception Exception : if 'node1' and 'node2' do not share the same genealogy.
1043 * \return The lowest common ancestor if it exists.
1046 ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) throw(YACS::Exception)
1048 const char what[]="The two nodes do not share the same genealogy";
1049 if(node1==0 || node2==0)
1050 throw Exception(what);
1052 if(dynamic_cast<ComposedNode *>(node1))
1053 temp=(ComposedNode *)node1;//->_father;
1055 temp=(ComposedNode *)node1->_father;
1056 set<ComposedNode *> s;
1063 if(dynamic_cast<ComposedNode *>(node2))
1064 temp=(ComposedNode *)node2;//->_father;
1066 temp=(ComposedNode *)node2->_father;
1067 set<ComposedNode *>::iterator iter=s.find(temp);
1068 while(temp && iter==s.end())
1074 throw Exception(what);
1079 * Same as getLowestCommonAncestor method except that absolute string representation is considered here instead of instances.
1081 std::string ComposedNode::getLowestCommonAncestorStr(const std::string& node1, const std::string& node2)
1084 std::size_t it1_b(0),it1_e(0),it2_b(0),it2_e(0);
1085 while(it1_b!=std::string::npos && it2_b!=std::string::npos)
1087 it1_e=node1.find(SEP_CHAR_BTW_LEVEL,it1_b);
1088 it2_e=node2.find(SEP_CHAR_BTW_LEVEL,it2_b);
1089 if(it1_e!=it2_e && it1_e!=std::string::npos && it2_e!=std::string::npos)
1091 std::string elt1(node1.substr(it1_b,it1_e-it1_b)),elt2(node2.substr(it2_b,it2_e-it2_b));
1095 ret+=SEP_CHAR_BTW_LEVEL;
1097 it1_b=node1.find_first_not_of(SEP_CHAR_BTW_LEVEL,it1_e);
1098 it2_b=node2.find_first_not_of(SEP_CHAR_BTW_LEVEL,it2_e);
1104 * This method recursively all redundant control links in this.
1106 void ComposedNode::removeRecursivelyRedundantCL()
1108 std::list<Node *> dd(edGetDirectDescendants());
1109 for(std::list<Node *>::const_iterator it=dd.begin();it!=dd.end();it++)
1111 ComposedNode *elt(dynamic_cast<ComposedNode *>(*it));
1113 elt->removeRecursivelyRedundantCL();
1117 list<ElementaryNode *> ComposedNode::getRecursiveConstituents() const
1119 list<ElementaryNode *> ret;
1120 list<Node *> setOfNode=edGetDirectDescendants();
1121 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1123 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1124 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1129 //! Idem getAllRecursiveNodes, but this node is NOT included.
1130 list<Node *> ComposedNode::getAllRecursiveConstituents()
1133 list<Node *> setOfNode=edGetDirectDescendants();
1134 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1136 if ( dynamic_cast<ComposedNode*> (*iter) )
1138 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveConstituents();
1139 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1140 ret.push_back(*iter);
1144 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1145 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1151 //! Get all children nodes elementary and composed including this node
1152 list<Node *> ComposedNode::getAllRecursiveNodes()
1155 list<Node *> setOfNode=edGetDirectDescendants();
1156 for(list<Node *>::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1158 if ( dynamic_cast<ElementaryNode*> (*iter) )
1160 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1161 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1165 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveNodes();
1166 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1169 ret.push_back(this);
1174 //! Get the progress weight for all elementary nodes
1176 * Only elementary nodes have weight. A simple composed node only sum up weight of all his descendants
1177 * (working is different for loop or switch nodes)
1179 list<ProgressWeight> ComposedNode::getProgressWeight() const
1181 list<ProgressWeight> ret;
1182 list<Node *> setOfNode=edGetDirectDescendants();
1183 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1185 list<ProgressWeight> myCurrentSet=((ComposedNode*)(*iter))->getProgressWeight();
1186 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1191 //! Get the input port name
1193 * get the input port name used by the current node, recursively built with children names.
1196 string ComposedNode::getInPortName(const InPort * inPort) const throw(YACS::Exception)
1198 return getPortName<InPort>(inPort);
1201 string ComposedNode::getOutPortName(const OutPort *outPort) const throw(YACS::Exception)
1203 return getPortName<OutPort>(outPort);
1206 int ComposedNode::getNumberOfInputPorts() const
1208 list<Node *> constituents=edGetDirectDescendants();
1210 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1211 ret+=(*iter)->getNumberOfInputPorts();
1215 int ComposedNode::getNumberOfOutputPorts() const
1217 list<Node *> constituents=edGetDirectDescendants();
1219 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1220 ret+=(*iter)->getNumberOfOutputPorts();
1224 list<InputPort *> ComposedNode::getSetOfInputPort() const
1226 list<Node *> constituents=edGetDirectDescendants();
1227 list<InputPort *> ret;
1228 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1230 list<InputPort *> currentsPorts=(*iter)->getSetOfInputPort();
1231 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1236 list<OutputPort *> ComposedNode::getSetOfOutputPort() const
1238 list<Node *> constituents=edGetDirectDescendants();
1239 list<OutputPort *> ret;
1240 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1242 list<OutputPort *> currentsPorts=(*iter)->getSetOfOutputPort();
1243 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1248 list<InputDataStreamPort *> ComposedNode::getSetOfInputDataStreamPort() const
1250 list<Node *> constituents=edGetDirectDescendants();
1251 list<InputDataStreamPort *> ret;
1252 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1254 list<InputDataStreamPort *> currentsPorts=(*iter)->getSetOfInputDataStreamPort();
1255 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1260 list<OutputDataStreamPort *> ComposedNode::getSetOfOutputDataStreamPort() const
1262 list<Node *> constituents=edGetDirectDescendants();
1263 list<OutputDataStreamPort *> ret;
1264 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1266 list<OutputDataStreamPort *> currentsPorts=(*iter)->getSetOfOutputDataStreamPort();
1267 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1272 OutPort *ComposedNode::getOutPort(const std::string& name) const throw(YACS::Exception)
1274 string portName, nodeName;
1275 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1277 Node *child = getChildByShortName(nodeName);
1278 return child->getOutPort(portName);
1282 string what("ComposedNode::getOutPort : the port with name "); what+=name; what+=" does not exist on the current level";
1283 throw Exception(what);
1287 //! Get an input port given its name
1289 * Contrary to YACS::ENGINE::ComposedNode::getOutputPort, this method is \b NOT recursive
1290 * and so the leaf of type ElementaryNode aggregating
1291 * this InputPort is directly invoked.
1293 InputPort * ComposedNode::getInputPort(const std::string& name) const throw(YACS::Exception)
1296 return Node::getInputPort(name);
1298 catch(Exception& e) {}
1300 string portName, nodeName;
1301 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1303 Node *child = getChildByName(nodeName);
1304 return child->getInputPort(portName);
1308 string what("ComposedNode::getInputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1309 throw Exception(what);
1313 //! Get an output port given its name
1315 * Contrary to YACS::ENGINE::ComposedNode::getInputPort, this method is recursive and go
1316 * down hierarchy step by step to complete its work.
1318 OutputPort * ComposedNode::getOutputPort(const std::string& name) const throw(YACS::Exception)
1320 string portName, nodeName;
1321 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1323 Node *child = getChildByShortName(nodeName);
1324 return child->getOutputPort(portName);
1328 string what("ComposedNode::getOutputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1329 throw Exception(what);
1333 InputDataStreamPort *ComposedNode::getInputDataStreamPort(const std::string& name) const throw(YACS::Exception)
1335 string portName, nodeName;
1336 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1338 Node *child = getChildByName(nodeName);
1339 return child->getInputDataStreamPort(portName);
1343 string what("ComposedNode::getInputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1344 throw Exception(what);
1348 OutputDataStreamPort *ComposedNode::getOutputDataStreamPort(const std::string& name) const throw(YACS::Exception)
1350 string portName, nodeName;
1351 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1353 Node *child = getChildByName(nodeName);
1354 return child->getOutputDataStreamPort(portName);
1358 string what("ComposedNode::getOutputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1359 throw Exception(what);
1363 //! Update node state on receiving event from a node
1366 * \note Runtime called method. Perform, the state updating, from the son node 'node'
1367 * emitting the event 'event' (among Executor static const var).
1368 * WARNING Precondition : this == node->_father
1369 * \return The event (among Executor static const var) destinated to this->_father node
1370 * to perform eventually up level update.
1372 * Calls ComposedNode::updateStateOnStartEventFrom if event is YACS::START
1374 * Calls ComposedNode::updateStateOnFinishedEventFrom if event is YACS::FINISH
1376 * Called by ComposedNode::notifyFrom
1378 YACS::Event ComposedNode::updateStateFrom(Node *node, //* I : node emitting event
1379 YACS::Event event, //* I : event emitted
1380 const Executor *execInst
1383 DEBTRACE("updateStateFrom: " << node->getName() << " " << event);
1389 return updateStateOnStartEventFrom(node);
1392 return updateStateOnFinishedEventFrom(node);
1395 return updateStateOnFailedEventFrom(node,execInst);
1398 return YACS::NOEVENT;//TODO unexpected type of event
1402 catch(YACS::Exception& ex)
1404 //unexpected exception: probably a bug in engine
1405 //try to keep a consistent global state
1406 DEBTRACE( "updateStateFrom: " << ex.what() );
1407 _errorDetails="Internal error: ";
1408 _errorDetails=_errorDetails + ex.what();
1409 setState(YACS::ERROR);
1415 //unexpected exception: probably a bug in engine
1416 //try to keep a consistent global state
1417 setState(YACS::ERROR);
1423 //! Method used to notify the node that a child node has started
1425 * Update the ComposedNode state and return the ComposedNode change state
1427 * \param node : the child node that has started
1428 * \return the loop state change
1430 YACS::Event ComposedNode::updateStateOnStartEventFrom(Node *node)
1432 setState(YACS::ACTIVATED);
1436 //! Method used to notify the node that a child node has failed
1437 YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node, const Executor *execInst)
1439 setState(YACS::FAILED);
1443 void ComposedNode::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
1444 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
1446 if((dynamic_cast<DataFlowPort *>(start) || dynamic_cast<DataFlowPort *>(end))
1447 && (dynamic_cast<DataStreamPort *>(start) || dynamic_cast<DataStreamPort *>(end)))
1448 {//cross protocol required : deeper check needed
1450 list<ComposedNode *>::const_iterator iter;
1451 for(iter=pointsOfViewStart.begin();iter!=pointsOfViewStart.end() && !isOK;iter++)
1452 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1453 for(iter=pointsOfViewEnd.begin();iter!=pointsOfViewEnd.end() && !isOK;iter++)
1454 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1456 throw Exception("ComposedNode::checkLinkPossibility : Request for cross protocol link impossible.");
1460 void ComposedNode::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
1464 void ComposedNode::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
1468 void ComposedNode::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1472 void ComposedNode::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1476 void ComposedNode::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1480 void ComposedNode::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1484 void ComposedNode::loaded()
1487 void ComposedNode::connected()
1491 void ComposedNode::accept(Visitor *visitor)
1493 list<Node *> constituents=edGetDirectDescendants();
1494 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1496 (*iter)->accept(visitor);
1500 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1501 std::list<InputPort *> ComposedNode::getLocalInputPorts() const
1503 std::list<InputPort *> lip; return lip; // empty list
1506 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1507 std::list<OutputPort *> ComposedNode::getLocalOutputPorts() const
1509 std::list<OutputPort *> lop; return lop; // empty list
1512 bool ComposedNode::isNameAlreadyUsed(const std::string& name) const
1517 void ComposedNode::edUpdateState()
1519 DEBTRACE("ComposedNode::edUpdateState(): " << _state << " " << _modified);
1520 YACS::StatesForNode state=YACS::READY;
1524 checkBasicConsistency();
1529 state=YACS::INVALID;
1530 _errorDetails=e.what();
1532 DEBTRACE("ComposedNode::edUpdateState: " << _errorDetails);
1534 //update children if needed
1535 list<Node *> constituents=edGetDirectDescendants();
1536 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1538 if(!(*iter)->isValid())
1539 state=YACS::INVALID;
1546 std::string ComposedNode::getErrorReport()
1548 DEBTRACE("ComposedNode::getErrorReport: " << getName() << " " << _state);
1549 YACS::StatesForNode effectiveState=getEffectiveState();
1551 if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
1554 std::string report="<error node= " + getName();
1555 switch(effectiveState)
1558 report=report+" state= INVALID";
1561 report=report+" state= ERROR";
1564 report=report+" state= FAILED";
1569 report=report + ">\n" ;
1570 if(_errorDetails != "")
1571 report=report+_errorDetails+"\n";
1573 list<Node *> constituents=edGetDirectDescendants();
1574 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1576 std::string rep=(*iter)->getErrorReport();
1579 report=report+rep+"\n";
1582 report=report+"</error>";
1588 void ComposedNode::checkBasicConsistency() const throw(YACS::Exception)
1590 DEBTRACE("ComposedNode::checkBasicConsistency");
1591 std::list<InputPort *>::const_iterator iter;
1592 std::list<InputPort *> inports=getLocalInputPorts();
1593 for(iter=inports.begin();iter!=inports.end();iter++)
1594 (*iter)->checkBasicConsistency();
1597 //! Stop all pending activities of the composed node
1599 * This method should be called when a Proc is finished and must be deleted from the YACS server
1601 void ComposedNode::shutdown(int level)
1604 DEBTRACE("ComposedNode::shutdown");
1605 list<Node *> nodes=edGetDirectDescendants();
1606 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1607 (*iter)->shutdown(level);
1610 //! Clean the composed node in case of not clean exit
1612 * This method should be called on a control-c or sigterm
1614 void ComposedNode::cleanNodes()
1616 DEBTRACE("ComposedNode::cleanNodes");
1617 list<Node *> nodes=edGetDirectDescendants();
1618 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1619 (*iter)->cleanNodes();
1622 //! Reset the state of the node and its children depending on the parameter level
1623 void ComposedNode::resetState(int level)
1627 DEBTRACE("ComposedNode::resetState " << level << "," << _state);
1628 if( _state==YACS::ERROR || _state==YACS::FAILED || _state==YACS::ACTIVATED )
1630 Node::resetState(level);
1631 std::list<Node *> nodes=edGetDirectDescendants();
1632 for(std::list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1633 (*iter)->resetState(level);