View Javadoc

1   /*
2   * The contents of this file are subject to the BT "ZEUS" Open Source 
3   * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file 
4   * except in compliance with the Licence. You may obtain a copy of the Licence
5   * from $ZEUS_INSTALL/licence.html or alternatively from
6   * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7   * 
8   * Except as stated in Clause 7 of the Licence, software distributed under the
9   * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or 
10  * implied. See the Licence for the specific language governing rights and 
11  * limitations under the Licence.
12  * 
13  * The Original Code is within the package zeus.*.
14  * The Initial Developer of the Original Code is British Telecommunications
15  * public limited company, whose registered office is at 81 Newgate Street, 
16  * London, EC1A 7AJ, England. Portions created by British Telecommunications 
17  * public limited company are Copyright 1996-9. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  /*
23   * @(#)Node.java 1.03b
24   */
25  
26  package zeus.actors.rtn;
27  
28  import java.util.*;
29  import zeus.util.*;
30  import zeus.actors.AgentContext;
31  
32  public class Node {
33     public static final int NOT_READY  = 0;
34     public static final int READY      = 1;
35     public static final int WAITING    = 2;
36     public static final int RUNNING    = 3;
37     public static final int DONE       = 4;
38     public static final int FAILED     = 5;
39  
40     protected static final int OK      = 1;
41     protected static final int FAIL    = 2;
42     protected static final int WAIT    = 3;
43     protected static final int OK_WAIT = 4;
44  
45     private static int count = 0;
46  
47     protected String[]     arcs = null;
48     protected String[]     nodes = null;
49     protected Object       input = null;
50     protected Object       output = null;
51     protected Node         previous_node = null;
52     protected Node[]       parents = null;
53     protected Graph        graph = null;
54     protected String       description = null;
55     protected int          state = NOT_READY;
56     protected int          current_arc = -1;
57     protected double       timeout = 0;
58     protected String       msg_wait_key = null;
59     protected AgentContext context = null;
60     protected Vector       parents_of_next_node =null;
61  
62     // LL 040500 1.03b
63     public  String       getDesc() {return null;};
64  
65     public void finaliser () { 
66      finals(); 
67     }
68  
69     public void finals () { 
70      if (arcs!=null) 
71      for (int count = 0; count< arcs.length; count++) { 
72          arcs[count] = null; 
73      }
74      arcs = null; 
75      if (nodes != null) 
76      for (int count = 0; count<nodes.length; count++) { 
77             nodes [count] = null; 
78      }
79      nodes = null; 
80      input = null; 
81      output = null; 
82      previous_node = null; 
83      if (parents!=null) 
84      for (int count = 0; count<parents.length; count++){ 
85        //  parents[count].finals(); // recursive structure to unwind this from the memory
86          parents[count] = null; }
87          parents = null; 
88     }
89  
90  
91     public Node(String description) {
92        this.description = description + "-" + (count++);
93        Core.DEBUG(3,"New node " + this.description + " created");
94     }
95  
96     public final String getDescription()  { return description; }
97     public final double getTimeout()      { return timeout; }
98     public final String getMsgWaitKey()   { return msg_wait_key; }
99     public final Object getOutput()       { return output; }
100    public final Node   getPrevious()     { return previous_node; }
101    public final Node[] getParents()      { return parents; }
102    public final int    getState()        { return state; }
103    public final Graph  getGraph()        { return graph; }
104 
105    final void set(Graph graph, String[] arcs, String[] nodes, Node previous) {
106       this.arcs = arcs;
107       this.nodes = nodes;
108       this.graph = graph;
109       this.previous_node = previous;
110 
111       if ( previous != null ) {
112          this.parents = new Node[1];
113          this.parents[0] = previous;
114       }
115    }
116    
117    
118    final void set(Graph graph, String[] arcs, String[] nodes, Node previous,
119                   Vector parents) {
120       this.arcs = arcs;
121       this.nodes = nodes;
122       this.graph = graph;
123       this.previous_node = previous;
124 
125       this.parents = new Node[parents.size()];
126       for(int i = 0; i < parents.size(); i++ )
127          this.parents[i] = (Node)parents.elementAt(i);
128    }
129    
130    
131    final void run(Engine engine) {
132       context = engine.getAgentContext();
133 
134       switch(state) {
135          case READY:
136          case WAITING:
137             if ( !graph.allow_exec() )
138                fail(engine,false,"Exec refused by graph");
139             else {
140                int result = (state == READY) ? exec() : continue_exec();
141                switch( result ){
142                   case OK:
143                      setState(engine,RUNNING);
144                      engine.add(this);
145                      break;
146                   case WAIT:
147                      engine.waitForMsg(this);
148                      setState(engine,WAITING);
149                      break;
150                   default:
151                      fail(engine,false,"Node exec failed");
152                      break;
153                }
154             }
155             break;
156          case RUNNING:
157             if ( !graph.allow_exec() )
158                fail(engine,true,"Exec refused by graph");
159             else if ( arcs == null )
160                done(engine,"terminal node reached");
161             else if ( current_arc >= arcs.length )
162                fail(engine,true,"All arcs traversed");
163             else
164                exec_arc(engine);
165             break;
166          default:
167             Core.ERROR(null,2,this);
168             break;
169       }
170       engine  = null; 
171       context = null; 
172    }
173    
174    
175    private void done(Engine engine, String reason) {
176       Core.DEBUG(3,description + " done: " + reason);
177       setState(engine,DONE);
178       graph.done(engine,this);
179    }
180    
181    
182    final void fail(Engine engine, boolean reset, String reason) {
183       Thread.yield(); 
184       Core.DEBUG(3,description + " failed: " + reason);
185       setState(engine,FAILED);
186       Thread.yield(); 
187       if ( reset ) reset();
188       graph.failed(engine,this);
189       Thread.yield(); 
190       if ( previous_node != null && graph.allow_backtrack(this) )
191          previous_node.nextArc(engine);
192     //  this.finals(); 
193    }
194    
195    
196    protected int exec() {
197       // prepare output
198       output = input;
199       return OK;
200    }
201    protected int continue_exec() {
202       // prepare output
203       output = input;
204       return OK;
205    }
206    protected void reset() {
207       // reset any state changed by exec()
208    }
209    final void setInput(Engine engine, Object input) {
210       Core.ERROR(state == NOT_READY, 1, this);
211       this.input = input;
212       current_arc = 0;
213       setState(engine,READY);
214    }
215    protected final void exec_arc(Engine engine) {
216       try {
217             Class c = Class.forName(arcs[current_arc]);
218             Arc arc = (Arc) c.newInstance();
219             engine.notifyArcMonitors(arc,this,Engine.ARC_CREATE);
220             arc.run1(engine,graph,this,output,nodes[current_arc]);
221       }
222       catch(Exception e) {
223          Core.USER_ERROR("Arc " + arcs[current_arc] + " cannot be executed" +
224                          "\nException " + e);
225          nextArc(engine);
226       }
227    }
228    final void nextArc(Engine engine) {
229       switch(state) {
230          // a done node  may be backtracked on when the node is the terminal
231          // node of a sub-graph in which case arcs == null and we have to fail
232          case DONE:
233          case RUNNING:
234             if ( !graph.allow_exec() )
235                fail(engine,true,"Next arc disallowed by graph");
236             else {
237                if ( state == DONE && arcs == null )
238                   fail(engine,true,"All arcs traversed");
239                else {
240                   setState(engine,RUNNING);
241                   current_arc++;
242                   engine.add(this);
243                }
244             }
245             break;
246          default:
247             Core.ERROR(null,3,this);
248             break;
249       }
250    }
251    
252    
253    final void setState(Engine engine, int value) {
254       state = value;
255       engine.notifyNodeMonitors(this,Engine.NODE_STATE_CHANGE);
256    }
257 
258    protected void finalize() throws Throwable {
259       if ( context != null )
260          context.Engine().notifyNodeMonitors(this,Engine.NODE_DISPOSE);
261     arcs = null;
262     nodes = null;
263     input = null;
264     output = null;
265     previous_node = null;
266     parents = null;
267     graph = null;
268     description = null;
269     msg_wait_key = null;
270     parents_of_next_node =null;
271 //    super.finalize();
272    }
273 
274    protected Graph createGraph(String name) {
275       try {
276          Class c = Class.forName(name);
277          Graph g = (Graph)c.newInstance();
278          if ( parents_of_next_node == null )
279 	    parents_of_next_node = new Vector();
280 	 parents_of_next_node.addElement(g);
281          context.Engine().notifyGraphMonitors(g,Engine.GRAPH_CREATE);
282          return g;
283       }
284       catch(Exception e) {
285          Core.USER_ERROR("Cannot create graph: " + name + "\n" + e);
286          return null;
287       }
288    }
289 
290    Vector getParentsOfNextNode() {
291       if ( parents_of_next_node == null || parents_of_next_node.isEmpty() )
292          return null;
293 
294       Vector out = new Vector();
295       Graph g;
296       for(int i = 0; i < parents_of_next_node.size(); i++ ) {
297          g = (Graph)parents_of_next_node.elementAt(i);
298          out = Misc.union(out,g.getTerminalNodes());
299       }
300       return out.isEmpty() ? null : out;
301    }
302 
303    protected Object createObject(String name) {
304       try {
305          Class c = Class.forName(name);
306          Object g = c.newInstance();
307          return g;
308       }
309       catch(Exception e) {
310          Core.USER_ERROR("Cannot create object: " + name + "\n" + e);
311          return null;
312       }
313    }
314    final boolean hasChildGraph(Graph g) {
315       Core.DEBUG(3,"hasChildGraph: " + g.getDescription() + " " + getDescription());
316       boolean b = parents_of_next_node != null && parents_of_next_node.contains(g);
317       Core.DEBUG(3,"\thasChildGraph = " + b);
318       return b;
319    }
320    
321    
322    public String toString() { return description; }
323 
324 
325     /***
326         overwrite this method in a Node to get behaviour from
327         a time out setting 
328         */
329    public boolean timeOut () { 
330     return false; //why not?
331    }
332 }