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