1 // Copyright (C) 2006-2008 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
19 #include "ComposedNode.hxx"
20 #include "LinkInfo.hxx"
21 #include "Container.hxx"
22 #include "InputPort.hxx"
23 #include "OutputPort.hxx"
24 #include "ServiceNode.hxx"
25 #include "DataFlowPort.hxx"
26 #include "DataStreamPort.hxx"
27 #include "ElementaryNode.hxx"
28 #include "ComponentInstance.hxx"
37 #include "YacsTrace.hxx"
39 using namespace YACS::ENGINE;
42 const char ComposedNode::SEP_CHAR_BTW_LEVEL[]=".";
44 ComposedNode::ComposedNode(const std::string& name):Node(name)
48 ComposedNode::ComposedNode(const ComposedNode& other, ComposedNode *father):Node(other,father)
52 ComposedNode::~ComposedNode()
56 void ComposedNode::performDuplicationOfPlacement(const Node& other)
58 const ComposedNode &otherC=*(dynamic_cast<const ComposedNode *>(&other));
59 DeploymentTree treeToDup=otherC.getDeploymentTree();
60 list< ElementaryNode * > clones=otherC.getRecursiveConstituents();
61 vector<Container *> conts=treeToDup.getAllContainers();
62 for(vector<Container *>::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++)
64 vector<ComponentInstance *> comps=treeToDup.getComponentsLinkedToContainer(*iterCt);
65 Container *contCloned=0;
67 contCloned=(*iterCt)->clone();
68 for(vector<ComponentInstance *>::iterator iterCp=comps.begin();iterCp!=comps.end();iterCp++)
70 vector<Task *> tasks=treeToDup.getTasksLinkedToComponent(*iterCp);
71 ComponentInstance *curCloned=(*iterCp)->clone();
72 curCloned->setContainer(contCloned);
73 for(vector<Task *>::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++)
75 //No risk for static cast : appendTask called by ComposedNode.
76 list< ElementaryNode * >::iterator res=find(clones.begin(),clones.end(),(ElementaryNode *)(*iterT));
77 //No risk here to because called only on cloning process...
78 ServiceNode *nodeC=(ServiceNode *)getChildByName(otherC.getChildName(*res));
79 nodeC->setComponent(curCloned);
84 contCloned->decrRef();
88 bool ComposedNode::isFinished()
90 if(_state==YACS::DONE)return true;
91 if(_state==YACS::ERROR)return true;
92 if(_state==YACS::FAILED)return true;
93 if(_state==YACS::DISABLED)return true;
97 void ComposedNode::init(bool start)
102 std::string ComposedNode::getName() const
104 return Node::getName();
107 std::string ComposedNode::getTaskName(Task *task) const
109 return getChildName(dynamic_cast<ElementaryNode *>(task));
112 //! Essentially for test. Use checkDeploymentTree instead to be sure that returned DeploymentTree is consistent.
113 DeploymentTree ComposedNode::getDeploymentTree() const
116 list< ElementaryNode * > tasks=getRecursiveConstituents();
117 for(list< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++)
118 ret.appendTask(*iter,(*iter)->getDynClonerIfExists(this));
122 //! Perform check of deployment consistency of the current graph.
124 * \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.
126 DeploymentTree ComposedNode::checkDeploymentTree(bool deep) const throw(Exception)
129 list< ElementaryNode * > tasks=getRecursiveConstituents();
130 for(list< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++)
132 switch(ret.appendTask(*iter,(*iter)->getDynClonerIfExists(this)))
134 case DeploymentTree::DUP_TASK_NOT_COMPATIBLE_WITH_EXISTING_TREE:
136 string what("ComposedNode::checkDeploymentTree : ServiceNode with name \""); what+=(*iter)->getName();
137 what+="\" coexists in a component with an another Task which context is incorrect with it.";
138 throw Exception(what);
140 case DeploymentTree::DEPLOYABLE_BUT_NOT_SPECIFIED :
144 string what("ComposedNode::checkDeploymentTree : ServiceNode with name \""); what+=(*iter)->getName();
145 what+="\" is deployable but no component is specified on it.";
146 throw Exception(what);
154 std::vector<Task *> ComposedNode::getNextTasks(bool& isMore)
163 //! Notify the node a task has emitted an event
166 * \note Runtime called method. Overloads the Scheduler::notifyFrom abstract method.
167 * Typically Called in Executor (in a parallel thread or not) by the Task 'task'
168 * to inform the scheduler that an event coded 'event' (in Executor static const var) happened.
169 * Contrary to updateStateFrom several levels may exist between 'sender' and 'this'.
171 * \param sender : task emitting event
172 * \param event : event emitted
174 * Called by Executor::functionForTaskExecution on YACS::FINISH event
176 * Called by Executor::launchTask on YACS::START event
178 * Calls ComposedNode::updateStateFrom to update state from task to root node
180 void ComposedNode::notifyFrom(const Task *sender, //* I : task emitting event
181 YACS::Event event //* I : event emitted
184 DEBTRACE("ComposedNode::notifyFrom " << event);
185 ElementaryNode *taskTyped=dynamic_cast<ElementaryNode *>((Task *)sender);
186 YACS::Event curEvent=event;
187 Node *lminus1LevelNode=taskTyped;
188 ComposedNode *curLevelNode=taskTyped->_father;
189 if(!curLevelNode)//Specific case of loop when 0 turn is specified without any enclosing bloc.
191 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
192 while(curEvent!=YACS::NOEVENT && curLevelNode!=this)
194 lminus1LevelNode=curLevelNode;
195 curLevelNode=curLevelNode->_father;
196 curEvent=curLevelNode->updateStateFrom(lminus1LevelNode,curEvent);
200 //! Add a dataflow link between two data ports.
202 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
203 * \exception Exception : if incompatibility between input and output (type), or 'start'/'end'
204 * is/are NOT in/outputPort contained in a node in descendance
205 * of 'this', or a multiple link to an input not supporting it.
206 * \return true if a new link has been created, false otherwise.
209 bool ComposedNode::edAddLink(OutPort *start, InPort *end) throw(Exception)
211 DEBTRACE("ComposedNode::edAddLink");
212 set<OutPort *> represented;
214 start->getAllRepresented(represented);
215 if(represented.size()!=1)
218 for(set<OutPort *>::iterator iter=represented.begin();iter!=represented.end();iter++)
219 ret|=edAddLink(*iter,end);
222 if(start->isAlreadyLinkedWith(end))
224 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
225 list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
226 list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
227 checkInMyDescendance(lwstCmnAnctr);
228 lwstCmnAnctr->checkLinkPossibility(start,allAscendanceOfNodeStart,end,allAscendanceOfNodeEnd);
230 if(dynamic_cast<ComposedNode *>(start->getNode()))
231 iterS=(ComposedNode *)start->getNode();
233 iterS=start->getNode()->_father;
234 pair<OutPort *, OutPort *> pO(start,start);
235 while(iterS!=lwstCmnAnctr)
237 iterS->buildDelegateOf(pO, end, allAscendanceOfNodeEnd);
238 iterS=iterS->_father;
240 if(dynamic_cast<ComposedNode *>(end->getNode()))
241 iterS=(ComposedNode *)end->getNode();
243 iterS=end->getNode()->_father;
245 InPort *currentPortI=end;
246 while(iterS!=lwstCmnAnctr)
248 iterS->buildDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
249 iterS=iterS->_father;
251 bool ret=(pO.first)->addInPort(currentPortI);
252 end->edNotifyReferencedBy(pO.second);
256 //! Connect an OutPort to an InPort and add the necessary control link
258 * Connect the ports with a data link (edAddLink) and add
259 * a control flow link between the children of the lowest common ancestor node.
261 * \param start : the OutPort to connect
262 * \param end : the InPort to connect
263 * \return true if a new link has been created, false otherwise.
265 bool ComposedNode::edAddDFLink(OutPort *start, InPort *end) throw(Exception)
267 Node* n1=start->getNode();
268 Node* n2=end->getNode();
269 DEBTRACE( n1->getName() << ":" << n2->getName())
270 ComposedNode* father=getLowestCommonAncestor(n1,n2);
271 DEBTRACE( "ComposedNode::edAddDFLink: this="<<this->getName()
272 << " father=" << father->getName() )
273 DEBTRACE( "ComposedNode::edAddDFLink: OutPort=" << start->getName()
274 << " InPort=" << end->getName() )
277 bool ret = father->edAddDFLink(start,end); // special treatement for loop
281 throw Exception("Back link authorized only in special context (loop for example)");
283 bool ret= edAddLink(start,end);
286 //add a control link only if nodes are not in the same descendance
287 //if n1 == father (n2 is after n1) : the control link is not needed
288 //if n2 == father (n1 is after n2) : it's a back link authorized only in loop context
289 while(n1->getFather() != father)
291 while(n2->getFather() != father)
297 catch (Exception& ex)
299 // --- remove DF link already created in case of cycle dtection
300 DEBTRACE("Cycle detected, remove CF link");
301 if(start->isAlreadyLinkedWith(end))
302 edRemoveLink(start, end);
309 //! Add a controlflow link between two control ports.
311 * \note Precondition : 'start' AND 'end' are in/outGate contained in a node
312 * in DIRECT descendance of 'this'.
313 * \exception Exception : If a cycle has been detected, or incompatibility
314 * between input and output, or 'start'/'end' is/are NOT in/outputPort contained
315 * in a node in descendance of 'this', or a mutilple link to an input not
317 * \return true if a new link has been created, false otherwise.
319 bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(Exception)
321 Node* n1=start->getNode();
322 Node* n2=end->getNode();
324 throw Exception("ComposedNode::edAddLink: can not add a control link to a node with itself");
325 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
327 throw Exception("ComposedNode::edAddLink: Trying to add CF link on orphan nodes.");
330 checkInMyDescendance(father);
331 return father->edAddLink(start,end);
333 bool ret=start->edAddInGate(end);
337 checkNoCyclePassingThrough(end->getNode());
339 catch (Exception& ex)
341 // --- remove created CF link in case of cycle detection
342 DEBTRACE("Cycle detected, remove CF link");
343 edRemoveCFLink(start->getNode(), end->getNode());
349 //! Add a controlflow link between two nodes.
351 * Add a controlflow link between two nodes by calling edAddLink on their control ports
353 bool ComposedNode::edAddCFLink(Node *nodeS, Node *nodeE) throw(Exception)
355 return edAddLink(nodeS->getOutGate(),nodeE->getInGate());
358 //! Remove a controlflow link.
359 void ComposedNode::edRemoveCFLink(Node *nodeS, Node *nodeE) throw(Exception)
361 edRemoveLink(nodeS->getOutGate(),nodeE->getInGate());
364 //! Remove a dataflow link.
366 * Precondition : 'start' AND 'end' are in/outputPort contained in a node in descendance of 'this'.
368 * \exception Exception : If the specified link does not exist. The content of Exception
369 * is different in accordance with the link from 'start' to 'end'
370 * implies DF/DS gateway.
373 void ComposedNode::edRemoveLink(OutPort *start, InPort *end) throw(Exception)
375 if(!start->isAlreadyLinkedWith(end))
376 throw Exception("ComposedNode::edRemoveLink : unexisting link");
377 ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode());
378 checkInMyDescendance(lwstCmnAnctr);
379 list<ComposedNode *> allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr);
380 list<ComposedNode *> allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr);
382 // --- Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created
384 ComposedNode *iterS=start->getNode()->_father;
385 pair<OutPort *,OutPort *> currentPortO(start,start);
386 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > > needsToDestroyO;
388 Node *nodeOTemp=start->getNode();
389 if(*nodeOTemp<*lwstCmnAnctr)
391 iterS=nodeOTemp->_father;
392 while(iterS!=lwstCmnAnctr)
397 what << "ComposedNode::edRemoveLink: "
398 << start->getNode()->getName() << "." <<start->getName() << "->"
399 << end->getNode()->getName() << "." << end->getName();
400 throw Exception(what.str());
402 OutPort *tmp=currentPortO.first;
403 iterS->getDelegateOf(currentPortO, end, allAscendanceOfNodeEnd);
404 needsToDestroyO.push_back(pair< ComposedNode * , pair < OutPort* , OutPort *> >(iterS,pair<OutPort* , OutPort *> (tmp,currentPortO.first)));
405 iterS=iterS->_father;
408 Node *nodeTemp=end->getNode();
409 InPort * currentPortI=end;
410 if(*nodeTemp<*lwstCmnAnctr)
412 iterS=nodeTemp->_father;
413 while(iterS!=lwstCmnAnctr)
418 what << "ComposedNode::edRemoveLink: "
419 << start->getNode()->getName() << "." <<start->getName() << "->"
420 << end->getNode()->getName() << "." << end->getName();
421 throw Exception(what.str());
423 iterS->getDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
424 iterS=iterS->_father;
427 // --- End of test for evt intermediate ports created
429 (currentPortO.first)->removeInPort(currentPortI,false);
431 (currentPortO.second)->getAllRepresented(repr);
433 end->edNotifyDereferencedBy(currentPortO.second);
435 // --- Performing deletion of intermediate ports
437 iterS=start->getNode()->_father;
438 vector<pair< ComposedNode * , pair < OutPort* , OutPort *> > >::reverse_iterator iter;
439 for(iter=needsToDestroyO.rbegin();iter!=needsToDestroyO.rend();iter++)
440 (*iter).first->releaseDelegateOf(((*iter).second).first, ((*iter).second).second, end,allAscendanceOfNodeEnd);
441 nodeTemp=end->getNode();
442 if(*nodeTemp<*lwstCmnAnctr)
444 iterS=end->getNode()->_father;
446 while(iterS!=lwstCmnAnctr)
448 iterS->releaseDelegateOf(currentPortI, start, allAscendanceOfNodeStart);
449 iterS=iterS->_father;
454 //! Remove a controlflow link.
455 void ComposedNode::edRemoveLink(OutGate *start, InGate *end) throw(Exception)
457 ComposedNode* father=checkHavingCommonFather(start->getNode(),end->getNode());
459 throw Exception("edRemoveLink : nodes not in direct descendance of this");
460 start->edRemoveInGate(end);
463 bool ComposedNode::edAddChild(Node *DISOWNnode) throw(Exception)
465 return false; // --- reimplemented in derived classes
468 //! Remove a child node.
469 void ComposedNode::edRemoveChild(Node *node) throw(Exception)
473 if (node->_father!=this)
475 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
476 throw Exception(what);
478 node->edDisconnectAllLinksWithMe();
480 //set _modified flag so edUpdateState() can refresh state
484 //! Splits name globalName in 2 parts using separator.
486 * \note 'priority' specifies if during search process of 'separator' the max part is
487 * for 'firstPart' (priority=true) or 'lastPart' (priority=false).
489 * \throw Exception : 'lastPart' or 'firstPart' is empty.
490 * \return true if split process succeeds false otherwise (typically when character
491 * separator was not found).
493 bool ComposedNode::splitNamesBySep(const std::string& globalName, const char separator[],
494 std::string& firstPart, std::string& lastPart, bool priority) throw(Exception)
496 const string delims(separator);
497 string portName, nodeName;
498 string::size_type idx;
500 idx = globalName.find_last_of(delims);
502 idx = globalName.find_first_of(delims);
503 if (idx == string::npos)
505 firstPart=globalName;
509 firstPart = globalName.substr(0,idx);
510 lastPart = globalName.substr(idx+1);
511 if ((firstPart.empty()) or (lastPart.empty()))
513 string what("the name "); what+= globalName ; what+=" is not a valid port name";
514 throw Exception(what);
519 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfInternalLinks() const
521 vector< pair<OutPort *, InPort *> > ret;
522 list<OutPort *> temp=getSetOfOutPort();
523 for(list<OutPort *>::const_iterator iter2=temp.begin();iter2!=temp.end();iter2++)
525 set<InPort *> temp2=(*iter2)->edSetInPort();
526 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
527 if(isInMyDescendance((*iter3)->getNode()))
528 ret.push_back(pair<OutPort *, InPort *>((*iter2),(*iter3)));
533 std::vector< std::pair<OutPort *, InPort *> > ComposedNode::getSetOfLinksLeavingCurrentScope() const
535 vector< pair<OutPort *, InPort *> > ret;
536 std::set<OutPort *> ports=getAllOutPortsLeavingCurrentScope();
537 for(set<OutPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
539 set<InPort *> temp2=(*iter2)->edSetInPort();
540 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
541 if(!isInMyDescendance((*iter3)->getNode()))
542 ret.push_back(pair<OutPort *, InPort *>(*iter2,*iter3));
547 void ComposedNode::checkConsistency(LinkInfo& info) const throw(Exception)
550 info.setPointOfView((ComposedNode *)this);
551 performCFComputations(info);
552 list<InputPort *> setOfInToTest=getSetOfInputPort();
553 for(list<InputPort *>::iterator iter1=setOfInToTest.begin();iter1!=setOfInToTest.end();iter1++)
555 vector<OutPort *> candidateForAdvCheck;
556 set<OutPort *> outPorts=(*iter1)->edSetOutPort();
557 //Filtering among outPorts, which of them, are candidates to fill *iter1 at the current scope.
558 for(set<OutPort *>::iterator iter2=outPorts.begin();iter2!=outPorts.end();iter2++)
560 (*iter2)->checkConsistency(info);
561 ComposedNode *manager=getLowestCommonAncestor((*iter2)->getNode(),(*iter1)->getNode());
562 if(isInMyDescendance(manager))
563 candidateForAdvCheck.push_back(*iter2);
565 if(!candidateForAdvCheck.empty())
566 //End of filtering. Now regarding CF constraints for the current InPutPort.
567 checkLinksCoherenceRegardingControl(candidateForAdvCheck,*iter1,info);
570 if(!(*iter1)->edIsManuallyInitialized())
571 info.pushErrLink(0,*iter1,E_NEVER_SET_INPUTPORT);
573 destructCFComputations(info);
577 * This method check that G1 <- G2 <- G3 <- G1 does not happened.
578 * Typically called by methods that set a hierarchy (Bloc::edAddChild, Loop::edSetNode, ...).
580 void ComposedNode::checkNoCrossHierachyWith(Node *node) const throw (Exception)
582 ComposedNode *nodeC=dynamic_cast<ComposedNode *>(node);
585 list<ComposedNode *> ascendants=getAllAscendanceOf();
586 if(find(ascendants.begin(),ascendants.end(),nodeC)!=ascendants.end())
588 const char what[]="ComposedNode::checkNoCrossHierachyWith : ComposedNode with name \"";
589 string stream(what); stream+=node->getName(); stream+="\" is already in hierarchy ascendance of node with name \"";
590 stream+=_name; stream+="\" ; So it can't be now in its descendance !";
591 throw Exception(stream);
595 //! perform \b recursively all CF computations.
596 void ComposedNode::performCFComputations(LinkInfo& info) const
598 list<Node *> nodes=edGetDirectDescendants();
599 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
600 if(dynamic_cast<ComposedNode *>(*iter))
601 ((ComposedNode *)(*iter))->performCFComputations(info);
604 //! destroy \b recursively all results of initial computations.
605 void ComposedNode::destructCFComputations(LinkInfo& info) const
607 list<Node *> nodes=edGetDirectDescendants();
608 for(list<Node *>::iterator iter=nodes.begin();iter!=nodes.end();iter++)
609 if(dynamic_cast<ComposedNode *>(*iter))
610 ((ComposedNode *)(*iter))->destructCFComputations(info);
614 * Returns the lowest Node (Elementary or Composed) (is sense of hierachy level ( operator< ) ) containing all 'ports'.
615 * Typically use in consistency computation.
616 * Precondition : 'ports' \b must contain at least one element. All elements of 'ports' should be in descendance of 'this'.
618 Node *ComposedNode::getLowestNodeDealingAll(const std::list<OutPort *>& ports) const
620 list< OutPort *>::const_iterator iter=ports.begin();
621 Node *ret=(*iter)->getNode();
623 for(;iter!=ports.end();iter++)
625 Node *tmp=(*iter)->getNode();
633 * call it only for 'starts' to 'end' links \b DEALED by 'this'.
635 void ComposedNode::checkLinksCoherenceRegardingControl(const std::vector<OutPort *>& starts, InputPort *end, LinkInfo& info) const throw(Exception)
637 map < ComposedNode *, list<OutPort *>, SortHierarc > outputs;//forward link classical
638 vector<OutPort *> outputsCross;//forward link cross
639 map < ComposedNode *, list<OutPort *>, SortHierarc > outputsBw;//backward
640 vector<OutPort *>::const_iterator iter1;
641 //vector<DataPort *> history=((*iter1).second)[0]->calculateHistoryOfLinkWith(end);
642 //DataPort *cross=DataPort::isCrossingType(history);
643 for(iter1=starts.begin();iter1!=starts.end();iter1++)
645 ComposedNode *manager=getLowestCommonAncestor((*iter1)->getNode(),end->getNode());
646 manager->checkControlDependancy((*iter1), end, false, outputs, outputsCross, outputsBw, info);
648 //Ok now let's regarding outputs all combinations : (outputs.size())*(outputs.size()-1)/2
649 unsigned char isAlreadyFed=FREE_ST;
650 //Dealing excusively with DS. Level is useless here because simultaneity is required for DS.
651 if(outputsCross.size()>0)
653 isAlreadyFed=FED_DS_ST;
654 if(outputsCross.size()>1)
655 for(vector< OutPort *>::const_iterator iter1=outputsCross.begin();iter1!=(outputsCross.end()-2);iter1++)
656 info.pushErrLink(*iter1,end,E_COLLAPSE_DS);
658 map < ComposedNode *, list<OutPort *>, SortHierarc >::iterator iter3=outputs.begin();
659 for(;iter3!=outputs.end();iter3++)
660 ((*iter3).first)->checkCFLinks((*iter3).second,end,isAlreadyFed,true,info);
661 if(isAlreadyFed==FREE_ST)
662 if(!end->edIsManuallyInitialized())
663 info.pushErrLink(0,end,E_ONLY_BACKWARD_DEFINED);
664 isAlreadyFed=FREE_ST;
666 map < ComposedNode *, list<OutPort *>, SortHierarc >::reverse_iterator iter5=outputsBw.rbegin();
667 for(;iter5!=outputsBw.rend();iter5++)
668 ((*iter5).first)->checkCFLinks((*iter5).second,end,isAlreadyFed,false,info);
672 * Internal method during CF links. This méthode is in charge to statuate on links consistency in the case that no control flow defined by user
675 void ComposedNode::solveObviousOrDelegateCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
677 static const char what[]="ComposedNode::solveObviousOrDelegateCFLinks : Internal error occured - uncorrect hierarchy detected !";
680 if(alreadyFed==FREE_ST)
683 info.pushInfoLink(*(starts.begin()),end,I_BACK);
686 else if(alreadyFed==FED_ST)
687 info.pushInfoLink(*(starts.begin()),end,direction ? I_USELESS : I_BACK_USELESS);
689 info.pushErrLink(*(starts.begin()),end,E_COLLAPSE_DFDS);
693 Node *levelOfDecision=getLowestNodeDealingAll(starts);
694 if(levelOfDecision==this)
695 throw Exception(what);
696 if(dynamic_cast<ElementaryNode *>(levelOfDecision))
699 if(alreadyFed==FREE_ST || alreadyFed==FED_ST)
701 if(alreadyFed==FREE_ST)
703 reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL;
707 reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS;
708 for(list< OutPort *>::const_iterator iter=starts.begin();iter!=starts.end();iter++)
709 info.pushWarnLink(*iter,end,reason);
713 ((ComposedNode *)levelOfDecision)->checkCFLinks(starts,end,alreadyFed,direction,info);
718 * \param starts If different of 0, must aggregate at leat \b 1 element.
719 * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port.
720 * \param direction If true : forward direction else backward direction.
722 void ComposedNode::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
724 static const char what[]="ComposedNode::checkCFLinks : Internal error occured - uncorrect hierarchy detected !";
725 Node *nodeEnd=isInMyDescendance(end->getNode());
727 return solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
728 //This case is typically dedicated when direct son is ElementaryNode and self link is defined on this.
729 if(!dynamic_cast<ElementaryNode *>(nodeEnd))
730 throw Exception(what);
731 list< OutPort *>::const_iterator iter=starts.begin();
732 Node *nodeStart=(*iter)->getNode();
734 if(nodeEnd!=nodeStart)
735 throw Exception(what);
736 for(;iter!=starts.end();iter++)
737 if((*iter)->getNode()!=nodeStart)
738 throw Exception(what);
739 //Ok at this step we are sure that we have back links on the same elementary node.
741 for(iter=starts.begin();iter!=starts.end();iter++)
742 info.pushWarnLink(*iter,end,W_BACK_COLLAPSE_EL);
743 else//here no need to look at 'alreadyFed' var because it is waranteed to be equal to FREE_ST by construction.
744 info.pushInfoLink(*(starts.begin()),end,I_BACK);
748 std::vector< std::pair<InPort *, OutPort *> > ComposedNode::getSetOfLinksComingInCurrentScope() const
750 vector< pair<InPort *, OutPort *> > ret;
751 set<InPort *> ports=getAllInPortsComingFromOutsideOfCurrentScope();
752 for(set<InPort *>::iterator iter2=ports.begin();iter2!=ports.end();iter2++)
754 set<OutPort *> temp2=(*iter2)->edSetOutPort();
755 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
756 if(!isInMyDescendance((*iter3)->getNode()))
757 ret.push_back(pair<InPort *, OutPort *>(*iter2,*iter3));
762 //! List all output ports of children nodes that are linked to out of scope input ports
764 * \note List all output ports of nodes sons of 'this' that are linked to input ports
765 * of nodes not in descendance of 'this'.
766 * This method contrary to getAllInPortsComingFromOutsideOfCurrentScope is NOT virtual
767 * because for the moment all daughter classes have no more hidden YACS::ENGINE::OutPort.
769 std::set<OutPort *> ComposedNode::getAllOutPortsLeavingCurrentScope() const
772 list<OutPort *> temp=getSetOfOutPort();
773 for(list<OutPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
775 set<InPort *> temp2=(*iter2)->edSetInPort();
776 for(set<InPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
777 if(!isInMyDescendance((*iter3)->getNode()))
786 //! List all input ports that are linked to out of scope ports
789 * List all input ports of 'this' so that, for each it exists at least 1 link coming
790 * from outside to it.
793 std::set<InPort *> ComposedNode::getAllInPortsComingFromOutsideOfCurrentScope() const
796 list<InPort *> temp=getSetOfInPort();
797 for(list<InPort *>::iterator iter2=temp.begin();iter2!=temp.end();iter2++)
799 set<OutPort *> temp2=(*iter2)->edSetOutPort();
800 for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
802 if(!isInMyDescendance((*iter3)->getNode()))
811 void ComposedNode::edDisconnectAllLinksWithMe()
815 Node::edDisconnectAllLinksWithMe();
818 vector< pair<OutPort *, InPort *> > linksToDestroy=getSetOfLinksLeavingCurrentScope();
819 vector< pair<OutPort *, InPort *> >::iterator iter;
820 for(iter=linksToDestroy.begin();iter!=linksToDestroy.end();iter++)
823 (*iter).first->removeInPort((*iter).second,true);
826 vector< pair<InPort *, OutPort *> > linksToDestroy2=getSetOfLinksComingInCurrentScope();
827 vector< pair<InPort *, OutPort *> >::iterator iter2;
828 for(iter2=linksToDestroy2.begin();iter2!=linksToDestroy2.end();iter2++)
831 (*iter2).second->removeInPort((*iter2).first,true);
835 ComposedNode *ComposedNode::getRootNode() const throw(Exception)
838 return (ComposedNode *)this;
839 return Node::getRootNode();
842 //! Check that Node 'node' is already a direct son of this.
843 bool ComposedNode::isNodeAlreadyAggregated(const Node *node) const
845 list<ComposedNode *> nodeAncestors = node->getAllAscendanceOf();
846 return find(nodeAncestors.begin(),nodeAncestors.end(),(ComposedNode *)this)!=nodeAncestors.end();
849 //! Returns the parent of a node that is the direct child of this node
851 * \note if 'nodeToTest'=='this' this is returned. Else if 'nodeToTest' is in descendance of
852 * 'this' the direct son is returned.
853 * Else 0 is returned.
855 * \param nodeToTest : the node to check
857 Node *ComposedNode::isInMyDescendance(Node *nodeToTest) const
861 if((ComposedNode *)nodeToTest==this)
863 Node *iterBack=nodeToTest;
864 ComposedNode *iter=nodeToTest->_father;
865 while(iter!=0 && iter!=this)
876 string ComposedNode::getChildName(const Node* node) const throw(Exception)
878 string nodeName=node->getQualifiedName();
879 if (!isNodeAlreadyAggregated(node))
881 if (node->getName() == "thisIsAFakeNode")
883 string child = node->getName()+".thisIsAFakeNode";
888 string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
889 throw Exception(what);
893 const Node *father = node->_father;
894 while (father != this)
896 nodeName = father->getQualifiedName() + SEP_CHAR_BTW_LEVEL + nodeName;
897 father = father->_father;
902 std::string ComposedNode::getMyQualifiedName(const Node *directSon) const
904 return directSon->getName();
907 Node *ComposedNode::getChildByName(const std::string& name) const throw(Exception)
909 string potentiallyDirectSonName, remainsPath;
910 bool forwardNeeded=ComposedNode::splitNamesBySep(name, SEP_CHAR_BTW_LEVEL,
911 potentiallyDirectSonName,remainsPath,false);
912 Node *child=getChildByShortName(potentiallyDirectSonName);
916 return child->getChildByName(remainsPath);
919 //! Check if a node is in the descendance of this node
921 * \note Check that 'nodeToTest' is in descendance of 'this' OR equal to 'this'
922 * \exception Exception : If 'nodeToTest' is NOT in descendance of 'this' AND not equal to 'this'
923 * \param nodeToTest : the node to check
925 void ComposedNode::checkInMyDescendance(Node *nodeToTest) const throw(Exception)
927 const char whatC[]=" is not the descendance of node ";
930 string what("node "); what+= nodeToTest->getName(); what+=" ";
931 what+=whatC; what+=_name;
932 throw Exception(what);
934 if((ComposedNode *)nodeToTest==this)
936 ComposedNode *iter=nodeToTest->_father;
937 while(iter!=0 && iter!=this)
941 string what("node "); what+= nodeToTest->getName(); what+=" ";
942 what+=whatC; what+=_name;
943 throw Exception(what);
947 //! Retrieves the lowest common ancestor of 2 nodes
950 * \note Retrieves the lowest common ancestor of 'node1' AND 'node2'.
951 * If 'node1' or 'node2' are both or indiscriminately instances of ComposedNode and that
952 * 'node1' is in descendance of 'node2' (resp. 'node2' in descendance of 'node1')
953 * 'node2' is returned (resp. 'node1').
954 * \exception Exception : if 'node1' and 'node2' do not share the same genealogy.
955 * \return The lowest common ancestor if it exists.
958 ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) throw(Exception)
960 const char what[]="2 nodes does not share the same genealogy";
961 if(node1==0 || node2==0)
962 throw Exception(what);
964 if(dynamic_cast<ComposedNode *>(node1))
965 temp=(ComposedNode *)node1;//->_father;
967 temp=(ComposedNode *)node1->_father;
968 set<ComposedNode *> s;
975 if(dynamic_cast<ComposedNode *>(node2))
976 temp=(ComposedNode *)node2;//->_father;
978 temp=(ComposedNode *)node2->_father;
979 set<ComposedNode *>::iterator iter=s.find(temp);
980 while(temp && iter==s.end())
986 throw Exception(what);
990 list<ElementaryNode *> ComposedNode::getRecursiveConstituents() const
992 list<ElementaryNode *> ret;
993 list<Node *> setOfNode=edGetDirectDescendants();
994 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
996 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
997 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1002 //! Idem getAllRecursiveNodes, but this node is NOT included.
1003 list<Node *> ComposedNode::getAllRecursiveConstituents()
1006 list<Node *> setOfNode=edGetDirectDescendants();
1007 for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1009 if ( dynamic_cast<ComposedNode*> (*iter) )
1011 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveConstituents();
1012 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1013 ret.push_back(*iter);
1017 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1018 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1024 //! Get all children nodes elementary and composed including this node
1025 list<Node *> ComposedNode::getAllRecursiveNodes()
1028 list<Node *> setOfNode=edGetDirectDescendants();
1029 for(list<Node *>::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
1031 if ( dynamic_cast<ElementaryNode*> (*iter) )
1033 list<ElementaryNode *> myCurrentSet=(*iter)->getRecursiveConstituents();
1034 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1038 list<Node *> myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveNodes();
1039 ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
1042 ret.push_back(this);
1046 //! Get the input port name
1048 * get the input port name used by the current node, recursively built with children names.
1051 string ComposedNode::getInPortName(const InPort * inPort) const throw (Exception)
1053 return getPortName<InPort>(inPort);
1056 string ComposedNode::getOutPortName(const OutPort *outPort) const throw (Exception)
1058 return getPortName<OutPort>(outPort);
1061 int ComposedNode::getNumberOfInputPorts() const
1063 list<Node *> constituents=edGetDirectDescendants();
1065 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1066 ret+=(*iter)->getNumberOfInputPorts();
1070 int ComposedNode::getNumberOfOutputPorts() const
1072 list<Node *> constituents=edGetDirectDescendants();
1074 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1075 ret+=(*iter)->getNumberOfOutputPorts();
1079 list<InputPort *> ComposedNode::getSetOfInputPort() const
1081 list<Node *> constituents=edGetDirectDescendants();
1082 list<InputPort *> ret;
1083 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1085 list<InputPort *> currentsPorts=(*iter)->getSetOfInputPort();
1086 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1091 list<OutputPort *> ComposedNode::getSetOfOutputPort() const
1093 list<Node *> constituents=edGetDirectDescendants();
1094 list<OutputPort *> ret;
1095 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1097 list<OutputPort *> currentsPorts=(*iter)->getSetOfOutputPort();
1098 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1103 list<InputDataStreamPort *> ComposedNode::getSetOfInputDataStreamPort() const
1105 list<Node *> constituents=edGetDirectDescendants();
1106 list<InputDataStreamPort *> ret;
1107 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1109 list<InputDataStreamPort *> currentsPorts=(*iter)->getSetOfInputDataStreamPort();
1110 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1115 list<OutputDataStreamPort *> ComposedNode::getSetOfOutputDataStreamPort() const
1117 list<Node *> constituents=edGetDirectDescendants();
1118 list<OutputDataStreamPort *> ret;
1119 for(list<Node *>::iterator iter=constituents.begin();iter!=constituents.end();iter++)
1121 list<OutputDataStreamPort *> currentsPorts=(*iter)->getSetOfOutputDataStreamPort();
1122 ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end());
1127 OutPort *ComposedNode::getOutPort(const std::string& name) const throw(Exception)
1129 string portName, nodeName;
1130 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1132 Node *child = getChildByShortName(nodeName);
1133 return child->getOutPort(portName);
1137 string what("ComposedNode::getOutPort : the port with name "); what+=name; what+=" does not exist on the current level";
1138 throw Exception(what);
1142 //! Get an input port given its name
1144 * Contrary to YACS::ENGINE::ComposedNode::getOutputPort, this method is \b NOT recursive
1145 * and so the leaf of type ElementaryNode aggregating
1146 * this InputPort is directly invoked.
1148 InputPort * ComposedNode::getInputPort(const std::string& name) const throw(Exception)
1150 string portName, nodeName;
1151 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1153 Node *child = getChildByName(nodeName);
1154 return child->getInputPort(portName);
1158 string what("ComposedNode::getInputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1159 throw Exception(what);
1163 //! Get an output port given its name
1165 * Contrary to YACS::ENGINE::ComposedNode::getInputPort, this method is recursive and go
1166 * down hierarchy step by step to complete its work.
1168 OutputPort * ComposedNode::getOutputPort(const std::string& name) const throw(Exception)
1170 string portName, nodeName;
1171 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false))
1173 Node *child = getChildByShortName(nodeName);
1174 return child->getOutputPort(portName);
1178 string what("ComposedNode::getOutputPort : the port with name "); what+=name; what+=" does not exist on the current level";
1179 throw Exception(what);
1183 InputDataStreamPort *ComposedNode::getInputDataStreamPort(const std::string& name) const throw(Exception)
1185 string portName, nodeName;
1186 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1188 Node *child = getChildByName(nodeName);
1189 return child->getInputDataStreamPort(portName);
1193 string what("ComposedNode::getInputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1194 throw Exception(what);
1198 OutputDataStreamPort *ComposedNode::getOutputDataStreamPort(const std::string& name) const throw(Exception)
1200 string portName, nodeName;
1201 if(splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true))
1203 Node *child = getChildByName(nodeName);
1204 return child->getOutputDataStreamPort(portName);
1208 string what("ComposedNode::getOutputDataStreamPort : the port with name "); what+=name; what+=" does not exist on the current level";
1209 throw Exception(what);
1213 //! Update node state on receiving event from a node
1216 * \note Runtime called method. Perform, the state updating, from the son node 'node'
1217 * emitting the event 'event' (among Executor static const var).
1218 * WARNING Precondition : this == node->_father
1219 * \return The event (among Executor static const var) destinated to this->_father node
1220 * to perform eventually up level update.
1222 * Calls ComposedNode::updateStateOnStartEventFrom if event is YACS::START
1224 * Calls ComposedNode::updateStateOnFinishedEventFrom if event is YACS::FINISH
1226 * Called by ComposedNode::notifyFrom
1228 YACS::Event ComposedNode::updateStateFrom(Node *node, //* I : node emitting event
1229 YACS::Event event //* I : event emitted
1232 DEBTRACE("updateStateFrom: " << node->getName() << " " << event);
1238 return updateStateOnStartEventFrom(node);
1241 return updateStateOnFinishedEventFrom(node);
1244 return updateStateOnFailedEventFrom(node);
1247 return YACS::NOEVENT;//TODO unexpected type of event
1251 catch(YACS::Exception& ex)
1253 //unexpected exception: probably a bug in engine
1254 //try to keep a consistent global state
1255 DEBTRACE( "updateStateFrom: " << ex.what() );
1256 setState(YACS::ERROR);
1262 //unexpected exception: probably a bug in engine
1263 //try to keep a consistent global state
1264 setState(YACS::ERROR);
1270 //! Method used to notify the node that a child node has started
1272 * Update the ComposedNode state and return the ComposedNode change state
1274 * \param node : the child node that has started
1275 * \return the loop state change
1277 YACS::Event ComposedNode::updateStateOnStartEventFrom(Node *node)
1279 setState(YACS::ACTIVATED);
1283 //! Method used to notify the node that a child node has failed
1284 YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node)
1286 setState(YACS::FAILED);
1290 void ComposedNode::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
1291 InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(Exception)
1293 if((dynamic_cast<DataFlowPort *>(start) or dynamic_cast<DataFlowPort *>(end))
1294 and (dynamic_cast<DataStreamPort *>(start) or dynamic_cast<DataStreamPort *>(end)))
1295 {//cross protocol required : deeper check needed
1297 list<ComposedNode *>::const_iterator iter;
1298 for(iter=pointsOfViewStart.begin();iter!=pointsOfViewStart.end() and !isOK;iter++)
1299 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1300 for(iter=pointsOfViewEnd.begin();iter!=pointsOfViewEnd.end() and !isOK;iter++)
1301 isOK=(*iter)->isRepeatedUnpredictablySeveralTimes();
1303 throw Exception("ComposedNode::checkLinkPossibility : Request for cross protocol link impossible.");
1307 void ComposedNode::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
1311 void ComposedNode::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
1315 void ComposedNode::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
1319 void ComposedNode::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
1323 void ComposedNode::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
1327 void ComposedNode::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
1331 void ComposedNode::loaded()
1334 void ComposedNode::connected()
1338 void ComposedNode::accept(Visitor *visitor)
1340 list<Node *> constituents=edGetDirectDescendants();
1341 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1343 (*iter)->accept(visitor);
1347 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1348 std::list<InputPort *> ComposedNode::getLocalInputPorts() const
1350 std::list<InputPort *> lip; return lip; // empty list
1353 //! redefined on derived class of ComposedNode. by default a ComposedNode has no port by itself
1354 std::list<OutputPort *> ComposedNode::getLocalOutputPorts() const
1356 std::list<OutputPort *> lop; return lop; // empty list
1359 bool ComposedNode::isNameAlreadyUsed(const std::string& name) const
1364 void ComposedNode::edUpdateState()
1366 DEBTRACE("ComposedNode::edUpdateState(): " << _state << " " << _modified);
1367 YACS::StatesForNode state=YACS::READY;
1371 checkBasicConsistency();
1376 state=YACS::INVALID;
1377 _errorDetails=e.what();
1379 DEBTRACE("ComposedNode::edUpdateState: " << _errorDetails);
1381 //update children if needed
1382 list<Node *> constituents=edGetDirectDescendants();
1383 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1385 if(!(*iter)->isValid())
1386 state=YACS::INVALID;
1393 std::string ComposedNode::getErrorReport()
1395 DEBTRACE("ComposedNode::getErrorReport: " << getName() << " " << _state);
1396 YACS::StatesForNode effectiveState=getEffectiveState();
1398 if(effectiveState != YACS::INVALID && effectiveState != YACS::ERROR && effectiveState != YACS::FAILED)
1401 std::string report="<error node= " + getName();
1402 switch(effectiveState)
1405 report=report+" state= INVALID";
1408 report=report+" state= ERROR";
1411 report=report+" state= FAILED";
1416 report=report + ">\n" ;
1417 if(_errorDetails != "")
1418 report=report+_errorDetails+"\n";
1420 list<Node *> constituents=edGetDirectDescendants();
1421 for(list<Node *>::iterator iter=constituents.begin(); iter!=constituents.end(); iter++)
1423 std::string rep=(*iter)->getErrorReport();
1426 report=report+rep+"\n";
1429 report=report+"</error>";
1435 void ComposedNode::checkBasicConsistency() const throw(Exception)
1437 DEBTRACE("ComposedNode::checkBasicConsistency");
1438 std::list<InputPort *>::const_iterator iter;
1439 std::list<InputPort *> inports=getLocalInputPorts();
1440 for(iter=inports.begin();iter!=inports.end();iter++)
1441 (*iter)->checkBasicConsistency();