org.jfree.xml.writer.RootXmlWriteHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jtstand-common Show documentation
Show all versions of jtstand-common Show documentation
jtstand-common is a library derived from jcommon, used by jtstand-chart, which is derived from jfreechart
/*
* Copyright (c) 2009 Albert Kurucz.
*
* This file, RootXmlWriteHandler.java is part of JTStand.
*
* JTStand is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JTStand is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GTStand. If not, see .
*/
package org.jfree.xml.writer;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import java.util.Vector;
import org.jfree.util.ObjectUtilities;
import org.jfree.xml.util.ManualMappingDefinition;
import org.jfree.xml.util.MultiplexMappingDefinition;
import org.jfree.xml.util.MultiplexMappingEntry;
import org.jfree.xml.util.ObjectFactory;
import org.jfree.xml.util.SimpleObjectFactory;
import org.jfree.xml.writer.coretypes.BasicStrokeWriteHandler;
import org.jfree.xml.writer.coretypes.ColorWriteHandler;
import org.jfree.xml.writer.coretypes.FontWriteHandler;
import org.jfree.xml.writer.coretypes.GenericWriteHandler;
import org.jfree.xml.writer.coretypes.GradientPaintWriteHandler;
import org.jfree.xml.writer.coretypes.InsetsWriteHandler;
import org.jfree.xml.writer.coretypes.ListWriteHandler;
import org.jfree.xml.writer.coretypes.Point2DWriteHandler;
import org.jfree.xml.writer.coretypes.Rectangle2DWriteHandler;
import org.jfree.xml.writer.coretypes.RenderingHintsWriteHandler;
/**
* A root handler for writing objects to XML format.
*/
public abstract class RootXmlWriteHandler {
/** A map containg the manual mappings. */
private SimpleObjectFactory classToHandlerMapping;
/**
* Creates a new RootXmlWrite handler with the default mappings enabled.
*/
public RootXmlWriteHandler() {
this.classToHandlerMapping = new SimpleObjectFactory();
// set up handling for Paint objects
final MultiplexMappingEntry[] paintEntries = new MultiplexMappingEntry[2];
paintEntries[0] = new MultiplexMappingEntry("color", Color.class.getName());
paintEntries[1] = new MultiplexMappingEntry("gradientPaint", GradientPaint.class.getName());
addMultiplexMapping(Paint.class, "type", paintEntries);
addManualMapping(GradientPaint.class, GradientPaintWriteHandler.class);
addManualMapping(Color.class, ColorWriteHandler.class);
// set up handling for Point2D objects
final MultiplexMappingEntry[] point2DEntries = new MultiplexMappingEntry[2];
point2DEntries[0] = new MultiplexMappingEntry("float", Point2D.Float.class.getName());
point2DEntries[1] = new MultiplexMappingEntry("double", Point2D.Double.class.getName());
addMultiplexMapping(Point2D.class, "type", point2DEntries);
addManualMapping(Point2D.Float.class, Point2DWriteHandler.class);
addManualMapping(Point2D.Double.class, Point2DWriteHandler.class);
// set up handling for Stroke objects
final MultiplexMappingEntry[] strokeEntries = new MultiplexMappingEntry[1];
strokeEntries[0] = new MultiplexMappingEntry("basic", BasicStroke.class.getName());
addMultiplexMapping(Stroke.class, "type", strokeEntries);
addManualMapping(BasicStroke.class, BasicStrokeWriteHandler.class);
// set up handling for Rectangle2D objects
final MultiplexMappingEntry[] rectangle2DEntries = new MultiplexMappingEntry[2];
rectangle2DEntries[0] = new MultiplexMappingEntry(
"float", Rectangle2D.Float.class.getName()
);
rectangle2DEntries[1] = new MultiplexMappingEntry(
"double", Rectangle2D.Double.class.getName()
);
addMultiplexMapping(Rectangle2D.class, "type", rectangle2DEntries);
addManualMapping(Rectangle2D.Float.class, Rectangle2DWriteHandler.class);
addManualMapping(Rectangle2D.Double.class, Rectangle2DWriteHandler.class);
// set up handling for List objects
final MultiplexMappingEntry[] listEntries = new MultiplexMappingEntry[4];
listEntries[0] = new MultiplexMappingEntry("array-list", ArrayList.class.getName());
listEntries[1] = new MultiplexMappingEntry("linked-list", LinkedList.class.getName());
listEntries[2] = new MultiplexMappingEntry("vector", Vector.class.getName());
listEntries[3] = new MultiplexMappingEntry("stack", Stack.class.getName());
addMultiplexMapping(List.class, "type", listEntries);
addManualMapping(LinkedList.class, ListWriteHandler.class);
addManualMapping(Vector.class, ListWriteHandler.class);
addManualMapping(ArrayList.class, ListWriteHandler.class);
addManualMapping(Stack.class, ListWriteHandler.class);
// handle all other direct mapping types
addManualMapping(RenderingHints.class, RenderingHintsWriteHandler.class);
addManualMapping(Insets.class, InsetsWriteHandler.class);
addManualMapping(Font.class, FontWriteHandler.class);
}
/**
* Returns the object factory.
*
* @return the object factory.
*/
protected abstract ObjectFactory getFactoryLoader();
/**
* Adds a new manual mapping to this handler.
*
* This method provides support for the manual mapping. The manual mapping
* will become active before the multiplexers were queried. This facility
* could be used to override the model definition.
*
* @param classToWrite the class, which should be handled
* @param handler the write handler implementation for that class.
*/
protected void addManualMapping(final Class classToWrite, final Class handler) {
if (handler == null) {
throw new NullPointerException("handler must not be null.");
}
if (classToWrite == null) {
throw new NullPointerException("classToWrite must not be null.");
}
if (!XmlWriteHandler.class.isAssignableFrom(handler)) {
throw new IllegalArgumentException("The given handler is no XmlWriteHandler.");
}
this.classToHandlerMapping.addManualMapping
(new ManualMappingDefinition(classToWrite, null, handler.getName()));
}
/**
* Adds a multiplex mapping.
*
* @param baseClass the base class.
* @param typeAttr the type attribute.
* @param mdef the mapping entries.
*/
protected void addMultiplexMapping(final Class baseClass,
final String typeAttr,
final MultiplexMappingEntry[] mdef) {
this.classToHandlerMapping.addMultiplexMapping(
new MultiplexMappingDefinition(baseClass, typeAttr, mdef)
);
}
/**
* Tries to find the mapping for the given class. This will first check
* the manual mapping and then try to use the object factory to resolve
* the class parameter into a write handler.
*
* @param classToWrite the class for which to find a handler.
* @return the write handler, never null.
* @throws XMLWriterException if no handler could be found for the given class.
*/
protected XmlWriteHandler getMapping(final Class classToWrite) throws XMLWriterException {
if (classToWrite == null) {
throw new NullPointerException("ClassToWrite is null.");
}
// search direct matches, first the direct definitions ...
ManualMappingDefinition manualMapping =
this.classToHandlerMapping.getManualMappingDefinition(classToWrite);
if (manualMapping == null) {
// search the manual mappings from the xml file.
manualMapping = getFactoryLoader().getManualMappingDefinition(classToWrite);
}
if (manualMapping != null) {
return loadHandlerClass(manualMapping.getWriteHandler());
}
// multiplexer definitions can be safely ignored here, as they are used to
// map parent classes to more specific child classes. In this case, we already
// know the child class and can look up the handler directly.
// of course we have to check for multiplexers later, so that we can apply
// the mutiplex-attributes.
// and finally try the generic handler matches ...
if (this.classToHandlerMapping.isGenericHandler(classToWrite)) {
return new GenericWriteHandler(
this.classToHandlerMapping.getFactoryForClass(classToWrite)
);
}
if (getFactoryLoader().isGenericHandler(classToWrite)) {
return new GenericWriteHandler(getFactoryLoader().getFactoryForClass(classToWrite));
}
throw new XMLWriterException("Unable to handle " + classToWrite);
}
/**
* Writes the given object with the specified tagname. This method will
* do nothing, if the given object is null.
*
* @param tagName the tagname for the xml-element containing the object
* definition. The tagname must not be null.
* @param object the object which should be written.
* @param baseClass the base class.
* @param writer the xml writer used to write the content, never null.
*
* @throws IOException if an IOException occures.
* @throws XMLWriterException if an object model related error occures during
* the writing.
*/
public void write(final String tagName, final Object object, final Class baseClass, final XMLWriter writer)
throws IOException, XMLWriterException {
if (object == null) {
return;
}
if (tagName == null) {
throw new NullPointerException("RootXmlWriteHandler.write(..) : tagName is null");
}
if (writer == null) {
throw new NullPointerException("RootXmlWriteHandler.write(..) : writer is null");
}
if (!baseClass.isInstance(object)) {
throw new ClassCastException("Object is no instance of " + baseClass);
}
final Class classToWrite = object.getClass();
final XmlWriteHandler handler = getMapping(classToWrite);
handler.setRootHandler(this);
String attributeName = null;
String attributeValue = null;
// find multiplexer for this class...
MultiplexMappingDefinition mplex =
getFactoryLoader().getMultiplexDefinition(baseClass);
if (mplex == null) {
mplex = this.classToHandlerMapping.getMultiplexDefinition(baseClass);
}
if (mplex != null) {
final MultiplexMappingEntry entry =
mplex.getEntryForClass(classToWrite.getName());
if (entry != null) {
attributeName = mplex.getAttributeName();
attributeValue = entry.getAttributeValue();
}
else {
throw new XMLWriterException(
"Unable to find child mapping for multiplexer "
+ baseClass + " to child " + classToWrite
);
}
}
handler.write(tagName, object, writer, attributeName, attributeValue);
writer.allowLineBreak();
}
/**
* Loads the given class, and ignores all exceptions which may occur
* during the loading. If the class was invalid, null is returned instead.
*
* @param className the name of the class to be loaded.
* @return the class or null.
*
* @throws XMLWriterException if there is a writer exception.
*/
protected XmlWriteHandler loadHandlerClass(final String className)
throws XMLWriterException {
if (className == null) {
throw new XMLWriterException("LoadHanderClass: Class name not defined");
}
try {
final Class c = ObjectUtilities.getClassLoader(getClass()).loadClass(className);
return (XmlWriteHandler) c.newInstance();
}
catch (Exception e) {
// ignore buggy classes for now ..
throw new XMLWriterException("LoadHanderClass: Unable to instantiate " + className, e);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy