Salome HOME
[EDF28020] Fix nested foreach-switch.
[modules/yacs.git] / src / engine / Switch.cxx
1 // Copyright (C) 2006-2022  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, or (at your option) any later version.
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
20 #include "Switch.hxx"
21 #include "Visitor.hxx"
22 #include "LinkInfo.hxx"
23
24 #include <iostream>
25 #include <sstream>
26 #include <cassert>
27
28 //#define _DEVDEBUG_
29 #include "YacsTrace.hxx"
30
31 using namespace YACS::ENGINE;
32 using namespace std;
33
34 const char Switch::DEFAULT_NODE_NAME[]="default";
35 const int Switch::ID_FOR_DEFAULT_NODE=-1973012217;
36 const char Switch::SELECTOR_INPUTPORT_NAME[]="select";
37
38 int CollectorSwOutPort::edGetNumberOfOutLinks() const
39 {
40   return 1;
41 }
42
43 std::set<InPort *> CollectorSwOutPort::edSetInPort() const
44 {
45   set<InPort *> ret;
46   if(_consumer)
47     ret.insert(_consumer);
48   return ret;
49 }
50
51 bool CollectorSwOutPort::isAlreadyLinkedWith(InPort *with) const
52 {
53   set<InPort *> s;
54   with->getAllRepresentants(s);
55   return s.find(_consumer)!=s.end();
56 }
57
58 std::string CollectorSwOutPort::getNameOfTypeOfCurrentInstance() const
59 {
60   return _className;
61 }
62
63 void CollectorSwOutPort::edRemoveAllLinksLinkedWithMe()
64 {
65   map<int, OutPort *>::iterator pt;
66   if(_consumer)
67     for(pt=_potentialProducers.begin();pt!=_potentialProducers.end();pt++)
68       ((*pt).second)->removeInPort(_consumer,true);
69 }
70
71 TypeOfChannel CollectorSwOutPort::getTypeOfChannel() const
72 {
73   return (*(_potentialProducers.begin())).second->getTypeOfChannel();
74 }
75
76 void CollectorSwOutPort::getAllRepresented(std::set<OutPort *>& represented) const
77 {
78   map<int, OutPort *>::const_iterator pt;
79   for(pt=_potentialProducers.begin();pt!=_potentialProducers.end();pt++)
80     ((*pt).second)->getAllRepresented(represented);
81 }
82
83 bool CollectorSwOutPort::addInPort(InPort *inPort)
84 {
85   bool ret = false;
86   if(_currentProducer)
87     {//a specific link is beeing done
88       ret=_currentProducer->addInPort(inPort);
89       _currentProducer=0;
90     }
91   else//global links asked
92     for(map<int, OutPort *>::iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++)
93       ret |= (*iter).second->addInPort(inPort);
94   return ret;
95 }
96
97 int CollectorSwOutPort::removeInPort(InPort *inPort, bool forward)
98 {
99   if(_currentProducer)
100     {
101       return _currentProducer->removeInPort(inPort,forward);
102     }
103   else
104     throw Exception("CollectorSwOutputPort::edRemoveInputPort : internal error on link removal.");
105   _currentProducer=0;
106 }
107
108 /*!
109  * \note : 'master' specifies the instance of Switch of which 'this' collects all of these direct 
110  *          or indirect outports going to the same port 'port' (which is out of scope of 'master').
111  */
112 CollectorSwOutPort::CollectorSwOutPort(Switch *master, InPort *port):OutPort("",master,port->edGetType()),
113                                                                      DataPort("",master,port->edGetType()),
114                                                                      Port(master),
115                                                                      _consumer(port),_currentProducer(0)
116 {
117   _name="Representant_of_";
118   _name+=master->getName();
119   _name+="_for_inport_";
120   _name+=port->getName();
121 }
122
123 CollectorSwOutPort::CollectorSwOutPort(const CollectorSwOutPort& other, Switch *master):OutPort("",master,other.edGetType()),
124                                                                                         DataPort("",master,other.edGetType()),
125                                                                                         Port(master),
126                                                                                         _consumer(0),_currentProducer(0)
127 {
128   _name=other._name;
129   Switch *othSw=(Switch *)other._node;
130   for(map<int, OutPort *>::const_iterator iter=other._potentialProducers.begin();iter!=other._potentialProducers.end();iter++)
131     {
132       string name=othSw->getOutPortName((*iter).second);
133       _potentialProducers[(*iter).first]=master->getOutPort(name);
134     }
135 }
136
137 void CollectorSwOutPort::addPotentialProducerForMaster(OutPort *port)
138 {
139   int i=((Switch *)_node)->getRankOfNode(port->getNode());
140   map<int, OutPort *>::iterator pt=_potentialProducers.find(i);
141   if(pt==_potentialProducers.end())
142     {
143       _potentialProducers[i]=port;
144       _currentProducer=port;
145     }
146   else
147     {
148       _currentProducer=(*pt).second;
149       if(_currentProducer!=port)
150         {
151           string what("CollectorSwOutPort::addPotentialProducerForMaster : In switch node "); what+=_node->getName();
152           what+=" for input named \'"; what+=_consumer->getName(); what+="\' the output "; what+=_currentProducer->getName();
153           what+=" already got out for case of label "; 
154           what+=Switch::getRepresentationOfCase((*pt).first); 
155           throw Exception(what);
156         }
157     }
158   _className=port->getNameOfTypeOfCurrentInstance();
159 }
160
161 bool CollectorSwOutPort::removePotentialProducerForMaster()
162 {
163   int i;
164   map<int, OutPort *>::iterator result;
165   for(result=_potentialProducers.begin();result!=_potentialProducers.end();result++)
166     if((*result).second==_currentProducer)
167       {
168         i=(*result).first;
169         break;
170       }
171   if(result==_potentialProducers.end())
172     {
173       ostringstream stream; stream << "CollectorSwOutPort::removePotentialProducerForMaster : link from the branch whith id ";
174       stream << i << " not defined";
175       throw Exception(stream.str());
176     }
177   if((*result).second!=_currentProducer)
178     {
179       ostringstream stream; stream << "CollectorSwOutPort::removePotentialProducerForMaster : link from the branch whith id ";
180       stream << i << " defined but the output specified is not compatible";
181       throw Exception(stream.str());
182     }
183   _potentialProducers.erase(result);
184   return _potentialProducers.empty();
185 }
186
187 bool CollectorSwOutPort::checkManagementOfPort(OutPort *port)
188 {
189   for(map<int, OutPort *>::iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++)
190     if((*iter).second==port)
191       {
192         _currentProducer=port;
193         return _potentialProducers.size()==1;
194       }
195   throw Exception("CollectorSwOutPort::checkManagementOfPort : unexported port");
196 }
197
198 /*!
199  * Called by Switch::checkCFLinks.
200  */
201 void CollectorSwOutPort::checkConsistency(LinkInfo& info) const
202 {
203   if(((Switch *)_node)->getNbOfCases()!=_potentialProducers.size())
204     info.pushErrSwitch((CollectorSwOutPort *)this);
205   for(map<int, OutPort *>::const_iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++)
206     (*iter).second->checkConsistency(info);
207 }
208
209 /*!
210  * Called by LinkInfo::getErrRepr to have a comprehensible message on throw.
211  * When called, typically checkCompletenessOfCases has detected that some potential producers were laking...
212  */
213 void CollectorSwOutPort::getHumanReprOfIncompleteCases(std::ostream& stream) const
214 {
215   set<int> lackingCases;
216   for(map< int ,Node * >::const_iterator iter=((Switch *)_node)->_mapOfNode.begin();iter!=((Switch *)_node)->_mapOfNode.end();iter++)
217     {
218       if(_potentialProducers.find((*iter).first)==_potentialProducers.end())
219         lackingCases.insert((*iter).first);
220     }
221   ostringstream streamForExc;
222   stream << "For link to " <<  _consumer->getName() << " of node " << _consumer->getNode()->getName() 
223          << " the cases of switch node named " << _node->getName() 
224          << " do not define links for following cases ids :";
225   for(set<int>::iterator iter=lackingCases.begin();iter!=lackingCases.end();iter++)
226       stream << Switch::getRepresentationOfCase(*iter) << " ";
227   stream << endl;
228 }
229
230 FakeNodeForSwitch::FakeNodeForSwitch(Switch *sw, bool normalFinish, bool internalError):ElementaryNode("thisIsAFakeNode"),
231                                                                                         _sw(sw),
232                                                                                         _normalFinish(normalFinish),
233                                                                                         _internalError(internalError)
234 {
235   _state=YACS::TOACTIVATE;
236   _father=_sw->getFather();
237 }
238
239 FakeNodeForSwitch::FakeNodeForSwitch(const FakeNodeForSwitch& other):ElementaryNode(other),_sw(0),
240                                                                      _normalFinish(false),
241                                                                      _internalError(true)
242 {
243 }
244
245 Node *FakeNodeForSwitch::simpleClone(ComposedNode *father, bool editionOnly) const
246 {
247   return new FakeNodeForSwitch(*this);
248 }
249
250 void FakeNodeForSwitch::exForwardFailed()
251 {
252   _sw->exForwardFailed();
253 }
254
255 void FakeNodeForSwitch::exForwardFinished()
256
257   _sw->exForwardFinished(); 
258 }
259
260 void FakeNodeForSwitch::execute()
261 {
262   if(!_normalFinish)
263     throw Exception("");//only to trigger ABORT on Executor
264 }
265
266 void FakeNodeForSwitch::aborted()
267 {
268   if(_internalError)
269     _sw->_state!=YACS::INTERNALERR;
270   else
271     _sw->setState(YACS::ERROR);
272 }
273
274 void FakeNodeForSwitch::finished()
275 {
276   _sw->setState(YACS::DONE);
277 }
278
279 /*! \class YACS::ENGINE::Switch
280  *  \brief Control node that emulates the C switch
281  *
282  *  \ingroup Nodes
283  */
284
285 Switch::Switch(const Switch& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_condition(other._condition,this),
286                                                                             _undispatchableNotificationNode(0)
287 {
288   for(map<int,Node *>::const_iterator iter=other._mapOfNode.begin();iter!=other._mapOfNode.end();iter++)
289     _mapOfNode[(*iter).first]=(*iter).second->clone(this,editionOnly);
290   if(!editionOnly)
291     for(map<InPort *, CollectorSwOutPort * >::const_iterator iter2=other._outPortsCollector.begin();iter2!=other._outPortsCollector.end();iter2++)
292       {
293         CollectorSwOutPort *newCol=new CollectorSwOutPort(*((*iter2).second),this);
294         _alreadyExistingCollectors.push_back(newCol);
295       }
296 }
297
298 Switch::Switch(const std::string& name):StaticDefinedComposedNode(name),_condition(SELECTOR_INPUTPORT_NAME,this,Runtime::_tc_int),_undispatchableNotificationNode(0)
299 {
300 }
301
302 Switch::~Switch()
303 {
304   if(_undispatchableNotificationNode)delete _undispatchableNotificationNode;
305
306   for(map< int , Node * >::iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
307     delete (*iter).second;
308   for(map<InPort *, CollectorSwOutPort * >::iterator iter2=_outPortsCollector.begin();iter2!=_outPortsCollector.end();iter2++)
309     delete (*iter2).second;
310   for(vector<CollectorSwOutPort *>::iterator iter3=_alreadyExistingCollectors.begin();iter3!=_alreadyExistingCollectors.end();iter3++)
311     delete (*iter3);
312 }
313
314 Node *Switch::simpleClone(ComposedNode *father, bool editionOnly) const
315 {
316   return new Switch(*this,father,editionOnly);
317 }
318
319 void Switch::exUpdateState()
320 {
321   DEBTRACE("Switch::exUpdateState " << _state);
322   if(_state == YACS::DISABLED)
323     return;
324   if(_inGate.exIsReady())
325     {
326       setState(YACS::ACTIVATED);
327       if(_condition.isEmpty())
328         _undispatchableNotificationNode=new FakeNodeForSwitch(this,false,true);
329       else
330         {
331           map< int , Node * >::iterator iter=_mapOfNode.find(_condition.getIntValue());
332           if(iter==_mapOfNode.end())
333             {
334               iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE);
335               if(iter==_mapOfNode.end())
336                 {
337                   bool normalFinish=getAllOutPortsLeavingCurrentScope().empty();
338                   delete _undispatchableNotificationNode;
339                   _undispatchableNotificationNode=new FakeNodeForSwitch(this,normalFinish);
340                 }
341               else
342                 ((*iter).second)->exUpdateState();
343             }
344           else
345             ((*iter).second)->exUpdateState();
346         }
347     }
348 }
349
350 void Switch::init(bool start)
351 {
352   DEBTRACE("Switch::init " << start);
353   StaticDefinedComposedNode::init(start);
354   int i=0;
355   for(map< int , Node * >::iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++, i++)
356     {
357       if(!(*iter).second)
358         {
359           ostringstream stream;
360           stream << "Switch::init : initialization failed due to unitialized branch of id " << (*iter).first;
361           throw Exception(stream.str());
362         }
363       ((*iter).second)->init(start);
364     }
365 }
366
367 void Switch::getReadyTasks(std::vector<Task *>& tasks)
368 {
369   /*
370    * To change the way ComposedNode state is handled, uncomment the following line
371    * see Bloc::getReadyTasks
372    */
373   if(_state==YACS::TOACTIVATE) setState(YACS::ACTIVATED);
374   if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED)
375     {
376       map< int , Node * >::iterator iter=_mapOfNode.find(_condition.getIntValue());
377       if(iter!=_mapOfNode.end())
378         ((*iter).second)->getReadyTasks(tasks);
379       else
380         {
381           iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE);
382           if(iter!=_mapOfNode.end())
383             (*iter).second->getReadyTasks(tasks);//Default Node is returned
384           else
385             if(_undispatchableNotificationNode)
386               _undispatchableNotificationNode->getReadyTasks(tasks);
387             else
388               throw Exception("Switch::getReadyTasks : internal error");
389         }
390     }
391 }
392
393 list<Node *> Switch::edGetDirectDescendants() const
394 {
395   list<Node *> ret;
396   for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
397     if((*iter).second)
398       ret.push_back((*iter).second);
399   return ret;
400 }
401
402 int Switch::getNumberOfInputPorts() const
403
404   return StaticDefinedComposedNode::getNumberOfInputPorts()+1;
405 }
406
407 int Switch::getMaxLevelOfParallelism() const
408 {
409   int ret(0);
410   for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++)
411     ret=std::max(ret,((*it).second)->getMaxLevelOfParallelism());
412   return ret;
413 }
414
415 void Switch::getWeightRegardingDPL(ComplexWeight *weight)
416 {
417   ComplexWeight localWeight;
418   for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++)
419   {
420     ((*it).second)->getWeightRegardingDPL(&localWeight);
421     weight->max(localWeight);
422     localWeight.setToZero();
423   }
424 }
425
426 void Switch::partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap)
427 {
428   for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++)
429     (*it).second->partitionRegardingDPL(pd,zeMap);
430 }
431
432 void Switch::edRemoveChild(Node *node)
433 {
434   map< int , Node * >::iterator iter=_mapOfNode.begin();
435   for(;iter!=_mapOfNode.end();iter++)
436     if(node==(*iter).second)
437       {
438         edReleaseCase((*iter).first);
439         return;
440       }
441   ostringstream what; what << "Switch::edRemoveChild : node with name " << node->getName() << " is not a direct child of Switch node " << _name; 
442   throw Exception(what.str());
443 }
444
445 std::list<InputPort *> Switch::getSetOfInputPort() const
446 {
447   list<InputPort *> ret=StaticDefinedComposedNode::getSetOfInputPort();
448   ret.push_back((InputPort *)&_condition);
449   return ret;
450 }
451
452
453 std::list<InputPort *> Switch::getLocalInputPorts() const
454 {
455   list<InputPort *> ret=StaticDefinedComposedNode::getLocalInputPorts();
456   ret.push_back((InputPort *)&_condition);
457   return ret;
458 }
459 OutPort *Switch::getOutPort(const std::string& name) const
460 {
461   for(map<InPort *, CollectorSwOutPort * >::const_iterator iter=_outPortsCollector.begin();iter!=_outPortsCollector.end();iter++)
462     if(name==(*iter).second->getName())
463       return (*iter).second;
464   for(vector<CollectorSwOutPort *>::const_iterator iter2=_alreadyExistingCollectors.begin();iter2!=_alreadyExistingCollectors.end();iter2++)
465     if(name==(*iter2)->getName())
466       return *iter2;
467   return StaticDefinedComposedNode::getOutPort(name);
468 }
469
470 InputPort *Switch::getInputPort(const std::string& name) const
471 {
472   if(name==SELECTOR_INPUTPORT_NAME)
473     return (InputPort *)&_condition;
474   return StaticDefinedComposedNode::getInputPort(name);
475 }
476
477 Node *Switch::getChildByShortName(const std::string& name) const
478 {
479   if(name==DEFAULT_NODE_NAME)
480     {
481       map< int , Node * >::const_iterator iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE);
482       if(iter!=_mapOfNode.end())
483         return (Node *)((*iter).second);
484       else
485         {
486           string what("Switch::getChildByShortName : no default node defined for switch of name "); what+=getName();
487           throw Exception(what);
488         }
489     }
490   for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
491     {
492       if(name==((*iter).second)->getQualifiedName())
493         return (*iter).second;
494     }
495   string what("node "); what+= name ; what+=" is not a child of node switch "; what += getName();
496   throw Exception(what);
497 }
498
499 Node *Switch::edSetDefaultNode(Node *node)
500 {
501   return edSetNode(ID_FOR_DEFAULT_NODE,node);
502 }
503
504 Node *Switch::edReleaseDefaultNode()
505 {
506   return edReleaseCase(ID_FOR_DEFAULT_NODE);
507 }
508
509 Node *Switch::edReleaseCase(int caseId)
510 {
511   map< int , Node * >::iterator iter=_mapOfNode.find(caseId);
512   if(iter==_mapOfNode.end())
513     { 
514       string what("Switch::edReleaseCase : the case # "); what+=getRepresentationOfCase(caseId);  what+=" is not set yet.";
515       throw Exception(what);
516     }
517   else
518     {
519       Node *ret=(*iter).second;
520       StaticDefinedComposedNode::edRemoveChild(ret);
521       _mapOfNode.erase(iter);
522       modified();
523       return ret;
524     }
525 }
526
527 Node *Switch::edGetNode(int caseId)
528 {
529   if (!_mapOfNode.count(caseId)) return 0;
530   return _mapOfNode[caseId];
531 }
532
533
534 /*!
535  * \param caseId : the case ID chosen to place 'node'
536  * \param node   : the node for the specified 'caseId'
537  * \return : If an old node with id equal to 'caseId' exists before, this old node is returned so that to be deallocated.
538  *           0 is returned if caseId is a new ID.
539  *  \b WARNING : 'node' is held by 'this' after call, whereas returned node is no more held. 
540  */
541 Node *Switch::edSetNode(int caseId, Node *node)
542 {
543   if(!node)
544     throw Exception("Switch::edSetNode : null node cannot be set as a case in switch node");
545   if(node->_father!=0)
546     throw Exception("Switch::edSetNode : node already held by another father");
547   checkNoCrossHierachyWith(node);
548   node->_father=this;
549   map< int , Node * >::iterator iter=_mapOfNode.find(caseId);
550   if(iter==_mapOfNode.end())
551     {
552       _mapOfNode[caseId]=node;
553       modified();
554       return 0;
555     }
556   else
557     {
558       if(node!=(*iter).second)
559         {
560           Node *ret=(*iter).second;
561           (*iter).second=node;
562           modified();
563           return ret;
564         }
565     }
566   return 0;
567 }
568
569 //! Change the case of a node
570 /*!
571  *  \param oldCase : the case value to change
572  *  \param newCase : the new value to set
573  *  raise an exception if the old case does not exist or if the new case already exists
574  */
575 void Switch::edChangeCase(int oldCase, int newCase)
576 {
577   std::map< int , Node * >::iterator iter=_mapOfNode.find(oldCase);
578   if(iter==_mapOfNode.end())
579     {
580       //the case does not exists
581       throw Exception("Switch::edChangeCase : case does not exist");
582     }
583   iter=_mapOfNode.find(newCase);
584   if(iter != _mapOfNode.end())
585     {
586       //the new case exists
587       throw Exception("Switch::edChangeCase : new case exists");
588     }
589   Node* node=_mapOfNode[oldCase];
590   _mapOfNode.erase(oldCase);
591   _mapOfNode[newCase]=node;
592   modified();
593 }
594
595 int Switch::getMaxCase()
596 {
597   int aCase = 0;
598   map<int, Node*>::const_iterator it = _mapOfNode.begin();
599   for(; it != _mapOfNode.end(); ++it)
600     if ((*it).first > aCase)
601       aCase = (*it).first;
602   return aCase;
603 }
604
605 //! Get the progress weight of the graph
606 /*!
607  * Only elementary nodes have weight. If the switch node is not done, we add the weight of all his descendants,
608  * otherwise only the weight of the used case count.
609  */
610 list<ProgressWeight> Switch::getProgressWeight() const
611 {
612   list<ProgressWeight> ret;
613   list<Node *> setOfNode=edGetDirectDescendants();
614   if (getState() == YACS::DONE)
615     {
616       for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
617       {
618         if (getEffectiveState(*iter) == YACS::DONE)
619           ret=(*iter)->getProgressWeight();
620       }
621     }
622   else
623     {
624       for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
625         {
626           list<ProgressWeight> myCurrentSet=(*iter)->getProgressWeight();
627           ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
628         }
629     }
630   return ret;
631 }
632
633 bool Switch::edAddChild(Node *node)
634 {
635   int aCase = getMaxCase() + 1;
636   DEBTRACE(aCase);
637   bool ret = edSetNode(aCase, node);
638   DEBTRACE(ret);
639   return ret;
640 }
641
642 YACS::Event Switch::updateStateOnFinishedEventFrom(Node *node)
643 {
644   setState(YACS::DONE);
645   return YACS::FINISH;//notify to father node that 'this' has becomed finished.
646 }
647
648 std::set<InPort *> Switch::getAllInPortsComingFromOutsideOfCurrentScope() const
649 {
650   set<InPort *> ret=StaticDefinedComposedNode::getAllInPortsComingFromOutsideOfCurrentScope();
651   set<OutPort *> temp2=_condition.edSetOutPort();
652   for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
653     if(!isInMyDescendance((*iter3)->getNode()))
654       {
655         ret.insert((InPort *)&_condition);
656         break;
657       }
658   return ret;
659 }
660
661 void Switch::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
662 {
663   map<InPort *, CollectorSwOutPort * >::const_iterator iter=_outPortsCollector.find(end);
664   if(iter!=_outPortsCollector.end())
665     {
666       set<OutPort *> represented;
667       (*iter).second->getAllRepresented(represented);
668       list<OutPort *> others;
669       for(list<OutPort *>::const_iterator iter2=starts.begin();iter2!=starts.end();iter2++)
670         if(represented.find(*iter2)==represented.end())
671           others.push_back(*iter2);
672       if(others.empty())
673         alreadyFed=FED_ST;
674       else
675         StaticDefinedComposedNode::checkCFLinks(others,end,alreadyFed,direction,info);//should never happend;
676     }
677   else
678     StaticDefinedComposedNode::checkCFLinks(starts,end,alreadyFed,direction,info);
679 }
680
681 void Switch::checkControlDependancy(OutPort *start, InPort *end, bool cross,
682                                     std::map < ComposedNode *,  std::list < OutPort * > >& fw,
683                                     std::vector<OutPort *>& fwCross,
684                                     std::map< ComposedNode *, std::list < OutPort *> >& bw,
685                                     LinkInfo& info) const
686 {
687   throw Exception("Switch::checkControlDependancy : a link was dectected between 2 cases of a switch. Impossible !");
688 }
689
690 void Switch::checkNoCyclePassingThrough(Node *node)
691 {
692   throw Exception("Switch::checkNoCyclePassingThrough : uncorrect control flow link relative to switch");
693 }
694
695 void Switch::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
696                                   InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd)
697 {
698   throw Exception("Switch::checkLinkPossibility : A link between 2 different cases of a same Switch requested -> Impossible");
699 }
700
701 void Switch::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
702 {
703   map<InPort *, CollectorSwOutPort * >::iterator result=_outPortsCollector.find(finalTarget);
704   CollectorSwOutPort *newCollector;
705   if(result!=_outPortsCollector.end())
706     newCollector=(*result).second;
707   else
708     {
709       newCollector=new CollectorSwOutPort(this,finalTarget);
710       newCollector->edSetType((port.first)->edGetType());
711       _outPortsCollector[finalTarget]=newCollector;
712     }
713   newCollector->addPotentialProducerForMaster(port.first);
714   port.second=newCollector;
715   port.first=newCollector;
716 }
717
718 void Switch::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
719 {
720   map<InPort *, CollectorSwOutPort * >::iterator iter=_outPortsCollector.find(finalTarget);
721   if(iter==_outPortsCollector.end())
722     {
723       string what("Switch::getDelegateOf : not exported OuputPort with name "); what+=(port.first)->getName(); what+=" for target inport of name ";
724       what+=finalTarget->getName();
725       throw Exception(what);
726     }
727   ((*iter).second)->checkManagementOfPort(port.first);
728   port.second=(*iter).second;
729   port.first=(*iter).second;
730 }
731
732 void Switch::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
733 {
734   set<OutPort *> repr;
735   portDwn->getAllRepresented(repr);
736   if(repr.size()==1)
737     {
738       CollectorSwOutPort *portCasted=dynamic_cast<CollectorSwOutPort *>(portUp);
739       if(portCasted->removePotentialProducerForMaster())//normally always true
740         {
741           delete portCasted;
742           _outPortsCollector.erase(finalTarget);
743         }
744     }
745 }
746
747 int Switch::getNbOfCases() const
748 {
749   return _mapOfNode.size();
750 }
751
752 int Switch::getRankOfNode(Node *node) const
753 {
754   Node *directSon=isInMyDescendance(node);
755   for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
756     if((*iter).second==directSon)
757       return (*iter).first;
758   throw Exception("Switch::getRankOfNode : node not in switch");
759 }
760
761 string Switch::getRepresentationOfCase(int i)
762 {
763   if(i!=ID_FOR_DEFAULT_NODE)
764     {
765       ostringstream stream;
766       stream << i;
767       return stream.str();
768     }
769   else
770     return DEFAULT_NODE_NAME;
771 }
772
773 //! Return the effective state of a node in the context of this switch (its father)
774 /*!
775  * \param node: the node which effective state is queried
776  * \return the effective node state
777  */
778 YACS::StatesForNode Switch::getEffectiveState(const Node* node) const
779 {
780   YACS::StatesForNode effectiveState=Node::getEffectiveState();
781   if(effectiveState==YACS::READY)
782     return YACS::READY;
783   if(effectiveState==YACS::TOACTIVATE)
784     return YACS::READY;
785   if(effectiveState==YACS::DISABLED)
786     return YACS::DISABLED;
787
788   return node->getState();
789 }
790 YACS::StatesForNode Switch::getEffectiveState() const
791 {
792   return Node::getEffectiveState();
793 }
794
795 void Switch::writeDot(std::ostream &os) const
796 {
797   os << "  subgraph cluster_" << getId() << "  {\n" ;
798   for(map<int,Node*>::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
799     {
800       Node* n=(*iter).second;
801       n->writeDot(os);
802       os << getId() << " -> " << n->getId() << ";\n";
803     }
804   os << "}\n" ;
805   os << getId() << "[fillcolor=\"" ;
806   YACS::StatesForNode state=Node::getEffectiveState();
807   os << getColorState(state);
808   os << "\" label=\"" << "Switch:" ;
809   os << getQualifiedName() <<"\"];\n";
810 }
811
812 std::string Switch::getMyQualifiedName(const Node *directSon) const
813 {
814   string id=getCaseId(directSon);
815   id+=directSon->getName();
816   return id;
817 }
818
819 std::string Switch::getCaseId(const Node *node) const
820 {
821   const char sep='_';
822   map<int, Node*>::const_iterator iter;
823   for (iter = _mapOfNode.begin(); iter != _mapOfNode.end(); iter++)
824       if (iter->second == node)
825         {
826           stringstream a;
827           if (iter->first == Switch::ID_FOR_DEFAULT_NODE)
828             a << DEFAULT_NODE_NAME << sep;
829           else if (iter->first <0)
830             a << "m" << -iter->first << sep;
831           else a  << "p" << iter->first << sep; 
832           return a.str();
833         }
834   string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
835   throw Exception(what);  
836 }
837
838 void Switch::accept(Visitor *visitor)
839 {
840   visitor->visitSwitch(this);
841 }