KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openharmonise > rm > commands > CommandProcessHandler


1 /*
2  * The contents of this file are subject to the
3  * Mozilla Public License Version 1.1 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS IS"
8  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
9  * See the License for the specific language governing rights and
10  * limitations under the License.
11  *
12  * The Initial Developer of the Original Code is Simulacra Media Ltd.
13  * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
14  *
15  * All Rights Reserved.
16  *
17  * Contributor(s):
18  */

19 package org.openharmonise.rm.commands;
20
21 import java.util.*;
22 import java.util.logging.*;
23
24 import org.openharmonise.commons.dsi.AbstractDataStoreInterface;
25 import org.openharmonise.rm.*;
26 import org.openharmonise.rm.config.ConfigSettings;
27 import org.openharmonise.rm.factory.*;
28 import org.openharmonise.rm.publishing.*;
29 import org.openharmonise.rm.resources.AbstractObject;
30 import org.openharmonise.rm.resources.publishing.*;
31 import org.w3c.dom.*;
32
33
34 /**
35  * This class processes commands specified in HaRP to be executed within
36  * Harmonise and possibly on a Harmoniseobject. Multiple commands and
37  * objects can be handled and the output will be published to HaRP.
38  *
39  * @author Michael Bell
40  * @version $Revision: 1.3 $
41  *
42  */

43 public class CommandProcessHandler implements Publishable {
44
45     //XML constants
46
/**
47      * The 'WorkflowEvent' tag name
48      */

49     public static final String JavaDoc TAG_WORKFLOW = "WorkflowEvent";
50     
51     /**
52      * The 'jump'/'skip' command tag name
53      */

54     public static final String JavaDoc JMP_CMD = "Jmp";
55     
56     /**
57      * The 'jump if'/'skip if' command tag name
58      */

59     public static final String JavaDoc JMPIF_CMD = "JmpIf";
60     
61     /**
62      * The 'stop' command tage name
63      */

64     public static final String JavaDoc STOP_CMD = "Stop";
65     
66     /**
67      * The standard command namespace for the Harmonise framework, this namespace
68      * forms the prefix to all the standard command class names, for example
69      * the 'Save' command is represented by a class of the name
70      * COMMANDS_NAMESPACE + "Save'
71      */

72     public static final String JavaDoc COMMANDS_NAMESPACE =
73         AbstractCmd.class.getPackage().getName() + ".Cmd";
74     
75     /**
76      * Prefix for configuration parameters which specify project specific
77      * command classes
78      */

79     public static final String JavaDoc PROJECT_COMMAND = "PROJECT_CMD_";
80
81     /**
82      * The XML element resultant of the command processing
83      */

84     private Element m_workflow_output;
85     
86     /**
87      * The owner document of the resultant XML of the command processing
88      */

89     private HarmoniseOutput m_workflow_output_document;
90     
91     /**
92      * The data store interface to be used in command processing
93      */

94     private AbstractDataStoreInterface m_dsi;
95     
96     /**
97      * The state context for the command processing
98      */

99     private State m_state = null;
100     
101     /**
102      * The list of names of all commands to be processed.
103      */

104     private List m_cmd_names;
105     
106     /**
107      * The list of command parameters.
108      */

109     private List m_cmd_parameters;
110     
111     /**
112      * Logger for this class.
113      */

114     private static final Logger m_logger = Logger.getLogger(CommandProcessHandler.class.getName());
115
116     /**
117      * Creates a new command process handler with a an interface to
118      * the data store.
119      *
120      * @param dsi the data store interface
121      */

122     public CommandProcessHandler(AbstractDataStoreInterface dsi) {
123         m_dsi = dsi;
124     }
125
126     /**
127      * Returns the <code>State</code> associated to this command processor.
128      *
129      * @return the <code>State</code> associated to this command processor.
130      */

131     public State getState() {
132         return m_state;
133     }
134
135     /**
136      * Returns the XML document associated to this command processor.
137      *
138      * @return the XML document associated to this command processor.
139      */

140     public org.w3c.dom.Document JavaDoc getXMLDocument() {
141         return m_workflow_output_document;
142     }
143
144
145     /* (non-Javadoc)
146      * @see org.openharmonise.rm.publishing.Publishable#publish(org.openharmonise.rm.resources.publishing.Template, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
147      */

148     public Element publish(Template template, HarmoniseOutput output, State state)
149         throws PublishException {
150         Element resultEl = null;
151
152         try {
153             resultEl =
154                 publish(template.getTemplateRootElement(), output, state);
155         } catch (DataAccessException e) {
156             throw new PublishException(e.getLocalizedMessage());
157         }
158
159         return resultEl;
160     }
161
162     /* (non-Javadoc)
163      * @see org.openharmonise.rm.publishing.Publishable#publish(org.w3c.dom.Element, org.openharmonise.rm.publishing.HarmoniseOutput, org.openharmonise.rm.publishing.State)
164      */

165     public Element publish(Element topEl, HarmoniseOutput output, State state)
166         throws PublishException {
167         if (topEl
168             .getTagName()
169             .equalsIgnoreCase(CommandProcessHandler.TAG_WORKFLOW)
170             == false) {
171             throw new InvalidXMLElementException("Workflow tag needed");
172         }
173
174         Element returnEl = null;
175
176         List wrkflowObjs;
177         try {
178             wrkflowObjs =
179                 HarmoniseObjectFactory.instantiateWorkflowObjects(
180                     this.m_dsi,
181                     topEl,
182                     state);
183         } catch (HarmoniseFactoryException e) {
184             throw new PublishException(
185                 "Error occured getting objects from factory",
186                 e);
187         }
188
189         m_workflow_output_document = output;
190         m_state = state;
191         m_cmd_names = new ArrayList();
192         m_cmd_parameters = new ArrayList();
193
194         m_workflow_output =
195             output.createElement(CommandProcessHandler.TAG_WORKFLOW);
196
197         NodeList event_nodes =
198             topEl.getElementsByTagName(AbstractCmd.TAG_COMMAND);
199
200         for (int i = 0; i < event_nodes.getLength(); i++) {
201             // Cmd names
202
Element this_workflow_element = (Element) event_nodes.item(i);
203
204             String JavaDoc cmd_name =
205                 this_workflow_element.getAttribute(AbstractObject.ATTRIB_NAME);
206
207             if ((cmd_name == null) || (cmd_name.length() == 0)) {
208                 throw new InvalidXMLElementException(
209                     "Command names for workflow events must be given in the "
210                         + AbstractObject.ATTRIB_NAME
211                         + " tag of the "
212                         + AbstractCmd.TAG_COMMAND
213                         + " element. "
214                         + " cmd_name:"
215                         + cmd_name);
216             }
217
218             m_cmd_names.add(cmd_name);
219
220             m_cmd_parameters.add(
221                 getWorkflowParameters(this_workflow_element.getChildNodes()));
222         }
223
224         Iterator iter = wrkflowObjs.iterator();
225         
226         while (iter.hasNext()) {
227             Object JavaDoc wf_obj = (Object JavaDoc) iter.next();
228             executeCommands(wf_obj);
229         }
230
231         return m_workflow_output;
232     }
233
234
235     /* (non-Javadoc)
236      * @see org.openharmonise.rm.publishing.Publishable#populate(org.w3c.dom.Element, org.openharmonise.rm.publishing.State)
237      */

238     public void populate(Element xmlElement, State state)
239         throws PopulateException {
240         //never going to be populating - are we?
241

242     }
243
244     /* (non-Javadoc)
245      * @see org.openharmonise.rm.publishing.Publishable#getTagName()
246      */

247     public String JavaDoc getTagName() {
248         return TAG_WORKFLOW;
249     }
250     
251
252     /*----------------------------------------------------------------------------
253     Protected methods
254     -----------------------------------------------------------------------------*/

255     
256     /**
257      * Executes the loaded commands on the specified object.
258      *
259      * @param commandObject the object commands are to be executed on
260      * @throws PublishException if any errors occur, caused either by a
261      * reference to an invalid command, invalid object or if there is
262      * an error executing the command
263      */

264     protected void executeCommands(Object JavaDoc commandObject) throws PublishException {
265
266         boolean cmd_successful = true;
267         String JavaDoc cmd_name;
268         int cmd_execution_point = 0;
269         
270         Context context = new Context();
271
272         while (cmd_execution_point < m_cmd_parameters.size()) {
273             // get the next command and arguments
274
cmd_name = (String JavaDoc) (m_cmd_names.get(cmd_execution_point));
275
276             // allow cmd_args to be null if there aren't any
277
Map cmd_parameter_map;
278
279             if (m_cmd_parameters.size() >= cmd_execution_point) {
280                 cmd_parameter_map =
281                     (Map) m_cmd_parameters.get(cmd_execution_point);
282             } else {
283                 cmd_parameter_map = null;
284             }
285
286             cmd_execution_point++;
287
288             //check for skipping or jumping rules
289
if (cmd_name.startsWith("-")) {
290                 String JavaDoc scmd_name = cmd_name.substring(1); // remove intial -
291

292                 int param_at_idx = scmd_name.indexOf('-');
293
294                 String JavaDoc sparam_value;
295
296                 if (param_at_idx != -1) {
297                     scmd_name = cmd_name.substring(1, param_at_idx + 1);
298                     // remove command within - -
299
sparam_value = cmd_name.substring(param_at_idx + 2);
300                 } else {
301                     sparam_value = "";
302                 }
303
304                 if (scmd_name.equals(JMP_CMD)
305                     || (scmd_name.equals(JMPIF_CMD) && cmd_successful)) {
306
307                     cmd_execution_point += getNumberOfCommandsToSkip(sparam_value);
308
309                     continue;
310                 } else if ((scmd_name.equals(JMPIF_CMD) && !cmd_successful)) {
311
312                     continue;
313                 } else if (scmd_name.equals(STOP_CMD)) {
314
315                     break;
316                 }
317             }
318
319             // Get command classname
320
String JavaDoc classname;
321             String JavaDoc proj_cmd = PROJECT_COMMAND + cmd_name;
322
323             try {
324                 classname = ConfigSettings.getProperty(proj_cmd);
325             } catch (Exception JavaDoc e) {
326                 classname = COMMANDS_NAMESPACE + cmd_name;
327             }
328             
329             if(classname == null) {
330                 classname = COMMANDS_NAMESPACE + cmd_name;
331             }
332
333             AbstractCmd cmd = null;
334
335             try {
336                 Class JavaDoc cls = Class.forName(classname);
337                 cmd = (AbstractCmd) cls.newInstance();
338             } catch (InstantiationException JavaDoc e) {
339                 throw new PublishException(
340                     "Cannot instantiate command class " + classname,
341                     e);
342             } catch (ClassNotFoundException JavaDoc e) {
343                 throw new PublishException(
344                     cmd_name
345                         + " is not a valid workflow command, expect command class "
346                         + classname,
347                     e);
348             } catch (IllegalAccessException JavaDoc e) {
349                 throw new PublishException("Illegal access to class", e);
350             }
351
352             if (cmd.isValidCommandObject(commandObject) == true) {
353
354                 if (commandObject != null) {
355                     cmd.setCommandObject(commandObject);
356                 }
357
358                 cmd.setParameters(cmd_parameter_map);
359                 cmd.setDataStoreInteface(m_dsi);
360
361                 if (m_state != null) {
362                     cmd.setState(m_state);
363                 }
364
365                 Object JavaDoc cmdResult = null;
366                 try {
367                     cmdResult = cmd.execute(context);
368                 } catch (CommandException e) {
369                     throw new PublishException("Error executing command", e);
370                 }
371
372                 String JavaDoc sTemplateId =
373                     cmd.getParameter(AbstractCmd.PARAM_TEMPLATE_ID);
374                 int nTemplateId = -1;
375
376                 if (sTemplateId != null) {
377
378                     nTemplateId = Integer.parseInt(sTemplateId);
379                     if (nTemplateId > 0) {
380                         try {
381                             Template template = (Template) HarmoniseObjectFactory.instantiateHarmoniseObject(
382                                                     m_dsi,
383                                                     Template.class.getName(),
384                                                     nTemplateId);
385                             
386                             if (cmdResult instanceof Publishable) {
387                                 Publishable pObj = (Publishable) cmdResult;
388                             
389                                 // instantaite template
390
addResult(pObj.publish(template, m_workflow_output_document, m_state));
391                                 
392                             
393                             } else if (cmdResult instanceof Collection) {
394                                 Collection collObj = (Collection) cmdResult;
395                             
396                                 Iterator iter = collObj.iterator();
397                             
398                                 while (iter.hasNext()) {
399                                     Object JavaDoc obj = iter.next();
400                             
401                                     if (obj instanceof Publishable) {
402                                         Publishable pObj = (Publishable) obj;
403                                         addResult(pObj.publish(template, m_workflow_output_document, m_state));
404                             
405                                     }
406                                 }
407                             }
408                         } catch (HarmoniseFactoryException e) {
409                             throw new PublishException("Error getting template from Factory",e);
410                         }
411                     }
412                 }
413                 String JavaDoc out_text = cmd.getParameter(AbstractCmd.PARAM_OUT_TEXT);
414                 addSimpleTextElement(WebPage.TAG_ANCILLARY_TEXT, out_text);
415             }
416         }
417
418     }
419     
420     /**
421      * Adds a result child element, the result of publishing the result
422      * of one command execution, to the overall result element of this
423      * command process.
424      *
425      * @param result_root the result XML element
426      */

427     protected void addResult(Element result_root) {
428         m_workflow_output.appendChild(
429             m_workflow_output_document.importNode((Node) result_root, true));
430     }
431
432     /**
433      * Returns a <code>Map</code> of the workflow parameters represented in the
434      * <code>NodeList</code>.
435      *
436      * @param param_nodes the list of nodes representing parameters
437      * @return a <code>Map</code> of the workflow parameters represented in the
438      * <code>NodeList</code>
439      */

440     protected Map getWorkflowParameters(NodeList param_nodes) {
441         // get params from template
442
HashMap cmd_params = new HashMap();
443
444         for (int j = 0; j < param_nodes.getLength(); j++) {
445             if (param_nodes.item(j).getNodeType() != Node.ELEMENT_NODE) {
446                 continue;
447             }
448
449             Element current_element = (Element) param_nodes.item(j);
450
451             if (!current_element
452                 .getTagName()
453                 .equals(AbstractCmd.TAG_COMMAND_PARAM)) {
454                 throw new RuntimeException JavaDoc(
455                     "Workflow event must only contain tags named:"
456                         + AbstractCmd.TAG_COMMAND_PARAM
457                         + " the node:"
458                         + current_element
459                         + " is not allowed ");
460             }
461
462             String JavaDoc param_name =
463                 current_element.getAttribute(AbstractObject.ATTRIB_NAME);
464
465             Text txt_node = (Text) current_element.getFirstChild();
466             String JavaDoc param_value = "";
467
468             if (txt_node != null) {
469                 param_value = txt_node.getNodeValue();
470             }
471
472             // Allow multiple values for the prameters (Hashmap to Name-Vector_of_values)
473
Vector existing_values = (Vector) cmd_params.get(param_name);
474
475             if (existing_values == null) {
476                 existing_values = new Vector();
477                 cmd_params.put(param_name, existing_values);
478             }
479
480             existing_values.addElement(param_value);
481         }
482
483         return cmd_params;
484     }
485     
486     
487     /*----------------------------------------------------------------------------
488     Private methods
489     -----------------------------------------------------------------------------*/

490
491     /**
492      * Adds a text element to the result element of the command processor
493      * under an XML element with the specified tag name.
494      *
495      * @param tag_name the tag name
496      * @param tag_txt the text to add
497      */

498     private void addSimpleTextElement(String JavaDoc tag_name, String JavaDoc tag_txt) {
499         Element simple_elm = m_workflow_output_document.createElement(tag_name);
500         Text simple_text = m_workflow_output_document.createTextNode(tag_txt);
501
502         simple_elm.appendChild(simple_text);
503
504         addResult(simple_elm);
505     }
506     
507     /**
508      * Returns the number of commands to skip.
509      *
510      * @param scmd_param <code>String</code> representation of number of commands to skip
511      *
512      * @return the number of commands to skip
513      */

514     private int getNumberOfCommandsToSkip(String JavaDoc scmd_param) {
515         int num_to_skip = 0;
516
517         try {
518             num_to_skip = Integer.parseInt(scmd_param);
519         } catch (NumberFormatException JavaDoc e) {
520             m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
521         }
522
523         return num_to_skip;
524     }
525 }
Popular Tags