View Javadoc

1   /*$Id: GroovyInterpreter.java,v 1.7 2004/12/03 14:47:41 jdt Exp $
2    * Created on 26-Jul-2004
3    *
4    * Copyright (C) AstroGrid. All rights reserved.
5    *
6    * This software is published under the terms of the AstroGrid 
7    * Software License version 1.2, a copy of which has been included 
8    * with this distribution in the LICENSE.txt file.  
9    *
10  **/
11  package org.astrogrid.jes.jobscheduler.impl.groovy;
12  
13  import org.astrogrid.applications.beans.v1.cea.castor.ResultListType;
14  import org.astrogrid.applications.beans.v1.cea.castor.types.ExecutionPhase;
15  import org.astrogrid.applications.beans.v1.parameters.ParameterValue;
16  import org.astrogrid.workflow.beans.v1.Step;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  /***(misnamed) Top level class of rules engine / state machine.
25   * 
26   *  Its a container for the store of states and rulebase. Provides methods to select next triggerable rule, run next rule, etc.
27   * <p>
28   * this object is serialized to xml, and then persisted to an 'extension' element in the workflow document. This 'pickles' all the execution state for
29   * the workflow, and enables the interpreter to be unpickled and continue where it left off. 
30   * <p>
31   * Some of the design of this class has been constrained by needing to be picklable. In particular, a nullary constructor is required - which means that dependencies
32   * are passed in via setters.
33   * @see XStreamPickler 
34   * @see ActivityStatusStore
35   * @see ActivityStatus
36   * @see Rule
37   * @see RuleStore
38   * @author Noel Winstanley nw@jb.man.ac.uk 26-Jul-2004
39   *
40   */
41  public class GroovyInterpreter  {
42  
43      /*** Construct a new Interpreter, with empty rule base.
44       * used by XStreamPickler to marshal / unmarshal from xml.
45       */
46      public GroovyInterpreter() {
47          this(new RuleStore());
48      }
49      /*** construct a new interpreter, passing in a list of rules 
50       *  Construct a new GroovyInterpreter
51       * @param rs list of {@link Rule} objects
52       */
53      public GroovyInterpreter(Map rs) {
54          this.ruleStore = new RuleStore(rs);   
55                 
56      }
57      private  static final Log logger = LogFactory.getLog(GroovyInterpreter.class);
58      /*** set of rules - keyed on their name..*/
59      protected RuleStore ruleStore;
60      /*** store of states */
61      protected ActivityStatusStore stateMap = new ActivityStatusStore();
62      /*** interface into scripting engine - used to execute script embedded within rules */
63      protected final transient JesShell shell = new JesShell();
64  
65       
66      /*** select a triggered rule, and then run it
67       * @see #findNext
68       * @throws ScriptEngineException
69       */
70      public void runNext() throws ScriptEngineException{
71          try {
72              Rule rule = ruleStore.findNext(shell,stateMap);
73              rule.fire(shell,stateMap,ruleStore);
74          } catch (Exception e) {
75              throw new ScriptEngineException("Failed to run next",e);
76          }
77      }
78      /*** run the interpreter, until no more rules can be triggered
79       * @see #runNext */
80      public void run() throws ScriptEngineException {
81          try {
82          for (Rule rule= ruleStore.findNext(shell,stateMap); rule != null; rule = ruleStore.findNext(shell,stateMap)) {
83              rule.fire(shell,stateMap,ruleStore);
84          } 
85             
86          }catch (Exception e) {
87              throw new ScriptEngineException("Failed to run interpreter",e);
88          }
89      }
90      
91      /*** update the status of an step - called when a cea server returns information about execution progress of a step execytion */ 
92      public void updateStepStatus(Step step, ExecutionPhase phase)  {
93          if (phase.equals(ExecutionPhase.COMPLETED)) {
94              stateMap.setStatus(step.getId(),Status.FINISH);
95          } else if (phase.equals(ExecutionPhase.ERROR)) {
96              stateMap.setStatus(step.getId(),Status.ERROR);
97          } else { // nothing we care about.
98              return;
99          }
100         
101     }
102     /***store the results of a step execution - called when a cea server returns step execution results.
103      * @param step
104      * @param results
105      */
106     public void storeResults(Step step, ResultListType results) {
107         String id = step.getId();
108         // copy results into a more groovy-friendly datastructure (not to mention xstream)
109         Map resultsMap = new HashMap();
110         for (int i = 0; i < results.getResultCount(); i++) {
111             ParameterValue pval = results.getResult(i);
112             resultsMap.put(pval.getName(),pval.getValue());
113         }
114         
115         stateMap.getEnv(step.getId()).set(step.getResultVar(),resultsMap);
116         stateMap.setStatus(step.getId() + "-results",Status.FINISHED);
117     }    
118     
119     /*** sets link to the jes interface component - provides the rules engine with necessary hooks into jes server.
120      * this is a setter, rather than my usual constructor-dependency-injection, so that the GroovyInterpreter can be created via reflection.
121      * @param jesInterface The jesInterface to set.
122      */
123     public void setJesInterface(JesInterface jesInterface) {
124         this.shell.setJesInterface(jesInterface);
125     }
126     /***
127      * Returns <code>true</code> if this <code>GroovyInterpreter</code> is the same as the o argument.
128      *
129      * @return <code>true</code> if this <code>GroovyInterpreter</code> is the same as the o argument.
130      */
131     public boolean equals(Object o) {
132         if (this == o) {
133             return true;
134         }
135         if (o == null) {
136             return false;
137         }
138         if (o.getClass() != getClass()) {
139             return false;
140         }
141         GroovyInterpreter castedObj = (GroovyInterpreter) o;
142         return ((this.ruleStore == null
143             ? castedObj.ruleStore == null
144             : this.ruleStore.equals(castedObj.ruleStore))
145             && (this.stateMap == null
146                 ? castedObj.stateMap == null
147                 : this.stateMap.equals(castedObj.stateMap)) );
148     }
149     /***
150      * Override hashCode.
151      *
152      * @return the Objects hashcode.
153      */
154     public int hashCode() {
155         int hashCode = 1;
156         hashCode = 31 * hashCode + (logger == null ? 0 : logger.hashCode());
157         hashCode = 31
158             * hashCode
159             + (ruleStore == null ? 0 : ruleStore.hashCode());
160         hashCode = 31 * hashCode + (stateMap == null ? 0 : stateMap.hashCode());
161         return hashCode;
162     }
163     public String toString() {
164         StringBuffer buffer = new StringBuffer();
165         buffer.append("[GroovyInterpreter:");
166         buffer.append(" ruleStore: ");
167         buffer.append(ruleStore);
168         buffer.append(" stateMap: ");
169         buffer.append(stateMap);
170 
171         buffer.append("]");
172         return buffer.toString();
173     }
174 
175 
176 }
177 
178 
179 /* 
180 $Log: GroovyInterpreter.java,v $
181 Revision 1.7  2004/12/03 14:47:41  jdt
182 Merges from workflow-nww-776
183 
184 Revision 1.6.14.1  2004/12/01 21:50:07  nw
185 organized import
186 
187 Revision 1.6  2004/11/05 16:52:42  jdt
188 Merges from branch nww-itn07-scratchspace
189 
190 Revision 1.5.26.1  2004/11/05 16:12:13  nw
191 moved findNext into RuleStore
192 
193 Revision 1.5  2004/09/06 16:30:25  nw
194 javadoc
195 
196 Revision 1.4  2004/08/09 17:32:18  nw
197 updated due to removing RuleStore
198 
199 Revision 1.3  2004/08/04 16:51:46  nw
200 added parameter propagation out of cea step call.
201 
202 Revision 1.2  2004/07/30 15:42:34  nw
203 merged in branch nww-itn06-bz#441 (groovy scripting)
204 
205 Revision 1.1.2.5  2004/07/30 14:00:10  nw
206 first working draft
207 
208 Revision 1.1.2.4  2004/07/28 16:24:23  nw
209 finished groovy beans.
210 moved useful tests from old python package.
211 removed python implemntation
212 
213 Revision 1.1.2.3  2004/07/27 23:50:09  nw
214 removed betwixt (duff). replaces with xstream.
215 
216 Revision 1.1.2.2  2004/07/27 23:37:59  nw
217 refactoed framework.
218 experimented with betwixt - can't get it to work.
219 got XStream working in 5 mins.
220 about to remove betwixt code.
221 
222 Revision 1.1.2.1  2004/07/26 15:51:19  nw
223 first stab at a groovy scheduler.
224 transcribed all the classes in the python prototype, and took copies of the
225 classes in the 'scripting' package.
226  
227 */