001 /*
002 * AbstractResource.java
003 *
004 * Copyright (c) 1995-2010, The University of Sheffield. See the file
005 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006 *
007 * This file is part of GATE (see http://gate.ac.uk/), and is free
008 * software, licenced under the GNU Library General Public License,
009 * Version 2, June 1991 (in the distribution as file licence.html,
010 * and also available at http://gate.ac.uk/gate/licence.html).
011 *
012 * Hamish Cunningham, 15/Oct/2000
013 *
014 * $Id: AbstractResource.java 12006 2009-12-01 17:24:28Z thomas_heitz $
015 */
016
017 package gate.creole;
018
019 import java.beans.*;
020 import java.io.Serializable;
021 import java.lang.reflect.Constructor;
022 import java.lang.reflect.InvocationTargetException;
023 import java.lang.reflect.Method;
024 import java.util.*;
025
026 import gate.*;
027 import gate.util.*;
028
029
030 /** A convenience implementation of Resource with some default code.
031 */
032 abstract public class AbstractResource
033 extends AbstractFeatureBearer implements Resource, Serializable
034 {
035 static final long serialVersionUID = -9196293927841163321L;
036
037 /** Initialise this resource, and return it. */
038 public Resource init() throws ResourceInstantiationException {
039 return this;
040 } // init()
041
042 /** Sets the name of this resource*/
043 public void setName(String name){
044 this.name = name;
045 }
046
047 /** Returns the name of this resource*/
048 public String getName(){
049 return name;
050 }
051
052 protected String name;
053 /**
054 * releases the memory allocated to this resource
055 */
056 public void cleanup(){
057 }
058
059 //Parameters utility methods
060 /**
061 * Gets the value of a parameter for a resource.
062 * @param resource the resource from which the parameter value will be
063 * obtained
064 * @param paramaterName the name of the parameter
065 * @return the current value of the parameter
066 */
067 public static Object getParameterValue(Resource resource,
068 String paramaterName)
069 throws ResourceInstantiationException{
070 // get the beaninfo for the resource bean, excluding data about Object
071 BeanInfo resBeanInf = null;
072 try {
073 resBeanInf = getBeanInfo(resource.getClass());
074 } catch(Exception e) {
075 throw new ResourceInstantiationException(
076 "Couldn't get bean info for resource " + resource.getClass().getName()
077 + Strings.getNl() + "Introspector exception was: " + e
078 );
079 }
080 PropertyDescriptor[] properties = resBeanInf.getPropertyDescriptors();
081
082 //find the property we're interested on
083 if(properties == null){
084 throw new ResourceInstantiationException(
085 "Couldn't get properties info for resource " +
086 resource.getClass().getName());
087 }
088 boolean done = false;
089 int i = 0;
090 Object value = null;
091 while(!done && i < properties.length){
092 PropertyDescriptor prop = properties[i];
093 if(prop.getName().equals(paramaterName)){
094 Method getMethod = prop.getReadMethod();
095 if(getMethod == null){
096 throw new ResourceInstantiationException(
097 "Couldn't get read accessor method for parameter " + paramaterName +
098 " in " + resource.getClass().getName());
099 }
100 // call the get method with the parameter value
101 Object[] args = new Object[0];
102 try {
103 value = getMethod.invoke(resource, args);
104 } catch(Exception e) {
105 throw new ResourceInstantiationException(
106 "couldn't invoke get method: " + e
107 );
108 }
109 done = true;
110 }//if(prop.getName().equals(paramaterName))
111 i++;
112 }//while(!done && i < properties.length)
113 if(done) return value;
114 else throw new ResourceInstantiationException(
115 "Couldn't find parameter named " + paramaterName +
116 " in " + resource.getClass().getName());
117 }
118
119 /**
120 * Sets the value for a specified parameter for a resource.
121 *
122 * @param resource the resource for which the parameter value will be set
123 * @param paramaterName the name for the parameter
124 * @param parameterValue the value the parameter will receive
125 */
126 public static void setParameterValue(Resource resource, BeanInfo resBeanInf,
127 String paramaterName,
128 Object parameterValue)
129 throws ResourceInstantiationException{
130 PropertyDescriptor[] properties = resBeanInf.getPropertyDescriptors();
131 //find the property we're interested on
132 if(properties == null){
133 throw new ResourceInstantiationException(
134 "Couldn't get properties info for resource " +
135 resource.getClass().getName());
136 }
137 boolean done = false;
138 int i = 0;
139 while(!done && i < properties.length){
140 PropertyDescriptor prop = properties[i];
141 if(prop.getName().equals(paramaterName)){
142 Method setMethod = prop.getWriteMethod();
143 if(setMethod == null){
144 throw new ResourceInstantiationException(
145 "Couldn't get write accessor method for parameter " +
146 paramaterName + " in " + resource.getClass().getName());
147 }
148
149 // convert the parameter to the right type eg String -> URL
150 if(parameterValue != null){
151 Class propertyType = prop.getPropertyType();
152 Class typeToCreate = propertyType;
153 if(Parameter.substituteClasses.containsKey(propertyType)) {
154 typeToCreate = Parameter.substituteClasses.get(propertyType);
155 }
156 Class paramType = parameterValue.getClass();
157 if(!propertyType.isAssignableFrom(paramType)) {
158 try {
159 Constructor mostSpecificConstructor =
160 Tools.getMostSpecificConstructor(typeToCreate, paramType);
161 parameterValue = mostSpecificConstructor
162 .newInstance( new Object[]{parameterValue} );
163 } catch(Exception e) {
164 //this didn't work; if the parameter value is String
165 //try to use the Parameter implementation for finding the
166 //value
167 if(String.class.isAssignableFrom(paramType)){
168 ResourceData rData = (ResourceData)Gate.getCreoleRegister().
169 get(resource.getClass().getName());
170 ParameterList pList = rData.getParameterList();
171 Parameter param = null;
172 Iterator disjIter = pList.getInitimeParameters().iterator();
173 while(param == null && disjIter.hasNext()){
174 Iterator paramIter = ((List)disjIter.next()).iterator();
175 while(param == null && paramIter.hasNext()){
176 Parameter aParam = (Parameter)paramIter.next();
177 if(aParam.getName().equals(paramaterName)) param = aParam;
178 }
179 }
180 disjIter = pList.getRuntimeParameters().iterator();
181 while(param == null && disjIter.hasNext()){
182 Iterator paramIter = ((List)disjIter.next()).iterator();
183 while(param == null && paramIter.hasNext()){
184 Parameter aParam = (Parameter)paramIter.next();
185 if(aParam.getName().equals(paramaterName)) param = aParam;
186 }
187 }
188 if(param != null){
189 try{
190 parameterValue = param.calculateValueFromString(
191 (String)parameterValue);
192 }catch(ParameterException pe){
193 throw new ResourceInstantiationException(pe);
194 }
195 }else{
196 //this should never happen
197 throw new LuckyException("Unknown parameter " + paramaterName +
198 " for resource " + resource.getClass().getName() +
199 "!");
200 }
201 }else{
202 throw new ResourceInstantiationException(
203 "Error converting " + parameterValue.getClass() +
204 " to " + propertyType + ": " + e.toString()
205 );
206 }
207 }
208 }
209 }//if(parameterValue != null)
210
211 // call the set method with the parameter value
212 Object[] args = new Object[1];
213 args[0] = parameterValue;
214 try {
215 setMethod.invoke(resource, args);
216 } catch(Exception e) {
217 e.printStackTrace(Err.getPrintWriter());
218 throw new ResourceInstantiationException(
219 "couldn't invoke set method for " + paramaterName +
220 " on " + resource.getClass().getName() + ": " + e);
221 }
222 done = true;
223 }//if(prop.getName().equals(paramaterName))
224 i++;
225 }//while(!done && i < properties.length)
226 if(!done) throw new ResourceInstantiationException(
227 "Couldn't find parameter named " + paramaterName +
228 " in " + resource.getClass().getName());
229 }//public void setParameterValue(String paramaterName, Object parameterValue)
230
231
232 /**
233 * Sets the values for more parameters for a resource in one step.
234 *
235 * @param parameters a feature map that has paramete names as keys and
236 * parameter values as values.
237 */
238 public static void setParameterValues(Resource resource,
239 FeatureMap parameters)
240 throws ResourceInstantiationException{
241 // get the beaninfo for the resource bean, excluding data about Object
242 BeanInfo resBeanInf = null;
243 try {
244 resBeanInf = getBeanInfo(resource.getClass());
245 } catch(Exception e) {
246 throw new ResourceInstantiationException(
247 "Couldn't get bean info for resource " + resource.getClass().getName()
248 + Strings.getNl() + "Introspector exception was: " + e
249 );
250 }
251
252 Iterator parnameIter = parameters.keySet().iterator();
253 while(parnameIter.hasNext()){
254 String parName = (String)parnameIter.next();
255 setParameterValue(resource, resBeanInf, parName, parameters.get(parName));
256 }
257 }
258
259
260 /**
261 * Adds listeners to a resource.
262 * @param listeners The listeners to be registered with the resource. A
263 * {@link java.util.Map} that maps from fully qualified class name (as a
264 * string) to listener (of the type declared by the key).
265 * @param resource the resource that listeners will be registered to.
266 */
267 public static void setResourceListeners(Resource resource, Map listeners)
268 throws
269 IntrospectionException, InvocationTargetException,
270 IllegalAccessException, GateException
271 {
272 // get the beaninfo for the resource bean, excluding data about Object
273 BeanInfo resBeanInfo = getBeanInfo(resource.getClass());
274
275 // get all the events the bean can fire
276 EventSetDescriptor[] events = resBeanInfo.getEventSetDescriptors();
277
278 // add the listeners
279 if (events != null) {
280 EventSetDescriptor event;
281 for(int i = 0; i < events.length; i++) {
282 event = events[i];
283
284 // did we get such a listener?
285 Object listener =
286 listeners.get(event.getListenerType().getName());
287 if(listener != null) {
288 Method addListener = event.getAddListenerMethod();
289
290 // call the set method with the parameter value
291 Object[] args = new Object[1];
292 args[0] = listener;
293 addListener.invoke(resource, args);
294 }
295 } // for each event
296 } // if events != null
297 } // setResourceListeners()
298
299 /**
300 * Removes listeners from a resource.
301 * @param listeners The listeners to be removed from the resource. A
302 * {@link java.util.Map} that maps from fully qualified class name
303 * (as a string) to listener (of the type declared by the key).
304 * @param resource the resource that listeners will be removed from.
305 */
306 public static void removeResourceListeners(Resource resource, Map listeners)
307 throws IntrospectionException, InvocationTargetException,
308 IllegalAccessException, GateException{
309
310 // get the beaninfo for the resource bean, excluding data about Object
311 BeanInfo resBeanInfo = getBeanInfo(resource.getClass());
312
313 // get all the events the bean can fire
314 EventSetDescriptor[] events = resBeanInfo.getEventSetDescriptors();
315
316 //remove the listeners
317 if(events != null) {
318 EventSetDescriptor event;
319 for(int i = 0; i < events.length; i++) {
320 event = events[i];
321
322 // did we get such a listener?
323 Object listener =
324 listeners.get(event.getListenerType().getName());
325 if(listener != null) {
326 Method removeListener = event.getRemoveListenerMethod();
327
328 // call the set method with the parameter value
329 Object[] args = new Object[1];
330 args[0] = listener;
331 removeListener.invoke(resource, args);
332 }
333 } // for each event
334 } // if events != null
335 } // removeResourceListeners()
336
337 /**
338 * Checks whether the provided {@link Resource} has values for all the
339 * required parameters from the provided list of parameters.
340 *
341 * @param resource the resource being checked
342 * @param parameters is a {@link List} of {@link List} of {@link Parameter}
343 * representing a list of parameter disjunctions (e.g. the one returned by
344 * {@link ParameterList#getRuntimeParameters()}).
345 * @return <tt>true</tt> if all the required parameters have non null values,
346 * <tt>false</tt> otherwise.
347 * @throws {@link ResourceInstantiationException} if problems occur while
348 * inspecting the parameters for the resource. These will normally be
349 * introspection problems and are usually caused by the lack of a parameter
350 * or of the read accessor for a parameter.
351 */
352 public static boolean checkParameterValues(Resource resource,
353 List parameters)
354 throws ResourceInstantiationException{
355 Iterator disIter = parameters.iterator();
356 while(disIter.hasNext()){
357 List disjunction = (List)disIter.next();
358 boolean required = !((Parameter)disjunction.get(0)).isOptional();
359 if(required){
360 //at least one parameter in the disjunction must have a value
361 boolean valueSet = false;
362 Iterator parIter = disjunction.iterator();
363 while(!valueSet && parIter.hasNext()){
364 Parameter par = (Parameter)parIter.next();
365 valueSet = (resource.getParameterValue(par.getName()) != null);
366 }
367 if(!valueSet) return false;
368 }
369 }
370 return true;
371 }
372
373
374
375 /**
376 * Gets the value of a parameter of this resource.
377 * @param paramaterName the name of the parameter
378 * @return the current value of the parameter
379 */
380 public Object getParameterValue(String paramaterName)
381 throws ResourceInstantiationException{
382 return getParameterValue(this, paramaterName);
383 }
384
385 /**
386 * Sets the value for a specified parameter for this resource.
387 *
388 * @param paramaterName the name for the parameter
389 * @param parameterValue the value the parameter will receive
390 */
391 public void setParameterValue(String paramaterName, Object parameterValue)
392 throws ResourceInstantiationException{
393 // get the beaninfo for the resource bean, excluding data about Object
394 BeanInfo resBeanInf = null;
395 try {
396 resBeanInf = getBeanInfo(this.getClass());
397 } catch(Exception e) {
398 throw new ResourceInstantiationException(
399 "Couldn't get bean info for resource " + this.getClass().getName()
400 + Strings.getNl() + "Introspector exception was: " + e
401 );
402 }
403 setParameterValue(this, resBeanInf, paramaterName, parameterValue);
404 }
405
406 /**
407 * Sets the values for more parameters for this resource in one step.
408 *
409 * @param parameters a feature map that has paramete names as keys and
410 * parameter values as values.
411 */
412 public void setParameterValues(FeatureMap parameters)
413 throws ResourceInstantiationException{
414 setParameterValues(this, parameters);
415 }
416
417 private static int beanCount = 0;
418 private static Hashtable beanInfoCache = new Hashtable();
419
420 public static BeanInfo getBeanInfo (Class c) throws IntrospectionException
421 {
422 beanCount = beanCount + 1;
423 BeanInfo r = ((BeanInfo) beanInfoCache.get(c));
424 if (r == null) {
425 r = Introspector.getBeanInfo(c, Object.class);
426 beanInfoCache.put(c, r);
427 }
428 return r;
429 }
430
431 } // class AbstractResource
|