]> SALOME platform Git repositories - modules/yacs.git/blob - src/engine/ForEachLoop.cxx
Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / src / engine / ForEachLoop.cxx
1 //  Copyright (C) 2006-2008  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include "ForEachLoop.hxx"
20 #include "TypeCode.hxx"
21 #include "Visitor.hxx"
22 #include "ComposedNode.hxx"
23 #include <iostream>
24 #include <sstream>
25
26 //#define _DEVDEBUG_
27 #include "YacsTrace.hxx"
28
29 using namespace YACS::ENGINE;
30 using namespace std;
31
32 const char FakeNodeForForEachLoop::NAME[]="thisIsAFakeNode";
33
34 const char SplitterNode::NAME_OF_SEQUENCE_INPUT[]="SmplsCollection";
35
36 const char ForEachLoop::NAME_OF_SPLITTERNODE[]="splitter";
37
38 const int ForEachLoop::NOT_RUNNING_BRANCH_ID=-1;
39
40 InterceptorInputPort::InterceptorInputPort(const std::string& name, Node *node, TypeCode* type):AnyInputPort(name,node,type),
41                                                                                                 DataPort(name,node,type),Port(node),
42                                                                                                 _repr(0)
43 {
44 }
45
46 InterceptorInputPort::InterceptorInputPort(const  InterceptorInputPort& other, Node *newHelder):AnyInputPort(other,newHelder),DataPort(other,newHelder),
47                                                                                                 Port(other,newHelder),
48                                                                                                 _repr(0)
49 {
50 }
51
52 void InterceptorInputPort::getAllRepresentants(std::set<InPort *>& repr) const
53 {
54   set<InPort *> ports=_repr->edSetInPort();
55   for(set<InPort *>::iterator iter=ports.begin();iter!=ports.end();iter++)
56     (*iter)->getAllRepresentants(repr);
57 }
58
59 InputPort *InterceptorInputPort::clone(Node *newHelder) const
60 {
61   return new InterceptorInputPort(*this,newHelder);
62 }
63
64 void InterceptorInputPort::setRepr(AnySplitOutputPort *repr)
65 {
66   _repr=repr;
67 }
68
69 bool AnySplitOutputPort::decrRef()
70 {
71   return (--_cnt==0);
72 }
73
74 void AnySplitOutputPort::incrRef() const
75 {
76   _cnt++;
77 }
78
79 AnySplitOutputPort::AnySplitOutputPort(const std::string& name, Node *node, TypeCode *type):OutputPort(name,node,type),
80                                                                                             DataPort(name,node,type),Port(node),
81                                                                                             _repr(0),_intercptr(0),_cnt(1)
82 {
83 }
84
85 AnySplitOutputPort::AnySplitOutputPort(const AnySplitOutputPort& other, Node *newHelder):OutputPort(other,newHelder),
86                                                                                          DataPort(other,newHelder),
87                                                                                          Port(other,newHelder),
88                                                                                          _repr(0),_intercptr(0),_cnt(1)
89 {
90 }
91
92 bool AnySplitOutputPort::addInPort(InPort *inPort) throw(Exception)
93 {
94   bool ret=OutputPort::addInPort(inPort);
95   if(_repr)
96     _repr->addInPort(_intercptr);
97   return ret;
98 }
99
100 void AnySplitOutputPort::getAllRepresented(std::set<OutPort *>& represented) const
101 {
102   if(!_repr)
103     OutPort::getAllRepresented(represented);
104   else
105     _repr->getAllRepresented(represented);
106 }
107
108 int AnySplitOutputPort::removeInPort(InPort *inPort, bool forward) throw(Exception)
109 {
110   bool ret=OutputPort::removeInPort(inPort,forward);
111   if(_repr)
112     if(_setOfInputPort.empty())
113       _repr->removeInPort(_intercptr,forward);
114   return ret;
115 }
116
117 void AnySplitOutputPort::addRepr(OutPort *repr, InterceptorInputPort *intercptr)
118 {
119   _repr=repr;
120   _intercptr=intercptr;
121 }
122
123 OutputPort *AnySplitOutputPort::clone(Node *newHelder) const
124 {
125   return new AnySplitOutputPort(*this,newHelder);
126 }
127
128 SeqAnyInputPort::SeqAnyInputPort(const std::string& name, Node *node, TypeCodeSeq* type):AnyInputPort(name,node,type),DataPort(name,node,type),Port(node)
129 {
130   _type->decrRef();
131 }
132
133 SeqAnyInputPort::SeqAnyInputPort(const  SeqAnyInputPort& other, Node *newHelder):AnyInputPort(other,newHelder),DataPort(other,newHelder),Port(other,newHelder)
134 {
135 }
136
137 InputPort *SeqAnyInputPort::clone(Node *newHelder) const
138 {
139   return new SeqAnyInputPort(*this,newHelder);
140 }
141
142 unsigned SeqAnyInputPort::getNumberOfElements() const
143 {
144   const SequenceAny * valCsted=(const SequenceAny *) _value;
145   if (valCsted) return valCsted->size();
146   return 0;
147 }
148
149 Any *SeqAnyInputPort::getValueAtRank(int i) const
150 {
151   const SequenceAny * valCsted=(const SequenceAny *) _value;
152   AnyPtr ret=(*valCsted)[i];
153   ret->incrRef();
154   return ret;
155 }
156
157 std::string SeqAnyInputPort::dump()
158 {
159   stringstream xmldump;
160   int nbElem = getNumberOfElements();
161   xmldump << "<value><array><data>" << endl;
162   for (int i = 0; i < nbElem; i++)
163     {
164       Any *val = getValueAtRank(i);
165       switch (val->getType()->kind())
166         {
167         case Double:
168           xmldump << "<value><double>" << val->getDoubleValue() << "</double></value>" << endl;
169           break;
170         case Int:
171           xmldump << "<value><int>" << val->getIntValue() << "</int></value>" << endl;
172           break;
173         case Bool:
174           xmldump << "<value><boolean>" << val->getBoolValue() << "</boolean></value>" << endl;
175           break;
176         case String:
177           xmldump << "<value><string>" << val->getStringValue() << "</string></value>" << endl;
178           break;
179         case Objref:
180           xmldump << "<value><objref>" << val->getStringValue() << "</objref></value>" << endl;
181           break;
182         default:
183           xmldump << "<value><error> NO_SERIALISATION_AVAILABLE </error></value>" << endl;
184           break;
185         }
186     }
187   xmldump << "</data></array></value>" << endl;
188   return xmldump.str();
189 }
190
191 SplitterNode::SplitterNode(const std::string& name, TypeCode *typeOfData, 
192                            ForEachLoop *father):ElementaryNode(name),
193                                                 _dataPortToDispatch(NAME_OF_SEQUENCE_INPUT,
194                                                                     this,(TypeCodeSeq *)TypeCode::sequenceTc("","",typeOfData))                     
195 {
196   _father=father;
197 }
198
199 SplitterNode::SplitterNode(const SplitterNode& other, ForEachLoop *father):ElementaryNode(other,father),
200                                                                            _dataPortToDispatch(other._dataPortToDispatch,this)
201 {
202 }
203
204 InputPort *SplitterNode::getInputPort(const std::string& name) const throw(Exception)
205 {
206   if(name==NAME_OF_SEQUENCE_INPUT)
207     return (InputPort *)&_dataPortToDispatch;
208   else
209     return ElementaryNode::getInputPort(name);
210 }
211
212 Node *SplitterNode::simpleClone(ComposedNode *father, bool editionOnly) const
213 {
214   return new SplitterNode(*this,(ForEachLoop *)father);
215 }
216
217 unsigned SplitterNode::getNumberOfElements() const
218 {
219   return _dataPortToDispatch.getNumberOfElements();
220 }
221
222 void SplitterNode::execute()
223 {
224   //Nothing : should never been called elsewhere big problem...
225 }
226
227 void SplitterNode::init(bool start)
228 {
229   ElementaryNode::init(start);
230   _dataPortToDispatch.exInit(start);
231 }
232
233 void SplitterNode::putSplittedValueOnRankTo(int rankInSeq, int branch, bool first)
234 {
235   Any *valueToDispatch=_dataPortToDispatch.getValueAtRank(rankInSeq);
236   ForEachLoop *fatherTyped=(ForEachLoop *)_father;
237   fatherTyped->putValueOnBranch(valueToDispatch,branch,first);
238   valueToDispatch->decrRef();
239 }
240
241 FakeNodeForForEachLoop::FakeNodeForForEachLoop(ForEachLoop *loop, bool normalFinish):ElementaryNode(NAME),
242                                                                                      _loop(loop),
243                                                                                      _normalFinish(normalFinish)
244 {
245   _state=YACS::TOACTIVATE;
246   _father=_loop->getFather();
247 }
248
249 FakeNodeForForEachLoop::FakeNodeForForEachLoop(const FakeNodeForForEachLoop& other):ElementaryNode(other),_loop(0),
250                                                                                     _normalFinish(false)
251 {
252 }
253
254 Node *FakeNodeForForEachLoop::simpleClone(ComposedNode *father, bool editionOnly) const
255 {
256   return new FakeNodeForForEachLoop(*this);
257 }
258
259 void FakeNodeForForEachLoop::exForwardFailed()
260 {
261   _loop->exForwardFailed();
262   FakeNodeForForEachLoop *normallyThis=_loop->_nodeForSpecialCases;
263   _loop->_nodeForSpecialCases=0;
264   delete normallyThis;
265 }
266
267 void FakeNodeForForEachLoop::exForwardFinished()
268
269   _loop->exForwardFinished();
270   FakeNodeForForEachLoop *normallyThis=_loop->_nodeForSpecialCases;
271   _loop->_nodeForSpecialCases=0;
272   delete normallyThis;
273 }
274
275 void FakeNodeForForEachLoop::execute()
276 {
277   if(!_normalFinish)
278     throw Exception("");//only to trigger ABORT on Executor
279   else
280     _loop->pushAllSequenceValues();
281 }
282
283 void FakeNodeForForEachLoop::aborted()
284 {
285   _loop->setState(YACS::ERROR);
286 }
287
288 void FakeNodeForForEachLoop::finished()
289 {
290   _loop->setState(YACS::DONE);
291 }
292
293 ForEachLoop::ForEachLoop(const std::string& name, TypeCode *typeOfDataSplitted):DynParaLoop(name,typeOfDataSplitted),
294                                                                                 _splitterNode(NAME_OF_SPLITTERNODE,typeOfDataSplitted,this),
295                                                                                 _execCurrentId(0),_nodeForSpecialCases(0)
296 {
297 }
298
299 ForEachLoop::ForEachLoop(const ForEachLoop& other, ComposedNode *father, bool editionOnly):DynParaLoop(other,father,editionOnly),
300                                                                                            _splitterNode(other._splitterNode,this),
301                                                                                            _execCurrentId(0),_nodeForSpecialCases(0)
302 {
303   int i=0;
304   if(!editionOnly)
305     for(vector<AnySplitOutputPort *>::const_iterator iter2=other._outGoingPorts.begin();iter2!=other._outGoingPorts.end();iter2++,i++)
306       {
307         AnySplitOutputPort *temp=new AnySplitOutputPort(*(*iter2),this);
308         InterceptorInputPort *interc=new InterceptorInputPort(*other._intecptrsForOutGoingPorts[i],this);
309         temp->addRepr(getOutPort((*iter2)->getName()),interc);
310         interc->setRepr(temp);
311         _outGoingPorts.push_back(temp);
312         _intecptrsForOutGoingPorts.push_back(interc);
313       }
314 }
315
316 Node *ForEachLoop::simpleClone(ComposedNode *father, bool editionOnly) const
317 {
318   return new ForEachLoop(*this,father,editionOnly);
319 }
320
321 ForEachLoop::~ForEachLoop()
322 {
323   cleanDynGraph();
324   for(vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();iter!=_outGoingPorts.end();iter++)
325     delete *iter;
326   for(vector<InterceptorInputPort *>::iterator iter2=_intecptrsForOutGoingPorts.begin();iter2!=_intecptrsForOutGoingPorts.end();iter2++)
327     delete *iter2;
328 }
329
330 void ForEachLoop::init(bool start)
331 {
332   DynParaLoop::init(start);
333   _splitterNode.init(start);
334   _execCurrentId=0;
335   cleanDynGraph();
336 }
337
338 void ForEachLoop::exUpdateState()
339 {
340   if(_state == YACS::DISABLED)
341     return;
342   if(_inGate.exIsReady())
343     {
344       //setState(YACS::TOACTIVATE); // call this method below
345       //internal graph update
346       int i;
347       int nbOfBr=_nbOfBranches.getIntValue();
348       int nbOfElts=_splitterNode.getNumberOfElements();
349       if(nbOfElts==0)
350         {
351           prepareSequenceValues(0);
352           delete _nodeForSpecialCases;
353           _nodeForSpecialCases=new FakeNodeForForEachLoop(this,true);
354           return ;
355         }
356       if(nbOfBr<=0)
357         {
358           delete _nodeForSpecialCases;
359           _nodeForSpecialCases=new FakeNodeForForEachLoop(this,getAllOutPortsLeavingCurrentScope().empty());
360           return ;
361         }
362       if(nbOfBr>nbOfElts)
363         nbOfBr=nbOfElts;
364       _execNodes.resize(nbOfBr);
365       _execIds.resize(nbOfBr);
366       _execOutGoingPorts.resize(nbOfBr);
367       prepareSequenceValues(nbOfElts);
368       if(_initNode)
369         _execInitNodes.resize(nbOfBr);
370
371       //Conversion exceptions can be thrown by createOutputOutOfScopeInterceptors 
372       //so catch them to control errors
373       try
374         {
375           for(i=0;i<nbOfBr;i++)
376             {
377               DEBTRACE( "-------------- 1" );
378               _execIds[i]=_execCurrentId;
379               DEBTRACE( "-------------- 2" );
380               _execNodes[i]=_node->clone(this,false);
381               DEBTRACE( "-------------- 3" );
382               if(_initNode)
383                 _execInitNodes[i]=_initNode->clone(this,false);
384               DEBTRACE( "-------------- 4" );
385               prepareInputsFromOutOfScope(i);
386               DEBTRACE( "-------------- 5" );
387               createOutputOutOfScopeInterceptors(i);
388               DEBTRACE( "-------------- 6" );
389               _splitterNode.putSplittedValueOnRankTo(_execCurrentId++,i,true);
390               DEBTRACE( "-------------- 7" );
391             } 
392         }
393       catch(YACS::Exception& ex)
394         {
395           //ForEachLoop must be put in error and the exception rethrown to notify the caller
396           DEBTRACE( "ForEachLoop::exUpdateState: " << ex.what() );
397           setState(YACS::ERROR);
398           exForwardFailed();
399           throw;
400         }
401
402       setState(YACS::TOACTIVATE); // move the calling of setState method there for adding observers for clone nodes in GUI part
403
404       //let's go
405       for(i=0;i<nbOfBr;i++)
406         if(_initNode)
407           _execInitNodes[i]->exUpdateState();
408         else
409           {
410             _nbOfEltConsumed++;
411             _execNodes[i]->exUpdateState();
412           }
413       if (_node) {
414         _node->setState(_execNodes[nbOfBr-1]->getState());
415         forwardExecStateToOriginalBody(_execNodes[nbOfBr-1]);
416       }
417     }
418 }
419
420 void ForEachLoop::getReadyTasks(std::vector<Task *>& tasks)
421 {
422   if(!_node)
423     return;
424   if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
425     {
426       if(_nodeForSpecialCases)
427         {
428           _nodeForSpecialCases->getReadyTasks(tasks);
429           return ;
430         }
431       for(vector<Node *>::iterator iter=_execNodes.begin();iter!=_execNodes.end();iter++)
432         (*iter)->getReadyTasks(tasks);
433       for(vector<Node *>::iterator iter2=_execInitNodes.begin();iter2!=_execInitNodes.end();iter2++)
434         (*iter2)->getReadyTasks(tasks);
435     }
436 }
437
438 int ForEachLoop::getNumberOfInputPorts() const
439 {
440   return DynParaLoop::getNumberOfInputPorts()+1;
441 }
442
443 void ForEachLoop::checkNoCyclePassingThrough(Node *node) throw(Exception)
444 {
445   //TO DO
446 }
447
448 void ForEachLoop::selectRunnableTasks(std::vector<Task *>& tasks)
449 {
450 }
451
452 std::list<InputPort *> ForEachLoop::getSetOfInputPort() const
453 {
454   list<InputPort *> ret=DynParaLoop::getSetOfInputPort();
455   ret.push_back((InputPort *)&_splitterNode._dataPortToDispatch);
456   return ret;
457 }
458
459 std::list<InputPort *> ForEachLoop::getLocalInputPorts() const
460 {
461   list<InputPort *> ret=DynParaLoop::getLocalInputPorts();
462   ret.push_back((InputPort *)&_splitterNode._dataPortToDispatch);
463   return ret;
464 }
465
466 InputPort *ForEachLoop::getInputPort(const std::string& name) const throw(Exception)
467 {
468   if(name==SplitterNode::NAME_OF_SEQUENCE_INPUT)
469     return (InputPort *)&_splitterNode._dataPortToDispatch;
470   else
471     return DynParaLoop::getInputPort(name);
472 }
473
474 OutputPort *ForEachLoop::getOutputPort(const std::string& name) const throw(Exception)
475 {
476   for(vector<AnySplitOutputPort *>::const_iterator iter=_outGoingPorts.begin();iter!=_outGoingPorts.end();iter++)
477     {
478       if(name==(*iter)->getName())
479         return (OutputPort *)(*iter);
480     }
481   return DynParaLoop::getOutputPort(name);
482 }
483
484 OutPort *ForEachLoop::getOutPort(const std::string& name) const throw(Exception)
485 {
486   for(vector<AnySplitOutputPort *>::const_iterator iter=_outGoingPorts.begin();iter!=_outGoingPorts.end();iter++)
487     {
488       if(name==(*iter)->getName())
489         return (OutPort *)(*iter);
490     }
491   return DynParaLoop::getOutPort(name);
492 }
493
494 Node *ForEachLoop::getChildByShortName(const std::string& name) const throw(Exception)
495 {
496   if(name==NAME_OF_SPLITTERNODE)
497     return (Node *)&_splitterNode;
498   else
499     return DynParaLoop::getChildByShortName(name);
500 }
501
502 YACS::Event ForEachLoop::updateStateOnFinishedEventFrom(Node *node)
503 {
504   unsigned int id;
505   switch(getIdentityOfNotifyerNode(node,id))
506     {
507     case INIT_NODE:
508       _execNodes[id]->exUpdateState();
509       _nbOfEltConsumed++;
510       break;
511     case WORK_NODE:
512       storeOutValsInSeqForOutOfScopeUse(_execIds[id],id);
513       if(_execCurrentId==_splitterNode.getNumberOfElements())
514         {//No more elements of _dataPortToDispatch to treat
515           _execIds[id]=NOT_RUNNING_BRANCH_ID;
516           //analyzing if some samples are still on treatment on other branches.
517           bool isFinished=true;
518           for(int i=0;i<_execIds.size() and isFinished;i++)
519             isFinished=(_execIds[i]==NOT_RUNNING_BRANCH_ID);
520           if(isFinished)
521             {
522               try 
523                 {
524                   pushAllSequenceValues();
525                   setState(YACS::DONE);
526                   
527                   if (_node)
528                     {
529                       _node->setState(YACS::DONE);
530                       
531                       ComposedNode* compNode = dynamic_cast<ComposedNode*>(_node);
532                       if (compNode)
533                         {
534                           list<Node *> aChldn = compNode->getAllRecursiveConstituents();
535                           list<Node *>::iterator iter=aChldn.begin();
536                           for(;iter!=aChldn.end();iter++)
537                             (*iter)->setState(YACS::DONE);
538                         }
539                     }
540                   
541                   return YACS::FINISH;
542                 }
543               catch(YACS::Exception& ex)
544                 {
545                   DEBTRACE("ForEachLoop::updateStateOnFinishedEventFrom: "<<ex.what());
546                   //no way to push results : put following nodes in FAILED state
547                   //TODO could be more fine grain : put only concerned nodes in FAILED state
548                   exForwardFailed();
549                   setState(YACS::ERROR);
550                   return YACS::ABORT;
551                 }
552             }
553         }
554       else
555         {//more elements to do
556           _execIds[id]=_execCurrentId;
557           node->init(false);
558           _splitterNode.putSplittedValueOnRankTo(_execCurrentId++,id,false);
559           node->exUpdateState();
560           if (_node)
561             {
562               _node->setState(node->getState());
563               forwardExecStateToOriginalBody(node);
564             }
565           _nbOfEltConsumed++;
566         }
567       break;
568     }
569   return YACS::NOEVENT;
570 }
571
572 void ForEachLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
573 {
574   DynParaLoop::buildDelegateOf(port,finalTarget,pointsOfView);
575   string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
576   if(typeOfPortInstance==OutputPort::NAME)
577     {
578       vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
579       int i=0;
580       for(;iter!=_outGoingPorts.end();iter++,i++)
581         if((*iter)->getRepr()==port.first)
582           break;
583       if(iter!=_outGoingPorts.end())
584         {
585           (*iter)->incrRef();
586           (*iter)->addRepr(port.first,_intecptrsForOutGoingPorts[i]);
587           port.first=*iter;
588         }
589       else
590         {
591           TypeCodeSeq *newTc=(TypeCodeSeq *)TypeCode::sequenceTc("","",port.first->edGetType());
592           AnySplitOutputPort *newPort=new AnySplitOutputPort(getPortName(port.first),this,newTc);
593           InterceptorInputPort *intercptor=new InterceptorInputPort(string("intercptr for ")+getPortName(port.first),this,port.first->edGetType());
594           intercptor->setRepr(newPort);
595           newTc->decrRef();
596           newPort->addRepr(port.first,intercptor);
597           _outGoingPorts.push_back(newPort);
598           _intecptrsForOutGoingPorts.push_back(intercptor);
599           port.first=newPort;
600         }
601     }
602   else
603     throw Exception("ForEachLoop::buildDelegateOf : not implemented for DS because not specified");
604 }
605
606 void ForEachLoop::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
607 {
608   string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance();
609   if(typeOfPortInstance==OutputPort::NAME)
610     {
611       vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
612       for(;iter!=_outGoingPorts.end();iter++)
613         if((*iter)->getRepr()==port.first)
614           break;
615       if(iter==_outGoingPorts.end())
616         {
617           string what("ForEachLoop::getDelegateOf : Port with name "); what+=port.first->getName(); what+=" not exported by ForEachLoop "; what+=_name; 
618           throw Exception(what);
619         }
620       else
621         port.first=(*iter);
622     }
623   else
624     throw Exception("ForEachLoop::getDelegateOf : not implemented because not specified");
625 }
626
627 void ForEachLoop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(Exception)
628 {
629   string typeOfPortInstance=portDwn->getNameOfTypeOfCurrentInstance();
630   if(typeOfPortInstance==OutputPort::NAME)
631     {
632       vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
633       vector<InterceptorInputPort *>::iterator iter2=_intecptrsForOutGoingPorts.begin();
634       for(;iter!=_outGoingPorts.end();iter++,iter2++)
635         if((*iter)->getRepr()==portDwn)
636           break;
637       //ASSERT(portUp==*iter.second)
638       if((*iter)->decrRef())
639         {
640           _outGoingPorts.erase(iter);
641           delete *iter2;
642           _intecptrsForOutGoingPorts.erase(iter2);
643           delete *iter;
644         }
645     }
646 }
647
648 void ForEachLoop::forwardExecStateToOriginalBody(Node *execNode)
649 {
650   ComposedNode* compNode = dynamic_cast<ComposedNode*>(_node);
651   ComposedNode* compNodeExe = dynamic_cast<ComposedNode*>(execNode);
652   if (compNode && compNodeExe)
653     {
654       list<Node *> aChldn = compNodeExe->getAllRecursiveConstituents();
655       list<Node *>::iterator iter=aChldn.begin();
656       for(;iter!=aChldn.end();iter++)
657         compNode->getChildByName(compNodeExe->getChildName(*iter))->setState((*iter)->getState());
658     }
659 }
660
661 OutPort *ForEachLoop::getDynOutPortByAbsName(int branchNb, const std::string& name)
662 {
663   string portName, nodeName;
664   splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
665   Node *staticChild = getChildByName(nodeName);
666   return _execNodes[branchNb]->getOutPort(portName);//It's impossible(garanteed by YACS::ENGINE::ForEachLoop::buildDelegateOf)
667   //that a link starting from _initNode goes out of scope of 'this'.
668 }
669
670 void ForEachLoop::cleanDynGraph()
671 {
672   DynParaLoop::cleanDynGraph();
673   for(vector< SequenceAny *>::iterator iter3=_execVals.begin();iter3!=_execVals.end();iter3++)
674     (*iter3)->decrRef();
675   _execVals.clear();
676   for(vector< vector<AnyInputPort *> >::iterator iter4=_execOutGoingPorts.begin();iter4!=_execOutGoingPorts.end();iter4++)
677     for(vector<AnyInputPort *>::iterator iter5=(*iter4).begin();iter5!=(*iter4).end();iter5++)
678       delete *iter5;
679   _execOutGoingPorts.clear();
680 }
681
682 void ForEachLoop::storeOutValsInSeqForOutOfScopeUse(int rank, int branchNb)
683 {
684   vector<AnyInputPort *>::iterator iter;
685   int i=0;
686   for(iter=_execOutGoingPorts[branchNb].begin();iter!=_execOutGoingPorts[branchNb].end();iter++,i++)
687     {
688       Any *val=(Any *)(*iter)->getValue();
689       _execVals[i]->setEltAtRank(rank,val);
690     }
691 }
692
693 void ForEachLoop::prepareSequenceValues(int sizeOfSamples)
694 {
695   _execVals.resize(_outGoingPorts.size());
696   vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
697   for(int i=0;iter!=_outGoingPorts.end();iter++,i++)
698     _execVals[i]=SequenceAny::New((*iter)->edGetType()->contentType(),sizeOfSamples);
699 }
700
701 void ForEachLoop::pushAllSequenceValues()
702 {
703   vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
704   int i=0;
705   for(;iter!=_outGoingPorts.end();iter++,i++)
706     (*iter)->put((const void *)_execVals[i]);
707 }
708
709 void ForEachLoop::createOutputOutOfScopeInterceptors(int branchNb)
710 {
711   vector<AnySplitOutputPort *>::iterator iter=_outGoingPorts.begin();
712   int i=0;
713   for(;iter!=_outGoingPorts.end();iter++,i++)
714     {
715       DEBTRACE( (*iter)->getName() << " " << (*iter)->edGetType()->kind() );
716       //AnyInputPort *interceptor=new AnyInputPort((*iter)->getName(),this,(*iter)->edGetType());
717       OutPort *portOut=getDynOutPortByAbsName(branchNb,getOutPortName(((*iter)->getRepr())));
718       DEBTRACE( portOut->getName() );
719       AnyInputPort *interceptor=new AnyInputPort((*iter)->getName(),this,portOut->edGetType());
720       portOut->addInPort(interceptor);
721       _execOutGoingPorts[branchNb].push_back(interceptor);
722     }
723 }
724
725 void ForEachLoop::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
726                                        InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(Exception)
727 {
728   if(isInMyDescendance(start->getNode())==_node)
729     throw Exception("ForEachLoop::checkLinkPossibility : A link from work node to init node not permitted");
730 }
731
732 std::list<OutputPort *> ForEachLoop::getLocalOutputPorts() const
733 {
734   list<OutputPort *> ret;
735   ret.push_back(getOutputPort(NAME_OF_SPLITTED_SEQ_OUT)); // OCC : mkr : add _splittedPort to the list of output ports
736   //ret.push_back(getOutputPort(SplitterNode::NAME_OF_SEQUENCE_INPUT));
737   return ret;
738 }
739
740 void ForEachLoop::accept(Visitor *visitor)
741 {
742   visitor->visitForEachLoop(this);
743 }
744
745 //! Dump the node state to a stream
746 /*!
747  * \param os : the output stream
748  */
749 void ForEachLoop::writeDot(std::ostream &os) const
750 {
751   os << "  subgraph cluster_" << getId() << "  {\n" ;
752   //only one node in a loop
753   if(_node)
754     {
755       _node->writeDot(os);
756       os << getId() << " -> " << _node->getId() << ";\n";
757     }
758   os << "}\n" ;
759   os << getId() << "[fillcolor=\"" ;
760   YACS::StatesForNode state=getEffectiveState();
761   os << getColorState(state);
762   os << "\" label=\"" << "Loop:" ;
763   os << getName() <<"\"];\n";
764 }