KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > test > xml > XMLReflect


1 /*
2
3    Copyright 2001-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.test.xml;
19
20 import java.lang.reflect.Constructor JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.util.Vector JavaDoc;
23
24 import org.w3c.dom.Element JavaDoc;
25 import org.w3c.dom.Node JavaDoc;
26 import org.w3c.dom.NodeList JavaDoc;
27
28 /**
29  * This helper class can be used to build Java object from their
30  * XML description.
31  *
32  * @author <a HREF="mailto:vhardy@apache.org">Vincent Hardy</a>
33  * @version $Id: XMLReflect.java,v 1.12 2004/08/18 07:17:06 vhardy Exp $
34  */

35 public class XMLReflect implements XMLReflectConstants{
36     /**
37      * An error happened while trying to construct a test. No constructor
38      * matching the list of arguments could be found
39      * {0} : The test's class name
40      * {1} : The list of argument types for which no constructor was found
41      */

42     public static final String JavaDoc NO_MATCHING_CONSTRUCTOR
43         = "xml.XMLReflect.error.no.matching.constructor";
44
45     /**
46      * Implementation helper: builds a generic object
47      */

48     public static Object JavaDoc buildObject(Element JavaDoc element) throws Exception JavaDoc {
49
50         Element JavaDoc classDefiningElement =
51             getClassDefiningElement(element);
52
53         String JavaDoc className
54             = classDefiningElement.getAttribute(XR_CLASS_ATTRIBUTE);
55
56         Class JavaDoc cl = Class.forName(className);
57         Object JavaDoc[] argsArray = null;
58         Class JavaDoc[] argsClasses = null;
59
60         NodeList JavaDoc children = element.getChildNodes();
61         if(children != null && children.getLength() > 0){
62             int n = children.getLength();
63             Vector JavaDoc args = new Vector JavaDoc();
64             for(int i=0; i<n; i++){
65                 Node JavaDoc child = children.item(i);
66                 if(child.getNodeType() == Node.ELEMENT_NODE){
67                     Element JavaDoc childElement = (Element JavaDoc)child;
68                     String JavaDoc tagName = childElement.getTagName().intern();
69                     if(tagName == XR_ARG_TAG){
70                         Object JavaDoc arg = buildArgument(childElement);
71                         args.addElement(arg);
72                     }
73                 }
74             }
75
76             if(args.size() > 0){
77                 argsArray = new Object JavaDoc[args.size()];
78                 args.copyInto(argsArray);
79
80                 argsClasses = new Class JavaDoc[args.size()];
81
82                 for(int i=0; i<args.size(); i++){
83                     argsClasses[i] = argsArray[i].getClass();
84                 }
85             }
86         }
87
88         Constructor JavaDoc constructor
89             = getDeclaredConstructor(cl, argsClasses);
90
91         if (constructor == null) {
92             String JavaDoc argsClassesStr = "null";
93             if (argsClasses != null) {
94                 argsClassesStr = "";
95                 for (int i=0; i<argsClasses.length; i++) {
96                     argsClassesStr += argsClasses[i].getName() + " / ";
97                 }
98             }
99             throw new Exception JavaDoc(Messages.formatMessage(NO_MATCHING_CONSTRUCTOR,
100                                                        new Object JavaDoc[] { className,
101                                                                       argsClassesStr }));
102         }
103         return configureObject(constructor.newInstance(argsArray),
104                                element, classDefiningElement);
105     }
106
107     /**
108      * Implementation helper: configures a generic object
109      */

110     public static Object JavaDoc configureObject(Object JavaDoc obj,
111                                          Element JavaDoc element,
112                                          Element JavaDoc classDefiningElement) throws Exception JavaDoc {
113         // First, build a vector of elements from the child element
114
// to the classDefiningElement so that we can go from the
115
// top (classDefiningElement) to the child and apply properties
116
// as we iterate
117
Vector JavaDoc v = new Vector JavaDoc();
118         v.addElement(element);
119         while (element != classDefiningElement) {
120             element = (Element JavaDoc) element.getParentNode();
121             v.addElement(element);
122         }
123
124         int ne = v.size();
125         for (int j=ne-1; j>=0; j--) {
126             element = (Element JavaDoc)v.elementAt(j);
127             NodeList JavaDoc children = element.getChildNodes();
128             if(children != null && children.getLength() > 0){
129                 int n = children.getLength();
130                 for(int i=0; i<n; i++){
131                     Node JavaDoc child = children.item(i);
132                     if(child.getNodeType() == Node.ELEMENT_NODE){
133                         Element JavaDoc childElement = (Element JavaDoc)child;
134                         String JavaDoc tagName = childElement.getTagName().intern();
135                         if(tagName == XR_PROPERTY_TAG){
136                             Object JavaDoc arg = buildArgument(childElement);
137                             String JavaDoc propertyName
138                                 = childElement.getAttribute(XR_NAME_ATTRIBUTE);
139                             setObjectProperty(obj, propertyName, arg);
140                         }
141                     }
142                 }
143                 
144             }
145         }
146
147         return obj;
148     }
149
150     /**
151      * Sets the property with given name on object to the input value
152      */

153     public static void setObjectProperty(Object JavaDoc obj,
154                                          String JavaDoc propertyName,
155                                          Object JavaDoc propertyValue)
156         throws Exception JavaDoc {
157         Class JavaDoc cl = obj.getClass();
158         Method JavaDoc m = null;
159         try {
160             m = cl.getMethod("set" + propertyName,
161                              new Class JavaDoc[]{propertyValue.getClass()});
162             
163         } catch (NoSuchMethodException JavaDoc e) {
164             //
165
// Check if the type was one of the primitive types, Double,
166
// Float, Boolean or Integer
167
//
168
Class JavaDoc propertyClass = propertyValue.getClass();
169             try {
170                 if (propertyClass == java.lang.Double JavaDoc.class) {
171                     m = cl.getMethod("set" + propertyName,
172                                      new Class JavaDoc[] {java.lang.Double.TYPE});
173                 } else if (propertyClass == java.lang.Float JavaDoc.class) {
174                     m = cl.getMethod("set" + propertyName,
175                                      new Class JavaDoc[] {java.lang.Float.TYPE});
176                 } else if (propertyClass == java.lang.Integer JavaDoc.class) {
177                     m = cl.getMethod("set" + propertyName,
178                                      new Class JavaDoc[] {java.lang.Integer.TYPE});
179                 } else if (propertyClass == java.lang.Boolean JavaDoc.class) {
180                     m = cl.getMethod("set" + propertyName,
181                                      new Class JavaDoc[] {java.lang.Boolean.TYPE});
182                 } else {
183                     System.err.println("Could not find a set method for property : " + propertyName
184                                        + " with value " + propertyValue + " and class " + propertyValue.getClass().getName());
185                     throw e;
186                 }
187             } catch (NoSuchMethodException JavaDoc nsme) {
188                 throw nsme;
189             }
190         }
191         if(m != null){
192             m.invoke(obj, new Object JavaDoc[]{propertyValue});
193         }
194     }
195
196
197     /**
198      * Returns a constructor that has can be used for the input class
199      * types.
200      */

201     public static Constructor JavaDoc getDeclaredConstructor(Class JavaDoc cl,
202                                                  Class JavaDoc[] argClasses){
203         Constructor JavaDoc[] cs = cl.getDeclaredConstructors();
204         for(int i=0; i<cs.length; i++){
205             Class JavaDoc[] reqArgClasses = cs[i].getParameterTypes();
206             if(reqArgClasses != null && reqArgClasses.length > 0){
207                 if(reqArgClasses.length == argClasses.length){
208                     int j=0;
209                     for(; j<argClasses.length; j++){
210                         if(!reqArgClasses[j].isAssignableFrom(argClasses[j])){
211                             break;
212                         }
213                     }
214                     if(j == argClasses.length){
215                         return cs[i];
216                     }
217                 }
218             }
219             else{
220                 if(argClasses == null || argClasses.length == 0){
221                     return cs[i];
222                 }
223             }
224         }
225
226         return null;
227     }
228
229     /**
230      * Limitation: Arguments *must* have a String based
231      * constructor. Or be an object that takes a set of string
232      * based arguments.
233      */

234     public static Object JavaDoc buildArgument(Element JavaDoc element) throws Exception JavaDoc {
235         if(!element.hasChildNodes()){
236             Element JavaDoc classDefiningElement =
237                 getClassDefiningElement(element);
238
239             String JavaDoc classAttr = classDefiningElement.getAttribute(XR_CLASS_ATTRIBUTE);
240
241             // String based argument
242
Class JavaDoc cl = Class.forName(classAttr);
243
244             if(element.hasAttribute(XR_VALUE_ATTRIBUTE)){
245                 String JavaDoc value = element.getAttribute(XR_VALUE_ATTRIBUTE);
246
247
248                 Constructor JavaDoc constructor
249                     = cl.getDeclaredConstructor(new Class JavaDoc[] { String JavaDoc.class });
250
251                 return constructor.newInstance(new Object JavaDoc[] {value});
252             }
253             else{
254                 // Default constructor
255
return cl.newInstance();
256             }
257         }
258         else{
259             return buildObject(element);
260         }
261     }
262
263     /**
264      * Gets the defining class element
265      */

266     public static Element JavaDoc getClassDefiningElement(Element JavaDoc element) {
267         if(element != null){
268             String JavaDoc classAttr = element.getAttribute(XR_CLASS_ATTRIBUTE);
269
270             if(classAttr == null || "".equals(classAttr)){
271                 Node JavaDoc parent = element.getParentNode();
272                 if(parent != null && parent.getNodeType() == Node.ELEMENT_NODE){
273                     return getClassDefiningElement((Element JavaDoc)parent);
274                 }
275                 else{
276                     return null;
277                 }
278             }
279             
280             return element;
281
282         }
283
284         return null;
285     }
286 }
287
Popular Tags