KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > jocl > JOCLContentHandler


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

16
17 package org.apache.commons.jocl;
18
19 import org.xml.sax.*;
20 import org.xml.sax.helpers.*;
21 import java.util.ArrayList JavaDoc;
22 import java.lang.reflect.InvocationTargetException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.Reader JavaDoc;
25 import java.io.File JavaDoc;
26 import java.io.FileInputStream JavaDoc;
27 import java.io.FileNotFoundException JavaDoc;
28 import java.io.IOException JavaDoc;
29
30 // to do:
31
// + add support for arrays
32
// + add support for strings as CDATA (makes multiline strings easier, for example)
33
// ? some kind of support for invoking methods?
34

35 /**
36  * A {@link org.xml.sax.ContentHandler}
37  * for the Java Object Configuration Language.
38  * <p>
39  * JOCL provides an XML syntax for constructing arbitrary Java
40  * {@link java.lang.Object} instances. It does not define a full
41  * XML document type (there's no root element), but rather an
42  * XML fragment describing the {@link java.lang.Object <tt>Object</tt>s} to be
43  * constructed.
44  * <p>
45  * In a JOCL fragment, one may define a series of objects using
46  * the <tt>object</tt> element. A trivial example is:
47  * <pre> &lt;object class="java.util.Date"/&gt;</pre>
48  * which constructs an instance of <tt>java.util.Date</tt>
49  * using the no-argument constructor.
50  * <p>
51  * After a "root-level" <tt>&lt;object&gt;</tt> element has been processed
52  * (that is, once {@link #endElement(java.lang.String,java.lang.String,java.lang.String)}
53  * has been invoked by the {@link XMLReader}), it will be appended to a list of <tt>Object</tt>s
54  * maintained by the <tt>JOCLContentHandler</tt>.
55  * <p>
56  * (See {@link #size},
57  * {@link #clear},
58  * {@link #clear(int)},
59  * {@link #getType(int)},
60  * {@link #getValue(int)},
61  * {@link #getTypeArray},
62  * and
63  * {@link #getValueArray}.)
64  * <p>
65  * You can list multiple <tt>object</tt> elements in a fragment. For example,
66  * after processing the JOCL fragment:
67  * <pre> &lt;object class="java.util.Date"/&gt;
68  * &lt;object class="java.util.Date"/&gt;</pre>
69  * The {@link #getTypeArray} method
70  * will return an composed
71  * of two instances of <tt>java.util.Date</tt>. The sequence of
72  * {@link java.lang.Object <tt>Object</tt>s} in the array
73  * will correspond to the sequence of <tt>&lt;object&gt;</tt> elements in the JOCL fragment.
74  * <p>
75  * As we've seen, when used with no child-elements, the <tt>&lt;object&gt;</tt>
76  * tag will cause the no-argument constructor of the specified class to be invoked.
77  * It is also possible to nest <tt>&lt;object&gt;</tt> tags to provide arguments
78  * for the constructor.
79  * For example, the fragment:
80  * <pre> &lt;object class="mypackage.Foo"&gt;
81  * &lt;object class="mypackage.Bar"/&gt;
82  * &lt;/object&gt;</pre>
83  * will add an instance of <tt>mypackage.Foo</tt> to the object list, constructed via
84  * <tt>new mypackage.Foo(new mypackage.Bar())</tt>.
85  * <p>
86  * There is a special syntax available creating primative values and arguments,
87  * as well as for constructing {@link java.lang.String <tt>String</tt>}s. Some examples:
88  * <p>
89  * <pre> &lt;byte value="3"/&gt;
90  * &lt;boolean value="false"/&gt;
91  * &lt;char value="c"/&gt;
92  * &lt;double value="3.14159"/&gt;
93  * &lt;float value="3.14"/&gt;
94  * &lt;int value="17"/&gt;
95  * &lt;long value="1700000"/&gt;
96  * &lt;short value="1"/&gt;
97  * &lt;string value="The quick brown fox..."/&gt;</pre>
98  * <p>
99  * When invoked at the "root" level (that is, with no <tt>&lt;object&gt;</tt> parent),
100  * this will cause the corresponding "object wrapper" to be added to the list of
101  * {@link java.lang.Object <tt>Object</tt>}s. The {@link #getType type} for these
102  * objects will reflect the proper primative type, however. When invoked with an
103  * <tt>&lt;object&gt;</tt> parent, these will be treated as primitive arguments to the
104  * specified {@link java.lang.Object <tt>Object</tt>}'s constructor. For example, while:
105  * <p>
106  * <pre> &lt;int value="5"/&gt;
107  * &lt;int value="26"/&gt;
108  * &lt;int value="100"/&gt;</pre>
109  * <p>
110  * results in three {@link java.lang.Integer} instances being added to the
111  * list of values, with types corresponding to {@link java.lang.Integer}, the fragment:
112  * <p>
113  * <pre> &lt;int value="5"/&gt;
114  * &lt;int value="26"/&gt;
115  * &lt;int value="100"/&gt;</pre>
116  * <p>
117  * results in three {@link java.lang.Integer} instances being added to the
118  * list of values, with types corresponding to {@link java.lang.Integer#TYPE}.
119  * <p>
120  * Hence if you want to invoke the <tt>mypackage.Foo(java.lang.Integer,java.lang.Integer,java.lang.Integer)</tt>
121  * constructor, use:
122  * <pre> &lt;object class="mypackage.Foo"/&gt;
123  * &lt;object class="java.lang.Integer"&gt;&lt;int value="5"/&gt;&lt;/object&gt;
124  * &lt;object class="java.lang.Integer"&gt;&lt;int value="26"/&gt;&lt;/object&gt;
125  * &lt;object class="java.lang.Integer"&gt;&lt;int value="100"/&gt;&lt;/object&gt;
126  * &lt;/object&gt;</pre>
127  * <p>
128  * If you want to invoke the <tt>mypackage.Foo(int,int,int)</tt>
129  * constructor, use:
130  * <pre> &lt;object class="mypackage.Foo"/&gt;
131  * &lt;int value="5"/&gt;
132  * &lt;int value="26"/&gt;
133  * &lt;int value="100"/&gt;
134  * &lt;/object&gt;</pre>
135  * <p>
136  * If you'd like to creat a <tt>null</tt> object, use:
137  * <pre> &lt;object class="mypackage.Bar" null="true"/&gt;</pre>
138  * <p>
139  * Here's a simple but complete example:
140  * <pre> &lt;?xml version="1.0"?&gt;
141  * &lt;arbitrary-root xmlns="http://apache.org/xml/xmlns/jakarta/commons/jocl"&gt;
142  * &lt;string value="Hello World!"/&gt;
143  * &lt;string/&gt;
144  * &lt;boolean/&gt;
145  * &lt;boolean value="true"/&gt;
146  * &lt;byte value="1"/&gt;
147  * &lt;short value="1"/&gt;
148  * &lt;int value="1"/&gt;
149  * &lt;long value="1"/&gt;
150  * &lt;float value="1.0"/&gt;
151  * &lt;double value="1.0"/&gt;
152  * &lt;object class="java.util.Date"/&gt;
153  * &lt;object class="java.util.Date"&gt;
154  * &lt;int value="1"/&gt;
155  * &lt;int value="1"/&gt;
156  * &lt;int value="1"/&gt;
157  * &lt;/object&gt;
158  * &lt;/arbitrary-root&gt;</pre>
159  * <p>
160  * Formally, a DTD for the JOCL grammar is as follows:
161  * <p>
162  * <pre>
163  * &lt;!ELEMENT object (object|byte|boolean|char|double|float|int|long|short|string)*&gt;
164  * &lt;!ATTLIST object
165  * class CDATA #REQUIRED
166  * null (true|false) "false"&gt;
167  *
168  * &lt;!ELEMENT byte EMPTY&gt;
169  * &lt;!ATTLIST byte value CDATA #REQUIRED&gt;
170  *
171  * &lt;!ELEMENT boolean EMPTY&gt;
172  * &lt;!ATTLIST boolean value (true|false) #REQUIRED&gt;
173  *
174  * &lt;!ELEMENT char EMPTY&gt;
175  * &lt;!ATTLIST char value CDATA #REQUIRED&gt;
176  *
177  * &lt;!ELEMENT double EMPTY&gt;
178  * &lt;!ATTLIST double value CDATA #REQUIRED&gt;
179  *
180  * &lt;!ELEMENT float EMPTY&gt;
181  * &lt;!ATTLIST float value CDATA #REQUIRED&gt;
182  *
183  * &lt;!ELEMENT int EMPTY&gt;
184  * &lt;!ATTLIST int value CDATA #REQUIRED&gt;
185  *
186  * &lt;!ELEMENT long EMPTY&gt;
187  * &lt;!ATTLIST long value CDATA #REQUIRED&gt;
188  *
189  * &lt;!ELEMENT short EMPTY&gt;
190  * &lt;!ATTLIST short value CDATA #REQUIRED&gt;
191  *
192  * &lt;!ELEMENT string EMPTY&gt;
193  * &lt;!ATTLIST string value CDATA #REQUIRED&gt;
194  * </pre>
195  * <p>
196  * This class can also be used as a base class for {@link org.xml.sax.ContentHandler}s
197  * that include JOCL as part of their grammar. Simply extend this class, and override the
198  * {@link #startElement},
199  * {@link #characters},
200  * and {@link #endElement} methods to handle
201  * your tags, and invoke the method of the parent class (i.e., <tt>super.<i>XXX</i></tt> for
202  * elements and data that you don't handle.
203  * <p>
204  * A number of static methods are available for simply reading a list of objects from
205  * a {@link InputStream}, {@link Reader} or {@link InputSource}.
206  * <p>
207  * <b>Note that this class is not synchronized.</b>
208  * <p>
209  * @author Rodney Waldhoff
210  * @version $Revision: 1.6 $ $Date: 2004/02/28 21:37:42 $
211  */

212 public class JOCLContentHandler extends DefaultHandler implements ContentHandler {
213
214     //--- Static Methods ---------------------------------------------
215
/**
216      * A simple tester method. Reads a JOCL document from standard in
217      * and prints a list of the objects created to standard out.
218      * (Use the <tt>org.xml.sax.driver</tt> system property to specify
219      * an {@link XMLReader}.
220      */

221     public static void main(String JavaDoc[] args) throws Exception JavaDoc {
222         JOCLContentHandler jocl = JOCLContentHandler.parse(System.in,null);
223         for(int i=0;i<jocl.size();i++) {
224             System.out.println("<" + jocl.getType(i) + ">\t" + jocl.getValue(i));
225         }
226     }
227
228     /**
229      * Parses a JOCL document from the specified file, using the
230      * {@link XMLReader} specified by the <tt>org.xml.sax.driver</tt>
231      * property.
232      * The returned {@link JOCLContentHandler} will contain the
233      * list of objects described by the file.
234      * @param f a {@link File} containing the JOCL document
235      * @return a {@link JOCLContentHandler} containing the list of objects described by the JOCL document
236      */

237     public static JOCLContentHandler parse(File JavaDoc f) throws SAXException, FileNotFoundException JavaDoc, IOException JavaDoc {
238         return JOCLContentHandler.parse(new FileInputStream JavaDoc(f),null);
239     }
240
241     /**
242      * Parses a JOCL document from the specified {@link Reader}, using the
243      * {@link XMLReader} specified by the <tt>org.xml.sax.driver</tt>
244      * property.
245      * The returned {@link JOCLContentHandler} will contain the
246      * list of objects described by the file.
247      * @param in a {@link Reader} containing the JOCL document
248      * @return a {@link JOCLContentHandler} containing the list of objects described by the JOCL document
249      */

250     public static JOCLContentHandler parse(Reader JavaDoc in) throws SAXException, IOException JavaDoc {
251         return JOCLContentHandler.parse(new InputSource(in),null);
252     }
253
254     /**
255      * Parses a JOCL document from the specified {@link InputStream}, using the
256      * {@link XMLReader} specified by the <tt>org.xml.sax.driver</tt>
257      * property.
258      * The returned {@link JOCLContentHandler} will contain the
259      * list of objects described by the file.
260      * @param in a {@link InputStream} containing the JOCL document
261      * @return a {@link JOCLContentHandler} containing the list of objects described by the JOCL document
262      */

263     public static JOCLContentHandler parse(InputStream JavaDoc in) throws SAXException, IOException JavaDoc {
264         return JOCLContentHandler.parse(new InputSource(in),null);
265     }
266
267     /**
268      * Parses a JOCL document from the specified {@link InputSource}, using thethe
269      * {@link XMLReader} specified by the <tt>org.xml.sax.driver</tt>
270      * property.
271      * The returned {@link JOCLContentHandler} will contain the
272      * list of objects described by the file.
273      * @param in a {@link InputSource} containing the JOCL document
274      * @return a {@link JOCLContentHandler} containing the list of objects described by the JOCL document
275      */

276     public static JOCLContentHandler parse(InputSource in) throws SAXException, IOException JavaDoc {
277         return JOCLContentHandler.parse(in,null);
278     }
279
280     /**
281      * Parses a JOCL document from the specified file, using the
282      * {@link XMLReader} specified by the <tt>org.xml.sax.driver</tt>
283      * property.
284      * The returned {@link JOCLContentHandler} will contain the
285      * list of objects described by the file.
286      * @param f a {@link File} containing the JOCL document
287      * @param reader the {@link XMLReader} to use to parse the file
288      * @return a {@link JOCLContentHandler} containing the list of objects described by the JOCL document
289      */

290     public static JOCLContentHandler parse(File JavaDoc f, XMLReader reader) throws SAXException, FileNotFoundException JavaDoc, IOException JavaDoc {
291         return JOCLContentHandler.parse(new FileInputStream JavaDoc(f),reader);
292     }
293
294     /**
295      * Parses a JOCL document from the specified {@link Reader}, using the specified
296      * {@link XMLReader}.
297      * The returned {@link JOCLContentHandler} will contain the
298      * list of objects described by the file.
299      * @param in a {@link Reader} containing the JOCL document
300      * @param reader the {@link XMLReader} to use to parse the document
301      * @return a {@link JOCLContentHandler} containing the list of objects described by the JOCL document
302      */

303     public static JOCLContentHandler parse(Reader JavaDoc in, XMLReader reader) throws SAXException, IOException JavaDoc {
304         return JOCLContentHandler.parse(new InputSource(in),reader);
305     }
306
307     /**
308      * Parses a JOCL document from the specified {@link InputStream}, using the specified
309      * {@link XMLReader}.
310      * The returned {@link JOCLContentHandler} will contain the
311      * list of objects described by the file.
312      * @param in a {@link InputStream} containing the JOCL document
313      * @param reader the {@link XMLReader} to use to parse the document
314      * @return a {@link JOCLContentHandler} containing the list of objects described by the JOCL document
315      */

316     public static JOCLContentHandler parse(InputStream JavaDoc in, XMLReader reader) throws SAXException, IOException JavaDoc {
317         return JOCLContentHandler.parse(new InputSource(in),reader);
318     }
319
320     /**
321      * Parses a JOCL document from the specified {@link InputSource}, using the
322      * specified {@link XMLReader}.
323      * The returned {@link JOCLContentHandler} will contain the
324      * list of objects described by the file.
325      * @param in a {@link InputSource} containing the JOCL document
326      * @param reader the {@link XMLReader} to use to parse the document
327      * @return a {@link JOCLContentHandler} containing the list of objects described by the JOCL document
328      */

329     public static JOCLContentHandler parse(InputSource in, XMLReader reader) throws SAXException, IOException JavaDoc {
330         JOCLContentHandler jocl = new JOCLContentHandler();
331         if(null == reader) {
332             reader = XMLReaderFactory.createXMLReader();
333         }
334         reader.setContentHandler(jocl);
335         reader.parse(in);
336         return jocl;
337     }
338
339     //--- Construtors ------------------------------------------------
340

341     /**
342      * Equivalent to {@link #JOCLContentHandler(boolean,boolean,boolean,boolean) JOCLContentHandler(true,true,true,true)}.
343      */

344     public JOCLContentHandler() {
345         this(true,true,true,true);
346     }
347
348     /**
349      * Construct a JOCLContentHandler.
350      * @param emtpyEltNs when <tt>true</tt> I should assume any element with an empty namespace is within the JOCL namespace
351      * @param joclEltPrefix when <tt>true</tt> I should assume any element who's prefix is <tt>jocl:</tt> and who's namespace is empty is within the JOCL namespace
352      * @param emptyAttrNS when <tt>true</tt> I should assume any attribute with an empty namespace is within the JOCL namespace
353      * @param joclAttrPrefix when <tt>true</tt> I should assume any attribute who's prefix is <tt>jocl:</tt> and who's namespace is empty is within the JOCL namespace
354      */

355     public JOCLContentHandler(boolean emptyEltNS, boolean joclEltPrefix, boolean emptyAttrNS, boolean joclAttrPrefix) {
356         _acceptEmptyNamespaceForElements = emptyEltNS;
357         _acceptJoclPrefixForElements = joclEltPrefix;
358         _acceptEmptyNamespaceForAttributes = emptyAttrNS;
359         _acceptJoclPrefixForAttributes = joclAttrPrefix;
360     }
361
362     //--- Public Methods - Accessing Objects -------------------------
363

364     /**
365      * Returns the number of values and types in my list.
366      * @return the number of values and types in my list.
367      */

368     public int size() {
369         return _typeList.size();
370     }
371
372     /**
373      * Clears all the values and types in my list.
374      */

375     public void clear() {
376         _typeList = new ArrayList JavaDoc();
377         _valueList = new ArrayList JavaDoc();
378     }
379
380     /**
381      * Removes the value/type pair at the specified index.
382      */

383     public void clear(int i) {
384         _typeList.remove(i);
385         _valueList.remove(i);
386     }
387
388     /**
389      * Returns the type of the object at the specified index.
390      */

391     public Class JavaDoc getType(int i) {
392         return(Class JavaDoc)(_typeList.get(i));
393     }
394
395     /**
396      * Returns the value of the object at the specified index.
397      */

398     public Object JavaDoc getValue(int i) {
399         return _valueList.get(i);
400     }
401
402     /**
403      * Returns a shallow copy of my list of values.
404      */

405     public Object JavaDoc[] getValueArray() {
406         return _valueList.toArray();
407     }
408
409     /**
410      * Returns a shallow copy of my list of types.
411      */

412     public Object JavaDoc[] getTypeArray() {
413         return _typeList.toArray();
414     }
415
416     //--- Public Methods - DocumentHandler ---------------------------
417

418     public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qname, Attributes attr) throws SAXException {
419         try {
420             if(isJoclNamespace(uri,localName,qname)) {
421                 if(ELT_OBJECT.equals(localName)) {
422                     String JavaDoc cname = getAttributeValue(ATT_CLASS,attr);
423                     String JavaDoc isnullstr = getAttributeValue(ATT_ISNULL,attr,"false");
424                     boolean isnull = ("true".equalsIgnoreCase(isnullstr) || "yes".equalsIgnoreCase(isnullstr));
425                     _cur = new ConstructorDetails(cname,_cur,isnull);
426                 } else if(ELT_BOOLEAN.equals(localName)) {
427                     String JavaDoc valstr = getAttributeValue(ATT_VALUE,attr,"false");
428                     boolean val = ("true".equalsIgnoreCase(valstr) || "yes".equalsIgnoreCase(valstr));
429                     addObject(Boolean.TYPE,new Boolean JavaDoc(val));
430                 } else if(ELT_BYTE.equals(localName)) {
431                     byte val = Byte.parseByte(getAttributeValue(ATT_VALUE,attr,"0"));
432                     addObject(Byte.TYPE,new Byte JavaDoc(val));
433                 } else if(ELT_CHAR.equals(localName)) {
434                     char val = '\u0000';
435                     String JavaDoc valstr = getAttributeValue(ATT_VALUE,attr);
436                     if(null == valstr) {
437                         val = '\u0000';
438                     } else if(valstr.length() > 1) {
439                         throw new SAXException("if present, char value must be exactly one character long");
440                     } else if(valstr.length()==1) {
441                         val = valstr.charAt(0);
442                     } else if(valstr.length()==0) {
443                         throw new SAXException("if present, char value must be exactly one character long");
444                     }
445                     addObject(Character.TYPE,new Character JavaDoc(val));
446                 } else if(ELT_DOUBLE.equals(localName)) {
447                     double val = Double.parseDouble(getAttributeValue(ATT_VALUE,attr,"0"));
448                     addObject(Double.TYPE,new Double JavaDoc(val));
449                 } else if(ELT_FLOAT.equals(localName)) {
450                     float val = Float.parseFloat(getAttributeValue(ATT_VALUE,attr,"0"));
451                     addObject(Float.TYPE,new Float JavaDoc(val));
452                 } else if(ELT_INT.equals(localName)) {
453                     int val = Integer.parseInt(getAttributeValue(ATT_VALUE,attr,"0"));
454                     addObject(Integer.TYPE,new Integer JavaDoc(val));
455                 } else if(ELT_LONG.equals(localName)) {
456                     long val = Long.parseLong(getAttributeValue(ATT_VALUE,attr,"0"));
457                     addObject(Long.TYPE,new Long JavaDoc(val));
458                 } else if(ELT_SHORT.equals(localName)) {
459                     short val = Short.parseShort(getAttributeValue(ATT_VALUE,attr,"0"));
460                     addObject(Short.TYPE,new Short JavaDoc(val));
461                 } else if(ELT_STRING.equals(localName)) {
462                     String JavaDoc val = getAttributeValue(ATT_VALUE,attr);
463                     addObject("".getClass(),val);
464                 } else {
465                     // unrecognized JOCL element warning?
466
}
467             }
468         } catch(Exception JavaDoc e) {
469             throw new SAXException(e);
470         }
471     }
472
473     public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qname) throws SAXException {
474         try {
475             if(isJoclNamespace(uri,localName,qname)) {
476                 if(ELT_OBJECT.equals(localName)) {
477                     ConstructorDetails temp = _cur;
478                     _cur = _cur.getParent();
479                     if(null == _cur) {
480                         _typeList.add(temp.getType());
481                         _valueList.add(temp.createObject());
482                     } else {
483                         _cur.addArgument(temp.getType(),temp.createObject());
484                     }
485                 } else if(ELT_BOOLEAN.equals(localName)) {
486                     // nothing to do here
487
} else if(ELT_BYTE.equals(localName)) {
488                     // nothing to do here
489
} else if(ELT_CHAR.equals(localName)) {
490                     // nothing to do here
491
} else if(ELT_DOUBLE.equals(localName)) {
492                     // nothing to do here
493
} else if(ELT_FLOAT.equals(localName)) {
494                     // nothing to do here
495
} else if(ELT_INT.equals(localName)) {
496                     // nothing to do here
497
} else if(ELT_LONG.equals(localName)) {
498                     // nothing to do here
499
} else if(ELT_SHORT.equals(localName)) {
500                     // nothing to do here
501
} else if(ELT_STRING.equals(localName)) {
502                     // nothing to do here
503
} else {
504                     // unrecognized JOCL element warning?
505
}
506             }
507         } catch(Exception JavaDoc e) {
508             throw new SAXException(e);
509         }
510     }
511
512     public void setDocumentLocator(Locator locator) {
513         _locator = locator;
514     }
515
516     //--- Protected Methods ------------------------------------------
517

518     /**
519      * Returns <tt>true</tt> if the given attributes define an
520      * element within the JOCL namespace (according to my current
521      * configuration.)
522      *
523      * @see #_acceptEmptyNamespaceForElements
524      * @see #_acceptJoclPrefixForElements
525      */

526     protected boolean isJoclNamespace(String JavaDoc uri, String JavaDoc localname, String JavaDoc qname) {
527         if(JOCL_NAMESPACE_URI.equals(uri)) {
528             return true;
529         } else if(_acceptEmptyNamespaceForElements && (null == uri || "".equals(uri))) {
530             return true;
531         } else if(_acceptJoclPrefixForElements && (null == uri || "".equals(uri)) && qname.startsWith(JOCL_PREFIX)) {
532             return true;
533         } else {
534             return false;
535         }
536     }
537
538     /**
539      * Equivalent to {@link #getAttributeValue(java.lang.String,org.xml.sax.Attributes,java.lang.String) <tt>getAttributeValue(localname,attr,null)</tt>}.
540      */

541     protected String JavaDoc getAttributeValue(String JavaDoc localname, Attributes attr) {
542         return getAttributeValue(localname,attr,null);
543     }
544
545     /**
546      * Returns the value of attribute with the given
547      * <tt><i>localname</i></tt> within the JOCL
548      * namespace from the given set of {@link Attributes}.
549      * If no such attribute can be found, returns
550      * <tt><i>implied</i></tt>.
551      *
552      * @param localname the unqualified name of the attribute to look for
553      * @param attr the Attributes in which to find the value
554      * @param implied the default value for the attribute
555      * @return the value of attribute with the given
556      * <tt><i>localname</i></tt> within the JOCL
557      * namespace from the given set of {@link Attributes}.
558      * If no such attribute can be found, returns
559      * <tt><i>implied</i></tt>.
560      */

561     protected String JavaDoc getAttributeValue(String JavaDoc localname, Attributes attr, String JavaDoc implied) {
562         String JavaDoc val = attr.getValue(JOCL_NAMESPACE_URI,localname);
563         if(null == val && _acceptEmptyNamespaceForAttributes) {
564             val = attr.getValue("",localname);
565         }
566         if(null == val && _acceptJoclPrefixForAttributes) {
567             val = attr.getValue("",JOCL_PREFIX + localname);
568         }
569         return(null == val ? implied : val);
570     }
571
572     /**
573      * Add the specified object either to my type/value list, or
574      * as an argument to the object I'm currently constructing.
575      */

576     protected void addObject(Class JavaDoc type, Object JavaDoc val) {
577         if(null == _cur) {
578             _typeList.add(type);
579             _valueList.add(val);
580         } else {
581             _cur.addArgument(type,val);
582         }
583     }
584
585     //--- Protected Attributes ---------------------------------------
586

587     /**
588      * The JOCL namespace URI, <tt>http://apache.org/xml/xmlns/jakarta/commons/jocl</tt>.
589      */

590     public static final String JavaDoc JOCL_NAMESPACE_URI = "http://apache.org/xml/xmlns/jakarta/commons/jocl";
591
592     /**
593      * The default JOCL prefix, <tt>jocl:</tt>.
594      */

595     public static final String JavaDoc JOCL_PREFIX = "jocl:";
596
597     /**
598      * A list of the types ({@link Class}es) already created via the parse.
599      */

600     protected ArrayList JavaDoc _typeList = new ArrayList JavaDoc();
601
602     /**
603      * A list of the values ({@link Object}s) already created via the parse.
604      */

605     protected ArrayList JavaDoc _valueList = new ArrayList JavaDoc();
606
607     /**
608      * The object I'm currently working on.
609      */

610     protected ConstructorDetails _cur = null;
611
612     /**
613      * When <tt>true</tt>, I will treat elements with an
614      * empty namespace URI as part of the JOCL namespace.
615      *
616      * @see #JOCL_NAMESPACE_URI
617      */

618     protected boolean _acceptEmptyNamespaceForElements = true;
619
620     /**
621      * When <tt>true</tt>, I will treat elements with the
622      * {@link #JOCL_PREFIX} but no namespace URI as being
623      * mapped to the jocl namespace.
624      *
625      * @see #JOCL_PREFIX
626      * @see #JOCL_NAMESPACE_URI
627      */

628     protected boolean _acceptJoclPrefixForElements = true;
629
630     /**
631      * When <tt>true</tt>, I will treat attributes with an
632      * empty namespace URI as part of the JOCL namespace.
633      *
634      * @see #JOCL_NAMESPACE_URI
635      */

636     protected boolean _acceptEmptyNamespaceForAttributes = true;
637
638     /**
639      * When <tt>true</tt>, I will treat attributes with the
640      * {@link #JOCL_PREFIX} but no namespace URI as being
641      * mapped to the jocl namespace.
642      *
643      * @see #JOCL_PREFIX
644      * @see #JOCL_NAMESPACE_URI
645      */

646     protected boolean _acceptJoclPrefixForAttributes = true;
647
648     /** My {@link Locator}. */
649     protected Locator _locator = null;
650
651     /** The name of the "object" element. */
652     protected static final String JavaDoc ELT_OBJECT = "object";
653
654     /** The name of the "object" element's "class" attribute. */
655     protected static final String JavaDoc ATT_CLASS = "class";
656
657     /** The name of the "object" element's "isnull" attribute. */
658     protected static final String JavaDoc ATT_ISNULL = "null";
659
660     /** The name of the "boolean" element. */
661     protected static final String JavaDoc ELT_BOOLEAN = "boolean";
662
663     /** The name of the "byte" element. */
664     protected static final String JavaDoc ELT_BYTE = "byte";
665
666     /** The name of the "char" element. */
667     protected static final String JavaDoc ELT_CHAR = "char";
668
669     /** The name of the "double" element. */
670     protected static final String JavaDoc ELT_DOUBLE = "double";
671
672     /** The name of the "float" element. */
673     protected static final String JavaDoc ELT_FLOAT = "float";
674
675     /** The name of the "int" element. */
676     protected static final String JavaDoc ELT_INT = "int";
677
678     /** The name of the "long" element. */
679     protected static final String JavaDoc ELT_LONG = "long";
680
681     /** The name of the "short" element. */
682     protected static final String JavaDoc ELT_SHORT = "short";
683
684     /** The name of the "string" element. */
685     protected static final String JavaDoc ELT_STRING = "string";
686
687     /** The name of the "value" attribute. */
688     protected static final String JavaDoc ATT_VALUE = "value";
689
690     class ConstructorDetails {
691         private ConstructorDetails _parent = null;
692         private Class JavaDoc _type = null;
693         private ArrayList JavaDoc _argTypes = null;
694         private ArrayList JavaDoc _argValues = null;
695         private boolean _isnull = false;
696
697         public ConstructorDetails(String JavaDoc classname, ConstructorDetails parent) throws ClassNotFoundException JavaDoc {
698             this(Class.forName(classname),parent,false);
699         }
700
701         public ConstructorDetails(String JavaDoc classname, ConstructorDetails parent, boolean isnull) throws ClassNotFoundException JavaDoc {
702             this(Class.forName(classname),parent,isnull);
703         }
704
705         public ConstructorDetails(Class JavaDoc type, ConstructorDetails parent, boolean isnull) {
706             _parent = parent;
707             _type = type;
708             _argTypes = new ArrayList JavaDoc();
709             _argValues = new ArrayList JavaDoc();
710             _isnull = isnull;
711         }
712
713         public void addArgument(Object JavaDoc value) {
714             addArgument(value.getClass(),value);
715         }
716
717         public void addArgument(Class JavaDoc type, Object JavaDoc val) {
718             if(_isnull) {
719                 throw new NullPointerException JavaDoc("can't add arguments to null instances");
720             }
721             _argTypes.add(type);
722             _argValues.add(val);
723         }
724
725         public Class JavaDoc getType() {
726             return _type;
727         }
728
729         public ConstructorDetails getParent() {
730             return _parent;
731         }
732
733         public Object JavaDoc createObject() throws InstantiationException JavaDoc, ClassNotFoundException JavaDoc, IllegalAccessException JavaDoc, InvocationTargetException JavaDoc {
734             if(_isnull) {
735                 return null;
736             } else {
737                 Class JavaDoc k = getType();
738                 Class JavaDoc[] argtypes = (Class JavaDoc[])_argTypes.toArray(new Class JavaDoc[0]);
739                 Object JavaDoc[] argvals = _argValues.toArray();
740                 return ConstructorUtil.invokeConstructor(k,argtypes,argvals);
741             }
742         }
743     }
744
745 }
746
Popular Tags