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