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  
24  package zeus.actors.rtn;
25  
26  import java.util.*;
27  import zeus.util.*;
28  
29  public abstract class Graph extends Arc {
30     public static final int READY   = 0;
31     public static final int RUNNING = 1;
32     public static final int DONE    = 2;
33     public static final int FAILED  = 3;
34  
35     private static int count = 0;
36  
37     protected String[][] nodes = null;
38     protected String     start_node = null;
39     protected String     next_node = null;
40     protected Node       previous_node = null;
41     protected Node       begin_node = null;
42     protected int        state = READY;
43     protected String     node_wakeup_key = null;
44     private   Node       last_node = null;
45  
46     public Graph(String description, String[][] nodes, String start_node) {
47        this.start_node = start_node;
48        this.nodes = nodes;
49        this.description = description + "-" + (count++);
50        Core.DEBUG(3,"New graph " + this.description + " created");
51     }
52  
53     public final int getState() { return state; }
54  
55     void run1(Engine engine, Graph graph, Node previous_node,
56               Object input, String next_node) {
57  
58        context = engine.getAgentContext();
59        this.graph = graph;
60        this.previous_node = previous_node;
61        this.next_node = next_node;
62        start(engine,input);
63     }
64     public void run(Engine engine, Object input) {
65        start(engine,input);
66     }
67     public void run(Engine engine, Node previous_node, Object input,
68                     String node_wakeup_key) {
69        this.node_wakeup_key = node_wakeup_key;
70        this.previous_node = previous_node;
71        start(engine,input);
72     }
73     protected void start(Engine engine, Object input) {
74        setState(engine,RUNNING);
75        begin_node = newNode(engine,start_node,previous_node);
76        if ( begin_node == null )
77           fail(engine,"Start node " + start_node + " not found");
78        else {
79           begin_node.setInput(engine,input);
80           engine.add(begin_node);
81        }
82     }
83     void done(Engine engine, Node node) {
84        Core.DEBUG(3,description + " done");
85        setState(engine,DONE);
86  
87        if ( graph != null ) {
88           Node next = graph.newNode(engine,next_node,node);
89           if ( next == null ) {
90              setState(engine,RUNNING);
91              node.nextArc(engine);
92           }
93           else {
94              Object local_input = node.getOutput();
95              next.setInput(engine,local_input);
96              engine.add(next);
97           }
98        }
99        else if ( node_wakeup_key != null )
100          engine.wakeup(node_wakeup_key);
101    }
102    void failed(Engine engine, Node node) {
103       if ( node == begin_node ) {
104          setState(engine,FAILED);
105          if ( node_wakeup_key != null )
106             engine.wakeup(node_wakeup_key);
107       }
108    }
109    protected void fail(Engine engine, String reason) {
110       Core.DEBUG(3,description + " failed: " + reason);
111       setState(engine,FAILED);
112       if ( node_wakeup_key != null )
113          engine.wakeup(node_wakeup_key);
114       if ( previous_node != null )
115          previous_node.nextArc(engine);
116    }
117 
118    Vector getTerminalNodes() {
119       Vector output;
120       if ( last_node != null ) {
121          if ( (output = last_node.getParentsOfNextNode()) != null )
122             return output;
123          else {
124             output = new Vector();
125             output.addElement(last_node);
126             return output;
127          }
128       }
129       else
130          return new Vector();
131    }
132 
133    Node newNode(Engine engine, String name, Node previous) {
134       Vector parents;
135       if ( previous != null ) {
136 Core.DEBUG(3,"NewNode preamble\n\tname = " + name +
137 "\n\tprevious = " + previous +
138 "\n\thasChild = " + previous.hasChildGraph(this) +
139 "\n\tparents = " + previous.getParentsOfNextNode());
140       }
141       if ( previous != null && !previous.hasChildGraph(this) &&
142            (parents = previous.getParentsOfNextNode()) != null )
143          return newNode(engine,name,previous,parents);
144       else
145          return newNode(engine,name,previous,null);
146    }
147 
148    Node newNode(Engine engine, String name, Node previous, Vector parents) {
149       Core.DEBUG(3,"NewNode:\n\tname = " + name + "\n\tprev = " + previous +
150                    "\n\tparents = " + parents);
151       try {
152          boolean found = false;
153          String[] arcs = null, vertices = null;
154          for(int i = 0; i < nodes.length; i++ ) {
155             if ( nodes[i][0].equals(name) ) {
156                found = true;
157                if ( nodes[i].length%2 != 1 )
158                   Core.USER_ERROR("Improperly specified graph description " +
159 		     description + "at node " + nodes[i][0]);
160                int k = 0;
161                for(int j = 1; j < nodes[i].length; k++ ) {
162                   if ( j == 1 ) {
163                      arcs = new String[(nodes[i].length-1)/2];
164                      vertices = new String[(nodes[i].length-1)/2];
165                   }
166                   arcs[k] = nodes[i][j++];
167                   vertices[k] = nodes[i][j++];
168                }
169                break;
170             }
171          }
172          if ( !found ) {
173             Core.USER_ERROR("Improperly specified graph description " +
174 		     description + ": No definintion for node " + name);
175 	    return null;
176          }
177          Class c = Class.forName(name);
178          last_node = (Node)c.newInstance();
179 
180          if ( parents != null )
181 	    last_node.set(this,arcs,vertices,previous,parents);
182          else
183 	    last_node.set(this,arcs,vertices,previous);
184          engine.notifyNodeMonitors(last_node,Engine.NODE_CREATE);
185          return last_node;
186       }
187       catch(Exception e) {
188          Core.USER_ERROR("Error in graph specification " + description +
189             "\nException: " + e);
190          return null;
191       }
192    }
193    boolean allow_exec() {
194       return state != FAILED;
195    }
196    boolean allow_backtrack(Node node) {
197       return ( node != begin_node || node_wakeup_key == null );
198    }
199    protected boolean exec() {
200       Core.ERROR(null,1,this); // should never be called
201       return false;
202    }
203    final void setState(Engine engine,int value) {
204       state = value;
205       engine.notifyGraphMonitors(this,Engine.GRAPH_STATE_CHANGE);
206    }
207    protected void finalize() {
208       if ( context != null )
209          context.Engine().notifyGraphMonitors(this,Engine.GRAPH_DISPOSE);
210    }
211 }