X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2Fengine%2FSwitch.cxx;h=2085096cbef0ef1685b433238bb3745828e2647b;hb=1894c52d0838df8676e770bef061fc23ca436452;hp=4d4ad76f72e29a53768ee1e8011be7356d9a6aaf;hpb=24ab175e1695bf31f5b1f47b43ec8b45322dc6d3;p=modules%2Fyacs.git diff --git a/src/engine/Switch.cxx b/src/engine/Switch.cxx index 4d4ad76f7..2085096cb 100644 --- a/src/engine/Switch.cxx +++ b/src/engine/Switch.cxx @@ -1,29 +1,841 @@ +// Copyright (C) 2006-2024 CEA, EDF +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + #include "Switch.hxx" +#include "Visitor.hxx" +#include "LinkInfo.hxx" + +#include +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" using namespace YACS::ENGINE; using namespace std; -Switch::Switch(const string& name):ComposedNode(name) +const char Switch::DEFAULT_NODE_NAME[]="default"; +const int Switch::ID_FOR_DEFAULT_NODE=-1973012217; +const char Switch::SELECTOR_INPUTPORT_NAME[]="select"; + +int CollectorSwOutPort::edGetNumberOfOutLinks() const +{ + return 1; +} + +std::set CollectorSwOutPort::edSetInPort() const +{ + set ret; + if(_consumer) + ret.insert(_consumer); + return ret; +} + +bool CollectorSwOutPort::isAlreadyLinkedWith(InPort *with) const +{ + set s; + with->getAllRepresentants(s); + return s.find(_consumer)!=s.end(); +} + +std::string CollectorSwOutPort::getNameOfTypeOfCurrentInstance() const +{ + return _className; +} + +void CollectorSwOutPort::edRemoveAllLinksLinkedWithMe() +{ + map::iterator pt; + if(_consumer) + for(pt=_potentialProducers.begin();pt!=_potentialProducers.end();pt++) + ((*pt).second)->removeInPort(_consumer,true); +} + +TypeOfChannel CollectorSwOutPort::getTypeOfChannel() const +{ + return (*(_potentialProducers.begin())).second->getTypeOfChannel(); +} + +void CollectorSwOutPort::getAllRepresented(std::set& represented) const +{ + map::const_iterator pt; + for(pt=_potentialProducers.begin();pt!=_potentialProducers.end();pt++) + ((*pt).second)->getAllRepresented(represented); +} + +bool CollectorSwOutPort::addInPort(InPort *inPort) +{ + bool ret = false; + if(_currentProducer) + {//a specific link is beeing done + ret=_currentProducer->addInPort(inPort); + _currentProducer=0; + } + else//global links asked + for(map::iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++) + ret |= (*iter).second->addInPort(inPort); + return ret; +} + +int CollectorSwOutPort::removeInPort(InPort *inPort, bool forward) +{ + if(_currentProducer) + { + return _currentProducer->removeInPort(inPort,forward); + } + else + throw Exception("CollectorSwOutputPort::edRemoveInputPort : internal error on link removal."); + _currentProducer=0; +} + +/*! + * \note : 'master' specifies the instance of Switch of which 'this' collects all of these direct + * or indirect outports going to the same port 'port' (which is out of scope of 'master'). + */ +CollectorSwOutPort::CollectorSwOutPort(Switch *master, InPort *port):OutPort("",master,port->edGetType()), + DataPort("",master,port->edGetType()), + Port(master), + _consumer(port),_currentProducer(0) +{ + _name="Representant_of_"; + _name+=master->getName(); + _name+="_for_inport_"; + _name+=port->getName(); +} + +CollectorSwOutPort::CollectorSwOutPort(const CollectorSwOutPort& other, Switch *master):OutPort("",master,other.edGetType()), + DataPort("",master,other.edGetType()), + Port(master), + _consumer(0),_currentProducer(0) +{ + _name=other._name; + Switch *othSw=(Switch *)other._node; + for(map::const_iterator iter=other._potentialProducers.begin();iter!=other._potentialProducers.end();iter++) + { + string name=othSw->getOutPortName((*iter).second); + _potentialProducers[(*iter).first]=master->getOutPort(name); + } +} + +void CollectorSwOutPort::addPotentialProducerForMaster(OutPort *port) +{ + int i=((Switch *)_node)->getRankOfNode(port->getNode()); + map::iterator pt=_potentialProducers.find(i); + if(pt==_potentialProducers.end()) + { + _potentialProducers[i]=port; + _currentProducer=port; + } + else + { + _currentProducer=(*pt).second; + if(_currentProducer!=port) + { + string what("CollectorSwOutPort::addPotentialProducerForMaster : In switch node "); what+=_node->getName(); + what+=" for input named \'"; what+=_consumer->getName(); what+="\' the output "; what+=_currentProducer->getName(); + what+=" already got out for case of label "; + what+=Switch::getRepresentationOfCase((*pt).first); + throw Exception(what); + } + } + _className=port->getNameOfTypeOfCurrentInstance(); +} + +bool CollectorSwOutPort::removePotentialProducerForMaster() +{ + int i; + map::iterator result; + for(result=_potentialProducers.begin();result!=_potentialProducers.end();result++) + if((*result).second==_currentProducer) + { + i=(*result).first; + break; + } + if(result==_potentialProducers.end()) + { + ostringstream stream; stream << "CollectorSwOutPort::removePotentialProducerForMaster : link from the branch whith id "; + stream << i << " not defined"; + throw Exception(stream.str()); + } + if((*result).second!=_currentProducer) + { + ostringstream stream; stream << "CollectorSwOutPort::removePotentialProducerForMaster : link from the branch whith id "; + stream << i << " defined but the output specified is not compatible"; + throw Exception(stream.str()); + } + _potentialProducers.erase(result); + return _potentialProducers.empty(); +} + +bool CollectorSwOutPort::checkManagementOfPort(OutPort *port) +{ + for(map::iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++) + if((*iter).second==port) + { + _currentProducer=port; + return _potentialProducers.size()==1; + } + throw Exception("CollectorSwOutPort::checkManagementOfPort : unexported port"); +} + +/*! + * Called by Switch::checkCFLinks. + */ +void CollectorSwOutPort::checkConsistency(LinkInfo& info) const +{ + if(((Switch *)_node)->getNbOfCases()!=_potentialProducers.size()) + info.pushErrSwitch((CollectorSwOutPort *)this); + for(map::const_iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++) + (*iter).second->checkConsistency(info); +} + +/*! + * Called by LinkInfo::getErrRepr to have a comprehensible message on throw. + * When called, typically checkCompletenessOfCases has detected that some potential producers were laking... + */ +void CollectorSwOutPort::getHumanReprOfIncompleteCases(std::ostream& stream) const +{ + set lackingCases; + for(map< int ,Node * >::const_iterator iter=((Switch *)_node)->_mapOfNode.begin();iter!=((Switch *)_node)->_mapOfNode.end();iter++) + { + if(_potentialProducers.find((*iter).first)==_potentialProducers.end()) + lackingCases.insert((*iter).first); + } + ostringstream streamForExc; + stream << "For link to " << _consumer->getName() << " of node " << _consumer->getNode()->getName() + << " the cases of switch node named " << _node->getName() + << " do not define links for following cases ids :"; + for(set::iterator iter=lackingCases.begin();iter!=lackingCases.end();iter++) + stream << Switch::getRepresentationOfCase(*iter) << " "; + stream << endl; +} + +FakeNodeForSwitch::FakeNodeForSwitch(Switch *sw, bool normalFinish, bool internalError):ElementaryNode("thisIsAFakeNode"), + _sw(sw), + _normalFinish(normalFinish), + _internalError(internalError) +{ + _state=YACS::TOACTIVATE; + _father=_sw->getFather(); +} + +FakeNodeForSwitch::FakeNodeForSwitch(const FakeNodeForSwitch& other):ElementaryNode(other),_sw(0), + _normalFinish(false), + _internalError(true) +{ +} + +Node *FakeNodeForSwitch::simpleClone(ComposedNode *father, bool editionOnly) const +{ + return new FakeNodeForSwitch(*this); +} + +void FakeNodeForSwitch::exForwardFailed() +{ + _sw->exForwardFailed(); +} + +void FakeNodeForSwitch::exForwardFinished() +{ + _sw->exForwardFinished(); +} + +void FakeNodeForSwitch::execute() +{ + if(!_normalFinish) + throw Exception("");//only to trigger ABORT on Executor +} + +void FakeNodeForSwitch::aborted() +{ + if(_internalError) + _sw->_state!=YACS::INTERNALERR; + else + _sw->setState(YACS::ERROR); +} + +void FakeNodeForSwitch::finished() +{ + _sw->setState(YACS::DONE); +} + +/*! \class YACS::ENGINE::Switch + * \brief Control node that emulates the C switch + * + * \ingroup Nodes + */ + +Switch::Switch(const Switch& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_condition(other._condition,this), + _undispatchableNotificationNode(0) +{ + for(map::const_iterator iter=other._mapOfNode.begin();iter!=other._mapOfNode.end();iter++) + _mapOfNode[(*iter).first]=(*iter).second->clone(this,editionOnly); + if(!editionOnly) + for(map::const_iterator iter2=other._outPortsCollector.begin();iter2!=other._outPortsCollector.end();iter2++) + { + CollectorSwOutPort *newCol=new CollectorSwOutPort(*((*iter2).second),this); + _alreadyExistingCollectors.push_back(newCol); + } +} + +Switch::Switch(const std::string& name):StaticDefinedComposedNode(name),_condition(SELECTOR_INPUTPORT_NAME,this,Runtime::_tc_int),_undispatchableNotificationNode(0) { } Switch::~Switch() { + if(_undispatchableNotificationNode)delete _undispatchableNotificationNode; + + for(map< int , Node * >::iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++) + delete (*iter).second; + for(map::iterator iter2=_outPortsCollector.begin();iter2!=_outPortsCollector.end();iter2++) + delete (*iter2).second; + for(vector::iterator iter3=_alreadyExistingCollectors.begin();iter3!=_alreadyExistingCollectors.end();iter3++) + delete (*iter3); +} + +Node *Switch::simpleClone(ComposedNode *father, bool editionOnly) const +{ + return new Switch(*this,father,editionOnly); +} + +void Switch::exUpdateState() +{ + DEBTRACE("Switch::exUpdateState " << _state); + if(_state == YACS::DISABLED) + return; + if(_inGate.exIsReady()) + { + setState(YACS::ACTIVATED); + if(_condition.isEmpty()) + _undispatchableNotificationNode=new FakeNodeForSwitch(this,false,true); + else + { + map< int , Node * >::iterator iter=_mapOfNode.find(_condition.getIntValue()); + if(iter==_mapOfNode.end()) + { + iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE); + if(iter==_mapOfNode.end()) + { + bool normalFinish=getAllOutPortsLeavingCurrentScope().empty(); + delete _undispatchableNotificationNode; + _undispatchableNotificationNode=new FakeNodeForSwitch(this,normalFinish); + } + else + ((*iter).second)->exUpdateState(); + } + else + ((*iter).second)->exUpdateState(); + } + } +} + +void Switch::init(bool start) +{ + DEBTRACE("Switch::init " << start); + StaticDefinedComposedNode::init(start); + int i=0; + for(map< int , Node * >::iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++, i++) + { + if(!(*iter).second) + { + ostringstream stream; + stream << "Switch::init : initialization failed due to unitialized branch of id " << (*iter).first; + throw Exception(stream.str()); + } + ((*iter).second)->init(start); + } +} + +void Switch::getReadyTasks(std::vector& tasks) +{ + /* + * To change the way ComposedNode state is handled, uncomment the following line + * see Bloc::getReadyTasks + */ + if(_state==YACS::TOACTIVATE) setState(YACS::ACTIVATED); + if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED) + { + map< int , Node * >::iterator iter=_mapOfNode.find(_condition.getIntValue()); + if(iter!=_mapOfNode.end()) + ((*iter).second)->getReadyTasks(tasks); + else + { + iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE); + if(iter!=_mapOfNode.end()) + (*iter).second->getReadyTasks(tasks);//Default Node is returned + else + if(_undispatchableNotificationNode) + _undispatchableNotificationNode->getReadyTasks(tasks); + else + throw Exception("Switch::getReadyTasks : internal error"); + } + } +} + +list Switch::edGetDirectDescendants() const +{ + list ret; + for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++) + if((*iter).second) + ret.push_back((*iter).second); + return ret; +} + +int Switch::getNumberOfInputPorts() const +{ + return StaticDefinedComposedNode::getNumberOfInputPorts()+1; } -void Switch::edSetNumberOfCases(int numberOfCases) +int Switch::getMaxLevelOfParallelism() const { - _vectorOfNode.resize(numberOfCases); + int ret(0); + for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++) + ret=std::max(ret,((*it).second)->getMaxLevelOfParallelism()); + return ret; } -void Switch::edSetNode(int caseId, Node *node) throw(Exception) +void Switch::getWeightRegardingDPL(ComplexWeight *weight) { - if(caseId>=_vectorOfNode.size()) - throw Exception("Switch::edSetNode : caseId is too large compared to number of cases"); - _vectorOfNode[caseId]=node; + ComplexWeight localWeight; + for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++) + { + ((*it).second)->getWeightRegardingDPL(&localWeight); + weight->max(localWeight); + localWeight.setToZero(); + } } -void Switch::checkNoCyclePassingThrough(Node *node) throw(Exception) +void Switch::partitionRegardingDPL(const PartDefinition *pd, std::map >& zeMap) +{ + for(std::map< int , Node * >::const_iterator it=_mapOfNode.begin();it!=_mapOfNode.end();it++) + (*it).second->partitionRegardingDPL(pd,zeMap); +} + +void Switch::edRemoveChild(Node *node) +{ + map< int , Node * >::iterator iter=_mapOfNode.begin(); + for(;iter!=_mapOfNode.end();iter++) + if(node==(*iter).second) + { + edReleaseCase((*iter).first); + return; + } + ostringstream what; what << "Switch::edRemoveChild : node with name " << node->getName() << " is not a direct child of Switch node " << _name; + throw Exception(what.str()); +} + +std::list Switch::getSetOfInputPort() const +{ + list ret=StaticDefinedComposedNode::getSetOfInputPort(); + ret.push_back((InputPort *)&_condition); + return ret; +} + + +std::list Switch::getLocalInputPorts() const +{ + list ret=StaticDefinedComposedNode::getLocalInputPorts(); + ret.push_back((InputPort *)&_condition); + return ret; +} +OutPort *Switch::getOutPort(const std::string& name) const +{ + for(map::const_iterator iter=_outPortsCollector.begin();iter!=_outPortsCollector.end();iter++) + if(name==(*iter).second->getName()) + return (*iter).second; + for(vector::const_iterator iter2=_alreadyExistingCollectors.begin();iter2!=_alreadyExistingCollectors.end();iter2++) + if(name==(*iter2)->getName()) + return *iter2; + return StaticDefinedComposedNode::getOutPort(name); +} + +InputPort *Switch::getInputPort(const std::string& name) const +{ + if(name==SELECTOR_INPUTPORT_NAME) + return (InputPort *)&_condition; + return StaticDefinedComposedNode::getInputPort(name); +} + +Node *Switch::getChildByShortName(const std::string& name) const +{ + if(name==DEFAULT_NODE_NAME) + { + map< int , Node * >::const_iterator iter=_mapOfNode.find(ID_FOR_DEFAULT_NODE); + if(iter!=_mapOfNode.end()) + return (Node *)((*iter).second); + else + { + string what("Switch::getChildByShortName : no default node defined for switch of name "); what+=getName(); + throw Exception(what); + } + } + for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++) + { + if(name==((*iter).second)->getQualifiedName()) + return (*iter).second; + } + string what("node "); what+= name ; what+=" is not a child of node switch "; what += getName(); + throw Exception(what); +} + +Node *Switch::edSetDefaultNode(Node *node) +{ + return edSetNode(ID_FOR_DEFAULT_NODE,node); +} + +Node *Switch::edReleaseDefaultNode() +{ + return edReleaseCase(ID_FOR_DEFAULT_NODE); +} + +Node *Switch::edReleaseCase(int caseId) +{ + map< int , Node * >::iterator iter=_mapOfNode.find(caseId); + if(iter==_mapOfNode.end()) + { + string what("Switch::edReleaseCase : the case # "); what+=getRepresentationOfCase(caseId); what+=" is not set yet."; + throw Exception(what); + } + else + { + Node *ret=(*iter).second; + StaticDefinedComposedNode::edRemoveChild(ret); + _mapOfNode.erase(iter); + modified(); + return ret; + } +} + +Node *Switch::edGetNode(int caseId) +{ + if (!_mapOfNode.count(caseId)) return 0; + return _mapOfNode[caseId]; +} + + +/*! + * \param caseId : the case ID chosen to place 'node' + * \param node : the node for the specified 'caseId' + * \return : If an old node with id equal to 'caseId' exists before, this old node is returned so that to be deallocated. + * 0 is returned if caseId is a new ID. + * \b WARNING : 'node' is held by 'this' after call, whereas returned node is no more held. + */ +Node *Switch::edSetNode(int caseId, Node *node) +{ + if(!node) + throw Exception("Switch::edSetNode : null node cannot be set as a case in switch node"); + if(node->_father!=0) + throw Exception("Switch::edSetNode : node already held by another father"); + checkNoCrossHierachyWith(node); + node->_father=this; + map< int , Node * >::iterator iter=_mapOfNode.find(caseId); + if(iter==_mapOfNode.end()) + { + _mapOfNode[caseId]=node; + modified(); + return 0; + } + else + { + if(node!=(*iter).second) + { + Node *ret=(*iter).second; + (*iter).second=node; + modified(); + return ret; + } + } + return 0; +} + +//! Change the case of a node +/*! + * \param oldCase : the case value to change + * \param newCase : the new value to set + * raise an exception if the old case does not exist or if the new case already exists + */ +void Switch::edChangeCase(int oldCase, int newCase) +{ + std::map< int , Node * >::iterator iter=_mapOfNode.find(oldCase); + if(iter==_mapOfNode.end()) + { + //the case does not exists + throw Exception("Switch::edChangeCase : case does not exist"); + } + iter=_mapOfNode.find(newCase); + if(iter != _mapOfNode.end()) + { + //the new case exists + throw Exception("Switch::edChangeCase : new case exists"); + } + Node* node=_mapOfNode[oldCase]; + _mapOfNode.erase(oldCase); + _mapOfNode[newCase]=node; + modified(); +} + +int Switch::getMaxCase() +{ + int aCase = 0; + map::const_iterator it = _mapOfNode.begin(); + for(; it != _mapOfNode.end(); ++it) + if ((*it).first > aCase) + aCase = (*it).first; + return aCase; +} + +//! Get the progress weight of the graph +/*! + * Only elementary nodes have weight. If the switch node is not done, we add the weight of all his descendants, + * otherwise only the weight of the used case count. + */ +list Switch::getProgressWeight() const +{ + list ret; + list setOfNode=edGetDirectDescendants(); + if (getState() == YACS::DONE) + { + for(list::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) + { + if (getEffectiveState(*iter) == YACS::DONE) + ret=(*iter)->getProgressWeight(); + } + } + else + { + for(list::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) + { + list myCurrentSet=(*iter)->getProgressWeight(); + ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end()); + } + } + return ret; +} + +bool Switch::edAddChild(Node *node) +{ + int aCase = getMaxCase() + 1; + DEBTRACE(aCase); + bool ret = edSetNode(aCase, node); + DEBTRACE(ret); + return ret; +} + +YACS::Event Switch::updateStateOnFinishedEventFrom(Node *node) +{ + setState(YACS::DONE); + return YACS::FINISH;//notify to father node that 'this' has becomed finished. +} + +std::set Switch::getAllInPortsComingFromOutsideOfCurrentScope() const +{ + set ret=StaticDefinedComposedNode::getAllInPortsComingFromOutsideOfCurrentScope(); + set temp2=_condition.edSetOutPort(); + for(set::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++) + if(!isInMyDescendance((*iter3)->getNode())) + { + ret.insert((InPort *)&_condition); + break; + } + return ret; +} + +void Switch::checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const +{ + map::const_iterator iter=_outPortsCollector.find(end); + if(iter!=_outPortsCollector.end()) + { + set represented; + (*iter).second->getAllRepresented(represented); + list others; + for(list::const_iterator iter2=starts.begin();iter2!=starts.end();iter2++) + if(represented.find(*iter2)==represented.end()) + others.push_back(*iter2); + if(others.empty()) + alreadyFed=FED_ST; + else + StaticDefinedComposedNode::checkCFLinks(others,end,alreadyFed,direction,info);//should never happend; + } + else + StaticDefinedComposedNode::checkCFLinks(starts,end,alreadyFed,direction,info); +} + +void Switch::checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * > >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *> >& bw, + LinkInfo& info) const +{ + throw Exception("Switch::checkControlDependancy : a link was dectected between 2 cases of a switch. Impossible !"); +} + +void Switch::checkNoCyclePassingThrough(Node *node) { throw Exception("Switch::checkNoCyclePassingThrough : uncorrect control flow link relative to switch"); } + +void Switch::checkLinkPossibility(OutPort *start, const std::list& pointsOfViewStart, + InPort *end, const std::list& pointsOfViewEnd) +{ + throw Exception("Switch::checkLinkPossibility : A link between 2 different cases of a same Switch requested -> Impossible"); +} + +void Switch::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) +{ + map::iterator result=_outPortsCollector.find(finalTarget); + CollectorSwOutPort *newCollector; + if(result!=_outPortsCollector.end()) + newCollector=(*result).second; + else + { + newCollector=new CollectorSwOutPort(this,finalTarget); + newCollector->edSetType((port.first)->edGetType()); + _outPortsCollector[finalTarget]=newCollector; + } + newCollector->addPotentialProducerForMaster(port.first); + port.second=newCollector; + port.first=newCollector; +} + +void Switch::getDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) +{ + map::iterator iter=_outPortsCollector.find(finalTarget); + if(iter==_outPortsCollector.end()) + { + string what("Switch::getDelegateOf : not exported OuputPort with name "); what+=(port.first)->getName(); what+=" for target inport of name "; + what+=finalTarget->getName(); + throw Exception(what); + } + ((*iter).second)->checkManagementOfPort(port.first); + port.second=(*iter).second; + port.first=(*iter).second; +} + +void Switch::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list& pointsOfView) +{ + set repr; + portDwn->getAllRepresented(repr); + if(repr.size()==1) + { + CollectorSwOutPort *portCasted=dynamic_cast(portUp); + if(portCasted->removePotentialProducerForMaster())//normally always true + { + delete portCasted; + _outPortsCollector.erase(finalTarget); + } + } +} + +int Switch::getNbOfCases() const +{ + return _mapOfNode.size(); +} + +int Switch::getRankOfNode(Node *node) const +{ + Node *directSon=isInMyDescendance(node); + for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++) + if((*iter).second==directSon) + return (*iter).first; + throw Exception("Switch::getRankOfNode : node not in switch"); +} + +string Switch::getRepresentationOfCase(int i) +{ + if(i!=ID_FOR_DEFAULT_NODE) + { + ostringstream stream; + stream << i; + return stream.str(); + } + else + return DEFAULT_NODE_NAME; +} + +//! Return the effective state of a node in the context of this switch (its father) +/*! + * \param node: the node which effective state is queried + * \return the effective node state + */ +YACS::StatesForNode Switch::getEffectiveState(const Node* node) const +{ + YACS::StatesForNode effectiveState=Node::getEffectiveState(); + if(effectiveState==YACS::READY) + return YACS::READY; + if(effectiveState==YACS::TOACTIVATE) + return YACS::READY; + if(effectiveState==YACS::DISABLED) + return YACS::DISABLED; + + return node->getState(); +} +YACS::StatesForNode Switch::getEffectiveState() const +{ + return Node::getEffectiveState(); +} + +void Switch::writeDot(std::ostream &os) const +{ + os << " subgraph cluster_" << getId() << " {\n" ; + for(map::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++) + { + Node* n=(*iter).second; + n->writeDot(os); + os << getId() << " -> " << n->getId() << ";\n"; + } + os << "}\n" ; + os << getId() << "[fillcolor=\"" ; + YACS::StatesForNode state=Node::getEffectiveState(); + os << getColorState(state); + os << "\" label=\"" << "Switch:" ; + os << getQualifiedName() <<"\"];\n"; +} + +std::string Switch::getMyQualifiedName(const Node *directSon) const +{ + string id=getCaseId(directSon); + id+=directSon->getName(); + return id; +} + +std::string Switch::getCaseId(const Node *node) const +{ + const char sep='_'; + map::const_iterator iter; + for (iter = _mapOfNode.begin(); iter != _mapOfNode.end(); iter++) + if (iter->second == node) + { + stringstream a; + if (iter->first == Switch::ID_FOR_DEFAULT_NODE) + a << DEFAULT_NODE_NAME << sep; + else if (iter->first <0) + a << "m" << -iter->first << sep; + else a << "p" << iter->first << sep; + return a.str(); + } + string what("node "); what+= node->getName() ; what+=" is not a child of node "; what += getName(); + throw Exception(what); +} + +void Switch::accept(Visitor *visitor) +{ + visitor->visitSwitch(this); +}