View Javadoc

1   /*
2    * Copyright (c) 2005 The University of Reading
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    * 1. Redistributions of source code must retain the above copyright
9    *    notice, this list of conditions and the following disclaimer.
10   * 2. Redistributions in binary form must reproduce the above copyright
11   *    notice, this list of conditions and the following disclaimer in the
12   *    documentation and/or other materials provided with the distribution.
13   * 3. Neither the name of the University of Reading, nor the names of the
14   *    authors or contributors may be used to endorse or promote products
15   *    derived from this software without specific prior written permission.
16   *
17   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20   * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   */
28  
29  package uk.ac.rdg.resc.jstyx.gridservice.config;
30  
31  import org.dom4j.Node;
32  
33  import com.martiansoftware.jsap.JSAP;
34  import com.martiansoftware.jsap.Parameter;
35  import com.martiansoftware.jsap.Switch;
36  import com.martiansoftware.jsap.Option;
37  import com.martiansoftware.jsap.FlaggedOption;
38  import com.martiansoftware.jsap.UnflaggedOption;
39  
40  /***
41   * Class containing information about the command-line parameters expected by
42   * the Styx Grid Service
43   *
44   * @author Jon Blower
45   * $Revision: 534 $
46   * $Date: 2005-12-07 17:53:34 +0000 (Wed, 07 Dec 2005) $
47   * $Log$
48   * Revision 1.4  2005/12/07 17:53:34  jonblower
49   * Added type to SGSParam (STRING, INPUT_FILE and OUTPUT_FILE)
50   *
51   * Revision 1.3  2005/11/10 08:56:41  jonblower
52   * Added link to output file
53   *
54   * Revision 1.2  2005/11/09 17:46:30  jonblower
55   * setInputFile() now only works for Options
56   *
57   * Revision 1.1  2005/11/07 20:59:34  jonblower
58   * Refactored SGS config classes to new package
59   *
60   */
61  
62  public class SGSParam
63  {
64      // Integer constants representing the type of the parameter
65      public static final int STRING = 0;
66      public static final int INPUT_FILE = 1;
67      public static final int OUTPUT_FILE = 2;
68      
69      private Parameter param;  // The JSAP parameter object
70      private SGSInput inputFile;   // The input file (if any) linked to this parameter
71      private SGSOutput outputFile; // The output file (if any) linked to this parameter
72      private int type; // The type of the parameter
73      
74      SGSParam(Node paramNode) throws SGSConfigException
75      {
76          this.param = createParameter(paramNode);
77          this.inputFile = null;
78          this.outputFile = null;
79          this.type = STRING;
80      }
81      
82      /***
83       * @return the JSAP parameter object associated with this parameter
84       */
85      public Parameter getParameter()
86      {
87          return this.param;
88      }
89      
90      /***
91       * @return the name of this parameter
92       */
93      public String getName()
94      {
95          return this.param.getID();
96      }
97      
98      /***
99       * Gets the type of this parameter:
100      * <table><tbody><tr><th>Type</th><th>Meaning</th></tr>
101      * <tr><td>STRING</td><td>Plain string</td></tr>
102      * <tr><td>INPUT_FILE</td><td>File that the executable will read: must be uploaded</td></tr>
103      * <tr><td>OUTPUT_FILE</td><td>File that the executable will write: can be downloaded</td></tr>
104      * </tbody></table>
105      * @return The parameter type as an integer
106      */
107     public int getType()
108     {
109         return this.type;
110     }
111     
112     /***
113      * Sets the input file that is linked to this parameter
114      * @throws NullPointerException if <code>inputFile</code> is null
115      * @throws SGSConfigException if this parameter is not an Option, or if the
116      * parameter is already linked to an output file
117      */
118     public void setInputFile(SGSInput inputFile) throws SGSConfigException
119     {
120         if (inputFile == null)
121         {
122             throw new NullPointerException("inputFile cannot be null");
123         }
124         if (this.outputFile != null)
125         {
126             throw new SGSConfigException("Parameter " + this.getName() + 
127                 " is already linked to an output file");
128         }
129         if (this.param instanceof Option)
130         {
131             this.inputFile = inputFile;
132             this.type = INPUT_FILE;
133         }
134         else
135         {
136             throw new SGSConfigException("Can only set an input file for an Option");
137         }
138     }
139     
140     /***
141      * Sets the output file that is linked to this parameter
142      * @throws NullPointerException if <code>outputFile</code> is null
143      * @throws SGSConfigException if this parameter is not an Option, or if the
144      * parameter is already linked to an input file
145      */
146     public void setOutputFile(SGSOutput outputFile) throws SGSConfigException
147     {
148         if (outputFile == null)
149         {
150             throw new NullPointerException("outputFile cannot be null");
151         }
152         if (this.inputFile != null)
153         {
154             throw new SGSConfigException("Parameter " + this.getName() + 
155                 " is already linked to an input file");
156         }
157         if (this.param instanceof Option)
158         {
159             this.outputFile = outputFile;
160             this.type = OUTPUT_FILE;
161         }
162         else
163         {
164             throw new SGSConfigException("Can only set an output file for an Option");
165         }
166     }
167     
168     /***
169      * @return the input file that is linked to this parameter, or null if 
170      * this parameter is not linked to an input file
171      */
172     public SGSInput getInputFile()
173     {
174         return this.inputFile;
175     }
176     
177     /***
178      * @return the output file that is linked to this parameter, or null if 
179      * this parameter is not linked to an output file
180      */
181     public SGSOutput getOutputFile()
182     {
183         return this.outputFile;
184     }
185     
186     /***
187      * @return a Parameter object (from the JSAP library) for the specification
188      * at the given node in the XML file
189      * @throws SGSConfigException if the parameter could not be created
190      */
191     private static Parameter createParameter(Node paramNode) throws SGSConfigException
192     {
193         // Name and paramType are compulsory attributes so must exist
194         String name = paramNode.valueOf("@name").trim();
195         String paramType = paramNode.valueOf("@paramType");
196         
197         // We must check to see if a default value has been set
198         String defaultValue;
199         if (paramNode.selectSingleNode("@defaultValue") == null)
200         {
201             // Note: JSAP.NO_DEFAULT == null (at least in current JSAP version)
202             defaultValue = JSAP.NO_DEFAULT;
203         }
204         else
205         {
206             defaultValue = paramNode.valueOf("@defaultValue");
207         }
208         
209         // All other strings other than "yes" are interpreted as "no"
210         boolean required = paramNode.valueOf("@required").equalsIgnoreCase("yes")
211             ? JSAP.REQUIRED : JSAP.NOT_REQUIRED;
212         
213         // The description is not compulsory: if it has not been set then 
214         // description will be the empty string
215         String description = paramNode.valueOf("@description");
216         
217         // Get the flags
218         char shortFlag;
219         if (paramNode.selectSingleNode("@flag") == null)
220         {
221             shortFlag = JSAP.NO_SHORTFLAG;
222         }
223         else
224         {
225             String shortFlagStr = paramNode.valueOf("@flag").trim();
226             if (shortFlagStr.equals(""))
227             {
228                 shortFlag = JSAP.NO_SHORTFLAG;
229             }
230             else if (shortFlagStr.length() == 1)
231             {
232                 shortFlag = shortFlagStr.charAt(0);
233             }
234             else
235             {
236                 throw new SGSConfigException("Short flag can only be 1 character long");
237             }
238         }
239         
240         String longFlag;
241         if (paramNode.selectSingleNode("@longFlag") == null)
242         {
243             longFlag = JSAP.NO_LONGFLAG;
244         }
245         else
246         {
247             longFlag = paramNode.valueOf("@longFlag").trim();
248             if (longFlag.equals(""))
249             {
250                 longFlag = JSAP.NO_LONGFLAG;
251             }
252         }
253         
254         if (paramType.equals("switch"))
255         {
256             Switch param = new Switch(name, shortFlag, longFlag, description);
257             if (defaultValue == JSAP.NO_DEFAULT
258                 || defaultValue.trim().equalsIgnoreCase("false"))
259             {
260                 param.setDefault("false");
261             }
262             else if (defaultValue.trim().equalsIgnoreCase("true"))
263             {
264                 param.setDefault("true");
265             }
266             else
267             {
268                 throw new SGSConfigException("Default value for " + name +
269                     " must be empty, \"true\" or \"false\"");
270             }
271             return param;
272         }
273         else
274         {
275             if (defaultValue != JSAP.NO_DEFAULT && defaultValue.trim().equals(""))
276             {
277                 throw new SGSConfigException("Default value for " + name
278                     + " cannot be empty");
279             }
280             else if (paramType.equals("flaggedOption"))
281             {
282                 return new FlaggedOption(name, JSAP.STRING_PARSER, 
283                     defaultValue, required, shortFlag, longFlag, description);
284             }
285             else if (paramType.equals("unflaggedOption"))
286             {
287                 boolean greedy = paramNode.valueOf("@greedy").equals("yes");
288                 return new UnflaggedOption(name, JSAP.STRING_PARSER, defaultValue, 
289                     required, greedy, description);
290             }
291             else
292             {
293                 throw new SGSConfigException("Illegal parameter type: " + paramType);
294             }
295         }
296     }
297     
298 }