1   /*
2    *  Parameter.java
3    *
4    *  Copyright (c) 1998-2001, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  Hamish Cunningham, 15/Oct/2000
12   *
13   *  $Id: Parameter.java,v 1.19 2002/05/15 14:34:32 valyt Exp $
14   */
15  
16  package gate.creole;
17  
18  import java.util.*;
19  import java.io.*;
20  
21  import gate.*;
22  import gate.util.*;
23  
24  
25  /** Models a resource parameter.
26    */
27  public class Parameter implements Serializable
28  {
29    /** The type name of the parameter */
30    String typeName;
31  
32    /** Set the type name for this parameter */
33    public void setTypeName(String typeName) { this.typeName = typeName; }
34  
35    /** Get the type name for this parameter */
36    public String getTypeName() { return typeName; }
37  
38    /** Is the parameter optional? */
39    boolean optional = false;
40  
41    /** Set optionality of this parameter */
42    public void setOptional(boolean optional) { this.optional = optional; }
43  
44    /** Is the parameter optional? */
45    public boolean isOptional() { return optional; }
46  
47    /** The name of the item's class. If the parameter is a collection then
48      * we need  to know the class of its items in order to create them the
49      * way we want.
50      */
51    String itemClassName = null;
52  
53    /** A set of strings representing suffixes for URL params*/
54    Set suffixes = null;
55  
56    /** Calculate and return the default value for this parameter */
57    public Object calculateDefaultValue() throws ParameterException {
58      // if there's no default string and this is a builtin type, return null
59      if(
60        defaultValueString == null && typeName != null &&
61        typeName.startsWith("java.")
62      )
63        return null;
64  
65      return calculateValueFromString(defaultValueString);
66    } // calculateDefaultValue()
67  
68    /** Calculate and return the value for this parameter starting from a String
69     */
70    public Object calculateValueFromString(String stringValue)
71    throws ParameterException {
72      //if we have no string we can't construct a value
73      Object value = null;
74  
75      // get the Class for the parameter via Class.forName or CREOLE register
76      Class paramClass = getParameterClass();
77  
78  
79      // Test if the paramClass is a collection and if it is, try to
80      // construct the param as a collection of items specified in the
81      // default string value...
82      if (Collection.class.isAssignableFrom(paramClass) &&
83          (!paramClass.isInterface())){
84        // Create an collection object belonging to paramClass
85        Collection colection = null;
86        try{
87          colection = (Collection)paramClass.getConstructor(new Class[]{}).
88                                    newInstance(new Object[]{});
89        } catch(Exception ex){
90            throw new ParameterException("Could not construct an object of type "
91              + typeName + " for param " + name +
92              "\nProblem was: " + ex.toString());
93        }// End try
94        // If an itemClassName was specified then try to create objects belonging
95        // to this class and add them to the collection. Otherwise add the
96        // string tokens to the collection.
97        if(itemClassName == null){
98          // Read the tokens from the default value and try to create items
99          // belonging to the itemClassName
100         StringTokenizer strTokenizer = new StringTokenizer(
101                                                       defaultValueString,";");
102         while(strTokenizer.hasMoreTokens()){
103           String itemStringValue = strTokenizer.nextToken();
104           colection.add(itemStringValue);
105         }// End while
106       }else{
107         Class itemClass = null;
108         try{
109           itemClass = Gate.getClassLoader().loadClass(itemClassName);
110         }catch(ClassNotFoundException e){
111           throw new ParameterException("Could not construct a class object for "
112             + itemClassName + " for param "+ name +
113             ", with type name="+ typeName);
114         }// End try
115         // Read the tokens from the default value and try to create items
116         // belonging to the itemClassName
117         StringTokenizer strTokenizer = new StringTokenizer(
118                                                       defaultValueString,";");
119         while(strTokenizer.hasMoreTokens()){
120           // Read a string item and construct an object belonging to
121           // itemClassName
122           String itemStringValue = strTokenizer.nextToken();
123           Object itemValue = null;
124           try{
125             itemValue = itemClass.getConstructor(new Class[]{String.class}).
126                                   newInstance(new Object[]{itemStringValue});
127           }catch(Exception e){
128             throw new ParameterException("Could not create an object of " +
129             itemClassName + " for param name "+ name + ", with type name ="+
130             typeName);
131           }// End try
132           // Add the item value object to the collection
133           colection.add(itemValue);
134         }// End while
135       }// End if(itemClassName == null)
136       return colection;
137     }// End if (Collection.class.isAssignableFrom(paramClass))
138     // java builtin types
139     if(typeName.startsWith("java.")) {
140       if(typeName.equals("java.lang.Boolean"))
141         value = Boolean.valueOf(stringValue);
142       else if(typeName.equals("java.lang.Long"))
143         value = Long.valueOf(stringValue);
144       else if(typeName.equals("java.lang.Integer"))
145         value = Integer.valueOf(stringValue);
146       else if(typeName.equals("java.lang.String"))
147         value = stringValue;
148       else if(typeName.equals("java.lang.Double"))
149         value = Double.valueOf(stringValue);
150       else if(typeName.equals("java.lang.Float"))
151         value = Float.valueOf(stringValue);
152       else{
153         //try to construct a new value from the string using a constructor
154         // e.g. for URLs
155         try{
156           if(!paramClass.isAssignableFrom(String.class)){
157             value = paramClass.getConstructor(new Class[]{String.class}).
158                          newInstance(new Object[]{stringValue});
159           }
160         }catch(Exception e){
161           throw new ParameterException("Unsupported parameter type " + typeName);
162         }
163       }
164     } else {
165       // non java types
166       if(resData == null)
167         resData = (ResourceData) Gate.getCreoleRegister().get(typeName);
168       if(resData == null){
169         //unknown type
170         return null;
171       }
172 
173       WeakBumpyStack instantiations = resData.getInstantiations();
174       if(! instantiations.isEmpty()) value = instantiations.peek();
175     }
176 
177     return value;
178   } // calculateValueFromString()
179 
180 
181   /** The resource data that this parameter is part of. */
182   protected ResourceData resData;
183 
184   /** Get the default value for this parameter. If the value is
185     * currently null it will try and calculate a value.
186     * @see #calculateDefaultValue()
187     */
188   public Object getDefaultValue() throws ParameterException {
189     return calculateDefaultValue();
190   } // getDefaultValue
191 
192   /** Default value string (unprocessed, from the metadata)
193     * for the parameter
194     */
195   String defaultValueString;
196 
197   /** Set the default value string (from the metadata)
198     * for the parameter
199     */
200   public void setDefaultValueString(String defaultValueString) {
201     this.defaultValueString = defaultValueString;
202   } // setDefaultValueString
203 
204   /** Get the default value string (unprocessed, from the metadata)
205     * for the parameter
206     */
207   public String getDefaultValueString() { return defaultValueString; }
208 
209   /** Comment for the parameter */
210   String comment;
211 
212   /** Set the comment for this parameter */
213   public void setComment(String comment) { this.comment = comment; }
214 
215   /** Get the comment for this parameter */
216   public String getComment() { return comment; }
217 
218   /** Name for the parameter */
219   String name;
220 
221   /** Set the name for this parameter */
222   public void setName(String name) { this.name = name; }
223 
224   /** Get the name for this parameter */
225   public String getName() { return name; }
226 
227   /** Get the suffixes atached with this param. If it's null then there are
228    *  no suffices attached with it
229    */
230   public Set getSuffixes(){ return suffixes;}
231 
232   /** Is this a run-time parameter? */
233   boolean runtime = false;
234 
235   /** Set runtime status of this parameter */
236   public void setRuntime(boolean runtime) { this.runtime = runtime; }
237 
238   /** Is the parameter runtime? */
239   public boolean isRuntime() { return runtime; }
240 
241   /** The Class for the parameter type */
242   protected Class paramClass;
243 
244   /** Find the class for this parameter type. */
245   protected Class getParameterClass() throws ParameterException
246   {
247     // get java builtin classes via class; else look in the register
248     try {
249       ResourceData resData = (ResourceData)
250                              Gate.getCreoleRegister().get(typeName);
251       if(resData == null){
252         paramClass = Gate.getClassLoader().loadClass(typeName);
253       }else{
254         paramClass = resData.getResourceClass();
255       }
256 
257 //      if(typeName.startsWith("java."))
258 //          paramClass = Class.forName(typeName);
259 //      else {
260 //        ResourceData resData =
261 //          (ResourceData) Gate.getCreoleRegister().get(typeName);
262 //        if(resData == null)
263 //          throw new ParameterException(
264 //            "No resource data for " + typeName + " in Parameter/getParamClz"
265 //          );
266 //        paramClass = resData.getResourceClass();
267 //      }
268     } catch(ClassNotFoundException e) {
269       throw new ParameterException(
270         "Couldn't find class " + typeName + ": " + Strings.getNl() + e
271       );
272     }
273 
274     if(paramClass == null)
275       throw new ParameterException("Couldn't find class " + typeName);
276 
277     return paramClass;
278   } // getParameterClass
279 
280   /** String representation */
281   public String toString() {
282     try{
283       return "Parameter: name="+ name+ "; valueString=" + typeName +
284              "; optional=" + optional +
285              "; defaultValueString=" + defaultValueString +
286              "; defaultValue=" + getDefaultValue() + "; comment=" +
287              comment + "; runtime=" + runtime +
288              "; itemClassName=" + itemClassName +
289              "; suffixes=" + suffixes;
290     }catch(ParameterException pe){
291       throw new GateRuntimeException(pe.toString());
292     }
293   }
294 
295   /**
296    * If this parameter is a List type this will return the type of the items
297    * in the list. If the type is <tt>null</tt> String will be assumed.
298    */
299   public String getItemClassName() {
300     return itemClassName;
301   } // toString()
302 } // class Parameter
303