1 // Copyright (C) 2006-2012 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.
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 bool ComposedNode::isFinished()
114 if(_state==YACS::DONE)return true;
115 if(_state==YACS::ERROR)return true;
116 if(_state==YACS::FAILED)return true;
117 if(_state==YACS::DISABLED)return true;
121 void ComposedNode::init(bool start)
126 std::string ComposedNode::getName() const
128 return Node::getName();
131 std::string ComposedNode::getTaskName(Task *task) const
133 return getChildName(dynamic_cast<ElementaryNode *>(task));
136 //! Essentially for test. Use checkDeploymentTree instead to be sure that returned DeploymentTree is consistent.
137 DeploymentTree ComposedNode::getDeploymentTree() const
140 list< ElementaryNode * > tasks=getRecursiveConstituents();
141 for(list< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++)
142 ret.appendTask(*iter,(*iter)->getDynClonerIfExists(this));
146 //! Perform check of deployment consistency of the current graph.
148 * \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.
150 DeploymentTree ComposedNode::checkDeploymentTree(bool deep) const throw(YACS::Exception)
153 list< ElementaryNode * > tasks=getRecursiveConstituents();
154 for(list< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++)
156 switch(ret.appendTask(*iter,(*iter)->getDynClonerIfExists(this)))
158 case DeploymentTree::DUP_TASK_NOT_COMPATIBLE_WITH_EXISTING_TREE:
160 string what("ComposedNode::checkDeploymentTree : ServiceNode with name \""); what+=(*iter)->getName();
161 what+="\" coexists in a component with an another Task which context is incompatible with it.";
162 throw Exception(what);
164 case DeploymentTree::DEPLOYABLE_BUT_NOT_SPECIFIED :
168 string what("ComposedNode::checkDeploymentTree : ServiceNode with name \""); what+=(*iter)->getName();
169 what+="\" is deployable but no component is specified on it.";
170 throw Exception(what);
178 std::vector<Task *> ComposedNode::getNextTasks(bool& isMore)
187 //! Notify the node a task has emitted an event
190 * \note Runtime called method. Overloads the Scheduler::notifyFrom abstract method.
191 * Typically Called in Executor (in a parallel thread or not) by the Task 'task'
192 * to inform the scheduler that an event coded 'event' (in Executor static const var) happened.
193 * Contrary to updateStateFrom several levels may exist between 'sender' and 'this'.
195 * \param sender : task emitting event
196 * \param event : event emitted
198 * Called by Executor::functionForTaskExecution on YACS::FINISH event
200 * Called by Executor::launchTask on YACS::START event
202 * Calls ComposedNode::updateStateFrom to update state from task to root node
204 void ComposedNode::notifyFrom(const Task *sender, //* I : task emitting event
205 YACS::Event event //* I : event emitted
208 DEBTRACE("ComposedNode::notifyFrom " << event);
209 ElementaryNode *taskTyped=dynamic_cast<ElementaryNode *>((Task *)sender);
210 YACS::Event curEvent=event;
211 Node *lminus1LevelNode=taskTyped;
212 ComposedNode *curLevelNode=taskTyped->_father;
213 if(!curLevelNode)//Specific case of loop when 0 turn is specified without any enclosing bloc.
215 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
216 while(curEvent!=YACS::NOEVENT && curLevelNode!=this)
218 lminus1LevelNode=curLevelNode;
219 curLevelNode=curLevelNode->_father;
220 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
224 //! Add a dataflow link between two data ports.
226 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
227 * \exception Exception : if incompatibility between input and output (type), or 'start'/'end'
228 * is/are NOT in/outputPort contained in a node in descendance
229 * of 'this', or a multiple link to an input not supporting it.
230 * \return true if a new link has been created, false otherwise.
233 bool ComposedNode::edAddLink(OutPort *start, InPort *end) throw(YACS::Exception)
235 DEBTRACE("ComposedNode::edAddLink");
236 set<OutPort *> represented;
238 start->getAllRepresented(represented);
239 if(represented.size()!=1)
242 for(set<OutPort *>::iterator iter=represented.begin();iter!=represented.end();iter++)
243 ret|=edAddLink(*iter,end);
246 if(start->isAlreadyLinkedWith(end))
248 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
249 list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
250 list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
251 checkInMyDescendance(lwstCmnAnctr);
252 lwstCmnAnctr->checkLinkPossibility(start,allAscendanceOfNodeStart,end,allAscendanceOfNodeEnd);
254 if(dynamic_cast<ComposedNode *>(start->getNode()))
255 iterS=(ComposedNode *)start->getNode();
257 iterS=start->getNode()->_father;
258 pair<OutPort *, OutPort *> pO(start,start);
259 while(iterS!=lwstCmnAnctr)
261 iterS->buildDelegateOf(pO, end, allAscendanceOfNodeEnd);
262 iterS=iterS->_father;
264 if(dynamic_cast<ComposedNode *>(end->getNode()))
265 iterS=(ComposedNode *)end->getNode();
267 iterS=end->getNode()->_father;
269 InPort *currentPortI=end;
270 while(iterS!=lwstCmnAnctr)
272 iterS->buildDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
273 iterS=iterS->_father;
275 bool ret=(pO.first)->addInPort(currentPortI);
276 end->edNotifyReferencedBy(pO.second);
280 //! Connect an OutPort to an InPort and add the necessary control link
282 * Connect the ports with a data link (edAddLink) and add
283 * a control flow link between the children of the lowest common ancestor node.
285 * \param start : the OutPort to connect
286 * \param end : the InPort to connect
287 * \return true if a new link has been created, false otherwise.
289 bool ComposedNode::edAddDFLink(OutPort *start, InPort *end) throw(YACS::Exception)
291 Node* n1=start->getNode();
292 Node* n2=end->getNode();
293 DEBTRACE( n1->getName() << ":" << n2->getName())
294 ComposedNode* father=getLowestCommonAncestor(n1,n2);
295 DEBTRACE( "ComposedNode::edAddDFLink: this="<<this->getName()
296 << " father=" << father->getName() )
297 DEBTRACE( "ComposedNode::edAddDFLink: OutPort=" << start->getName()
298 << " InPort=" << end->getName() )
301 bool ret = father->edAddDFLink(start,end); // special treatement for loop
305 throw Exception("Back link authorized only in special context (loop for example)");
307 bool ret= edAddLink(start,end);
310 //add a control link only if nodes are not in the same descendance
311 //if n1 == father (n2 is after n1) : the control link is not needed
312 //if n2 == father (n1 is after n2) : it's a back link authorized only in loop context
313 while(n1->getFather() != father)
315 while(n2->getFather() != father)
321 catch (Exception& ex)
323 // --- remove DF link already created in case of cycle dtection
324 DEBTRACE("Cycle detected, remove CF link");
325 if(start->isAlreadyLinkedWith(end))
326 edRemoveLink(start, end);
333 //! Add a controlflow link between two control ports.
335 * \note Precondition : 'start' AND 'end' are in/outGate contained in a node
336 * in DIRECT descendance of 'this'.
337 * \exception Exception : If a cycle has been detected, or incompatibility
338 * between input and output, or 'start'/'end' is/are NOT in/outputPort contained
339 * in a node in descendance of 'this', or a mutilple link to an input not
341 * \return true if a new link has been created, false otherwise.
343 bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(YACS::Exception)
345 Node* n1=start->getNode();
346 Node* n2=end->getNode();
348 throw Exception("ComposedNode::edAddLink: can not add a control link to a node with itself",1);
349 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
351 throw Exception("ComposedNode::edAddLink: Trying to add CF link on orphan nodes.");
354 checkInMyDescendance(father);
355 return father->edAddLink(start,end);
357 bool ret=start->edAddInGate(end);
361 checkNoCyclePassingThrough(end->getNode());
363 catch (Exception& ex)
365 // --- remove created CF link in case of cycle detection
366 DEBTRACE("Cycle detected, remove CF link");
367 edRemoveCFLink(start->getNode(), end->getNode());
373 //! Add a controlflow link between two nodes.
375 * Add a controlflow link between two nodes by calling edAddLink on their control ports
377 bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE) throw(YACS::Exception)
379 return edAddLink(nodeS->getOutGate(),nodeE->getInGate());
382 //! Remove a controlflow link.
383 void ComposedNode::edRemoveCFLink(Node *nodeS, Node *nodeE) throw(YACS::Exception)
385 edRemoveLink(nodeS->getOutGate(),nodeE->getInGate());
388 //! Remove a dataflow link.
390 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
392 * \exception Exception : If the specified link does not exist. The content of Exception
393 * is different in accordance with the link from 'start' to 'end'
394 * implies DF/DS gateway.
397 void ComposedNode::edRemoveLink(OutPort *start, InPort *end) throw(YACS::Exception)
399 if(!start->isAlreadyLinkedWith(end))
400 throw Exception("ComposedNode::edRemoveLink : unexisting link");
401 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
402 checkInMyDescendance(lwstCmnAnctr);
403 list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
404 list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
406 // --- Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created
408 ComposedNode *iterS=start->getNode()->_father;
409 pair<OutPort *,OutPort *> currentPortO(start,start);
410 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > > needsToDestroyO;
412 Node *nodeOTemp=start->getNode();
413 if(*nodeOTemp<*lwstCmnAnctr)
415 iterS=nodeOTemp->_father;
416 while(iterS!=lwstCmnAnctr)
421 what << "ComposedNode::edRemoveLink: "
422 << start->getNode()->getName() << "." <<start->getName() << "->"
423 << end->getNode()->getName() << "." << end->getName();
424 throw Exception(what.str());
426 OutPort *tmp=currentPortO.first;
427 iterS->getDelegateOf(currentPortO, end, allAscendanceOfNodeEnd);
428 needsToDestroyO.push_back(pair< ComposedNode * , pair < OutPort* , OutPort *> >(iterS,pair<OutPort* , OutPort *> (tmp,currentPortO.first)));
429 iterS=iterS->_father;
432 Node *nodeTemp=end->getNode();
433 InPort * currentPortI=end;
434 if(*nodeTemp<*lwstCmnAnctr)
436 iterS=nodeTemp->_father;
437 while(iterS!=lwstCmnAnctr)
442 what << "ComposedNode::edRemoveLink: "
443 << start->getNode()->getName() << "." <<start->getName() << "->"
444 << end->getNode()->getName() << "." << end->getName();
445 throw Exception(what.str());
447 iterS->getDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
448 iterS=iterS->_father;
451 // --- End of test for evt intermediate ports created
453 (currentPortO.first)->removeInPort(currentPortI,false);
455 (currentPortO.second)->getAllRepresented(repr);
457 end->edNotifyDereferencedBy(currentPortO.second);
459 // --- Performing deletion of intermediate ports
461 iterS=start->getNode()->_father;
462 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > >::reverse_iterator iter;
463 for(iter=needsToDestroyO.rbegin();iter!=needsToDestroyO.rend();iter++)
464 (*iter).first->releaseDelegateOf(((*iter).second).first, ((*iter).second).second, end,allAscendanceOfNodeEnd);
465 nodeTemp=end->getNode();
466 if(*nodeTemp<*lwstCmnAnctr)
468 iterS=end->getNode()->_father;
470 while(iterS!=lwstCmnAnctr)
472 iterS->releaseDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
473 iterS=iterS->_father;
478 //! Remove a controlflow link.
479 void ComposedNode::edRemoveLink(OutGate *start, InGate *end) throw(YACS::Exception)
481 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
483 throw Exception("edRemoveLink : nodes not in direct descendance of this");
484 start->edRemoveInGate(end);
487 bool ComposedNode::edAddChild(Node *DISOWNnode) throw(YACS::Exception)
489 return false; // --- reimplemented in derived classes
492 //! Remove a child node.
493 void ComposedNode::edRemoveChild(Node *node) throw(YACS::Exception)
497 if (node->_father!=this)
499 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
500 throw Exception(what);
502 node->edDisconnectAllLinksWithMe();
504 //set _modified flag so edUpdateState() can refresh state
508 //! Splits name globalName in 2 parts using separator.
510 * \note 'priority' specifies if during search process of 'separator' the max part is
511 * for 'firstPart' (priority=true) or 'lastPart' (priority=false).
513 * \throw Exception : 'lastPart' or 'firstPart' is empty.
514 * \return true if split process succeeds false otherwise (typically when character
515 * separator was not found).
517 bool ComposedNode::splitNamesBySep(const std::string& globalName, const char separator[],
518 std::string& firstPart, std::string& lastPart, bool priority) throw(YACS::Exception)
520 const string delims(separator);
521 string portName, nodeName;
522 string::size_type idx;
524 idx = globalName.find_last_of(delims);
526 idx = globalName.find_first_of(delims);
527 if (idx == string::npos)
529 firstPart=globalName;
533 firstPart = globalName.substr(0,idx);
534 lastPart = globalName.substr(idx+1);
535 if ((firstPart.empty()) || (lastPart.empty()))
537 string what("the name "); what+= globalName ; what+=" is not a valid port name";
538 throw Exception(what);
543 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfInternalLinks() const
545 vector< pair<OutPort *, InPort *> > ret;
546 list<OutPort *> temp=getSetOfOutPort();
547 for(list<OutPort *>::const_iterator iter2=temp.begin();iter2!=temp.end();iter2++)
549 set<InPort *> temp2=(*iter2)->edSetInPort();
550 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
551 if(isInMyDescendance((*iter3)->getNode()))
552 ret.push_back(pair<OutPort *, InPort *>((*iter2),(*iter3)));
557 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfLinksLeavingCurrentScope() const
559 vector< pair<OutPort *, InPort *> > ret;
560 std::set<OutPort *> ports=getAllOutPortsLeavingCurrentScope();
561 for(set<OutPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
563 set<InPort *> temp2=(*iter2)->edSetInPort();
564 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
565 if(!isInMyDescendance((*iter3)->getNode()))
566 ret.push_back(pair<OutPort *, InPort *>(*iter2,*iter3));
571 void ComposedNode::checkConsistency(LinkInfo& info) const throw(YACS::Exception)
574 info.setPointOfView((ComposedNode *)this);
575 performCFComputations(info);
576 list<InputPort *> setOfInToTest=getSetOfInputPort();
577 for(list<InputPort *>::iterator iter1=setOfInToTest.begin();iter1!=setOfInToTest.end();iter1++)
579 vector<OutPort *> candidateForAdvCheck;
580 set<OutPort *> outPorts=(*iter1)->edSetOutPort();
581 //Filtering among outPorts, which of them, are candidates to fill *iter1 at the current scope.
582 for(set<OutPort *>::iterator iter2=outPorts.begin();iter2!=outPorts.end();iter2++)
584 (*iter2)->checkConsistency(info);
585 ComposedNode *manager=getLowestCommonAncestor((*iter2)->getNode(),(*iter1)->getNode());
586 if(isInMyDescendance(manager))
587 candidateForAdvCheck.push_back(*iter2);
589 if(!candidateForAdvCheck.empty())
590 //End of filtering. Now regarding CF constraints for the current InPutPort.
593 checkLinksCoherenceRegardingControl(candidateForAdvCheck,*iter1,info);
595 catch(YACS::Exception& ex)
597 std::string what=ex.what();
598 what += "\nfor input port: ";
599 what += (*iter1)->getNode()->getName();
601 what += (*iter1)->getName();
603 destructCFComputations(info);
604 throw YACS::Exception(what);
608 if(!(*iter1)->canBeNull() && !(*iter1)->edIsManuallyInitialized())
609 info.pushErrLink(0,*iter1,E_NEVER_SET_INPUTPORT);
611 destructCFComputations(info);
615 * This method check that G1 <- G2 <- G3 <- G1 does not happened.
616 * Typically called by methods that set a hierarchy (Bloc::edAddChild, Loop::edSetNode, ...).
618 void ComposedNode::checkNoCrossHierachyWith(Node *node) const throw(YACS::Exception)
620 ComposedNode *nodeC=dynamic_cast<ComposedNode *>(node);
623 list<ComposedNode *> ascendants=getAllAscendanceOf();
624 if(find(ascendants.begin(),ascendants.end(),nodeC)!=ascendants.end())
626 const char what[]="ComposedNode::checkNoCrossHierachyWith : ComposedNode with name \"";
627 string stream(what); stream+=node->getName(); stream+="\" is already in hierarchy ascendance of node with name \"";
628 stream+=_name; stream+="\" ; So it can't be now in its descendance !";
629 throw Exception(stream);
633 //! perform \b recursively all CF computations.
634 void ComposedNode::performCFComputations(LinkInfo& info) const
636 list<Node *> nodes=edGetDirectDescendants();
637 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
638 if(dynamic_cast<ComposedNode *>(*iter))
639 ((ComposedNode *)(*iter))->performCFComputations(info);
642 //! destroy \b recursively all results of initial computations.
643 void ComposedNode::destructCFComputations(LinkInfo& info) const
645 list<Node *> nodes=edGetDirectDescendants();
646 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
647 if(dynamic_cast<ComposedNode *>(*iter))
648 ((ComposedNode *)(*iter))->destructCFComputations(info);
652 * Returns the lowest Node (Elementary or Composed) (is sense of hierachy level ( operator< ) ) containing all 'ports'.
653 * Typically use in consistency computation.
654 * Precondition : 'ports' \b must contain at least one element. All elements of 'ports' should be in descendance of 'this'.
656 Node *ComposedNode::getLowestNodeDealingAll(const std::list<OutPort *>& ports) const
658 list< OutPort *>::const_iterator iter=ports.begin();
659 Node *ret=(*iter)->getNode();
661 for(;iter!=ports.end();iter++)
663 Node *tmp=(*iter)->getNode();
671 * call it only for 'starts' to 'end' links \b DEALED by 'this'.
673 void ComposedNode::checkLinksCoherenceRegardingControl(const std::vector<OutPort *>& starts, InputPort *end, LinkInfo& info) const throw(YACS::Exception)
675 map < ComposedNode *, list<OutPort *>, SortHierarc > outputs;//forward link classical
676 vector<OutPort *> outputsCross;//forward link cross
677 map < ComposedNode *, list<OutPort *>, SortHierarc > outputsBw;//backward
678 vector<OutPort *>::const_iterator iter1;
679 //vector<DataPort *> history=((*iter1).second)[0]->calculateHistoryOfLinkWith(end);
680 //DataPort *cross=DataPort::isCrossingType(history);
681 for(iter1=starts.begin();iter1!=starts.end();iter1++)
683 ComposedNode *manager=getLowestCommonAncestor((*iter1)->getNode(),end->getNode());
684 manager->checkControlDependancy((*iter1), end, false, outputs, outputsCross, outputsBw, info);
686 //Ok now let's regarding outputs all combinations : (outputs.size())*(outputs.size()-1)/2
687 unsigned char isAlreadyFed=FREE_ST;
688 //Dealing excusively with DS. Level is useless here because simultaneity is required for DS.
689 if(outputsCross.size()>0)
691 isAlreadyFed=FED_DS_ST;
692 if(outputsCross.size()>1)
693 for(vector< OutPort *>::const_iterator iter1=outputsCross.begin();iter1!=(outputsCross.end()-2);iter1++)
694 info.pushErrLink(*iter1,end,E_COLLAPSE_DS);
696 map < ComposedNode *, list<OutPort *>, SortHierarc >::iterator iter3=outputs.begin();
697 for(;iter3!=outputs.end();iter3++)
698 ((*iter3).first)->checkCFLinks((*iter3).second,end,isAlreadyFed,true,info);
699 if(isAlreadyFed==FREE_ST)
700 if(!end->edIsManuallyInitialized())
701 info.pushErrLink(0,end,E_ONLY_BACKWARD_DEFINED);
702 isAlreadyFed=FREE_ST;
704 map < ComposedNode *, list<OutPort *>, SortHierarc >::reverse_iterator iter5=outputsBw.rbegin();
705 for(;iter5!=outputsBw.rend();iter5++)
706 ((*iter5).first)->checkCFLinks((*iter5).second,end,isAlreadyFed,false,info);
710 * Internal method during CF links. This methode is in charge to statuate on links consistency in the case
711 * that no control flow defined by user is set.
713 void ComposedNode::solveObviousOrDelegateCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
715 static const char what[]="ComposedNode::solveObviousOrDelegateCFLinks : Internal error occured - uncorrect hierarchy detected !";
718 if(alreadyFed==FREE_ST)
721 info.pushInfoLink(*(starts.begin()),end,I_BACK);
724 else if(alreadyFed==FED_ST)
725 info.pushInfoLink(*(starts.begin()),end,direction ? I_USELESS : I_BACK_USELESS);
727 info.pushErrLink(*(starts.begin()),end,E_COLLAPSE_DFDS);
731 Node *levelOfDecision=getLowestNodeDealingAll(starts);
732 if(levelOfDecision==this)
733 throw Exception(what);
734 if(dynamic_cast<ElementaryNode *>(levelOfDecision))
737 if(alreadyFed==FREE_ST || alreadyFed==FED_ST)
739 if(alreadyFed==FREE_ST)
741 reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL;
745 reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS;
746 for(list< OutPort *>::const_iterator iter=starts.begin();iter!=starts.end();iter++)
747 info.pushWarnLink(*iter,end,reason);
751 ((ComposedNode *)levelOfDecision)->checkCFLinks(starts,end,alreadyFed,direction,info);
755 //! check control flow links
757 * \param starts If different of 0, must aggregate at leat \b 1 element.
759 * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
760 * \param direction If true : forward direction else backward direction.
761 * \param info : informations collectedduring the check
763 void ComposedNode::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
765 static const char what[]="ComposedNode::checkCFLinks : Internal error occured - uncorrect hierarchy detected !";
766 Node *nodeEnd=isInMyDescendance(end->getNode());
768 return solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
769 //This case is typically dedicated when direct son is ElementaryNode and self link is defined on this.
770 if(!dynamic_cast<ElementaryNode *>(nodeEnd))
771 throw Exception(what);
773 list< OutPort *>::const_iterator iter=starts.begin();
774 Node *nodeStart=(*iter)->getNode();
776 if(nodeEnd!=nodeStart)
777 throw Exception(what);
779 for(;iter!=starts.end();iter++)
780 if((*iter)->getNode()!=nodeStart)
781 throw Exception(what);
782 //Ok at this step we are sure that we have back links on the same elementary node.
784 for(iter=starts.begin();iter!=starts.end();iter++)
785 info.pushWarnLink(*iter,end,W_BACK_COLLAPSE_EL);
786 else//here no need to look at 'alreadyFed' var because it is waranteed to be equal to FREE_ST by construction.
787 info.pushInfoLink(*(starts.begin()),end,I_BACK);
791 std::vector< std::pair<InPort *, OutPort *> > ComposedNode::getSetOfLinksComingInCurrentScope() const
793 vector< pair<InPort *, OutPort *> > ret;
794 set<InPort *> ports=getAllInPortsComingFromOutsideOfCurrentScope();
795 for(set<InPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
797 set<OutPort *> temp2=(*iter2)->edSetOutPort();
798 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
800 if(isInMyDescendance((*iter3)->getNode()))continue;
801 std::set<OutPort *> trueOutPorts;
802 (*iter3)->getAllRepresented(trueOutPorts);
803 for(std::set<OutPort *>::iterator iter4=trueOutPorts.begin();iter4!=trueOutPorts.end();++iter4)
804 ret.push_back(pair<InPort *, OutPort *>(*iter2,*iter4));
810 //! List all output ports of children nodes that are linked to out of scope input ports
812 * \note List all output ports of nodes sons of 'this' that are linked to input ports
813 * of nodes not in descendance of 'this'.
814 * This method contrary to getAllInPortsComingFromOutsideOfCurrentScope is NOT virtual
815 * because for the moment all daughter classes have no more hidden YACS::ENGINE::OutPort.
817 std::set<OutPort *> ComposedNode::getAllOutPortsLeavingCurrentScope() const
820 list<OutPort *> temp=getSetOfOutPort();
821 for(list<OutPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
823 set<InPort *> temp2=(*iter2)->edSetInPort();
824 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
825 if(!isInMyDescendance((*iter3)->getNode()))
834 //! List all input ports that are linked to out of scope ports
837 * List all input ports of 'this' so that, for each it exists at least 1 link coming
838 * from outside to it.
841 std::set<InPort *> ComposedNode::getAllInPortsComingFromOutsideOfCurrentScope() const
844 list<InPort *> temp=getSetOfInPort();
845 for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
847 set<OutPort *> temp2=(*iter2)->edSetOutPort();
848 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
850 if(!isInMyDescendance((*iter3)->getNode()))
859 void ComposedNode::edDisconnectAllLinksWithMe()
863 Node::edDisconnectAllLinksWithMe();
866 vector< pair<OutPort *, InPort *> > linksToDestroy=getSetOfLinksLeavingCurrentScope();
867 vector< pair<OutPort *, InPort *> >::iterator iter;
868 for(iter=linksToDestroy.begin();iter!=linksToDestroy.end();iter++)
871 (*iter).first->removeInPort((*iter).second,true);
874 vector< pair<InPort *, OutPort *> > linksToDestroy2=getSetOfLinksComingInCurrentScope();
875 vector< pair<InPort *, OutPort *> >::iterator iter2;
876 for(iter2=linksToDestroy2.begin();iter2!=linksToDestroy2.end();iter2++)
879 (*iter2).second->removeInPort((*iter2).first,true);
883 ComposedNode *ComposedNode::getRootNode() const throw(YACS::Exception)
886 return (ComposedNode *)this;
887 return Node::getRootNode();
890 //! Check that Node 'node' is already a direct son of this.
891 bool ComposedNode::isNodeAlreadyAggregated(const Node *node) const
893 list<ComposedNode *> nodeAncestors = node->getAllAscendanceOf();
894 return find(nodeAncestors.begin(),nodeAncestors.end(),(ComposedNode *)this)!=nodeAncestors.end();
897 //! Returns the parent of a node that is the direct child of this node
899 * \note if 'nodeToTest'=='this' this is returned. Else if 'nodeToTest' is in descendance of
900 * 'this' the direct son is returned.
901 * Else 0 is returned.
903 * \param nodeToTest : the node to check
905 Node *ComposedNode::isInMyDescendance(Node *nodeToTest) const
909 if((ComposedNode *)nodeToTest==this)
911 Node *iterBack=nodeToTest;
912 ComposedNode *iter=nodeToTest->_father;
913 while(iter!=0 && iter!=this)
924 string ComposedNode::getChildName(const Node* node) const throw(YACS::Exception)
926 string nodeName=node->getQualifiedName();
927 if (!isNodeAlreadyAggregated(node))
929 if (node->getName() == "thisIsAFakeNode")
931 string child = node->getName()+".thisIsAFakeNode";
936 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
937 throw Exception(what);
941 const Node *father = node->_father;
942 while (father != this)
944 nodeName = father->getQualifiedName() + SEP_CHAR_BTW_LEVEL + nodeName;
945 father = father->_father;
950 std::string ComposedNode::getMyQualifiedName(const Node *directSon) const
952 return directSon->getName();
955 Node *ComposedNode::getChildByName(const std::string& name) const throw(YACS::Exception)
957 string potentiallyDirectSonName, remainsPath;
958 bool forwardNeeded=ComposedNode::splitNamesBySep(name, SEP_CHAR_BTW_LEVEL,
959 potentiallyDirectSonName,remainsPath,false);
960 Node *child=getChildByShortName(potentiallyDirectSonName);
964 return child->getChildByName(remainsPath);
967 //! Check if a node is in the descendance of this node
969 * \note Check that 'nodeToTest' is in descendance of 'this' OR equal to 'this'
970 * \exception Exception : If 'nodeToTest' is NOT in descendance of 'this' AND not equal to 'this'
971 * \param nodeToTest : the node to check
973 void ComposedNode::checkInMyDescendance(Node *nodeToTest) const throw(YACS::Exception)
975 const char whatC[]=" is not the descendance of node ";
978 string what("node "); what+= nodeToTest->getName(); what+=" ";
979 what+=whatC; what+=_name;
980 throw Exception(what);
982 if((ComposedNode *)nodeToTest==this)
984 ComposedNode *iter=nodeToTest->_father;
985 while(iter!=0 && iter!=this)
989 string what("node "); what+= nodeToTest->getName(); what+=" ";
990 what+=whatC; what+=_name;
991 throw Exception(what);
995 //! Retrieves the lowest common ancestor of 2 nodes
998 * \note Retrieves the lowest common ancestor of 'node1' AND 'node2'.
999 * If 'node1' or 'node2' are both or indiscriminately instances of ComposedNode and that
1000 * 'node1' is in descendance of 'node2' (resp. 'node2' in descendance of 'node1')
1001 * 'node2' is returned (resp. 'node1').
1002 * \exception Exception : if 'node1' and 'node2' do not share the same genealogy.
1003 * \return The lowest common ancestor if it exists.
1006 ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) throw(YACS::Exception)
1008 const char what[]="2 nodes does not share the same genealogy";
1009 if(node1==0 || node2==0)
1010 throw Exception(what);
1012 if(dynamic_cast<ComposedNode *>(node1))
1013 temp=(ComposedNode *)node1;//->_father;
1015 temp=(ComposedNode *)node1->_father;
1016 set<ComposedNode *> s;
1023 if(dynamic_cast<ComposedNode *>(node2))
1024 temp=(ComposedNode *)node2;//->_father;
1026 temp=(ComposedNode *)node2->_father;
1027 set<ComposedNode *>::iterator iter=s.find(temp);
1028 while(temp && iter==s.end())
1034 throw Exception(what);
1038 list<ElementaryNode *> ComposedNode::getRecursiveConstituents() const
1040 list<ElementaryNode *> ret;
1041 list<Node *> setOfNode=edGetDirectDescendants();
1042 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1044 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1045 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1050 //! Idem getAllRecursiveNodes, but this node is NOT included.
1051 list<Node *> ComposedNode::getAllRecursiveConstituents()
1054 list<Node *> setOfNode=edGetDirectDescendants();
1055 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1057 if ( dynamic_cast<ComposedNode*> (*iter) )
1059 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveConstituents();
1060 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1061 ret.push_back(*iter);
1065 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1066 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1072 //! Get all children nodes elementary and composed including this node
1073 list<Node *> ComposedNode::getAllRecursiveNodes()
1076 list<Node *> setOfNode=edGetDirectDescendants();
1077 for(list<Node *>::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1079 if ( dynamic_cast<ElementaryNode*> (*iter) )
1081 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1082 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1086 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveNodes();
1087 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1090 ret.push_back(this);
1094 //! Get the input port name
1096 * get the input port name used by the current node, recursively built with children names.
1099 string ComposedNode::getInPortName(const InPort * inPort) const throw(YACS::Exception)
1101 return getPortName<InPort>(inPort);
1104 string ComposedNode::getOutPortName(const OutPort *outPort) const throw(YACS::Exception)
1106 return getPortName<OutPort>(outPort);
1109 int ComposedNode::getNumberOfInputPorts() const
1111 list<Node *> constituents=edGetDirectDescendants();
1113 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1114 ret+=(*iter)->getNumberOfInputPorts();
1118 int ComposedNode::getNumberOfOutputPorts() const
1120 list<Node *> constituents=edGetDirectDescendants();
1122 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1123 ret+=(*iter)->getNumberOfOutputPorts();
1127 list<InputPort *> ComposedNode::getSetOfInputPort() const
1129 list<Node *> constituents=edGetDirectDescendants();
1130 list<InputPort *> ret;
1131 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1133 list<InputPort *> currentsPorts=(*iter)->getSetOfInputPort();
1134 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1139 list<OutputPort *> ComposedNode::getSetOfOutputPort() const
1141 list<Node *> constituents=edGetDirectDescendants();
1142 list<OutputPort *> ret;
1143 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1145 list<OutputPort *> currentsPorts=(*iter)->getSetOfOutputPort();
1146 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1151 list<InputDataStreamPort *> ComposedNode::getSetOfInputDataStreamPort() const
1153 list<Node *> constituents=edGetDirectDescendants();
1154 list<InputDataStreamPort *> ret;
1155 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1157 list<InputDataStreamPort *> currentsPorts=(*iter)->getSetOfInputDataStreamPort();
1158 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1163 list<OutputDataStreamPort *> ComposedNode::getSetOfOutputDataStreamPort() const
1165 list<Node *> constituents=edGetDirectDescendants();
1166 list<OutputDataStreamPort *> ret;
1167 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1169 list<OutputDataStreamPort *> currentsPorts=(*iter)->getSetOfOutputDataStreamPort();
1170 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1175 OutPort *ComposedNode::getOutPort(const std::string& name) const throw(YACS::Exception)
1177 string portName, nodeName;
1178 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1180 Node *child = getChildByShortName(nodeName);
1181 return child->getOutPort(portName);
1185 string what("ComposedNode::getOutPort : the port with name "); what+=name; what+=" does not exist on the current level";
1186 throw Exception(what);
1190 //! Get an input port given its name
1192 * Contrary to YACS::ENGINE::ComposedNode::getOutputPort, this method is \b NOT recursive
1193 * and so the leaf of type ElementaryNode aggregating
1194 * this InputPort is directly invoked.
1196 InputPort * ComposedNode::getInputPort(const std::string& name) const throw(YACS::Exception)
1199 return Node::getInputPort(name);
1201 catch(Exception& e) {}
1203 string portName, nodeName;
1204 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1206 Node *child = getChildByName(nodeName);
1207 return child->getInputPort(portName);
1211 string what("ComposedNode::getInputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1212 throw Exception(what);
1216 //! Get an output port given its name
1218 * Contrary to YACS::ENGINE::ComposedNode::getInputPort, this method is recursive and go
1219 * down hierarchy step by step to complete its work.
1221 OutputPort * ComposedNode::getOutputPort(const std::string& name) const throw(YACS::Exception)
1223 string portName, nodeName;
1224 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1226 Node *child = getChildByShortName(nodeName);
1227 return child->getOutputPort(portName);
1231 string what("ComposedNode::getOutputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1232 throw Exception(what);
1236 InputDataStreamPort *ComposedNode::getInputDataStreamPort(const std::string& name) const throw(YACS::Exception)
1238 string portName, nodeName;
1239 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1241 Node *child = getChildByName(nodeName);
1242 return child->getInputDataStreamPort(portName);
1246 string what("ComposedNode::getInputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1247 throw Exception(what);
1251 OutputDataStreamPort *ComposedNode::getOutputDataStreamPort(const std::string& name) const throw(YACS::Exception)
1253 string portName, nodeName;
1254 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1256 Node *child = getChildByName(nodeName);
1257 return child->getOutputDataStreamPort(portName);
1261 string what("ComposedNode::getOutputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1262 throw Exception(what);
1266 //! Update node state on receiving event from a node
1269 * \note Runtime called method. Perform, the state updating, from the son node 'node'
1270 * emitting the event 'event' (among Executor static const var).
1271 * WARNING Precondition : this == node->_father
1272 * \return The event (among Executor static const var) destinated to this->_father node
1273 * to perform eventually up level update.
1275 * Calls ComposedNode::updateStateOnStartEventFrom if event is YACS::START
1277 * Calls ComposedNode::updateStateOnFinishedEventFrom if event is YACS::FINISH
1279 * Called by ComposedNode::notifyFrom
1281 YACS::Event ComposedNode::updateStateFrom(Node *node, //* I : node emitting event
1282 YACS::Event event //* I : event emitted
1285 DEBTRACE("updateStateFrom: " << node->getName() << " " << event);
1291 return updateStateOnStartEventFrom(node);
1294 return updateStateOnFinishedEventFrom(node);
1297 return updateStateOnFailedEventFrom(node);
1300 return YACS::NOEVENT;//TODO unexpected type of event
1304 catch(YACS::Exception& ex)
1306 //unexpected exception: probably a bug in engine
1307 //try to keep a consistent global state
1308 DEBTRACE( "updateStateFrom: " << ex.what() );
1309 _errorDetails="Internal error: ";
1310 _errorDetails=_errorDetails + ex.what();
1311 setState(YACS::ERROR);
1317 //unexpected exception: probably a bug in engine
1318 //try to keep a consistent global state
1319 setState(YACS::ERROR);
1325 //! Method used to notify the node that a child node has started
1327 * Update the ComposedNode state and return the ComposedNode change state
1329 * \param node : the child node that has started
1330 * \return the loop state change
1332 YACS::Event ComposedNode::updateStateOnStartEventFrom(Node *node)
1334 setState(YACS::ACTIVATED);
1338 //! Method used to notify the node that a child node has failed
1339 YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node)
1341 setState(YACS::FAILED);
1345 void ComposedNode::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
1346 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
1348 if((dynamic_cast<DataFlowPort *>(start) || dynamic_cast<DataFlowPort *>(end))
1349 && (dynamic_cast<DataStreamPort *>(start) || dynamic_cast<DataStreamPort *>(end)))
1350 {//cross protocol required : deeper check needed
1352 list<ComposedNode *>::const_iterator iter;
1353 for(iter=pointsOfViewStart.begin();iter!=pointsOfViewStart.end() && !isOK;iter++)
1354 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1355 for(iter=pointsOfViewEnd.begin();iter!=pointsOfViewEnd.end() && !isOK;iter++)
1356 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1358 throw Exception("ComposedNode::checkLinkPossibility : Request for cross protocol link impossible.");
1362 void ComposedNode::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
1366 void ComposedNode::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
1370 void ComposedNode::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1374 void ComposedNode::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1378 void ComposedNode::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1382 void ComposedNode::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1386 void ComposedNode::loaded()
1389 void ComposedNode::connected()
1393 void ComposedNode::accept(Visitor *visitor)
1395 list<Node *> constituents=edGetDirectDescendants();
1396 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1398 (*iter)->accept(visitor);
1402 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1403 std::list<InputPort *> ComposedNode::getLocalInputPorts() const
1405 std::list<InputPort *> lip; return lip; // empty list
1408 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1409 std::list<OutputPort *> ComposedNode::getLocalOutputPorts() const
1411 std::list<OutputPort *> lop; return lop; // empty list
1414 bool ComposedNode::isNameAlreadyUsed(const std::string& name) const
1419 void ComposedNode::edUpdateState()
1421 DEBTRACE("ComposedNode::edUpdateState(): " << _state << " " << _modified);
1422 YACS::StatesForNode state=YACS::READY;
1426 checkBasicConsistency();
1431 state=YACS::INVALID;
1432 _errorDetails=e.what();
1434 DEBTRACE("ComposedNode::edUpdateState: " << _errorDetails);
1436 //update children if needed
1437 list<Node *> constituents=edGetDirectDescendants();
1438 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1440 if(!(*iter)->isValid())
1441 state=YACS::INVALID;
1448 std::string ComposedNode::getErrorReport()
1450 DEBTRACE("ComposedNode::getErrorReport: " << getName() << " " << _state);
1451 YACS::StatesForNode effectiveState=getEffectiveState();
1453 if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
1456 std::string report="<error node= " + getName();
1457 switch(effectiveState)
1460 report=report+" state= INVALID";
1463 report=report+" state= ERROR";
1466 report=report+" state= FAILED";
1471 report=report + ">\n" ;
1472 if(_errorDetails != "")
1473 report=report+_errorDetails+"\n";
1475 list<Node *> constituents=edGetDirectDescendants();
1476 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1478 std::string rep=(*iter)->getErrorReport();
1481 report=report+rep+"\n";
1484 report=report+"</error>";
1490 void ComposedNode::checkBasicConsistency() const throw(YACS::Exception)
1492 DEBTRACE("ComposedNode::checkBasicConsistency");
1493 std::list<InputPort *>::const_iterator iter;
1494 std::list<InputPort *> inports=getLocalInputPorts();
1495 for(iter=inports.begin();iter!=inports.end();iter++)
1496 (*iter)->checkBasicConsistency();
1499 //! Stop all pending activities of the composed node
1501 * This method should be called when a Proc is finished and must be deleted from the YACS server
1503 void ComposedNode::shutdown(int level)
1506 DEBTRACE("ComposedNode::shutdown");
1507 list<Node *> nodes=edGetDirectDescendants();
1508 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1509 (*iter)->shutdown(level);
1512 //! Clean the composed node in case of not clean exit
1514 * This method should be called on a control-c or sigterm
1516 void ComposedNode::cleanNodes()
1518 DEBTRACE("ComposedNode::cleanNodes");
1519 list<Node *> nodes=edGetDirectDescendants();
1520 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1521 (*iter)->cleanNodes();
1524 //! Reset the state of the node and its children depending on the parameter level
1525 void ComposedNode::resetState(int level)
1529 DEBTRACE("ComposedNode::resetState " << level << "," << _state);
1530 if( _state==YACS::ERROR || _state==YACS::FAILED || _state==YACS::ACTIVATED )
1532 Node::resetState(level);
1533 std::list<Node *> nodes=edGetDirectDescendants();
1534 for(std::list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1535 (*iter)->resetState(level);