1 // Copyright (C) 2006-2014 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
247 DEBTRACE("ComposedNode::notifyFrom " << event);
248 ElementaryNode *taskTyped=dynamic_cast<ElementaryNode *>((Task *)sender);
249 YACS::Event curEvent=event;
250 Node *lminus1LevelNode=taskTyped;
251 ComposedNode *curLevelNode=taskTyped->_father;
252 if(!curLevelNode)//Specific case of loop when 0 turn is specified without any enclosing bloc.
254 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
255 while(curEvent!=YACS::NOEVENT && curLevelNode!=this)
257 lminus1LevelNode=curLevelNode;
258 curLevelNode=curLevelNode->_father;
259 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
263 //! Add a dataflow link between two data ports.
265 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
266 * \exception Exception : if incompatibility between input and output (type), or 'start'/'end'
267 * is/are NOT in/outputPort contained in a node in descendance
268 * of 'this', or a multiple link to an input not supporting it.
269 * \return true if a new link has been created, false otherwise.
272 bool ComposedNode::edAddLink(OutPort *start, InPort *end) throw(YACS::Exception)
274 DEBTRACE("ComposedNode::edAddLink");
275 set<OutPort *> represented;
277 start->getAllRepresented(represented);
278 if(represented.size()!=1)
281 for(set<OutPort *>::iterator iter=represented.begin();iter!=represented.end();iter++)
282 ret|=edAddLink(*iter,end);
285 if(start->isAlreadyLinkedWith(end))
287 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
288 list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
289 list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
290 checkInMyDescendance(lwstCmnAnctr);
291 lwstCmnAnctr->checkLinkPossibility(start,allAscendanceOfNodeStart,end,allAscendanceOfNodeEnd);
293 if(dynamic_cast<ComposedNode *>(start->getNode()))
294 iterS=(ComposedNode *)start->getNode();
296 iterS=start->getNode()->_father;
297 pair<OutPort *, OutPort *> pO(start,start);
298 while(iterS!=lwstCmnAnctr)
300 iterS->buildDelegateOf(pO, end, allAscendanceOfNodeEnd);
301 iterS=iterS->_father;
303 if(dynamic_cast<ComposedNode *>(end->getNode()))
304 iterS=(ComposedNode *)end->getNode();
306 iterS=end->getNode()->_father;
308 InPort *currentPortI=end;
309 while(iterS!=lwstCmnAnctr)
311 iterS->buildDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
312 iterS=iterS->_father;
314 bool ret=(pO.first)->addInPort(currentPortI);
315 end->edNotifyReferencedBy(pO.second);
319 //! Connect an OutPort to an InPort and add the necessary control link
321 * Connect the ports with a data link (edAddLink) and add
322 * a control flow link between the children of the lowest common ancestor node.
324 * \param start : the OutPort to connect
325 * \param end : the InPort to connect
326 * \return true if a new link has been created, false otherwise.
328 bool ComposedNode::edAddDFLink(OutPort *start, InPort *end) throw(YACS::Exception)
330 Node* n1=start->getNode();
331 Node* n2=end->getNode();
332 DEBTRACE( n1->getName() << ":" << n2->getName())
333 ComposedNode* father=getLowestCommonAncestor(n1,n2);
334 DEBTRACE( "ComposedNode::edAddDFLink: this="<<this->getName()
335 << " father=" << father->getName() )
336 DEBTRACE( "ComposedNode::edAddDFLink: OutPort=" << start->getName()
337 << " InPort=" << end->getName() )
340 bool ret = father->edAddDFLink(start,end); // special treatement for loop
344 throw Exception("Back link authorized only in special context (loop for example)");
346 bool ret= edAddLink(start,end);
349 //add a control link only if nodes are not in the same descendance
350 //if n1 == father (n2 is after n1) : the control link is not needed
351 //if n2 == father (n1 is after n2) : it's a back link authorized only in loop context
352 while(n1->getFather() != father)
354 while(n2->getFather() != father)
360 catch (Exception& ex)
362 // --- remove DF link already created in case of cycle dtection
363 DEBTRACE("Cycle detected, remove CF link");
364 if(start->isAlreadyLinkedWith(end))
365 edRemoveLink(start, end);
372 //! Add a controlflow link between two control ports.
374 * \note Precondition : 'start' AND 'end' are in/outGate contained in a node
375 * in DIRECT descendance of 'this'.
376 * \exception Exception : If a cycle has been detected, or incompatibility
377 * between input and output, or 'start'/'end' is/are NOT in/outputPort contained
378 * in a node in descendance of 'this', or a mutilple link to an input not
380 * \return true if a new link has been created, false otherwise.
382 bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(YACS::Exception)
384 Node* n1=start->getNode();
385 Node* n2=end->getNode();
387 throw Exception("ComposedNode::edAddLink: can not add a control link to a node with itself",1);
388 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
390 throw Exception("ComposedNode::edAddLink: Trying to add CF link on orphan nodes.");
393 checkInMyDescendance(father);
394 return father->edAddLink(start,end);
396 bool ret=start->edAddInGate(end);
400 checkNoCyclePassingThrough(end->getNode());
402 catch (Exception& ex)
404 // --- remove created CF link in case of cycle detection
405 DEBTRACE("Cycle detected, remove CF link");
406 edRemoveCFLink(start->getNode(), end->getNode());
412 //! Add a controlflow link between two nodes.
414 * Add a controlflow link between two nodes by calling edAddLink on their control ports
416 bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE) throw(YACS::Exception)
418 return edAddLink(nodeS->getOutGate(),nodeE->getInGate());
421 //! Remove a controlflow link.
422 void ComposedNode::edRemoveCFLink(Node *nodeS, Node *nodeE) throw(YACS::Exception)
424 edRemoveLink(nodeS->getOutGate(),nodeE->getInGate());
427 //! Remove a dataflow link.
429 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
431 * \exception Exception : If the specified link does not exist. The content of Exception
432 * is different in accordance with the link from 'start' to 'end'
433 * implies DF/DS gateway.
436 void ComposedNode::edRemoveLink(OutPort *start, InPort *end) throw(YACS::Exception)
438 if(!start->isAlreadyLinkedWith(end))
439 throw Exception("ComposedNode::edRemoveLink : unexisting link");
440 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
441 checkInMyDescendance(lwstCmnAnctr);
442 list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
443 list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
445 // --- Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created
447 ComposedNode *iterS=start->getNode()->_father;
448 pair<OutPort *,OutPort *> currentPortO(start,start);
449 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > > needsToDestroyO;
451 Node *nodeOTemp=start->getNode();
452 if(*nodeOTemp<*lwstCmnAnctr)
454 iterS=nodeOTemp->_father;
455 while(iterS!=lwstCmnAnctr)
460 what << "ComposedNode::edRemoveLink: "
461 << start->getNode()->getName() << "." <<start->getName() << "->"
462 << end->getNode()->getName() << "." << end->getName();
463 throw Exception(what.str());
465 OutPort *tmp=currentPortO.first;
466 iterS->getDelegateOf(currentPortO, end, allAscendanceOfNodeEnd);
467 needsToDestroyO.push_back(pair< ComposedNode * , pair < OutPort* , OutPort *> >(iterS,pair<OutPort* , OutPort *> (tmp,currentPortO.first)));
468 iterS=iterS->_father;
471 Node *nodeTemp=end->getNode();
472 InPort * currentPortI=end;
473 if(*nodeTemp<*lwstCmnAnctr)
475 iterS=nodeTemp->_father;
476 while(iterS!=lwstCmnAnctr)
481 what << "ComposedNode::edRemoveLink: "
482 << start->getNode()->getName() << "." <<start->getName() << "->"
483 << end->getNode()->getName() << "." << end->getName();
484 throw Exception(what.str());
486 iterS->getDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
487 iterS=iterS->_father;
490 // --- End of test for evt intermediate ports created
492 (currentPortO.first)->removeInPort(currentPortI,false);
494 (currentPortO.second)->getAllRepresented(repr);
496 end->edNotifyDereferencedBy(currentPortO.second);
498 // --- Performing deletion of intermediate ports
500 iterS=start->getNode()->_father;
501 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > >::reverse_iterator iter;
502 for(iter=needsToDestroyO.rbegin();iter!=needsToDestroyO.rend();iter++)
503 (*iter).first->releaseDelegateOf(((*iter).second).first, ((*iter).second).second, end,allAscendanceOfNodeEnd);
504 nodeTemp=end->getNode();
505 if(*nodeTemp<*lwstCmnAnctr)
507 iterS=end->getNode()->_father;
509 while(iterS!=lwstCmnAnctr)
511 iterS->releaseDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
512 iterS=iterS->_father;
517 //! Remove a controlflow link.
518 void ComposedNode::edRemoveLink(OutGate *start, InGate *end) throw(YACS::Exception)
520 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
522 throw Exception("edRemoveLink : nodes not in direct descendance of this");
523 start->edRemoveInGate(end);
526 bool ComposedNode::edAddChild(Node *DISOWNnode) throw(YACS::Exception)
528 return false; // --- reimplemented in derived classes
531 //! Remove a child node.
532 void ComposedNode::edRemoveChild(Node *node) throw(YACS::Exception)
536 if (node->_father!=this)
538 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
539 throw Exception(what);
541 node->edDisconnectAllLinksWithMe();
543 //set _modified flag so edUpdateState() can refresh state
547 //! Splits name globalName in 2 parts using separator.
549 * \note 'priority' specifies if during search process of 'separator' the max part is
550 * for 'firstPart' (priority=true) or 'lastPart' (priority=false).
552 * \throw Exception : 'lastPart' or 'firstPart' is empty.
553 * \return true if split process succeeds false otherwise (typically when character
554 * separator was not found).
556 bool ComposedNode::splitNamesBySep(const std::string& globalName, const char separator[],
557 std::string& firstPart, std::string& lastPart, bool priority) throw(YACS::Exception)
559 const string delims(separator);
560 string portName, nodeName;
561 string::size_type idx;
563 idx = globalName.find_last_of(delims);
565 idx = globalName.find_first_of(delims);
566 if (idx == string::npos)
568 firstPart=globalName;
572 firstPart = globalName.substr(0,idx);
573 lastPart = globalName.substr(idx+1);
574 if ((firstPart.empty()) || (lastPart.empty()))
576 string what("the name "); what+= globalName ; what+=" is not a valid port name";
577 throw Exception(what);
582 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfInternalLinks() const
584 vector< pair<OutPort *, InPort *> > ret;
585 list<OutPort *> temp=getSetOfOutPort();
586 for(list<OutPort *>::const_iterator iter2=temp.begin();iter2!=temp.end();iter2++)
588 set<InPort *> temp2=(*iter2)->edSetInPort();
589 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
590 if(isInMyDescendance((*iter3)->getNode()))
591 ret.push_back(pair<OutPort *, InPort *>((*iter2),(*iter3)));
596 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfLinksLeavingCurrentScope() const
598 vector< pair<OutPort *, InPort *> > ret;
599 std::set<OutPort *> ports=getAllOutPortsLeavingCurrentScope();
600 for(set<OutPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
602 set<InPort *> temp2=(*iter2)->edSetInPort();
603 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
604 if(!isInMyDescendance((*iter3)->getNode()))
605 ret.push_back(pair<OutPort *, InPort *>(*iter2,*iter3));
610 void ComposedNode::checkConsistency(LinkInfo& info) const throw(YACS::Exception)
613 info.setPointOfView((ComposedNode *)this);
614 performCFComputations(info);
615 list<InputPort *> setOfInToTest=getSetOfInputPort();
616 for(list<InputPort *>::iterator iter1=setOfInToTest.begin();iter1!=setOfInToTest.end();iter1++)
618 vector<OutPort *> candidateForAdvCheck;
619 set<OutPort *> outPorts=(*iter1)->edSetOutPort();
620 //Filtering among outPorts, which of them, are candidates to fill *iter1 at the current scope.
621 for(set<OutPort *>::iterator iter2=outPorts.begin();iter2!=outPorts.end();iter2++)
623 (*iter2)->checkConsistency(info);
624 ComposedNode *manager=getLowestCommonAncestor((*iter2)->getNode(),(*iter1)->getNode());
625 if(isInMyDescendance(manager))
626 candidateForAdvCheck.push_back(*iter2);
628 if(!candidateForAdvCheck.empty())
629 //End of filtering. Now regarding CF constraints for the current InPutPort.
632 checkLinksCoherenceRegardingControl(candidateForAdvCheck,*iter1,info);
634 catch(YACS::Exception& ex)
636 std::string what=ex.what();
637 what += "\nfor input port: ";
638 what += (*iter1)->getNode()->getName();
640 what += (*iter1)->getName();
642 destructCFComputations(info);
643 throw YACS::Exception(what);
647 if(!(*iter1)->canBeNull() && !(*iter1)->edIsManuallyInitialized())
648 info.pushErrLink(0,*iter1,E_NEVER_SET_INPUTPORT);
650 destructCFComputations(info);
654 * This method check that G1 <- G2 <- G3 <- G1 does not happened.
655 * Typically called by methods that set a hierarchy (Bloc::edAddChild, Loop::edSetNode, ...).
657 void ComposedNode::checkNoCrossHierachyWith(Node *node) const throw(YACS::Exception)
659 ComposedNode *nodeC=dynamic_cast<ComposedNode *>(node);
662 list<ComposedNode *> ascendants=getAllAscendanceOf();
663 if(find(ascendants.begin(),ascendants.end(),nodeC)!=ascendants.end())
665 const char what[]="ComposedNode::checkNoCrossHierachyWith : ComposedNode with name \"";
666 string stream(what); stream+=node->getName(); stream+="\" is already in hierarchy ascendance of node with name \"";
667 stream+=_name; stream+="\" ; So it can't be now in its descendance !";
668 throw Exception(stream);
672 //! perform \b recursively all CF computations.
673 void ComposedNode::performCFComputations(LinkInfo& info) const
675 list<Node *> nodes=edGetDirectDescendants();
676 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
677 if(dynamic_cast<ComposedNode *>(*iter))
678 ((ComposedNode *)(*iter))->performCFComputations(info);
681 //! destroy \b recursively all results of initial computations.
682 void ComposedNode::destructCFComputations(LinkInfo& info) const
684 list<Node *> nodes=edGetDirectDescendants();
685 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
686 if(dynamic_cast<ComposedNode *>(*iter))
687 ((ComposedNode *)(*iter))->destructCFComputations(info);
691 * Returns the lowest Node (Elementary or Composed) (is sense of hierachy level ( operator< ) ) containing all 'ports'.
692 * Typically use in consistency computation.
693 * Precondition : 'ports' \b must contain at least one element. All elements of 'ports' should be in descendance of 'this'.
695 Node *ComposedNode::getLowestNodeDealingAll(const std::list<OutPort *>& ports) const
697 list< OutPort *>::const_iterator iter=ports.begin();
698 Node *ret=(*iter)->getNode();
700 for(;iter!=ports.end();iter++)
702 Node *tmp=(*iter)->getNode();
710 * call it only for 'starts' to 'end' links \b DEALED by 'this'.
712 void ComposedNode::checkLinksCoherenceRegardingControl(const std::vector<OutPort *>& starts, InputPort *end, LinkInfo& info) const throw(YACS::Exception)
714 map < ComposedNode *, list<OutPort *>, SortHierarc > outputs;//forward link classical
715 vector<OutPort *> outputsCross;//forward link cross
716 map < ComposedNode *, list<OutPort *>, SortHierarc > outputsBw;//backward
717 vector<OutPort *>::const_iterator iter1;
718 //vector<DataPort *> history=((*iter1).second)[0]->calculateHistoryOfLinkWith(end);
719 //DataPort *cross=DataPort::isCrossingType(history);
720 for(iter1=starts.begin();iter1!=starts.end();iter1++)
722 ComposedNode *manager=getLowestCommonAncestor((*iter1)->getNode(),end->getNode());
723 manager->checkControlDependancy((*iter1), end, false, outputs, outputsCross, outputsBw, info);
725 //Ok now let's regarding outputs all combinations : (outputs.size())*(outputs.size()-1)/2
726 unsigned char isAlreadyFed=FREE_ST;
727 //Dealing excusively with DS. Level is useless here because simultaneity is required for DS.
728 if(outputsCross.size()>0)
730 isAlreadyFed=FED_DS_ST;
731 if(outputsCross.size()>1)
732 for(vector< OutPort *>::const_iterator iter1=outputsCross.begin();iter1!=(outputsCross.end()-2);iter1++)
733 info.pushErrLink(*iter1,end,E_COLLAPSE_DS);
735 map < ComposedNode *, list<OutPort *>, SortHierarc >::iterator iter3=outputs.begin();
736 for(;iter3!=outputs.end();iter3++)
737 ((*iter3).first)->checkCFLinks((*iter3).second,end,isAlreadyFed,true,info);
738 if(isAlreadyFed==FREE_ST)
739 if(!end->edIsManuallyInitialized())
740 info.pushErrLink(0,end,E_ONLY_BACKWARD_DEFINED);
741 isAlreadyFed=FREE_ST;
743 map < ComposedNode *, list<OutPort *>, SortHierarc >::reverse_iterator iter5=outputsBw.rbegin();
744 for(;iter5!=outputsBw.rend();iter5++)
745 ((*iter5).first)->checkCFLinks((*iter5).second,end,isAlreadyFed,false,info);
749 * Internal method during CF links. This methode is in charge to statuate on links consistency in the case
750 * that no control flow defined by user is set.
752 void ComposedNode::solveObviousOrDelegateCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
754 static const char what[]="ComposedNode::solveObviousOrDelegateCFLinks : Internal error occured - uncorrect hierarchy detected !";
757 if(alreadyFed==FREE_ST)
760 info.pushInfoLink(*(starts.begin()),end,I_BACK);
763 else if(alreadyFed==FED_ST)
764 info.pushInfoLink(*(starts.begin()),end,direction ? I_USELESS : I_BACK_USELESS);
766 info.pushErrLink(*(starts.begin()),end,E_COLLAPSE_DFDS);
770 Node *levelOfDecision=getLowestNodeDealingAll(starts);
771 if(levelOfDecision==this)
772 throw Exception(what);
773 if(dynamic_cast<ElementaryNode *>(levelOfDecision))
776 if(alreadyFed==FREE_ST || alreadyFed==FED_ST)
778 if(alreadyFed==FREE_ST)
780 reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL;
784 reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS;
785 for(list< OutPort *>::const_iterator iter=starts.begin();iter!=starts.end();iter++)
786 info.pushWarnLink(*iter,end,reason);
790 ((ComposedNode *)levelOfDecision)->checkCFLinks(starts,end,alreadyFed,direction,info);
794 //! check control flow links
796 * \param starts If different of 0, must aggregate at leat \b 1 element.
798 * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
799 * \param direction If true : forward direction else backward direction.
800 * \param info : informations collectedduring the check
802 void ComposedNode::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
804 static const char what[]="ComposedNode::checkCFLinks : Internal error occured - uncorrect hierarchy detected !";
805 Node *nodeEnd=isInMyDescendance(end->getNode());
807 return solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
808 //This case is typically dedicated when direct son is ElementaryNode and self link is defined on this.
809 if(!dynamic_cast<ElementaryNode *>(nodeEnd))
810 throw Exception(what);
812 list< OutPort *>::const_iterator iter=starts.begin();
813 Node *nodeStart=(*iter)->getNode();
815 if(nodeEnd!=nodeStart)
816 throw Exception(what);
818 for(;iter!=starts.end();iter++)
819 if((*iter)->getNode()!=nodeStart)
820 throw Exception(what);
821 //Ok at this step we are sure that we have back links on the same elementary node.
823 for(iter=starts.begin();iter!=starts.end();iter++)
824 info.pushWarnLink(*iter,end,W_BACK_COLLAPSE_EL);
825 else//here no need to look at 'alreadyFed' var because it is waranteed to be equal to FREE_ST by construction.
826 info.pushInfoLink(*(starts.begin()),end,I_BACK);
830 std::vector< std::pair<InPort *, OutPort *> > ComposedNode::getSetOfLinksComingInCurrentScope() const
832 vector< pair<InPort *, OutPort *> > ret;
833 set<InPort *> ports=getAllInPortsComingFromOutsideOfCurrentScope();
834 for(set<InPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
836 set<OutPort *> temp2=(*iter2)->edSetOutPort();
837 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
839 if(isInMyDescendance((*iter3)->getNode()))continue;
840 std::set<OutPort *> trueOutPorts;
841 (*iter3)->getAllRepresented(trueOutPorts);
842 for(std::set<OutPort *>::iterator iter4=trueOutPorts.begin();iter4!=trueOutPorts.end();++iter4)
843 ret.push_back(pair<InPort *, OutPort *>(*iter2,*iter4));
849 //! List all output ports of children nodes that are linked to out of scope input ports
851 * \note List all output ports of nodes sons of 'this' that are linked to input ports
852 * of nodes not in descendance of 'this'.
853 * This method contrary to getAllInPortsComingFromOutsideOfCurrentScope is NOT virtual
854 * because for the moment all daughter classes have no more hidden YACS::ENGINE::OutPort.
856 std::set<OutPort *> ComposedNode::getAllOutPortsLeavingCurrentScope() const
859 list<OutPort *> temp=getSetOfOutPort();
860 for(list<OutPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
862 set<InPort *> temp2=(*iter2)->edSetInPort();
863 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
864 if(!isInMyDescendance((*iter3)->getNode()))
873 //! List all input ports that are linked to out of scope ports
876 * List all input ports of 'this' so that, for each it exists at least 1 link coming
877 * from outside to it.
880 std::set<InPort *> ComposedNode::getAllInPortsComingFromOutsideOfCurrentScope() const
883 list<InPort *> temp=getSetOfInPort();
884 for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
886 set<OutPort *> temp2=(*iter2)->edSetOutPort();
887 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
889 if(!isInMyDescendance((*iter3)->getNode()))
898 void ComposedNode::edDisconnectAllLinksWithMe()
902 Node::edDisconnectAllLinksWithMe();
905 vector< pair<OutPort *, InPort *> > linksToDestroy=getSetOfLinksLeavingCurrentScope();
906 vector< pair<OutPort *, InPort *> >::iterator iter;
907 for(iter=linksToDestroy.begin();iter!=linksToDestroy.end();iter++)
910 (*iter).first->removeInPort((*iter).second,true);
913 vector< pair<InPort *, OutPort *> > linksToDestroy2=getSetOfLinksComingInCurrentScope();
914 vector< pair<InPort *, OutPort *> >::iterator iter2;
915 for(iter2=linksToDestroy2.begin();iter2!=linksToDestroy2.end();iter2++)
918 (*iter2).second->removeInPort((*iter2).first,true);
922 ComposedNode *ComposedNode::getRootNode() const throw(YACS::Exception)
925 return (ComposedNode *)this;
926 return Node::getRootNode();
929 //! Check that Node 'node' is already a direct son of this.
930 bool ComposedNode::isNodeAlreadyAggregated(const Node *node) const
932 list<ComposedNode *> nodeAncestors = node->getAllAscendanceOf();
933 return find(nodeAncestors.begin(),nodeAncestors.end(),(ComposedNode *)this)!=nodeAncestors.end();
936 //! Returns the parent of a node that is the direct child of this node
938 * \note if 'nodeToTest'=='this' this is returned. Else if 'nodeToTest' is in descendance of
939 * 'this' the direct son is returned.
940 * Else 0 is returned.
942 * \param nodeToTest : the node to check
944 Node *ComposedNode::isInMyDescendance(Node *nodeToTest) const
948 if((ComposedNode *)nodeToTest==this)
950 Node *iterBack=nodeToTest;
951 ComposedNode *iter=nodeToTest->_father;
952 while(iter!=0 && iter!=this)
963 string ComposedNode::getChildName(const Node* node) const throw(YACS::Exception)
965 string nodeName=node->getQualifiedName();
966 if (!isNodeAlreadyAggregated(node))
968 if (node->getName() == "thisIsAFakeNode")
970 string child = node->getName()+".thisIsAFakeNode";
975 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
976 throw Exception(what);
980 const Node *father = node->_father;
981 while (father != this)
983 nodeName = father->getQualifiedName() + SEP_CHAR_BTW_LEVEL + nodeName;
984 father = father->_father;
989 std::string ComposedNode::getMyQualifiedName(const Node *directSon) const
991 return directSon->getName();
994 Node *ComposedNode::getChildByName(const std::string& name) const throw(YACS::Exception)
996 string potentiallyDirectSonName, remainsPath;
997 bool forwardNeeded=ComposedNode::splitNamesBySep(name, SEP_CHAR_BTW_LEVEL,
998 potentiallyDirectSonName,remainsPath,false);
999 Node *child=getChildByShortName(potentiallyDirectSonName);
1003 return child->getChildByName(remainsPath);
1006 //! Check if a node is in the descendance of this node
1008 * \note Check that 'nodeToTest' is in descendance of 'this' OR equal to 'this'
1009 * \exception Exception : If 'nodeToTest' is NOT in descendance of 'this' AND not equal to 'this'
1010 * \param nodeToTest : the node to check
1012 void ComposedNode::checkInMyDescendance(Node *nodeToTest) const throw(YACS::Exception)
1014 const char whatC[]=" is not the descendance of node ";
1017 string what("node "); what+= nodeToTest->getName(); what+=" ";
1018 what+=whatC; what+=_name;
1019 throw Exception(what);
1021 if((ComposedNode *)nodeToTest==this)
1023 ComposedNode *iter=nodeToTest->_father;
1024 while(iter!=0 && iter!=this)
1028 string what("node "); what+= nodeToTest->getName(); what+=" ";
1029 what+=whatC; what+=_name;
1030 throw Exception(what);
1034 //! Retrieves the lowest common ancestor of 2 nodes
1037 * \note Retrieves the lowest common ancestor of 'node1' AND 'node2'.
1038 * If 'node1' or 'node2' are both or indiscriminately instances of ComposedNode and that
1039 * 'node1' is in descendance of 'node2' (resp. 'node2' in descendance of 'node1')
1040 * 'node2' is returned (resp. 'node1').
1041 * \exception Exception : if 'node1' and 'node2' do not share the same genealogy.
1042 * \return The lowest common ancestor if it exists.
1045 ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) throw(YACS::Exception)
1047 const char what[]="2 nodes does not share the same genealogy";
1048 if(node1==0 || node2==0)
1049 throw Exception(what);
1051 if(dynamic_cast<ComposedNode *>(node1))
1052 temp=(ComposedNode *)node1;//->_father;
1054 temp=(ComposedNode *)node1->_father;
1055 set<ComposedNode *> s;
1062 if(dynamic_cast<ComposedNode *>(node2))
1063 temp=(ComposedNode *)node2;//->_father;
1065 temp=(ComposedNode *)node2->_father;
1066 set<ComposedNode *>::iterator iter=s.find(temp);
1067 while(temp && iter==s.end())
1073 throw Exception(what);
1077 list<ElementaryNode *> ComposedNode::getRecursiveConstituents() const
1079 list<ElementaryNode *> ret;
1080 list<Node *> setOfNode=edGetDirectDescendants();
1081 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1083 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1084 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1089 //! Idem getAllRecursiveNodes, but this node is NOT included.
1090 list<Node *> ComposedNode::getAllRecursiveConstituents()
1093 list<Node *> setOfNode=edGetDirectDescendants();
1094 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1096 if ( dynamic_cast<ComposedNode*> (*iter) )
1098 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveConstituents();
1099 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1100 ret.push_back(*iter);
1104 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1105 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1111 //! Get all children nodes elementary and composed including this node
1112 list<Node *> ComposedNode::getAllRecursiveNodes()
1115 list<Node *> setOfNode=edGetDirectDescendants();
1116 for(list<Node *>::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1118 if ( dynamic_cast<ElementaryNode*> (*iter) )
1120 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1121 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1125 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveNodes();
1126 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1129 ret.push_back(this);
1133 //! Get the input port name
1135 * get the input port name used by the current node, recursively built with children names.
1138 string ComposedNode::getInPortName(const InPort * inPort) const throw(YACS::Exception)
1140 return getPortName<InPort>(inPort);
1143 string ComposedNode::getOutPortName(const OutPort *outPort) const throw(YACS::Exception)
1145 return getPortName<OutPort>(outPort);
1148 int ComposedNode::getNumberOfInputPorts() const
1150 list<Node *> constituents=edGetDirectDescendants();
1152 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1153 ret+=(*iter)->getNumberOfInputPorts();
1157 int ComposedNode::getNumberOfOutputPorts() const
1159 list<Node *> constituents=edGetDirectDescendants();
1161 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1162 ret+=(*iter)->getNumberOfOutputPorts();
1166 list<InputPort *> ComposedNode::getSetOfInputPort() const
1168 list<Node *> constituents=edGetDirectDescendants();
1169 list<InputPort *> ret;
1170 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1172 list<InputPort *> currentsPorts=(*iter)->getSetOfInputPort();
1173 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1178 list<OutputPort *> ComposedNode::getSetOfOutputPort() const
1180 list<Node *> constituents=edGetDirectDescendants();
1181 list<OutputPort *> ret;
1182 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1184 list<OutputPort *> currentsPorts=(*iter)->getSetOfOutputPort();
1185 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1190 list<InputDataStreamPort *> ComposedNode::getSetOfInputDataStreamPort() const
1192 list<Node *> constituents=edGetDirectDescendants();
1193 list<InputDataStreamPort *> ret;
1194 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1196 list<InputDataStreamPort *> currentsPorts=(*iter)->getSetOfInputDataStreamPort();
1197 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1202 list<OutputDataStreamPort *> ComposedNode::getSetOfOutputDataStreamPort() const
1204 list<Node *> constituents=edGetDirectDescendants();
1205 list<OutputDataStreamPort *> ret;
1206 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1208 list<OutputDataStreamPort *> currentsPorts=(*iter)->getSetOfOutputDataStreamPort();
1209 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1214 OutPort *ComposedNode::getOutPort(const std::string& name) const throw(YACS::Exception)
1216 string portName, nodeName;
1217 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1219 Node *child = getChildByShortName(nodeName);
1220 return child->getOutPort(portName);
1224 string what("ComposedNode::getOutPort : the port with name "); what+=name; what+=" does not exist on the current level";
1225 throw Exception(what);
1229 //! Get an input port given its name
1231 * Contrary to YACS::ENGINE::ComposedNode::getOutputPort, this method is \b NOT recursive
1232 * and so the leaf of type ElementaryNode aggregating
1233 * this InputPort is directly invoked.
1235 InputPort * ComposedNode::getInputPort(const std::string& name) const throw(YACS::Exception)
1238 return Node::getInputPort(name);
1240 catch(Exception& e) {}
1242 string portName, nodeName;
1243 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1245 Node *child = getChildByName(nodeName);
1246 return child->getInputPort(portName);
1250 string what("ComposedNode::getInputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1251 throw Exception(what);
1255 //! Get an output port given its name
1257 * Contrary to YACS::ENGINE::ComposedNode::getInputPort, this method is recursive and go
1258 * down hierarchy step by step to complete its work.
1260 OutputPort * ComposedNode::getOutputPort(const std::string& name) const throw(YACS::Exception)
1262 string portName, nodeName;
1263 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1265 Node *child = getChildByShortName(nodeName);
1266 return child->getOutputPort(portName);
1270 string what("ComposedNode::getOutputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1271 throw Exception(what);
1275 InputDataStreamPort *ComposedNode::getInputDataStreamPort(const std::string& name) const throw(YACS::Exception)
1277 string portName, nodeName;
1278 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1280 Node *child = getChildByName(nodeName);
1281 return child->getInputDataStreamPort(portName);
1285 string what("ComposedNode::getInputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1286 throw Exception(what);
1290 OutputDataStreamPort *ComposedNode::getOutputDataStreamPort(const std::string& name) const throw(YACS::Exception)
1292 string portName, nodeName;
1293 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1295 Node *child = getChildByName(nodeName);
1296 return child->getOutputDataStreamPort(portName);
1300 string what("ComposedNode::getOutputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1301 throw Exception(what);
1305 //! Update node state on receiving event from a node
1308 * \note Runtime called method. Perform, the state updating, from the son node 'node'
1309 * emitting the event 'event' (among Executor static const var).
1310 * WARNING Precondition : this == node->_father
1311 * \return The event (among Executor static const var) destinated to this->_father node
1312 * to perform eventually up level update.
1314 * Calls ComposedNode::updateStateOnStartEventFrom if event is YACS::START
1316 * Calls ComposedNode::updateStateOnFinishedEventFrom if event is YACS::FINISH
1318 * Called by ComposedNode::notifyFrom
1320 YACS::Event ComposedNode::updateStateFrom(Node *node, //* I : node emitting event
1321 YACS::Event event //* I : event emitted
1324 DEBTRACE("updateStateFrom: " << node->getName() << " " << event);
1330 return updateStateOnStartEventFrom(node);
1333 return updateStateOnFinishedEventFrom(node);
1336 return updateStateOnFailedEventFrom(node);
1339 return YACS::NOEVENT;//TODO unexpected type of event
1343 catch(YACS::Exception& ex)
1345 //unexpected exception: probably a bug in engine
1346 //try to keep a consistent global state
1347 DEBTRACE( "updateStateFrom: " << ex.what() );
1348 _errorDetails="Internal error: ";
1349 _errorDetails=_errorDetails + ex.what();
1350 setState(YACS::ERROR);
1356 //unexpected exception: probably a bug in engine
1357 //try to keep a consistent global state
1358 setState(YACS::ERROR);
1364 //! Method used to notify the node that a child node has started
1366 * Update the ComposedNode state and return the ComposedNode change state
1368 * \param node : the child node that has started
1369 * \return the loop state change
1371 YACS::Event ComposedNode::updateStateOnStartEventFrom(Node *node)
1373 setState(YACS::ACTIVATED);
1377 //! Method used to notify the node that a child node has failed
1378 YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node)
1380 setState(YACS::FAILED);
1384 void ComposedNode::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
1385 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
1387 if((dynamic_cast<DataFlowPort *>(start) || dynamic_cast<DataFlowPort *>(end))
1388 && (dynamic_cast<DataStreamPort *>(start) || dynamic_cast<DataStreamPort *>(end)))
1389 {//cross protocol required : deeper check needed
1391 list<ComposedNode *>::const_iterator iter;
1392 for(iter=pointsOfViewStart.begin();iter!=pointsOfViewStart.end() && !isOK;iter++)
1393 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1394 for(iter=pointsOfViewEnd.begin();iter!=pointsOfViewEnd.end() && !isOK;iter++)
1395 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1397 throw Exception("ComposedNode::checkLinkPossibility : Request for cross protocol link impossible.");
1401 void ComposedNode::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
1405 void ComposedNode::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
1409 void ComposedNode::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1413 void ComposedNode::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1417 void ComposedNode::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1421 void ComposedNode::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
1425 void ComposedNode::loaded()
1428 void ComposedNode::connected()
1432 void ComposedNode::accept(Visitor *visitor)
1434 list<Node *> constituents=edGetDirectDescendants();
1435 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1437 (*iter)->accept(visitor);
1441 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1442 std::list<InputPort *> ComposedNode::getLocalInputPorts() const
1444 std::list<InputPort *> lip; return lip; // empty list
1447 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1448 std::list<OutputPort *> ComposedNode::getLocalOutputPorts() const
1450 std::list<OutputPort *> lop; return lop; // empty list
1453 bool ComposedNode::isNameAlreadyUsed(const std::string& name) const
1458 void ComposedNode::edUpdateState()
1460 DEBTRACE("ComposedNode::edUpdateState(): " << _state << " " << _modified);
1461 YACS::StatesForNode state=YACS::READY;
1465 checkBasicConsistency();
1470 state=YACS::INVALID;
1471 _errorDetails=e.what();
1473 DEBTRACE("ComposedNode::edUpdateState: " << _errorDetails);
1475 //update children if needed
1476 list<Node *> constituents=edGetDirectDescendants();
1477 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1479 if(!(*iter)->isValid())
1480 state=YACS::INVALID;
1487 std::string ComposedNode::getErrorReport()
1489 DEBTRACE("ComposedNode::getErrorReport: " << getName() << " " << _state);
1490 YACS::StatesForNode effectiveState=getEffectiveState();
1492 if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
1495 std::string report="<error node= " + getName();
1496 switch(effectiveState)
1499 report=report+" state= INVALID";
1502 report=report+" state= ERROR";
1505 report=report+" state= FAILED";
1510 report=report + ">\n" ;
1511 if(_errorDetails != "")
1512 report=report+_errorDetails+"\n";
1514 list<Node *> constituents=edGetDirectDescendants();
1515 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1517 std::string rep=(*iter)->getErrorReport();
1520 report=report+rep+"\n";
1523 report=report+"</error>";
1529 void ComposedNode::checkBasicConsistency() const throw(YACS::Exception)
1531 DEBTRACE("ComposedNode::checkBasicConsistency");
1532 std::list<InputPort *>::const_iterator iter;
1533 std::list<InputPort *> inports=getLocalInputPorts();
1534 for(iter=inports.begin();iter!=inports.end();iter++)
1535 (*iter)->checkBasicConsistency();
1538 //! Stop all pending activities of the composed node
1540 * This method should be called when a Proc is finished and must be deleted from the YACS server
1542 void ComposedNode::shutdown(int level)
1545 DEBTRACE("ComposedNode::shutdown");
1546 list<Node *> nodes=edGetDirectDescendants();
1547 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1548 (*iter)->shutdown(level);
1551 //! Clean the composed node in case of not clean exit
1553 * This method should be called on a control-c or sigterm
1555 void ComposedNode::cleanNodes()
1557 DEBTRACE("ComposedNode::cleanNodes");
1558 list<Node *> nodes=edGetDirectDescendants();
1559 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1560 (*iter)->cleanNodes();
1563 //! Reset the state of the node and its children depending on the parameter level
1564 void ComposedNode::resetState(int level)
1568 DEBTRACE("ComposedNode::resetState " << level << "," << _state);
1569 if( _state==YACS::ERROR || _state==YACS::FAILED || _state==YACS::ACTIVATED )
1571 Node::resetState(level);
1572 std::list<Node *> nodes=edGetDirectDescendants();
1573 for(std::list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
1574 (*iter)->resetState(level);