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.17 2001/11/05 16:07:48 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      Object value = null;
73  
74      // get the Class for the parameter via Class.forName or CREOLE register
75      Class paramClass = getParameterClass();
76  
77      // Test if the paramClass is a collection and if it is, try to
78      // construct the param as a collection of items specified in the
79      // default string value...
80      if (Collection.class.isAssignableFrom(paramClass)){
81        // Create an collection object bellonging to  paramClass
82        Collection colection = null;
83        try{
84          colection = (Collection)paramClass.getConstructor(new Class[]{}).
85                                    newInstance(new Object[]{});
86        } catch(Exception ex){
87            throw new ParameterException("Could not construct an object of "
88              + typeName + " for param " + name);
89        }// End try
90        // If an itemClassName was specified then try to create objects belonging
91        // to this class and add them to the collection. Otherwise add the
92        // string tokens to the collection.
93        if(itemClassName == null){
94          // Read the tokens from the default value and try to create items
95          // belonging to the itemClassName
96          StringTokenizer strTokenizer = new StringTokenizer(
97                                                        defaultValueString,";");
98          while(strTokenizer.hasMoreTokens()){
99            String itemStringValue = strTokenizer.nextToken();
100           colection.add(itemStringValue);
101         }// End while
102       }else{
103         Class itemClass = null;
104         try{
105           itemClass = Gate.getClassLoader().loadClass(itemClassName);
106         }catch(ClassNotFoundException e){
107           throw new ParameterException("Could not construct a class object for "
108             + itemClassName + " for param "+ name +
109             ", with type name="+ typeName);
110         }// End try
111         // Read the tokens from the default value and try to create items
112         // belonging to the itemClassName
113         StringTokenizer strTokenizer = new StringTokenizer(
114                                                       defaultValueString,";");
115         while(strTokenizer.hasMoreTokens()){
116           // Read a string item and construct an object belonging to
117           // itemClassName
118           String itemStringValue = strTokenizer.nextToken();
119           Object itemValue = null;
120           try{
121             itemValue = itemClass.getConstructor(new Class[]{String.class}).
122                                   newInstance(new Object[]{itemStringValue});
123           }catch(Exception e){
124             throw new ParameterException("Could not create an object of " +
125             itemClassName + " for param name "+ name + ", with type name ="+
126             typeName);
127           }// End try
128           // Add the item value object to the collection
129           colection.add(itemValue);
130         }// End while
131       }// End if(itemClassName == null)
132       return colection;
133     }// End if (Collection.class.isAssignableFrom(paramClass))
134     // java builtin types
135     if(typeName.startsWith("java.")) {
136       if(typeName.equals("java.lang.Boolean"))
137         value = Boolean.valueOf(stringValue);
138       else if(typeName.equals("java.lang.Long"))
139         value = Long.valueOf(stringValue);
140       else if(typeName.equals("java.lang.Integer"))
141         value = Integer.valueOf(stringValue);
142       else if(typeName.equals("java.lang.String"))
143         value = stringValue;
144       else if(typeName.equals("java.lang.Double"))
145         value = Double.valueOf(stringValue);
146       else if(typeName.equals("java.lang.Float"))
147         value = Float.valueOf(stringValue);
148       else{
149         //try to construct a new value from the string using a constructor
150         // e.g. for URLs
151         try{
152           if(!paramClass.isAssignableFrom(String.class)){
153             value = paramClass.getConstructor(new Class[]{String.class}).
154                          newInstance(new Object[]{stringValue});
155           }
156         }catch(Exception e){
157           throw new ParameterException("Unsupported parameter type " + typeName);
158         }
159       }
160     } else {
161       // non java types
162       if(resData == null)
163         resData = (ResourceData) Gate.getCreoleRegister().get(typeName);
164       if(resData == null){
165         //unknown type
166         return null;
167       }
168 
169       WeakBumpyStack instantiations = resData.getInstantiations();
170       if(! instantiations.isEmpty()) value = instantiations.peek();
171     }
172 
173     return value;
174   } // calculateValueFromString()
175 
176 
177   /** The resource data that this parameter is part of. */
178   protected ResourceData resData;
179 
180   /** Get the default value for this parameter. If the value is
181     * currently null it will try and calculate a value.
182     * @see #calculateDefaultValue()
183     */
184   public Object getDefaultValue() throws ParameterException {
185     return calculateDefaultValue();
186   } // getDefaultValue
187 
188   /** Default value string (unprocessed, from the metadata)
189     * for the parameter
190     */
191   String defaultValueString;
192 
193   /** Set the default value string (from the metadata)
194     * for the parameter
195     */
196   public void setDefaultValueString(String defaultValueString) {
197     this.defaultValueString = defaultValueString;
198   } // setDefaultValueString
199 
200   /** Get the default value string (unprocessed, from the metadata)
201     * for the parameter
202     */
203   public String getDefaultValueString() { return defaultValueString; }
204 
205   /** Comment for the parameter */
206   String comment;
207 
208   /** Set the comment for this parameter */
209   public void setComment(String comment) { this.comment = comment; }
210 
211   /** Get the comment for this parameter */
212   public String getComment() { return comment; }
213 
214   /** Name for the parameter */
215   String name;
216 
217   /** Set the name for this parameter */
218   public void setName(String name) { this.name = name; }
219 
220   /** Get the name for this parameter */
221   public String getName() { return name; }
222 
223   /** Get the suffixes atached with this param. If it's null then there are
224    *  no suffices attached with it
225    */
226   public Set getSuffixes(){ return suffixes;}
227 
228   /** Is this a run-time parameter? */
229   boolean runtime = false;
230 
231   /** Set runtime status of this parameter */
232   public void setRuntime(boolean runtime) { this.runtime = runtime; }
233 
234   /** Is the parameter runtime? */
235   public boolean isRuntime() { return runtime; }
236 
237   /** The Class for the parameter type */
238   protected Class paramClass;
239 
240   /** Find the class for this parameter type. */
241   protected Class getParameterClass() throws ParameterException
242   {
243     // get java builtin classes via class; else look in the register
244     try {
245       ResourceData resData = (ResourceData)
246                              Gate.getCreoleRegister().get(typeName);
247       if(resData == null){
248         paramClass = Gate.getClassLoader().loadClass(typeName);
249       }else{
250         paramClass = resData.getResourceClass();
251       }
252 
253 //      if(typeName.startsWith("java."))
254 //          paramClass = Class.forName(typeName);
255 //      else {
256 //        ResourceData resData =
257 //          (ResourceData) Gate.getCreoleRegister().get(typeName);
258 //        if(resData == null)
259 //          throw new ParameterException(
260 //            "No resource data for " + typeName + " in Parameter/getParamClz"
261 //          );
262 //        paramClass = resData.getResourceClass();
263 //      }
264     } catch(ClassNotFoundException e) {
265       throw new ParameterException(
266         "Couldn't find class " + typeName + ": " + Strings.getNl() + e
267       );
268     }
269 
270     if(paramClass == null)
271       throw new ParameterException("Couldn't find class " + typeName);
272 
273     return paramClass;
274   } // getParameterClass
275 
276   /** String representation */
277   public String toString() {
278     try{
279       return "Parameter: name="+ name+ "; valueString=" + typeName +
280              "; optional=" + optional +
281              "; defaultValueString=" + defaultValueString +
282              "; defaultValue=" + getDefaultValue() + "; comment=" +
283              comment + "; runtime=" + runtime +
284              "; itemClassName=" + itemClassName +
285              "; suffixes=" + suffixes;
286     }catch(ParameterException pe){
287       throw new GateRuntimeException(pe.toString());
288     }
289   }
290 
291   /**
292    * If this parameter is a List type this will return the type of the items
293    * in the list. If the type is <tt>null</tt> String will be assumed.
294    */
295   public String getItemClassName() {
296     return itemClassName;
297   } // toString()
298 } // class Parameter
299