Version: 8.3.0
Switch.cxx
Go to the documentation of this file.
1 // Copyright (C) 2006-2016 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 
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 
52 {
53  set<InPort *> s;
54  with->getAllRepresentants(s);
55  return s.find(_consumer)!=s.end();
56 }
57 
59 {
60  return _className;
61 }
62 
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 
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 
84 {
85  if(_currentProducer)
86  {//a specific link is beeing done
87  bool ret=_currentProducer->addInPort(inPort);
88  _currentProducer=0;
89  return ret;
90  }
91  else//global links asked
92  for(map<int, OutPort *>::iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++)
93  (*iter).second->addInPort(inPort);
94 }
95 
96 int CollectorSwOutPort::removeInPort(InPort *inPort, bool forward) throw(YACS::Exception)
97 {
98  if(_currentProducer)
99  {
100  return _currentProducer->removeInPort(inPort,forward);
101  }
102  else
103  throw Exception("CollectorSwOutputPort::edRemoveInputPort : internal error on link removal.");
104  _currentProducer=0;
105 }
106 
111 CollectorSwOutPort::CollectorSwOutPort(Switch *master, InPort *port):OutPort("",master,port->edGetType()),
112  DataPort("",master,port->edGetType()),
113  Port(master),
114  _consumer(port),_currentProducer(0)
115 {
116  _name="Representant_of_"; _name+=master->getName(); _name+="_for_inport_"; _name+=master->getRootNode()->getInPortName(_consumer);
117 }
118 
119 CollectorSwOutPort::CollectorSwOutPort(const CollectorSwOutPort& other, Switch *master):OutPort("",master,other.edGetType()),
120  DataPort("",master,other.edGetType()),
121  Port(master),
122  _consumer(0),_currentProducer(0)
123 {
124  _name=other._name;
125  Switch *othSw=(Switch *)other._node;
126  for(map<int, OutPort *>::const_iterator iter=other._potentialProducers.begin();iter!=other._potentialProducers.end();iter++)
127  {
128  string name=othSw->getOutPortName((*iter).second);
129  _potentialProducers[(*iter).first]=master->getOutPort(name);
130  }
131 }
132 
134 {
135  int i=((Switch *)_node)->getRankOfNode(port->getNode());
136  map<int, OutPort *>::iterator pt=_potentialProducers.find(i);
137  if(pt==_potentialProducers.end())
138  {
139  _potentialProducers[i]=port;
140  _currentProducer=port;
141  }
142  else
143  {
144  _currentProducer=(*pt).second;
145  if(_currentProducer!=port)
146  {
147  string what("CollectorSwOutPort::addPotentialProducerForMaster : In switch node "); what+=_node->getName();
148  what+=" for input named \'"; what+=_consumer->getName(); what+="\' the output "; what+=_currentProducer->getName();
149  what+=" already got out for case of label ";
150  what+=Switch::getRepresentationOfCase((*pt).first);
151  throw Exception(what);
152  }
153  }
155 }
156 
158 {
159  int i;
160  map<int, OutPort *>::iterator result;
161  for(result=_potentialProducers.begin();result!=_potentialProducers.end();result++)
162  if((*result).second==_currentProducer)
163  {
164  i=(*result).first;
165  break;
166  }
167  if(result==_potentialProducers.end())
168  {
169  ostringstream stream; stream << "CollectorSwOutPort::removePotentialProducerForMaster : link from the branch whith id ";
170  stream << i << " not defined";
171  throw Exception(stream.str());
172  }
173  if((*result).second!=_currentProducer)
174  {
175  ostringstream stream; stream << "CollectorSwOutPort::removePotentialProducerForMaster : link from the branch whith id ";
176  stream << i << " defined but the output specified is not compatible";
177  throw Exception(stream.str());
178  }
179  _potentialProducers.erase(result);
180  return _potentialProducers.empty();
181 }
182 
184 {
185  for(map<int, OutPort *>::iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++)
186  if((*iter).second==port)
187  {
188  _currentProducer=port;
189  return _potentialProducers.size()==1;
190  }
191  throw Exception("CollectorSwOutPort::checkManagementOfPort : unexported port");
192 }
193 
198 {
199  if(((Switch *)_node)->getNbOfCases()!=_potentialProducers.size())
200  info.pushErrSwitch((CollectorSwOutPort *)this);
201  for(map<int, OutPort *>::const_iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++)
202  (*iter).second->checkConsistency(info);
203 }
204 
210 {
211  set<int> lackingCases;
212  for(map< int ,Node * >::const_iterator iter=((Switch *)_node)->_mapOfNode.begin();iter!=((Switch *)_node)->_mapOfNode.end();iter++)
213  {
214  if(_potentialProducers.find((*iter).first)==_potentialProducers.end())
215  lackingCases.insert((*iter).first);
216  }
217  ostringstream streamForExc;
218  stream << "For link to " << _consumer->getName() << " of node " << _consumer->getNode()->getName()
219  << " the cases of switch node named " << _node->getName()
220  << " do not define links for following cases ids :";
221  for(set<int>::iterator iter=lackingCases.begin();iter!=lackingCases.end();iter++)
222  stream << Switch::getRepresentationOfCase(*iter) << " ";
223  stream << endl;
224 }
225 
226 FakeNodeForSwitch::FakeNodeForSwitch(Switch *sw, bool normalFinish, bool internalError):ElementaryNode("thisIsAFakeNode"),
227  _sw(sw),
228  _normalFinish(normalFinish),
229  _internalError(internalError)
230 {
232  _father=_sw->getFather();
233 }
234 
236  _normalFinish(false),
237  _internalError(true)
238 {
239 }
240 
241 Node *FakeNodeForSwitch::simpleClone(ComposedNode *father, bool editionOnly) const
242 {
243  return new FakeNodeForSwitch(*this);
244 }
245 
247 {
248  _sw->exForwardFailed();
249 }
250 
252 {
254 }
255 
257 {
258  if(!_normalFinish)
259  throw Exception("");//only to trigger ABORT on Executor
260 }
261 
263 {
264  if(_internalError)
266  else
268 }
269 
271 {
273 }
274 
281 Switch::Switch(const Switch& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_condition(other._condition,this),
282  _undispatchableNotificationNode(0)
283 {
284  for(map<int,Node *>::const_iterator iter=other._mapOfNode.begin();iter!=other._mapOfNode.end();iter++)
285  _mapOfNode[(*iter).first]=(*iter).second->clone(this,editionOnly);
286  if(!editionOnly)
287  for(map<InPort *, CollectorSwOutPort * >::const_iterator iter2=other._outPortsCollector.begin();iter2!=other._outPortsCollector.end();iter2++)
288  {
289  CollectorSwOutPort *newCol=new CollectorSwOutPort(*((*iter2).second),this);
290  _alreadyExistingCollectors.push_back(newCol);
291  }
292 }
293 
294 Switch::Switch(const std::string& name):StaticDefinedComposedNode(name),_condition(SELECTOR_INPUTPORT_NAME,this,Runtime::_tc_int),_undispatchableNotificationNode(0)
295 {
296 }
297 
299 {
301 
302  for(map< int , Node * >::iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
303  delete (*iter).second;
304  for(map<InPort *, CollectorSwOutPort * >::iterator iter2=_outPortsCollector.begin();iter2!=_outPortsCollector.end();iter2++)
305  delete (*iter2).second;
306  for(vector<CollectorSwOutPort *>::iterator iter3=_alreadyExistingCollectors.begin();iter3!=_alreadyExistingCollectors.end();iter3++)
307  delete (*iter3);
308 }
309 
310 Node *Switch::simpleClone(ComposedNode *father, bool editionOnly) const
311 {
312  return new Switch(*this,father,editionOnly);
313 }
314 
316 {
317  DEBTRACE("Switch::exUpdateState " << _state);
318  if(_state == YACS::DISABLED)
319  return;
320  if(_inGate.exIsReady())
321  {
323  if(_condition.isEmpty())
325  else
326  {
327  map< int , Node * >::iterator iter=_mapOfNode.find(_condition.getIntValue());
328  if(iter==_mapOfNode.end())
329  {
330  iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE);
331  if(iter==_mapOfNode.end())
332  {
333  bool normalFinish=getAllOutPortsLeavingCurrentScope().empty();
335  _undispatchableNotificationNode=new FakeNodeForSwitch(this,normalFinish);
336  }
337  else
338  ((*iter).second)->exUpdateState();
339  }
340  else
341  ((*iter).second)->exUpdateState();
342  }
343  }
344 }
345 
346 void Switch::init(bool start)
347 {
348  DEBTRACE("Switch::init " << start);
350  int i=0;
351  for(map< int , Node * >::iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++, i++)
352  {
353  if(!(*iter).second)
354  {
355  ostringstream stream;
356  stream << "Switch::init : initialization failed due to unitialized branch of id " << (*iter).first;
357  throw Exception(stream.str());
358  }
359  ((*iter).second)->init(start);
360  }
361 }
362 
363 void Switch::getReadyTasks(std::vector<Task *>& tasks)
364 {
365  /*
366  * To change the way ComposedNode state is handled, uncomment the following line
367  * see Bloc::getReadyTasks
368  */
371  {
372  map< int , Node * >::iterator iter=_mapOfNode.find(_condition.getIntValue());
373  if(iter!=_mapOfNode.end())
374  ((*iter).second)->getReadyTasks(tasks);
375  else
376  {
377  iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE);
378  if(iter!=_mapOfNode.end())
379  (*iter).second->getReadyTasks(tasks);//Default Node is returned
380  else
383  else
384  throw Exception("Switch::getReadyTasks : internal error");
385  }
386  }
387 }
388 
389 list<Node *> Switch::edGetDirectDescendants() const
390 {
391  list<Node *> ret;
392  for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
393  if((*iter).second)
394  ret.push_back((*iter).second);
395  return ret;
396 }
397 
399 {
401 }
402 
404 {
405  int ret(0);
406  for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++)
407  ret=std::max(ret,((*it).second)->getMaxLevelOfParallelism());
408  return ret;
409 }
410 
412 {
413  map< int , Node * >::iterator iter=_mapOfNode.begin();
414  for(;iter!=_mapOfNode.end();iter++)
415  if(node==(*iter).second)
416  {
417  edReleaseCase((*iter).first);
418  return;
419  }
420  ostringstream what; what << "Switch::edRemoveChild : node with name " << node->getName() << " is not a direct child of Switch node " << _name;
421  throw Exception(what.str());
422 }
423 
424 std::list<InputPort *> Switch::getSetOfInputPort() const
425 {
427  ret.push_back((InputPort *)&_condition);
428  return ret;
429 }
430 
431 
432 std::list<InputPort *> Switch::getLocalInputPorts() const
433 {
435  ret.push_back((InputPort *)&_condition);
436  return ret;
437 }
438 OutPort *Switch::getOutPort(const std::string& name) const throw(YACS::Exception)
439 {
440  for(map<InPort *, CollectorSwOutPort * >::const_iterator iter=_outPortsCollector.begin();iter!=_outPortsCollector.end();iter++)
441  if(name==(*iter).second->getName())
442  return (*iter).second;
443  for(vector<CollectorSwOutPort *>::const_iterator iter2=_alreadyExistingCollectors.begin();iter2!=_alreadyExistingCollectors.end();iter2++)
444  if(name==(*iter2)->getName())
445  return *iter2;
447 }
448 
449 InputPort *Switch::getInputPort(const std::string& name) const throw(YACS::Exception)
450 {
451  if(name==SELECTOR_INPUTPORT_NAME)
452  return (InputPort *)&_condition;
454 }
455 
456 Node *Switch::getChildByShortName(const std::string& name) const throw(YACS::Exception)
457 {
458  if(name==DEFAULT_NODE_NAME)
459  {
460  map< int , Node * >::const_iterator iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE);
461  if(iter!=_mapOfNode.end())
462  return (Node *)((*iter).second);
463  else
464  {
465  string what("Switch::getChildByShortName : no default node defined for switch of name "); what+=getName();
466  throw Exception(what);
467  }
468  }
469  for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
470  {
471  if(name==((*iter).second)->getQualifiedName())
472  return (*iter).second;
473  }
474  string what("node "); what+= name ; what+=" is not a child of node switch "; what += getName();
475  throw Exception(what);
476 }
477 
479 {
480  return edSetNode(ID_FOR_DEFAULT_NODE,node);
481 }
482 
484 {
486 }
487 
489 {
490  map< int , Node * >::iterator iter=_mapOfNode.find(caseId);
491  if(iter==_mapOfNode.end())
492  {
493  string what("Switch::edReleaseCase : the case # "); what+=getRepresentationOfCase(caseId); what+=" is not set yet.";
494  throw Exception(what);
495  }
496  else
497  {
498  Node *ret=(*iter).second;
500  _mapOfNode.erase(iter);
501  modified();
502  return ret;
503  }
504 }
505 
507 {
508  if (!_mapOfNode.count(caseId)) return 0;
509  return _mapOfNode[caseId];
510 }
511 
512 
520 Node *Switch::edSetNode(int caseId, Node *node) throw(YACS::Exception)
521 {
522  if(!node)
523  throw Exception("Switch::edSetNode : null node cannot be set as a case in switch node");
524  if(node->_father!=0)
525  throw Exception("Switch::edSetNode : node already held by another father");
526  checkNoCrossHierachyWith(node);
527  node->_father=this;
528  map< int , Node * >::iterator iter=_mapOfNode.find(caseId);
529  if(iter==_mapOfNode.end())
530  {
531  _mapOfNode[caseId]=node;
532  modified();
533  return 0;
534  }
535  else
536  {
537  if(node!=(*iter).second)
538  {
539  Node *ret=(*iter).second;
540  (*iter).second=node;
541  modified();
542  return ret;
543  }
544  }
545 }
546 
548 
553 void Switch::edChangeCase(int oldCase, int newCase)
554 {
555  std::map< int , Node * >::iterator iter=_mapOfNode.find(oldCase);
556  if(iter==_mapOfNode.end())
557  {
558  //the case does not exists
559  throw Exception("Switch::edChangeCase : case does not exist");
560  }
561  iter=_mapOfNode.find(newCase);
562  if(iter != _mapOfNode.end())
563  {
564  //the new case exists
565  throw Exception("Switch::edChangeCase : new case exists");
566  }
567  Node* node=_mapOfNode[oldCase];
568  _mapOfNode.erase(oldCase);
569  _mapOfNode[newCase]=node;
570  modified();
571 }
572 
574 {
575  int aCase = 0;
576  map<int, Node*>::const_iterator it = _mapOfNode.begin();
577  for(; it != _mapOfNode.end(); ++it)
578  if ((*it).first > aCase)
579  aCase = (*it).first;
580  return aCase;
581 }
582 
584 
588 list<ProgressWeight> Switch::getProgressWeight() const
589 {
590  list<ProgressWeight> ret;
591  list<Node *> setOfNode=edGetDirectDescendants();
592  if (getState() == YACS::DONE)
593  {
594  for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
595  {
596  if (getEffectiveState(*iter) == YACS::DONE)
597  ret=(*iter)->getProgressWeight();
598  }
599  }
600  else
601  {
602  for(list<Node *>::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++)
603  {
604  list<ProgressWeight> myCurrentSet=(*iter)->getProgressWeight();
605  ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end());
606  }
607  }
608  return ret;
609 }
610 
612 {
613  int aCase = getMaxCase() + 1;
614  DEBTRACE(aCase);
615  bool ret = edSetNode(aCase, node);
616  DEBTRACE(ret);
617  return ret;
618 }
619 
621 {
623  return YACS::FINISH;//notify to father node that 'this' has becomed finished.
624 }
625 
627 {
629  set<OutPort *> temp2=_condition.edSetOutPort();
630  for(set<OutPort *>::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++)
631  if(!isInMyDescendance((*iter3)->getNode()))
632  {
633  ret.insert((InPort *)&_condition);
634  break;
635  }
636  return ret;
637 }
638 
639 void Switch::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
640 {
641  map<InPort *, CollectorSwOutPort * >::const_iterator iter=_outPortsCollector.find(end);
642  if(iter!=_outPortsCollector.end())
643  {
644  set<OutPort *> represented;
645  (*iter).second->getAllRepresented(represented);
646  list<OutPort *> others;
647  for(list<OutPort *>::const_iterator iter2=starts.begin();iter2!=starts.end();iter2++)
648  if(represented.find(*iter2)==represented.end())
649  others.push_back(*iter2);
650  if(others.empty())
651  alreadyFed=FED_ST;
652  else
653  StaticDefinedComposedNode::checkCFLinks(others,end,alreadyFed,direction,info);//should never happend;
654  }
655  else
656  StaticDefinedComposedNode::checkCFLinks(starts,end,alreadyFed,direction,info);
657 }
658 
659 void Switch::checkControlDependancy(OutPort *start, InPort *end, bool cross,
660  std::map < ComposedNode *, std::list < OutPort * > >& fw,
661  std::vector<OutPort *>& fwCross,
662  std::map< ComposedNode *, std::list < OutPort *> >& bw,
663  LinkInfo& info) const
664 {
665  throw Exception("Switch::checkControlDependancy : a link was dectected between 2 cases of a switch. Impossible !");
666 }
667 
669 {
670  throw Exception("Switch::checkNoCyclePassingThrough : uncorrect control flow link relative to switch");
671 }
672 
673 void Switch::checkLinkPossibility(OutPort *start, const std::list<ComposedNode *>& pointsOfViewStart,
674  InPort *end, const std::list<ComposedNode *>& pointsOfViewEnd) throw(YACS::Exception)
675 {
676  throw Exception("Switch::checkLinkPossibility : A link between 2 different cases of a same Switch requested -> Impossible");
677 }
678 
679 void Switch::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
680 {
681  map<InPort *, CollectorSwOutPort * >::iterator result=_outPortsCollector.find(finalTarget);
682  CollectorSwOutPort *newCollector;
683  if(result!=_outPortsCollector.end())
684  newCollector=(*result).second;
685  else
686  {
687  newCollector=new CollectorSwOutPort(this,finalTarget);
688  newCollector->edSetType((port.first)->edGetType());
689  _outPortsCollector[finalTarget]=newCollector;
690  }
691  newCollector->addPotentialProducerForMaster(port.first);
692  port.second=newCollector;
693  port.first=newCollector;
694 }
695 
696 void Switch::getDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
697 {
698  map<InPort *, CollectorSwOutPort * >::iterator iter=_outPortsCollector.find(finalTarget);
699  if(iter==_outPortsCollector.end())
700  {
701  string what("Switch::getDelegateOf : not exported OuputPort with name "); what+=(port.first)->getName(); what+=" for target inport of name ";
702  what+=finalTarget->getName();
703  throw Exception(what);
704  }
705  ((*iter).second)->checkManagementOfPort(port.first);
706  port.second=(*iter).second;
707  port.first=(*iter).second;
708 }
709 
710 void Switch::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView) throw(YACS::Exception)
711 {
712  set<OutPort *> repr;
713  portDwn->getAllRepresented(repr);
714  if(repr.size()==1)
715  {
716  CollectorSwOutPort *portCasted=dynamic_cast<CollectorSwOutPort *>(portUp);
717  if(portCasted->removePotentialProducerForMaster())//normally always true
718  {
719  delete portCasted;
720  _outPortsCollector.erase(finalTarget);
721  }
722  }
723 }
724 
725 int Switch::getNbOfCases() const
726 {
727  return _mapOfNode.size();
728 }
729 
730 int Switch::getRankOfNode(Node *node) const
731 {
732  Node *directSon=isInMyDescendance(node);
733  for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
734  if((*iter).second==directSon)
735  return (*iter).first;
736  throw Exception("Switch::getRankOfNode : node not in switch");
737 }
738 
739 string Switch::getRepresentationOfCase(int i)
740 {
741  if(i!=ID_FOR_DEFAULT_NODE)
742  {
743  ostringstream stream;
744  stream << i;
745  return stream.str();
746  }
747  else
748  return DEFAULT_NODE_NAME;
749 }
750 
752 
756 YACS::StatesForNode Switch::getEffectiveState(const Node* node) const
757 {
758  YACS::StatesForNode effectiveState=Node::getEffectiveState();
759  if(effectiveState==YACS::READY)
760  return YACS::READY;
761  if(effectiveState==YACS::TOACTIVATE)
762  return YACS::READY;
763  if(effectiveState==YACS::DISABLED)
764  return YACS::DISABLED;
765 
766  return node->getState();
767 }
768 YACS::StatesForNode Switch::getEffectiveState() const
769 {
770  return Node::getEffectiveState();
771 }
772 
773 void Switch::writeDot(std::ostream &os) const
774 {
775  os << " subgraph cluster_" << getId() << " {\n" ;
776  for(map<int,Node*>::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++)
777  {
778  Node* n=(*iter).second;
779  n->writeDot(os);
780  os << getId() << " -> " << n->getId() << ";\n";
781  }
782  os << "}\n" ;
783  os << getId() << "[fillcolor=\"" ;
784  YACS::StatesForNode state=Node::getEffectiveState();
785  os << getColorState(state);
786  os << "\" label=\"" << "Switch:" ;
787  os << getQualifiedName() <<"\"];\n";
788 }
789 
790 std::string Switch::getMyQualifiedName(const Node *directSon) const
791 {
792  string id=getCaseId(directSon);
793  id+=directSon->getName();
794  return id;
795 }
796 
797 std::string Switch::getCaseId(const Node *node) const throw(YACS::Exception)
798 {
799  const char sep='_';
800  map<int, Node*>::const_iterator iter;
801  for (iter = _mapOfNode.begin(); iter != _mapOfNode.end(); iter++)
802  if (iter->second == node)
803  {
804  stringstream a;
805  if (iter->first == Switch::ID_FOR_DEFAULT_NODE)
806  a << DEFAULT_NODE_NAME << sep;
807  else if (iter->first <0)
808  a << "m" << -iter->first << sep;
809  else a << "p" << iter->first << sep;
810  return a.str();
811  }
812  string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName();
813  throw Exception(what);
814 }
815 
816 void Switch::accept(Visitor *visitor)
817 {
818  visitor->visitSwitch(this);
819 }