KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > xml > writer > RootXmlWriteHandler


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  * RootXmlWriteHandler.java
29  * ------------------------
30  * (C) Copyright 2002-2005, by Object Refinery Limited.
31  *
32  * Original Author: Peter Becker;
33  * Contributor(s): -;
34  *
35  * $Id: RootXmlWriteHandler.java,v 1.5 2005/10/18 13:35:06 mungady Exp $
36  *
37  * Changes
38  * -------
39  * 23-Dec-2003 : Added missing Javadocs (DG);
40  *
41  */

42 package org.jfree.xml.writer;
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.io.IOException JavaDoc;
55 import java.util.ArrayList 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.util.ManualMappingDefinition;
63 import org.jfree.xml.util.MultiplexMappingDefinition;
64 import org.jfree.xml.util.MultiplexMappingEntry;
65 import org.jfree.xml.util.ObjectFactory;
66 import org.jfree.xml.util.SimpleObjectFactory;
67 import org.jfree.xml.writer.coretypes.BasicStrokeWriteHandler;
68 import org.jfree.xml.writer.coretypes.ColorWriteHandler;
69 import org.jfree.xml.writer.coretypes.FontWriteHandler;
70 import org.jfree.xml.writer.coretypes.GenericWriteHandler;
71 import org.jfree.xml.writer.coretypes.GradientPaintWriteHandler;
72 import org.jfree.xml.writer.coretypes.InsetsWriteHandler;
73 import org.jfree.xml.writer.coretypes.ListWriteHandler;
74 import org.jfree.xml.writer.coretypes.Point2DWriteHandler;
75 import org.jfree.xml.writer.coretypes.Rectangle2DWriteHandler;
76 import org.jfree.xml.writer.coretypes.RenderingHintsWriteHandler;
77
78 /**
79  * A root handler for writing objects to XML format.
80  */

81 public abstract class RootXmlWriteHandler {
82
83     /** A map containg the manual mappings. */
84     private SimpleObjectFactory classToHandlerMapping;
85
86     /**
87      * Creates a new RootXmlWrite handler with the default mappings enabled.
88      */

89     public RootXmlWriteHandler() {
90         this.classToHandlerMapping = new SimpleObjectFactory();
91
92         // set up handling for Paint objects
93
final MultiplexMappingEntry[] paintEntries = new MultiplexMappingEntry[2];
94         paintEntries[0] = new MultiplexMappingEntry("color", Color JavaDoc.class.getName());
95         paintEntries[1] = new MultiplexMappingEntry("gradientPaint", GradientPaint JavaDoc.class.getName());
96         addMultiplexMapping(Paint JavaDoc.class, "type", paintEntries);
97         addManualMapping(GradientPaint JavaDoc.class, GradientPaintWriteHandler.class);
98         addManualMapping(Color JavaDoc.class, ColorWriteHandler.class);
99
100         // set up handling for Point2D objects
101
final MultiplexMappingEntry[] point2DEntries = new MultiplexMappingEntry[2];
102         point2DEntries[0] = new MultiplexMappingEntry("float", Point2D.Float JavaDoc.class.getName());
103         point2DEntries[1] = new MultiplexMappingEntry("double", Point2D.Double JavaDoc.class.getName());
104         addMultiplexMapping(Point2D JavaDoc.class, "type", point2DEntries);
105         addManualMapping(Point2D.Float JavaDoc.class, Point2DWriteHandler.class);
106         addManualMapping(Point2D.Double JavaDoc.class, Point2DWriteHandler.class);
107
108         // set up handling for Stroke objects
109
final MultiplexMappingEntry[] strokeEntries = new MultiplexMappingEntry[1];
110         strokeEntries[0] = new MultiplexMappingEntry("basic", BasicStroke JavaDoc.class.getName());
111         addMultiplexMapping(Stroke JavaDoc.class, "type", strokeEntries);
112         addManualMapping(BasicStroke JavaDoc.class, BasicStrokeWriteHandler.class);
113
114         // set up handling for Rectangle2D objects
115
final MultiplexMappingEntry[] rectangle2DEntries = new MultiplexMappingEntry[2];
116         rectangle2DEntries[0] = new MultiplexMappingEntry(
117             "float", Rectangle2D.Float JavaDoc.class.getName()
118         );
119         rectangle2DEntries[1] = new MultiplexMappingEntry(
120             "double", Rectangle2D.Double JavaDoc.class.getName()
121         );
122         addMultiplexMapping(Rectangle2D JavaDoc.class, "type", rectangle2DEntries);
123         addManualMapping(Rectangle2D.Float JavaDoc.class, Rectangle2DWriteHandler.class);
124         addManualMapping(Rectangle2D.Double JavaDoc.class, Rectangle2DWriteHandler.class);
125
126         // set up handling for List objects
127
final MultiplexMappingEntry[] listEntries = new MultiplexMappingEntry[4];
128         listEntries[0] = new MultiplexMappingEntry("array-list", ArrayList JavaDoc.class.getName());
129         listEntries[1] = new MultiplexMappingEntry("linked-list", LinkedList JavaDoc.class.getName());
130         listEntries[2] = new MultiplexMappingEntry("vector", Vector JavaDoc.class.getName());
131         listEntries[3] = new MultiplexMappingEntry("stack", Stack JavaDoc.class.getName());
132         addMultiplexMapping(List JavaDoc.class, "type", listEntries);
133         addManualMapping(LinkedList JavaDoc.class, ListWriteHandler.class);
134         addManualMapping(Vector JavaDoc.class, ListWriteHandler.class);
135         addManualMapping(ArrayList JavaDoc.class, ListWriteHandler.class);
136         addManualMapping(Stack JavaDoc.class, ListWriteHandler.class);
137
138         // handle all other direct mapping types
139
addManualMapping(RenderingHints JavaDoc.class, RenderingHintsWriteHandler.class);
140         addManualMapping(Insets JavaDoc.class, InsetsWriteHandler.class);
141         addManualMapping(Font JavaDoc.class, FontWriteHandler.class);
142     }
143
144     /**
145      * Returns the object factory.
146      *
147      * @return the object factory.
148      */

149     protected abstract ObjectFactory getFactoryLoader();
150
151     /**
152      * Adds a new manual mapping to this handler.
153      *
154      * This method provides support for the manual mapping. The manual mapping
155      * will become active before the multiplexers were queried. This facility
156      * could be used to override the model definition.
157      *
158      * @param classToWrite the class, which should be handled
159      * @param handler the write handler implementation for that class.
160      */

161     protected void addManualMapping(final Class JavaDoc classToWrite, final Class JavaDoc handler) {
162         if (handler == null) {
163             throw new NullPointerException JavaDoc("handler must not be null.");
164         }
165         if (classToWrite == null) {
166             throw new NullPointerException JavaDoc("classToWrite must not be null.");
167         }
168         if (!XmlWriteHandler.class.isAssignableFrom(handler)) {
169             throw new IllegalArgumentException JavaDoc("The given handler is no XmlWriteHandler.");
170         }
171
172         this.classToHandlerMapping.addManualMapping
173             (new ManualMappingDefinition(classToWrite, null, handler.getName()));
174     }
175
176     /**
177      * Adds a multiplex mapping.
178      *
179      * @param baseClass the base class.
180      * @param typeAttr the type attribute.
181      * @param mdef the mapping entries.
182      */

183     protected void addMultiplexMapping(final Class JavaDoc baseClass,
184                                        final String JavaDoc typeAttr,
185                                        final MultiplexMappingEntry[] mdef) {
186         
187         this.classToHandlerMapping.addMultiplexMapping(
188             new MultiplexMappingDefinition(baseClass, typeAttr, mdef)
189         );
190         
191     }
192
193     /**
194      * Tries to find the mapping for the given class. This will first check
195      * the manual mapping and then try to use the object factory to resolve
196      * the class parameter into a write handler.
197      *
198      * @param classToWrite the class for which to find a handler.
199      * @return the write handler, never null.
200      * @throws XMLWriterException if no handler could be found for the given class.
201      */

202     protected XmlWriteHandler getMapping(final Class JavaDoc classToWrite) throws XMLWriterException {
203
204         if (classToWrite == null) {
205             throw new NullPointerException JavaDoc("ClassToWrite is null.");
206         }
207
208         // search direct matches, first the direct definitions ...
209
ManualMappingDefinition manualMapping =
210             this.classToHandlerMapping.getManualMappingDefinition(classToWrite);
211         if (manualMapping == null) {
212             // search the manual mappings from the xml file.
213
manualMapping = getFactoryLoader().getManualMappingDefinition(classToWrite);
214         }
215         if (manualMapping != null) {
216             return loadHandlerClass(manualMapping.getWriteHandler());
217         }
218
219
220         // multiplexer definitions can be safely ignored here, as they are used to
221
// map parent classes to more specific child classes. In this case, we already
222
// know the child class and can look up the handler directly.
223

224         // of course we have to check for multiplexers later, so that we can apply
225
// the mutiplex-attributes.
226

227         // and finally try the generic handler matches ...
228
if (this.classToHandlerMapping.isGenericHandler(classToWrite)) {
229             return new GenericWriteHandler(
230                 this.classToHandlerMapping.getFactoryForClass(classToWrite)
231             );
232         }
233         if (getFactoryLoader().isGenericHandler(classToWrite)) {
234             return new GenericWriteHandler(getFactoryLoader().getFactoryForClass(classToWrite));
235         }
236
237         throw new XMLWriterException("Unable to handle " + classToWrite);
238     }
239
240     /**
241      * Writes the given object with the specified tagname. This method will
242      * do nothing, if the given object is null.
243      *
244      * @param tagName the tagname for the xml-element containing the object
245      * definition. The tagname must not be null.
246      * @param object the object which should be written.
247      * @param baseClass the base class.
248      * @param writer the xml writer used to write the content, never null.
249      *
250      * @throws IOException if an IOException occures.
251      * @throws XMLWriterException if an object model related error occures during
252      * the writing.
253      */

254     public void write(final String JavaDoc tagName, final Object JavaDoc object, final Class JavaDoc baseClass, final XMLWriter writer)
255         throws IOException JavaDoc, XMLWriterException {
256         if (object == null) {
257             return;
258         }
259         if (tagName == null) {
260             throw new NullPointerException JavaDoc("RootXmlWriteHandler.write(..) : tagName is null");
261         }
262         if (writer == null) {
263             throw new NullPointerException JavaDoc("RootXmlWriteHandler.write(..) : writer is null");
264         }
265         if (!baseClass.isInstance(object)) {
266             throw new ClassCastException JavaDoc("Object is no instance of " + baseClass);
267         }
268         final Class JavaDoc classToWrite = object.getClass();
269         final XmlWriteHandler handler = getMapping(classToWrite);
270         handler.setRootHandler(this);
271
272         String JavaDoc attributeName = null;
273         String JavaDoc attributeValue = null;
274
275         // find multiplexer for this class...
276
MultiplexMappingDefinition mplex =
277             getFactoryLoader().getMultiplexDefinition(baseClass);
278         if (mplex == null) {
279             mplex = this.classToHandlerMapping.getMultiplexDefinition(baseClass);
280         }
281         if (mplex != null) {
282             final MultiplexMappingEntry entry =
283                 mplex.getEntryForClass(classToWrite.getName());
284             if (entry != null) {
285                 attributeName = mplex.getAttributeName();
286                 attributeValue = entry.getAttributeValue();
287             }
288             else {
289                 throw new XMLWriterException(
290                     "Unable to find child mapping for multiplexer "
291                     + baseClass + " to child " + classToWrite
292                 );
293             }
294         }
295
296         handler.write(tagName, object, writer, attributeName, attributeValue);
297         writer.allowLineBreak();
298     }
299
300     /**
301      * Loads the given class, and ignores all exceptions which may occur
302      * during the loading. If the class was invalid, null is returned instead.
303      *
304      * @param className the name of the class to be loaded.
305      * @return the class or null.
306      *
307      * @throws XMLWriterException if there is a writer exception.
308      */

309     protected XmlWriteHandler loadHandlerClass(final String JavaDoc className)
310         throws XMLWriterException {
311         if (className == null) {
312             throw new XMLWriterException("LoadHanderClass: Class name not defined");
313         }
314         try {
315             final Class JavaDoc c = ObjectUtilities.getClassLoader(getClass()).loadClass(className);
316             return (XmlWriteHandler) c.newInstance();
317         }
318         catch (Exception JavaDoc e) {
319             // ignore buggy classes for now ..
320
throw new XMLWriterException("LoadHanderClass: Unable to instantiate " + className, e);
321         }
322     }
323     
324 }
325
Popular Tags