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