KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > xml > parser > RootXmlReadHandler


1 /* ========================================================================
2  * JCommon : a free general purpose class library for the Java(tm) platform
3  * ========================================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jcommon/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * -----------------------
28  * RootXmlReadHandler.java
29  * -----------------------
30  * (C)opyright 2003, 2004, by Thomas Morgner and Contributors.
31  *
32  * Original Author: Thomas Morgner;
33  * Contributor(s): David Gilbert (for Object Refinery Limited);
34  *
35  * $Id: RootXmlReadHandler.java,v 1.8 2005/10/18 13:32:52 mungady Exp $
36  *
37  * Changes (from 25-Nov-2003)
38  * --------------------------
39  * 25-Nov-2003 : Added Javadocs (DG);
40  * 22-Feb-2005 : Fixed a bug when ending nested tags with the same tagname.
41  */

42 package org.jfree.xml.parser;
43
44 import java.awt.BasicStroke JavaDoc;
45 import java.awt.Color JavaDoc;
46 import java.awt.Font JavaDoc;
47 import java.awt.GradientPaint JavaDoc;
48 import java.awt.Insets JavaDoc;
49 import java.awt.Paint JavaDoc;
50 import java.awt.RenderingHints JavaDoc;
51 import java.awt.Stroke JavaDoc;
52 import java.awt.geom.Point2D JavaDoc;
53 import java.awt.geom.Rectangle2D JavaDoc;
54 import java.util.ArrayList JavaDoc;
55 import java.util.HashMap JavaDoc;
56 import java.util.LinkedList JavaDoc;
57 import java.util.List JavaDoc;
58 import java.util.Stack JavaDoc;
59 import java.util.Vector JavaDoc;
60
61 import org.jfree.util.ObjectUtilities;
62 import org.jfree.xml.FrontendDefaultHandler;
63 import org.jfree.xml.ParseException;
64 import org.jfree.xml.ElementDefinitionException;
65 import org.jfree.xml.parser.coretypes.BasicStrokeReadHandler;
66 import org.jfree.xml.parser.coretypes.ColorReadHandler;
67 import org.jfree.xml.parser.coretypes.FontReadHandler;
68 import org.jfree.xml.parser.coretypes.GenericReadHandler;
69 import org.jfree.xml.parser.coretypes.GradientPaintReadHandler;
70 import org.jfree.xml.parser.coretypes.InsetsReadHandler;
71 import org.jfree.xml.parser.coretypes.ListReadHandler;
72 import org.jfree.xml.parser.coretypes.Point2DReadHandler;
73 import org.jfree.xml.parser.coretypes.Rectangle2DReadHandler;
74 import org.jfree.xml.parser.coretypes.RenderingHintsReadHandler;
75 import org.jfree.xml.parser.coretypes.StringReadHandler;
76 import org.jfree.xml.util.ManualMappingDefinition;
77 import org.jfree.xml.util.MultiplexMappingDefinition;
78 import org.jfree.xml.util.MultiplexMappingEntry;
79 import org.jfree.xml.util.ObjectFactory;
80 import org.jfree.xml.util.SimpleObjectFactory;
81 import org.xml.sax.Attributes JavaDoc;
82 import org.xml.sax.SAXException JavaDoc;
83
84 /**
85  * A base root SAX handler.
86  */

87 public abstract class RootXmlReadHandler extends FrontendDefaultHandler {
88
89     /** The current handlers. */
90     private Stack JavaDoc currentHandlers;
91
92     /** ??. */
93     private Stack JavaDoc outerScopes;
94
95     /** The root handler. */
96     private XmlReadHandler rootHandler;
97
98     /** The object registry. */
99     private HashMap JavaDoc objectRegistry;
100
101     /** Maps classes to handlers. */
102     private SimpleObjectFactory classToHandlerMapping;
103
104     private boolean rootHandlerInitialized;
105
106     /**
107      * Creates a new root SAX handler.
108      */

109     public RootXmlReadHandler() {
110         this.objectRegistry = new HashMap JavaDoc();
111         this.classToHandlerMapping = new SimpleObjectFactory();
112     }
113
114     protected void addDefaultMappings () {
115
116         final MultiplexMappingEntry[] paintEntries = new MultiplexMappingEntry[2];
117         paintEntries[0] = new MultiplexMappingEntry("color", Color JavaDoc.class.getName());
118         paintEntries[1] = new MultiplexMappingEntry("gradientPaint", GradientPaint JavaDoc.class.getName());
119         addMultiplexMapping(Paint JavaDoc.class, "type", paintEntries);
120         addManualMapping(Color JavaDoc.class, ColorReadHandler.class);
121         addManualMapping(GradientPaint JavaDoc.class, GradientPaintReadHandler.class);
122
123         final MultiplexMappingEntry[] point2DEntries = new MultiplexMappingEntry[2];
124         point2DEntries[0] = new MultiplexMappingEntry("float", Point2D.Float JavaDoc.class.getName());
125         point2DEntries[1] = new MultiplexMappingEntry("double", Point2D.Double JavaDoc.class.getName());
126         addMultiplexMapping(Point2D JavaDoc.class, "type", point2DEntries);
127         addManualMapping(Point2D.Float JavaDoc.class, Point2DReadHandler.class);
128         addManualMapping(Point2D.Double JavaDoc.class, Point2DReadHandler.class);
129
130         final MultiplexMappingEntry[] rectangle2DEntries = new MultiplexMappingEntry[2];
131         rectangle2DEntries[0] = new MultiplexMappingEntry(
132             "float", Rectangle2D.Float JavaDoc.class.getName()
133         );
134         rectangle2DEntries[1] = new MultiplexMappingEntry(
135             "double", Rectangle2D.Double JavaDoc.class.getName()
136         );
137         addMultiplexMapping(Rectangle2D JavaDoc.class, "type", rectangle2DEntries);
138         addManualMapping(Rectangle2D.Float JavaDoc.class, Rectangle2DReadHandler.class);
139         addManualMapping(Rectangle2D.Double JavaDoc.class, Rectangle2DReadHandler.class);
140
141         // Handle list types
142
final MultiplexMappingEntry[] listEntries = new MultiplexMappingEntry[4];
143         listEntries[0] = new MultiplexMappingEntry("array-list", ArrayList JavaDoc.class.getName());
144         listEntries[1] = new MultiplexMappingEntry("linked-list", LinkedList JavaDoc.class.getName());
145         listEntries[2] = new MultiplexMappingEntry("vector", Vector JavaDoc.class.getName());
146         listEntries[3] = new MultiplexMappingEntry("stack", Stack JavaDoc.class.getName());
147         addMultiplexMapping(List JavaDoc.class, "type", listEntries);
148         addManualMapping(LinkedList JavaDoc.class, ListReadHandler.class);
149         addManualMapping(Vector JavaDoc.class, ListReadHandler.class);
150         addManualMapping(ArrayList JavaDoc.class, ListReadHandler.class);
151         addManualMapping(Stack JavaDoc.class, ListReadHandler.class);
152
153         final MultiplexMappingEntry[] strokeEntries = new MultiplexMappingEntry[1];
154         strokeEntries[0] = new MultiplexMappingEntry("basic", BasicStroke JavaDoc.class.getName());
155         addMultiplexMapping(Stroke JavaDoc.class, "type", strokeEntries);
156         addManualMapping(BasicStroke JavaDoc.class, BasicStrokeReadHandler.class);
157
158         addManualMapping(Font JavaDoc.class, FontReadHandler.class);
159         addManualMapping(Insets JavaDoc.class, InsetsReadHandler.class);
160         addManualMapping(RenderingHints JavaDoc.class, RenderingHintsReadHandler.class);
161         addManualMapping(String JavaDoc.class, StringReadHandler.class);
162     }
163
164     /**
165      * Returns the object factory.
166      *
167      * @return The object factory.
168      */

169     public abstract ObjectFactory getFactoryLoader();
170
171     /**
172      * Adds a mapping between a class and the handler for the class.
173      *
174      * @param classToRead the class.
175      * @param handler the handler class.
176      */

177     protected void addManualMapping(final Class JavaDoc classToRead, final Class JavaDoc handler) {
178         if (handler == null) {
179             throw new NullPointerException JavaDoc("handler must not be null.");
180         }
181         if (classToRead == null) {
182             throw new NullPointerException JavaDoc("classToRead must not be null.");
183         }
184         if (!XmlReadHandler.class.isAssignableFrom(handler)) {
185             throw new IllegalArgumentException JavaDoc("The given handler is no XmlReadHandler.");
186         }
187         this.classToHandlerMapping.addManualMapping
188             (new ManualMappingDefinition(classToRead, handler.getName(), null));
189     }
190
191     /**
192      * Adds a multiplex mapping.
193      *
194      * @param baseClass the base class.
195      * @param typeAttr the type attribute.
196      * @param mdef the mapping entry.
197      */

198     protected void addMultiplexMapping(final Class JavaDoc baseClass,
199                                        final String JavaDoc typeAttr,
200                                        final MultiplexMappingEntry[] mdef) {
201         
202         this.classToHandlerMapping.addMultiplexMapping(
203             new MultiplexMappingDefinition(baseClass, typeAttr, mdef)
204         );
205     }
206
207     /**
208      * Adds an object to the registry.
209      *
210      * @param key the key.
211      * @param value the object.
212      */

213     public void setHelperObject(final String JavaDoc key, final Object JavaDoc value) {
214         if (value == null) {
215             this.objectRegistry.remove(key);
216         }
217         else {
218             this.objectRegistry.put(key, value);
219         }
220     }
221
222     /**
223      * Returns an object from the registry.
224      *
225      * @param key the key.
226      *
227      * @return The object.
228      */

229     public Object JavaDoc getHelperObject(final String JavaDoc key) {
230         return this.objectRegistry.get(key);
231     }
232
233     /**
234      * Creates a SAX handler for the specified class.
235      *
236      * @param classToRead the class.
237      * @param tagName the tag name.
238      * @param atts the attributes.
239      *
240      * @return a SAX handler.
241      *
242      * @throws XmlReaderException if there is a problem with the reader.
243      */

244     public XmlReadHandler createHandler(final Class JavaDoc classToRead, final String JavaDoc tagName, final Attributes JavaDoc atts)
245         throws XmlReaderException {
246
247         final XmlReadHandler retval = findHandlerForClass(classToRead, atts, new ArrayList JavaDoc());
248         if (retval == null) {
249             throw new NullPointerException JavaDoc("Unable to find handler for class: " + classToRead);
250         }
251         retval.init(this, tagName);
252         return retval;
253     }
254
255     /**
256      * Finds a handler for the specified class.
257      *
258      * @param classToRead the class to be read.
259      * @param atts the attributes.
260      * @param history the history.
261      *
262      * @return A handler for the specified class.
263      *
264      * @throws XmlReaderException if there is a problem with the reader.
265      */

266     private XmlReadHandler findHandlerForClass(final Class JavaDoc classToRead, final Attributes JavaDoc atts,
267                                                final ArrayList JavaDoc history)
268         throws XmlReaderException {
269         final ObjectFactory genericFactory = getFactoryLoader();
270
271         if (history.contains(classToRead)) {
272             throw new IllegalStateException JavaDoc("Circular reference detected: " + history);
273         }
274         history.add(classToRead);
275         // check the manual mappings ...
276
ManualMappingDefinition manualDefinition =
277             this.classToHandlerMapping.getManualMappingDefinition(classToRead);
278         if (manualDefinition == null) {
279             manualDefinition = genericFactory.getManualMappingDefinition(classToRead);
280         }
281         if (manualDefinition != null) {
282             // Log.debug ("Locating handler for " + manualDefinition.getBaseClass());
283
return loadHandlerClass(manualDefinition.getReadHandler());
284         }
285
286         // check whether a multiplexer is defined ...
287
// find multiplexer for this class...
288
MultiplexMappingDefinition mplex =
289             getFactoryLoader().getMultiplexDefinition(classToRead);
290         if (mplex == null) {
291             mplex = this.classToHandlerMapping.getMultiplexDefinition(classToRead);
292         }
293         if (mplex != null) {
294             final String JavaDoc attributeValue = atts.getValue(mplex.getAttributeName());
295             if (attributeValue == null) {
296                 throw new XmlReaderException(
297                     "Multiplexer type attribute is not defined: " + mplex.getAttributeName()
298                     + " for " + classToRead
299                 );
300             }
301             final MultiplexMappingEntry entry =
302                 mplex.getEntryForType(attributeValue);
303             if (entry == null) {
304                 throw new XmlReaderException(
305                     "Invalid type attribute value: " + mplex.getAttributeName() + " = "
306                     + attributeValue
307                 );
308             }
309             final Class JavaDoc c = loadClass(entry.getTargetClass());
310             if (!c.equals(mplex.getBaseClass())) {
311                 return findHandlerForClass(c, atts, history);
312             }
313         }
314
315         // check for generic classes ...
316
// and finally try the generic handler matches ...
317
if (this.classToHandlerMapping.isGenericHandler(classToRead)) {
318             return new GenericReadHandler
319                 (this.classToHandlerMapping.getFactoryForClass(classToRead));
320         }
321         if (getFactoryLoader().isGenericHandler(classToRead)) {
322             return new GenericReadHandler
323                 (getFactoryLoader().getFactoryForClass(classToRead));
324         }
325         return null;
326     }
327
328     /**
329      * Sets the root SAX handler.
330      *
331      * @param handler the SAX handler.
332      */

333     protected void setRootHandler(final XmlReadHandler handler) {
334         this.rootHandler = handler;
335         this.rootHandlerInitialized = false;
336     }
337
338     /**
339      * Returns the root SAX handler.
340      *
341      * @return the root SAX handler.
342      */

343     protected XmlReadHandler getRootHandler() {
344         return this.rootHandler;
345     }
346
347     /**
348      * Start a new handler stack and delegate to another handler.
349      *
350      * @param handler the handler.
351      * @param tagName the tag name.
352      * @param attrs the attributes.
353      *
354      * @throws XmlReaderException if there is a problem with the reader.
355      * @throws SAXException if there is a problem with the parser.
356      */

357     public void recurse(final XmlReadHandler handler, final String JavaDoc tagName, final Attributes JavaDoc attrs)
358         throws XmlReaderException, SAXException JavaDoc {
359         
360         this.outerScopes.push(this.currentHandlers);
361         this.currentHandlers = new Stack JavaDoc();
362         this.currentHandlers.push(handler);
363         handler.startElement(tagName, attrs);
364     
365     }
366
367     /**
368      * Delegate to another handler.
369      *
370      * @param handler the new handler.
371      * @param tagName the tag name.
372      * @param attrs the attributes.
373      *
374      * @throws XmlReaderException if there is a problem with the reader.
375      * @throws SAXException if there is a problem with the parser.
376      */

377     public void delegate(final XmlReadHandler handler, final String JavaDoc tagName, final Attributes JavaDoc attrs)
378         throws XmlReaderException, SAXException JavaDoc {
379         this.currentHandlers.push(handler);
380         handler.init(this, tagName);
381         handler.startElement(tagName, attrs);
382     }
383
384     /**
385      * Hand control back to the previous handler.
386      *
387      * @param tagName the tagname.
388      *
389      * @throws SAXException if there is a problem with the parser.
390      * @throws XmlReaderException if there is a problem with the reader.
391      */

392     public void unwind(final String JavaDoc tagName) throws SAXException JavaDoc, XmlReaderException {
393       // remove current handler from stack ..
394
this.currentHandlers.pop();
395         if (this.currentHandlers.isEmpty() && !this.outerScopes.isEmpty()) {
396             // if empty, but "recurse" had been called, then restore the old handler stack ..
397
// but do not end the recursed element ..
398
this.currentHandlers = (Stack JavaDoc) this.outerScopes.pop();
399         }
400         else if (!this.currentHandlers.isEmpty()) {
401             // if there are some handlers open, close them too (these handlers must be delegates)..
402
getCurrentHandler().endElement(tagName);
403         }
404     }
405
406     /**
407      * Returns the current handler.
408      *
409      * @return The current handler.
410      */

411     protected XmlReadHandler getCurrentHandler() {
412         return (XmlReadHandler) this.currentHandlers.peek();
413     }
414
415     /**
416      * Starts processing a document.
417      *
418      * @throws SAXException not in this implementation.
419      */

420     public void startDocument() throws SAXException JavaDoc {
421         this.outerScopes = new Stack JavaDoc();
422         this.currentHandlers = new Stack JavaDoc();
423         this.currentHandlers.push(this.rootHandler);
424     }
425
426     /**
427      * Starts processing an element.
428      *
429      * @param uri the URI.
430      * @param localName the local name.
431      * @param qName the qName.
432      * @param attributes the attributes.
433      *
434      * @throws SAXException if there is a parsing problem.
435      */

436     public void startElement(final String JavaDoc uri, final String JavaDoc localName,
437                              final String JavaDoc qName, final Attributes JavaDoc attributes)
438         throws SAXException JavaDoc {
439         if (rootHandlerInitialized == false) {
440             rootHandler.init(this, qName);
441             rootHandlerInitialized = true;
442         }
443
444         try {
445             getCurrentHandler().startElement(qName, attributes);
446         }
447         catch (XmlReaderException xre) {
448             throw new ParseException(xre, getLocator());
449         }
450     }
451
452     /**
453      * Process character data.
454      *
455      * @param ch the character buffer.
456      * @param start the start index.
457      * @param length the length of the character data.
458      *
459      * @throws SAXException if there is a parsing error.
460      */

461     public void characters(final char[] ch, final int start, final int length) throws SAXException JavaDoc {
462         try {
463             getCurrentHandler().characters(ch, start, length);
464         }
465         catch (SAXException JavaDoc se) {
466             throw se;
467         }
468         catch (Exception JavaDoc e) {
469             throw new ParseException(e, getLocator());
470         }
471     }
472
473     /**
474      * Finish processing an element.
475      *
476      * @param uri the URI.
477      * @param localName the local name.
478      * @param qName the qName.
479      *
480      * @throws SAXException if there is a parsing error.
481      */

482     public void endElement(final String JavaDoc uri, final String JavaDoc localName, final String JavaDoc qName)
483         throws SAXException JavaDoc {
484         try {
485             getCurrentHandler().endElement(qName);
486         }
487         catch (XmlReaderException xre) {
488             throw new ParseException(xre, getLocator());
489         }
490     }
491
492     /**
493      * Loads the given class, and ignores all exceptions which may occur
494      * during the loading. If the class was invalid, null is returned instead.
495      *
496      * @param className the name of the class to be loaded.
497      * @return the class or null.
498      * @throws XmlReaderException if there is a reader error.
499      */

500     protected XmlReadHandler loadHandlerClass(final String JavaDoc className)
501         throws XmlReaderException {
502         try {
503             final Class JavaDoc c = loadClass(className);
504             return (XmlReadHandler) c.newInstance();
505         }
506         catch (Exception JavaDoc e) {
507             // ignore buggy classes for now ..
508
throw new XmlReaderException("LoadHanderClass: Unable to instantiate " + className, e);
509         }
510     }
511
512     /**
513      * Loads the given class, and ignores all exceptions which may occur
514      * during the loading. If the class was invalid, null is returned instead.
515      *
516      * @param className the name of the class to be loaded.
517      * @return the class or null.
518      * @throws XmlReaderException if there is a reader error.
519      */

520     protected Class JavaDoc loadClass(final String JavaDoc className)
521         throws XmlReaderException {
522         if (className == null) {
523             throw new XmlReaderException("LoadHanderClass: Class name not defined");
524         }
525         try {
526             final Class JavaDoc c = ObjectUtilities.getClassLoader(getClass()).loadClass(className);
527             return c;
528         }
529         catch (Exception JavaDoc e) {
530             // ignore buggy classes for now ..
531
throw new XmlReaderException("LoadHanderClass: Unable to load " + className, e);
532         }
533     }
534
535     public Object JavaDoc getResult () throws SAXException JavaDoc
536     {
537         if (this.rootHandler != null) {
538           try
539           {
540             return this.rootHandler.getObject();
541           }
542           catch (XmlReaderException e)
543           {
544             throw new ElementDefinitionException(e);
545           }
546         }
547         return null;
548     }
549 }
550
Popular Tags