Salome HOME
copy tag mergefrom_BR_V0_1_CC_Salome_04oct07
[modules/yacs.git] / src / engine / ForLoop.cxx
1 #include "ForLoop.hxx"
2 #include "Runtime.hxx"
3 #include "OutputPort.hxx"
4 #include "Visitor.hxx"
5 #include <iostream>
6
7 using namespace YACS::ENGINE;
8 using namespace std;
9
10 const char ForLoop::NAME_OF_NSTEPS_NUMBER[]="nsteps";
11
12 ForLoop::ForLoop(const std::string& name):Loop(name),_nbOfTimesPort(NAME_OF_NSTEPS_NUMBER,this,Runtime::_tc_int)
13 {
14 }
15
16 ForLoop::ForLoop(const ForLoop& other, ComposedNode *father, bool editionOnly):Loop(other,father,editionOnly),
17                                                                                _nbOfTimesPort(other._nbOfTimesPort,this)
18 {
19 }
20
21 Node *ForLoop::simpleClone(ComposedNode *father, bool editionOnly) const
22 {
23   return new ForLoop(*this,father,editionOnly);
24 }
25
26 int ForLoop::getNumberOfInputPorts() const
27
28   return StaticDefinedComposedNode::getNumberOfInputPorts()+1; 
29 }
30
31 std::list<InputPort *> ForLoop::getSetOfInputPort() const
32 {
33   list<InputPort *> ret=StaticDefinedComposedNode::getSetOfInputPort();
34   ret.push_back((InputPort *)&_nbOfTimesPort);
35   return ret;
36 }
37
38 InputPort* ForLoop::getInputPort(const std::string& name) const throw(Exception)
39 {
40     if(name == NAME_OF_NSTEPS_NUMBER)return (InputPort*)&_nbOfTimesPort;
41     return Loop::getInputPort(name);
42
43 }
44
45 //! Initialize the node
46 /*!
47  * \param start: a boolean flag to indicate the initialization mode
48  *
49  * If start is true, it's a complete initialization (with port values initialization)
50  * If start is false, there is no port values initialization
51  *
52  */
53 void ForLoop::init(bool start)
54 {
55   Loop::init(start);
56   _nbOfTimesPort.exInit(start);
57 }
58
59 //! Update the state of the for loop
60 /*!
61  * If the inGate port is ready goes to YACS::TOACTIVATE state
62  * If the steps number is 0, create an special internal node
63  *
64  */
65 void ForLoop::exUpdateState()
66 {
67   if(_state == YACS::DISABLED)
68     return;
69   if(_inGate.exIsReady())
70     {
71       setState(YACS::TOACTIVATE);
72       _node->exUpdateState();
73       if(_nbOfTimesPort.isEmpty())
74         {
75           delete _nodeForNullTurnOfLoops;
76           _nodeForNullTurnOfLoops=new FakeNodeForLoop(this,false,true);
77         }
78       else
79         {
80           if(_nbOfTimesPort.getIntValue()==0)
81             {
82               bool normalFinish=getAllOutPortsLeavingCurrentScope().empty();
83               delete _nodeForNullTurnOfLoops;
84               _nodeForNullTurnOfLoops=new FakeNodeForLoop(this,normalFinish);
85             }
86           else if(_nbOfTimesPort.getIntValue()<0)
87             {
88               delete _nodeForNullTurnOfLoops;
89               _nodeForNullTurnOfLoops=new FakeNodeForLoop(this,false);
90             }
91           else
92             {
93               delete _nodeForNullTurnOfLoops;
94               _nodeForNullTurnOfLoops=0;
95             }
96         }
97     }
98 }
99
100 //! Method used to notify the node that a child node has ended
101 /*!
102  * Update the loop state and return the loop change state 
103  *
104  *  \param node : the child node that has ended
105  *  \return the loop state change
106  */
107 YACS::Event ForLoop::updateStateOnFinishedEventFrom(Node *node)
108 {
109   if((++_nbOfTurns)>=_nbOfTimesPort.getIntValue())
110     {
111       setState(YACS::DONE);
112       return YACS::FINISH;
113     }
114   else
115     {
116       node->init(false);
117       node->exUpdateState();
118     }
119   return YACS::NOEVENT;
120 }
121
122 void ForLoop::accept(Visitor *visitor)
123 {
124   visitor->visitForLoop(this);
125 }
126
127 std::list<InputPort *> ForLoop::getLocalInputPorts() const
128 {
129   list<InputPort *> ret;
130   ret.push_back((InputPort *)&_nbOfTimesPort);
131   return ret;
132 }