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