KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sapia > util > xml > confix > AbstractXMLProcessor


1 package org.sapia.util.xml.confix;
2
3
4 // Import of Sun's JDK classes
5
// ---------------------------
6
import java.lang.reflect.InvocationTargetException JavaDoc;
7 import java.lang.reflect.Method JavaDoc;
8
9
10 /**
11  * This class defines the behavior for generating an object graph from an
12  * XML document.
13  *
14  * @author Yanick Duchesne
15  * @author Jean-Cedric Desrochers
16  *
17  * <dl>
18  * <dt><b>Copyright:</b><dd>Copyright &#169; 2002-2003 <a HREF="http://www.sapia-oss.org">Sapia Open Source Software</a>. All Rights Reserved.</dd></dt>
19  * <dt><b>License:</b><dd>Read the license.txt file of the jar or visit the
20  * <a HREF="http://www.sapia-oss.org/license.html">license page</a> at the Sapia OSS web site</dd></dt>
21  * </dl>
22  */

23 public abstract class AbstractXMLProcessor implements ConfixProcessorIF {
24   /////////////////////////////////////////////////////////////////////////////////////////
25
///////////////////////////////// INSTANCE ATTRIBUTES /////////////////////////////////
26
/////////////////////////////////////////////////////////////////////////////////////////
27

28   /** The object factory of this processor. */
29   private ObjectFactoryIF _theObjectFactory;
30
31   /////////////////////////////////////////////////////////////////////////////////////////
32
//////////////////////////////////// CONSTRUCTORS /////////////////////////////////////
33
/////////////////////////////////////////////////////////////////////////////////////////
34

35   /**
36    * Creates a new AbstractXMLProcessor instance with the argument passed in.
37    *
38    * @param anObjectFactory The object factory of this processor.
39    */

40   public AbstractXMLProcessor(ObjectFactoryIF anObjectFactory) {
41     _theObjectFactory = anObjectFactory;
42   }
43
44   /////////////////////////////////////////////////////////////////////////////////////////
45
/////////////////////////////////// STATIC METHODS ////////////////////////////////////
46
/////////////////////////////////////////////////////////////////////////////////////////
47

48   /**
49    * Assigns the given <code>child</code> object to the <code>parent</code> one.
50    * This method searches for the method name based on the <code>elementName</code>
51    * parameter, which is the name of an XML element. The method name must match
52    * either the setXXX or addXXX pattern; for example, for an XML element named
53    * 'elephant', the class of the <code>parent</code> object should contain either
54    * the <code>setElephant</code> or <code>addElephant</code> method.
55    *
56    * @param aParent the object to <code>child</code> will be set or added
57    * @param aChild the object to add to <code>parent</code>
58    * @param anElementName the name of the XML element to which a addXXX or
59    * setXXX method should correspond in the parent object.
60    * @throws ConfigurationException
61    */

62   protected static void assignToParent(Object JavaDoc aParent, Object JavaDoc aChild,
63     String JavaDoc anElementName) throws ConfigurationException {
64     try {
65       String JavaDoc aMethodName = "set" +
66         toMethodName(formatElementName(anElementName));
67       invokeMethod(aMethodName, aParent, aChild);
68     } catch (ConfigurationException ce) {
69       String JavaDoc aMessage = "Error assigning the child object " + aChild +
70         " with the setXXX method on the parent object " + aParent;
71       throw new ConfigurationException(aMessage, ce);
72     } catch (NoSuchMethodException JavaDoc nsme) {
73       try {
74         String JavaDoc aMethodName = "add" +
75           toMethodName(formatElementName(anElementName));
76         try{
77           invokeMethod(aMethodName, aParent, aChild);
78         }catch(NoSuchMethodException JavaDoc e){
79           try{
80             invokeSetterOrAdder(aParent, aChild);
81           }catch(NoSuchMethodException JavaDoc e2){
82             throw e;
83           }
84         }
85       } catch (ConfigurationException ce) {
86         String JavaDoc aMessage = "Error assigning the child object " + aChild +
87           " with the addXXX method on the parent object " + aParent;
88         throw new ConfigurationException(aMessage, ce);
89       } catch (NoSuchMethodException JavaDoc nsme2) {
90         // If the parent is an object wrapper, takes the wrappep object
91
if (aParent instanceof ObjectWrapperIF) {
92           aParent = ((ObjectWrapperIF) aParent).getWrappedObject();
93           assignToParent(aParent, aChild, anElementName);
94         }
95         // If the parent is an object handler, delegate it the object
96
else if (aParent instanceof ObjectHandlerIF) {
97           ((ObjectHandlerIF) aParent).handleObject(anElementName, aChild);
98         } else {
99           String JavaDoc aMessage =
100             "There's no setXXX or addXXX method to assign the object " +
101             aChild + " on the parent object " + aParent;
102           throw new ConfigurationException(aMessage);
103         }
104       }
105     }
106   }
107
108   /**
109    * Invokes the setXXXX/addXXXX method corresponding to the given attribute name.
110    * The method is invoked on the target instance. The passed in value is
111    * coerced to the type expected by the setter or adder method.
112    *
113    * @param anElementName the XML element name corresponding to the passed in target.
114    * @param aTarget the instance on which to invoke the method.
115    * @param anAttributeName the name of the attribute whose corresponding method
116    * is called.
117    * @param aValue the value to assign to the setter/adder method - the value is
118    * coerced to the type expected by the method.
119    */

120   protected static void invokeSetter(String JavaDoc anElementName, Object JavaDoc aTarget,
121     String JavaDoc anAttributeName, String JavaDoc aValue) throws ConfigurationException {
122     try {
123       String JavaDoc aMethodName = "set" +
124         toMethodName(formatElementName(anAttributeName));
125       invokeMethod(aMethodName, aTarget, aValue);
126     } catch (ConfigurationException ce) {
127       String JavaDoc aMessage =
128         "Application error invoking the setXXX method to assign the value " +
129         aValue + " for the attribute " + anAttributeName + " on the object " +
130         aTarget;
131       throw new ConfigurationException(aMessage, ce);
132     } catch (NoSuchMethodException JavaDoc nsme) {
133       try{
134         String JavaDoc aMethodName = "add" + toMethodName(formatElementName(anAttributeName));
135         invokeMethod(aMethodName, aTarget, aValue);
136           // If the target object is an ObjectWrapperIF use the wrapped object
137
}catch(NoSuchMethodException JavaDoc nsme2){
138           if (aTarget instanceof ObjectWrapperIF) {
139             aTarget = ((ObjectWrapperIF) aTarget).getWrappedObject();
140             invokeSetter(anElementName, aTarget, anAttributeName, aValue);
141           }
142           // If the target object is an ObjectHandlerIF, delegate it the value
143
else if (aTarget instanceof ObjectHandlerIF) {
144             ((ObjectHandlerIF) aTarget).handleObject(anAttributeName, aValue);
145           }
146           // Otherwise throw a configuration exception
147
else {
148             String JavaDoc aMessage = "There's no setXXX method to assign the value " +
149               aValue + " for the attribute/element " + anAttributeName +
150               " on the object " + aTarget;
151             throw new ConfigurationException(aMessage, nsme);
152           }
153       }
154     }
155   }
156   
157   /**
158    * @param aTarget the <code>Object</code> on which to attempt the method calls.
159    * @param aValue the <code>Object</code> to assign.
160    * @return the return value of the method call.
161    * @throws ConfigurationException if a problem occurs invoking the method.
162    * @throws NoSuchMethodException if no adder or setter could be found.
163    */

164   protected static Object JavaDoc invokeSetterOrAdder(Object JavaDoc aTarget, Object JavaDoc aValue)
165     throws ConfigurationException, NoSuchMethodException JavaDoc{
166     String JavaDoc methodName = "set";
167     try{
168       return invokeMethod(methodName, aTarget, aValue);
169     }catch(NoSuchMethodException JavaDoc e){
170       methodName = "add";
171       return invokeMethod(methodName, aTarget, aValue);
172     }
173   }
174
175   /**
176    * Invokes the method whose name is given on the provided target
177    * instance.
178    *
179    * @param aMethodName the name of the method to invoke.
180    * @param aTarget the instance on which to invoke the method.
181    * @param aValue the value to pass to the method that will be called.
182    */

183   protected static Object JavaDoc invokeMethod(String JavaDoc aMethodName, Object JavaDoc aTarget,
184     Object JavaDoc aValue) throws ConfigurationException, NoSuchMethodException JavaDoc {
185     try {
186       Method JavaDoc[] someMethods = aTarget.getClass().getMethods();
187
188       for (int i = 0; i < someMethods.length; i++) {
189         if (someMethods[i].getName().equals(aMethodName) &&
190               (someMethods[i].getParameterTypes().length == 1)) {
191           Method JavaDoc aMethod = someMethods[i];
192
193           Class JavaDoc aParamType = aMethod.getParameterTypes()[0];
194
195           if (aParamType.isAssignableFrom(aValue.getClass())) {
196             return aMethod.invoke(aTarget, new Object JavaDoc[] { aValue });
197           }
198           // If the method parameter is a boolean type
199
else if ((aParamType.equals(boolean.class) ||
200                 aParamType.equals(Boolean JavaDoc.class)) && aValue instanceof String JavaDoc) {
201             String JavaDoc aStringValue = (String JavaDoc) aValue;
202             Boolean JavaDoc aBoolean = new Boolean JavaDoc(aStringValue.equalsIgnoreCase("true") ||
203                 aStringValue.equalsIgnoreCase("yes"));
204
205             return aMethod.invoke(aTarget, new Object JavaDoc[] { aBoolean });
206           } else if (aParamType.equals(boolean.class) &&
207                 aValue instanceof Boolean JavaDoc) {
208             return aMethod.invoke(aTarget, new Object JavaDoc[] { aValue });
209           }
210           // If the method parameter is byte type
211
else if ((aParamType.equals(byte.class) ||
212                 aParamType.equals(Byte JavaDoc.class)) && aValue instanceof String JavaDoc) {
213             String JavaDoc aStringValue = (String JavaDoc) aValue;
214             Byte JavaDoc aByte = new Byte JavaDoc(Byte.parseByte(aStringValue));
215
216             return aMethod.invoke(aTarget, new Object JavaDoc[] { aByte });
217           } else if (aParamType.equals(byte.class) && aValue instanceof Byte JavaDoc) {
218             return aMethod.invoke(aTarget, new Object JavaDoc[] { aValue });
219           }
220           // If the method parameter is a short type
221
else if ((aParamType.equals(short.class) ||
222                 aParamType.equals(Short JavaDoc.class)) && aValue instanceof String JavaDoc) {
223             String JavaDoc aStringValue = (String JavaDoc) aValue;
224             Short JavaDoc aShort = new Short JavaDoc(Short.parseShort(aStringValue));
225
226             return aMethod.invoke(aTarget, new Object JavaDoc[] { aShort });
227           } else if (aParamType.equals(short.class) && aValue instanceof Short JavaDoc) {
228             return aMethod.invoke(aTarget, new Object JavaDoc[] { aValue });
229           }
230           // If the method parameter is a char type
231
else if ((aParamType.equals(char.class) ||
232                 aParamType.equals(Character JavaDoc.class)) &&
233                 aValue instanceof String JavaDoc) {
234             String JavaDoc aStringValue = (String JavaDoc) aValue;
235
236             if (aStringValue.length() != 1) {
237               throw new ConfigurationException("'" + aStringValue +
238                 "' must be a single character string");
239             }
240
241             Character JavaDoc aChar = new Character JavaDoc(aStringValue.charAt(0));
242
243             return aMethod.invoke(aTarget, new Object JavaDoc[] { aChar });
244           } else if (aParamType.equals(char.class) &&
245                 aValue instanceof Character JavaDoc) {
246             return aMethod.invoke(aTarget, new Object JavaDoc[] { aValue });
247           }
248           // If the method parameter is a int type
249
else if ((aParamType.equals(int.class) ||
250                 aParamType.equals(Integer JavaDoc.class)) && aValue instanceof String JavaDoc) {
251             String JavaDoc aStringValue = (String JavaDoc) aValue;
252             Integer JavaDoc aInt = new Integer JavaDoc(Integer.parseInt(aStringValue));
253
254             return aMethod.invoke(aTarget, new Object JavaDoc[] { aInt });
255           } else if (aParamType.equals(int.class) && aValue instanceof Integer JavaDoc) {
256             return aMethod.invoke(aTarget, new Object JavaDoc[] { aValue });
257           }
258           // If the method parameter is a long type
259
else if ((aParamType.equals(long.class) ||
260                 aParamType.equals(Long JavaDoc.class)) && aValue instanceof String JavaDoc) {
261             String JavaDoc aStringValue = (String JavaDoc) aValue;
262             Long JavaDoc aLong = new Long JavaDoc(Long.parseLong(aStringValue));
263
264             return aMethod.invoke(aTarget, new Object JavaDoc[] { aLong });
265           } else if (aParamType.equals(long.class) && aValue instanceof Long JavaDoc) {
266             return aMethod.invoke(aTarget, new Object JavaDoc[] { aValue });
267           }
268           // If the method parameter is a float type
269
else if ((aParamType.equals(float.class) ||
270                 aParamType.equals(Float JavaDoc.class)) && aValue instanceof String JavaDoc) {
271             String JavaDoc aStringValue = (String JavaDoc) aValue;
272             Float JavaDoc aFloat = new Float JavaDoc(Float.parseFloat(aStringValue));
273
274             return aMethod.invoke(aTarget, new Object JavaDoc[] { aFloat });
275           } else if (aParamType.equals(float.class) && aValue instanceof Float JavaDoc) {
276             return aMethod.invoke(aTarget, new Object JavaDoc[] { aValue });
277           }
278           // If the method parameter is a double type
279
else if ((aParamType.equals(double.class) ||
280                 aParamType.equals(Double JavaDoc.class)) && aValue instanceof String JavaDoc) {
281             String JavaDoc aStringValue = (String JavaDoc) aValue;
282             Double JavaDoc aDouble = new Double JavaDoc(Double.parseDouble(aStringValue));
283
284             return aMethod.invoke(aTarget, new Object JavaDoc[] { aDouble });
285           } else if (aParamType.equals(double.class) &&
286                 aValue instanceof Double JavaDoc) {
287             return aMethod.invoke(aTarget, new Object JavaDoc[] { aValue });
288           }
289         }
290       }
291     } catch (NumberFormatException JavaDoc nfe) {
292       String JavaDoc aMessage = "'" + aValue +
293         "' is not a valid numeric value for method '" + aMethodName + "'";
294       throw new ConfigurationException(aMessage, nfe);
295     } catch (IllegalAccessException JavaDoc iae) {
296       String JavaDoc aMessage = "Security error invoking the method '" + aMethodName +
297         "'to assign the value " + aValue + " on the object " + aTarget;
298       throw new ConfigurationException(aMessage, iae);
299     } catch (InvocationTargetException JavaDoc ite) {
300       String JavaDoc aMessage = "Application error invoking the method '" +
301         aMethodName + "'to assign the value " + aValue + " on the object " +
302         aTarget;
303
304       if (ite.getTargetException() == null) {
305         throw new ConfigurationException(aMessage, ite);
306       } else {
307         throw new ConfigurationException(aMessage, ite.getTargetException());
308       }
309     }
310
311     String JavaDoc aMessage = "No method found for the name '" + aMethodName +
312       "' on the object " + aTarget + " - value: " + aValue + " (" +
313       aValue.getClass() + ")";
314     throw new NoSuchMethodException JavaDoc(aMessage);
315   }
316
317   /**
318    * Converts the given attribute name to a method name. The following
319    * indicates how attribute names are converted to method names - the method
320    * name does not include the "set" or "add" prefix. All the following attribute
321    * names are resolved to "FirstName":
322    *
323    * <ul>
324    * <li>firstName
325    * <li>FirstName
326    * <li>first-name
327    * <li>First-name
328    * <li>first-Name
329    * <li>first.name
330    * <li>First.name
331    * <li>first.Name
332    * </ul>
333    */

334   protected static String JavaDoc toMethodName(String JavaDoc attrName) {
335     return convertChars(new char[] { '-', '.' }, attrName);
336   }
337
338   protected static boolean containsMethod(String JavaDoc prefix, Object JavaDoc target,
339     String JavaDoc elemName) {
340     Method JavaDoc[] methods = target.getClass().getMethods();
341     String JavaDoc name = prefix + toMethodName(elemName);
342
343     for (int i = 0; i < methods.length; i++) {
344       if (methods[i].getName().equals(name)) {
345         return true;
346       }
347     }
348     if(target instanceof ObjectWrapperIF){
349       try{
350         Object JavaDoc wrapped = ((ObjectWrapperIF)target).getWrappedObject();
351         if(wrapped != null)
352           return containsMethod(prefix, wrapped, elemName);
353       }catch(RuntimeException JavaDoc e){
354         return false;
355       }
356     }
357
358     return false;
359   }
360
361   /**
362    * Formats an element name according to the rules defined
363    * by the above method.
364    */

365   protected static String JavaDoc formatElementName(String JavaDoc elemName) {
366     return convertChars(new char[] { '-', '.' }, elemName);
367   }
368
369   protected static String JavaDoc convertChars(char[] toConvert, String JavaDoc aSource) {
370     StringBuffer JavaDoc aBuffer = new StringBuffer JavaDoc(aSource.length());
371     char current;
372
373     for (int i = 0; i < aSource.length(); i++) {
374       current = aSource.charAt(i);
375
376       if (isToConvert(toConvert, current)) {
377         if ((i + 1) < (aSource.length() - 1)) {
378           i++;
379           aBuffer.append(Character.toUpperCase(aSource.charAt(i)));
380
381           continue;
382         }
383       }
384
385       if (i == 0) {
386         current = Character.toUpperCase(current);
387       }
388
389       aBuffer.append(current);
390     }
391
392     return aBuffer.toString();
393   }
394
395   private static boolean isToConvert(char[] toConvert, char current) {
396     for (int i = 0; i < toConvert.length; i++) {
397       if (toConvert[i] == current) {
398         return true;
399       }
400     }
401
402     return false;
403   }
404
405   /////////////////////////////////////////////////////////////////////////////////////////
406
////////////////////////////////// ACCESSOR METHODS ///////////////////////////////////
407
/////////////////////////////////////////////////////////////////////////////////////////
408

409   /**
410    * Returns the <code>ObjectFactoryIF</code> method held within this
411    * instance.
412    */

413   protected ObjectFactoryIF getObjectFactory() {
414     return _theObjectFactory;
415   }
416 }
417
Popular Tags