I am working on an JFreeChart based charting app. One of the final things that are missing is a templating mechanism that allows users to apply predefined formats to a chart.
For that purpose I need to serialize and deserialize Color,Font,Stroke,Shape etc. objects.
I have discovered the class inside the org.jfree.xml.* packages that already seemd to do most of what I needed.
So far I have succeeded in serializing and deserializing some objects but I can´t get really my mind around these. After a lot of experimentation and head scratching I came up with the following test case:
Code: Select all
import java.io.*;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import org.jfree.xml.writer.*;
import org.jfree.xml.parser.*;
import org.jfree.xml.util.*;
import org.jfree.xml.parser.coretypes.*;
import org.jfree.xml.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
public class JFreeXMLDemo{
public static void main(String[] args){
try{
FileWriter writer = new FileWriter("freexmltest.xml");
ConfigXmlWriteHandler configwriter = new ConfigXmlWriteHandler();
XMLWriter xmlwriter = new XMLWriter(writer);
xmlwriter.writeTag(writer,"root");
configwriter.write("stroke", new BasicStroke(3.0f),BasicStroke.class,xmlwriter);
configwriter.write("color", new Color(255,128,0),Color.class,xmlwriter);
configwriter.write("shape", new Rectangle2D.Double(30,30,10,10),Rectangle2D.class,xmlwriter);
xmlwriter.writeCloseTag(writer,"root");
xmlwriter.close();
Drawer drawer = new Drawer(new Rectangle2D.Double(10,10,100,100),Color.BLUE);
ConfigXmlReadHandler configreader = new ConfigXmlReadHandler(drawer);
XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
System.out.println("ConfigXmlReadHandler --> "+configreader);
reader.setContentHandler(configreader);
try{
InputStream is = new FileInputStream("freexmltest.xml");
System.out.println("InputStream --> "+is);
InputSource source = new InputSource(is);
System.out.println("InputSource --> "+source);
reader.parse(source);
JFrame frame = new JFrame("JFree XML Demo");
frame.getContentPane().add(drawer);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
catch(ParseException pe){
System.out.println("Error on parsing! "+pe.getClass().getName()+", "+pe.getMessage());
}
catch(NullPointerException npe){
System.out.println("Error on parsing! "+npe.getClass().getName()+", "+npe.getMessage());
}
}
catch(Exception e){
System.out.println("Error##! "+e.getClass().getName()+", "+e.getMessage());
}
}
}
class ConfigXmlWriteHandler extends RootXmlWriteHandler{
ObjectFactory of = new SimpleObjectFactory();
ConfigXmlWriteHandler(){
super();
}
public ObjectFactory getFactoryLoader(){
return this.of;
}
}
class MyXmlReadHandler extends AbstractXmlReadHandler{
private XmlReadHandler handler;
MyXmlReadHandler(){
super();
}
public Object getObject(){
try{
if(handler != null){
return handler.getObject();
}
else return new String("No object definition for MyXmlReadHandler");
}
catch(XmlReaderException e){
return new String("Error in handler.getObject(): "+e.getClass().getName()+", "+e.getMessage());
}
}
protected XmlReadHandler getHandlerForChild(final String tagName, final Attributes atts)
throws XmlReaderException, SAXException {
if(tagName.equals("color")){
ColorReadHandler colorhandler = new ColorReadHandler();
this.handler = colorhandler;
return colorhandler;
}
else {
this.handler = null;
return null;
}
}
}
class ConfigXmlReadHandler extends RootXmlReadHandler{
ObjectFactory of = new SimpleObjectFactory();
private Drawer d;
ConfigXmlReadHandler(Drawer d){
super();
this.d = d;
XmlReadHandler roothandler = new MyXmlReadHandler();
setRootHandler(roothandler);
}
public FrontendDefaultHandler newInstance(){
return this;
}
public ObjectFactory getFactoryLoader(){
return this.of;
}
public void characters(char[] ch, int start, int length){
}
public void startElement(String uri,String localeName,String qName,Attributes attributes){
try{
System.out.println("[ConfigXmlReadHandler.startElement] begin");
try{
super.startElement(uri,localeName,qName,attributes);
}
catch(NullPointerException npe){
System.out.println("[ConfigXmlReadHandler.startElement] NullPointerException in RootXmlReadHandler.startElement()");
}
System.out.println("[ConfigXmlReadHandler.startElement] result ");
if(getResult() instanceof Color){
d.setColor((Color)getResult());
}
System.out.println(getResult());
}
catch(Exception e){
System.out.println("[ConfigXmlReadHandler.startElement] Error "+e.getClass().getName()+", message "+e.getMessage());
}
}
}
class Drawer extends JComponent{
private Dimension preferredSize = new Dimension(200,200);
private Shape shape;
private Color color;
Drawer(Shape shape, Color color){
this.shape = shape;
this.color = color;
}
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g;
g2.setColor(color);
g2.draw(shape);
}
public void setColor(Color color){
this.color = color;
}
public Dimension getPreferredSize(){
return preferredSize;
}
}
And I am not sure whether I have really understood how things work. Is the above procedure a useful one?
- a) create an object that extends RootXmlReadHandler and that contains an "inner object" that should be generated or modified based on the informations stored in the xml file.
b) for the RootXmlReadHandler, use an object as rootHandler (I was very confused by the fact that a RootXmlReadHandler contains a rootHandler that, despite the similaritiy in the names, does not extend RootXmlReadHandler and that doesn´t even share a common ancestor with RootXmlReadHandler in the inheritance hierarchie) that extends AbstractXmlReadHandler and is mainly responsible for
b1) translating the tag names into object classes from which a suitable child XmlReadHandler class can be obtained and
b2) making the objects returned by the child XmlReadHandler classes accessible to the surrounding RootXmlReadHandlerinstance
Regards and thanks, paradoxoff