View Javadoc

1   /*
2    * $Id: CommandLineDescriptionsLoader.java,v 1.7 2004/11/27 13:20:03 pah Exp $
3    *
4    * Created on 26 November 2003 by Paul Harrison
5    * Copyright 2003 AstroGrid. All rights reserved.
6    *
7    * This software is published under the terms of the AstroGrid
8    * Software License version 1.2, a copy of which has been included
9    * with this distribution in the LICENSE.txt file.
10   */
11  
12  package org.astrogrid.applications.commandline.digester;
13  
14  import java.net.URL;
15  
16  import javax.xml.parsers.ParserConfigurationException;
17  
18  import org.apache.commons.digester.AbstractObjectCreationFactory;
19  import org.apache.commons.digester.Digester;
20  import org.apache.commons.digester.NodeCreateRule;
21  import org.apache.commons.digester.RegexRules;
22  import org.apache.commons.digester.SimpleRegexMatcher;
23  import org.astrogrid.applications.beans.v1.ParameterRef;
24  import org.astrogrid.applications.commandline.CommandLineParameterDescription;
25  import org.astrogrid.applications.description.ApplicationDescription;
26  import org.astrogrid.applications.description.BaseApplicationDescriptionLibrary;
27  import org.astrogrid.applications.description.base.ApplicationDescriptionEnvironment;
28  import org.astrogrid.applications.description.exception.ApplicationDescriptionNotLoadedException;
29  import org.w3c.dom.Node;
30  import org.xml.sax.Attributes;
31  
32  /*** ApplicationDescrptions Library for use with commandline apps.
33   * Loads the application descriptions from the description file into a set of {@link ApplicationDescription} objects. It uses the {@link org.apache.commons.digester.Digester} to parse the XML file. 
34   * The schema for these definitions is located at <a href="http://www.astrogrid.org/viewcvs/%2Acheckout%2A/astrogrid/applications/schema/AGParameterDefinition.xsd?rev=HEAD&content-type=text/plain">schema</a>
35   * @author Paul Harrison (pah@jb.man.ac.uk)
36   * @version $Name:  $
37   * @since iteration4
38   * @TODO make namespace aware - this is a bit of a hack with namespaces at the moment.... 
39   * @TODO validate the input xml
40   * @TODO really better to use castor
41   * @TODO perhaps better to refactor the schema into the commandline project.
42   */
43  public class CommandLineDescriptionsLoader extends BaseApplicationDescriptionLibrary {
44     static private org.apache.commons.logging.Log logger =
45        org.apache.commons.logging.LogFactory.getLog(CommandLineDescriptionsLoader.class);
46  
47      public interface DescriptionURL {
48          URL getURL();
49      }
50  
51  
52     public CommandLineDescriptionsLoader(DescriptionURL finder, CommandLineApplicationDescriptionFactory appDescFactory, ApplicationDescriptionEnvironment envin) 
53     throws ApplicationDescriptionNotLoadedException {
54            super(envin);
55            this.configFile = finder.getURL();
56            this.appDescFactory = appDescFactory;
57            loadDescription();
58     }
59     protected final URL configFile;
60     protected final CommandLineApplicationDescriptionFactory appDescFactory; 
61     
62     public final void loadDescription() throws ApplicationDescriptionNotLoadedException {
63        logger.info( "loading application descriptions from " + configFile.toString());
64  
65        try {
66           Digester digester = createDigester();         
67           digester.parse(configFile.openStream());              
68           if(getApplicationNames().length == 0 ) {
69              throw new ApplicationDescriptionNotLoadedException("0 descriptions loaded from "+configFile.toString());          
70           } 
71        }
72        catch (Exception e) {
73           throw new ApplicationDescriptionNotLoadedException("failed to load descriptions from "+configFile.toString(),e);
74        }
75        
76     }
77     /***
78      * Creates the digester suitable for reading the application description file. The correct funtioning ot this method is highly dependent on the details of the schema.
79      * @return
80      */
81     private Digester createDigester() throws ParserConfigurationException {
82  
83        Digester digester = new Digester();
84        digester.setValidating(false); //TODO would be better to make this validate...
85        digester.setNamespaceAware(false);
86        digester.setRules(new RegexRules(new SimpleRegexMatcher())); // to allow matches on any children....
87  
88      digester.push(this);
89        //digester.addObjectCreate(ApplicationDescriptionConstants.APPLICATION_ELEMENT, CommandLineApplicationDescription.class);
90        digester.addFactoryCreate(CommandLineApplicationDescriptionsConstants.APPLICATION_ELEMENT,appDescFactory);
91        // set the appropriate attributes
92        digester.addSetProperties(CommandLineApplicationDescriptionsConstants.APPLICATION_ELEMENT);
93        digester.addCallMethod(CommandLineApplicationDescriptionsConstants.EXPATH_ELEMENT, "setExecutionPath", 0);
94        digester.addCallMethod(CommandLineApplicationDescriptionsConstants.LONGNAME_ELEMENT, "setUIName", 0);      
95        digester.addCallMethod(CommandLineApplicationDescriptionsConstants.DESCRIPTION_ELEMENT, "setAppDescription", 0);
96        digester.addCallMethod(CommandLineApplicationDescriptionsConstants.URL_ELEMENT, "setReferenceURL", 0);
97  
98        // add the appropriate paramter element and set its properties
99        digester.addObjectCreate(CommandLineApplicationDescriptionsConstants.PARAMETER_ELEMENT,CommandLineParameterDescription.class);
100       digester.addSetProperties(CommandLineApplicationDescriptionsConstants.PARAMETER_ELEMENT,"type","typeString");
101       
102       //set some extra property values from the body elements of children
103       digester.addCallMethod(CommandLineApplicationDescriptionsConstants.UI_NAME_ELEMENT, "setDisplayName", 0);
104       digester.addRule(CommandLineApplicationDescriptionsConstants.UI_DESC_ELEMENT, new NodeCreateRule(Node.ELEMENT_NODE));
105       digester.addRule(CommandLineApplicationDescriptionsConstants.UI_DESC_ELEMENT, new AllBodyIncElementsRule("displayDescription", true));
106       digester.addCallMethod(CommandLineApplicationDescriptionsConstants.UCD_ELEMENT, "setUcd", 0);
107       digester.addCallMethod(CommandLineApplicationDescriptionsConstants.DEFVAL_ELEMENT, "setDefaultValue", 0);
108       digester.addCallMethod(CommandLineApplicationDescriptionsConstants.UNITSL_ELEMENT, "setUnits", 0);
109       
110            
111       // add the parameter to the list of paramters      
112       digester.addSetNext(CommandLineApplicationDescriptionsConstants.PARAMETER_ELEMENT, "addParameterDescription");
113      
114       digester.addFactoryCreate(CommandLineApplicationDescriptionsConstants.INTERFACE_ELEMENT,new BaseApplicationInterfaceFactory());
115 
116       digester.addSetProperties(CommandLineApplicationDescriptionsConstants.INTERFACE_ELEMENT);      
117       //input and output parameter references
118       digester.addCallMethod(CommandLineApplicationDescriptionsConstants.INPUT_PREFS, "addInputParameterAsPref", 1, new Class[]{ParameterRef.class});
119       digester.addObjectCreate(CommandLineApplicationDescriptionsConstants.INPUT_PREFS, ParameterRef.class);
120       digester.addSetProperties(CommandLineApplicationDescriptionsConstants.INPUT_PREFS);
121       digester.addCallParam(CommandLineApplicationDescriptionsConstants.INPUT_PREFS, 0, true);
122       
123       
124       //input and output parameter references
125       digester.addCallMethod(CommandLineApplicationDescriptionsConstants.OUTPUT_PREFS, "addOutputParameterAsPref", 1, new Class[]{ParameterRef.class});
126       digester.addObjectCreate(CommandLineApplicationDescriptionsConstants.OUTPUT_PREFS, ParameterRef.class);
127       digester.addSetProperties(CommandLineApplicationDescriptionsConstants.OUTPUT_PREFS);
128       digester.addCallParam(CommandLineApplicationDescriptionsConstants.OUTPUT_PREFS, 0, true);
129      
130       
131       
132       digester.addSetNext(CommandLineApplicationDescriptionsConstants.INTERFACE_ELEMENT, "addInterface");
133 
134       // finally add the application description to the list
135       digester.addSetNext(CommandLineApplicationDescriptionsConstants.APPLICATION_ELEMENT, "addApplicationDescription");
136       return digester;
137  
138      
139    }
140    
141 
142 
143    
144    private static class BaseApplicationInterfaceFactory extends AbstractObjectCreationFactory {
145 
146     public Object createObject(Attributes arg0) throws Exception {
147         String name = "**unknown";
148         if (arg0.getValue(CommandLineApplicationDescriptionsConstants.NAME_ATTR) != null) {
149             name = arg0.getValue(CommandLineApplicationDescriptionsConstants.NAME_ATTR);
150         }
151         ApplicationDescription appDescription = (ApplicationDescription)this.digester.peek(); // i.e. the description we want is at the top of the stack.
152         return new CommandLineApplicationInterface(name,appDescription);
153     }
154    }
155    
156    
157 
158 }