2 #include "InputPort.hxx"
3 #include "OutputPort.hxx"
4 #include "ComposedNode.hxx"
5 #include "Dispatcher.hxx"
6 #include "InputDataStreamPort.hxx"
7 #include "OutputDataStreamPort.hxx"
11 #include "YacsTrace.hxx"
13 using namespace YACS::ENGINE;
16 const char Node::SEP_CHAR_IN_PORT[]=".";
19 std::map<int,Node*> Node::idMap;
21 Node::Node(const std::string& name):_name(name),_inGate(this),_outGate(this),_father(0),_state(YACS::INITED),
22 _implementation(Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME)
24 // Should be protected by lock ??
29 Node::Node(const Node& other, ComposedNode *father):_inGate(this),_outGate(this),_name(other._name),_father(father),
30 _state(YACS::INITED),_implementation(other._implementation),
31 _propertyMap(other._propertyMap)
42 * initialisation of all input and output ports and gates, for execution
45 void Node::init(bool start)
49 if(_state == YACS::DISABLED)
51 exDisabledState(); // to refresh propagation of DISABLED state
54 setState(YACS::INITED);
57 Node *Node::clone(ComposedNode *father, bool editionOnly) const
59 Node *ret=simpleClone(father,editionOnly);
60 ret->performDuplicationOfPlacement(*this);
65 * get the set of all nodes connected to the outGate
68 set<Node *> Node::getOutNodes() const
71 set<InGate *> inGates=_outGate.edSetInGate();
72 for(set<InGate *>::iterator iter=inGates.begin();iter!=inGates.end();iter++)
73 ret.insert((*iter)->getNode());
77 bool Node::exIsControlReady() const
79 return _inGate.exIsReady();
83 * \note : Update the '_state' attribute.
84 * Typically called by 'this->_inGate' when 'this->_inGate' is ready.
86 * Called by InGate::exNotifyFromPrecursor
89 void Node::exUpdateState()
91 if(_state==YACS::DISABLED)return;
92 if(_inGate.exIsReady())
93 setState(YACS::TOACTIVATE);
96 //! Notify this node that its execution has failed
98 * The node goes in FAILED state and
99 * propagate the notification through the outGate port
102 void Node::exFailedState()
104 DEBTRACE( "Node::exFailedState: " << getName() );
105 setState(YACS::FAILED);
106 _outGate.exNotifyFailed();
109 //! Notify this node that it has been disabled
111 * The node goes in DISABLED state and
112 * propagate the notification through the outGate port
115 void Node::exDisabledState()
117 DEBTRACE( "Node::exDisabledState: " << getName() );
118 setState(YACS::DISABLED);
119 _outGate.exNotifyDisabled();
122 InPort *Node::getInPort(const std::string& name) const throw(Exception)
127 ret=getInputPort(name);
131 ret=getInputDataStreamPort(name);
137 * \note: Contrary to getOutputPort method, this method returns the output port at highest level, possible.
138 * That is to say in some ComposedNode, like ForEachLoop or Switch, an outport inside 'this' is seen differently than the true outport.
140 OutPort *Node::getOutPort(const std::string& name) const throw(Exception)
145 ret=getOutputPort(name);
149 ret=getOutputDataStreamPort(name);
154 std::list<InPort *> Node::getSetOfInPort() const
157 list<InputPort *> data=getSetOfInputPort();
158 ret.insert(ret.end(),data.begin(),data.end());
159 list<InputDataStreamPort *> ds=getSetOfInputDataStreamPort();
160 ret.insert(ret.end(),ds.begin(),ds.end());
164 std::list<OutPort *> Node::getSetOfOutPort() const
167 list<OutputPort *> data=getSetOfOutputPort();
168 ret.insert(ret.end(),data.begin(),data.end());
169 list<OutputDataStreamPort *> ds=getSetOfOutputDataStreamPort();
170 ret.insert(ret.end(),ds.begin(),ds.end());
175 * gets a set of the composed nodes that constitute the ascendancy of this node, starting from root
176 * or from a particular ancestor
177 * \b WARNING : returned set is not sorted !
178 * @param levelToStop composed node which is the oldest ancestor required
179 * @return ascendancy, direct father first in set.
182 std::set<ComposedNode *> Node::getAllAscendanceOf(ComposedNode *levelToStop)
184 set<ComposedNode *> ret;
185 if(this==levelToStop)
187 for(ComposedNode *iter=_father;iter!=levelToStop && iter!=0; iter=iter->_father)
193 * @return Implementation of node: C++, Python, CORBA...
194 * _implementation is set by a derived class in a Runtime
195 * it normally applies only to elementaryNodes and it is used by Ports to select Data Converters.
196 * Potential problem with Ports attached to composed Nodes...
199 string Node::getImplementation()
201 return _implementation;
204 //! Becomes deprecated soon. Replaced by ComposedNode::CheckConsistency.
205 set<InputPort *> Node::edGetSetOfUnitializedInputPort() const
207 set<InputPort *> setOfUnitializedInputPort;
208 list<InputPort *> allOfInputPorts=getSetOfInputPort();
209 for(list<InputPort *>::const_iterator iter=allOfInputPorts.begin();iter!=allOfInputPorts.end();iter++)
211 if ( ! (*iter)->edIsInitialized() )
212 setOfUnitializedInputPort.insert(*iter);
214 return setOfUnitializedInputPort;
217 //! Becomes deprecated soon. Replaced by ComposedNode::CheckConsistency.
218 bool Node::edAreAllInputPortInitialized() const
220 set<InputPort *> setOfUnitializedInputPort = edGetSetOfUnitializedInputPort();
221 return ( setOfUnitializedInputPort.size() == 0);
225 * Called typically by Bloc to notify failure on potentially next nodes on the same scope of 'this'
227 void Node::exForwardFailed()
229 _outGate.exNotifyFailed();
233 * Called typically by Bloc to activate potentially next nodes on the same scope of 'this'
235 void Node::exForwardFinished()
237 _outGate.exNotifyDone();
241 * Called typically by ComposedNode to correctly update DF/CF/DS links
243 void Node::edDisconnectAllLinksWithMe()
245 _inGate.edDisconnectAllLinksToMe();
246 _outGate.edDisconnectAllLinksFromMe();
249 ComposedNode *Node::getRootNode() throw(Exception)
252 throw Exception("No root node");
253 ComposedNode *iter=_father;
260 * checks validity of ports name, that must not contain a particular character '?'
261 * USAGE NOT CLEAR, not used so far, when are those characters set ?
264 void Node::checkValidityOfPortName(const std::string& name) throw(Exception)
266 if(name.find(SEP_CHAR_IN_PORT, 0 )!=string::npos)
268 string what("Port name "); what+=name; what+="not valid because it contains character "; what+=SEP_CHAR_IN_PORT;
269 throw Exception(what);
274 * @note : Check that 'node1' and 'node2' have exactly the same father
275 * @exception : If 'node1' and 'node2' have NOT exactly the same father
277 ComposedNode *Node::checkHavingCommonFather(Node *node1, Node *node2) throw(Exception)
279 if(node1!=0 && node2!=0)
281 if(node1->_father==node2->_father)
282 return node1->_father;
284 throw Exception("check failed : nodes have not the same father");
287 const std::string Node::getId()
289 std::string id=getRootNode()->getName();
290 if(getRootNode() != this)
291 id= id+'.'+ getRootNode()->getChildName(this);
292 string::size_type debut =id.find_first_of('.');
293 while(debut != std::string::npos){
295 debut=id.find_first_of('.',debut);
300 void Node::setProperty(const std::string& name, const std::string& value)
302 _propertyMap[name]=value;
305 //! Return the node state in the context of its father
307 * \return the effective node state
309 * The node state is stored in a private attribute _state.
310 * This state is relative to its father state : a node with a
311 * TOACTIVATE state with a father node in a INITED state is not
312 * to activate. Its effective state is only INITED.
313 * This method returns the effective state of the node taking
314 * into account that of its father.
316 YACS::StatesForNode Node::getEffectiveState()
318 if(!_father) //the root node
320 if(_state==YACS::DISABLED)
321 return YACS::DISABLED;
322 return _father->getEffectiveState(this);
325 //! Return the effective state of a node in the context of this one (its father)
327 * \param node: the node which effective state is queried
328 * \return the effective node state
330 YACS::StatesForNode Node::getEffectiveState(Node* node)
332 if(node->getState()==YACS::DISABLED)
333 return YACS::DISABLED;
335 YACS::StatesForNode effectiveState=getEffectiveState();
336 switch(effectiveState)
340 case YACS::TOACTIVATE:
343 return YACS::DISABLED;
347 return node->getState();
351 //! Return the color associated to a state
353 * \param state : the node state
354 * \return the associated color
356 std::string Node::getColorState(YACS::StatesForNode state)
366 case YACS::TOACTIVATE:
368 case YACS::ACTIVATED:
385 //! Dump to the input stream a dot representation of the node
387 * \param os : the input stream
389 void Node::writeDot(std::ostream &os)
391 os << getId() << "[fillcolor=\"" ;
392 YACS::StatesForNode state=getEffectiveState();
393 os << getColorState(state);
394 os << "\" label=\"" << getImplementation() << "Node:" ;
395 os << getQualifiedName() <<"\"];\n";
398 //! same as Node::getName() in most cases, but differs for children of switch
400 * used by writeDot to distinguish children of switch, by adding a prefix to the name.
401 * prefix is built on case id.
404 std::string Node::getQualifiedName() const
407 return _father->getMyQualifiedName(this);
411 //! return node instance identifiant, unique for each node instance
413 * node instance identifiant is used to check if to nodes pointers refers to the same instance
420 //! Sets the given state for node.
421 /*! It is strongly recommended to use this function if you want to
422 * change the state of the node, instead of direct access to _state field (_state = ...).
424 void Node::setState(YACS::StatesForNode theState)
427 // emit notification to all observers registered with the dispatcher on any change of the node's state
431 //! emit notification to all observers registered with the dispatcher
433 * The dispatcher is unique and can be obtained by getDispatcher()
435 void Node::sendEvent(const std::string& event)
437 Dispatcher* disp=Dispatcher::getDispatcher();
438 disp->dispatch(this,event);
442 * For use only when loading a previously saved execution
445 void YACS::ENGINE::StateLoader(Node* node, YACS::StatesForNode state)
447 node->setState(state);