/* * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI for * visualizing and manipulating spatial features with geometry and attributes. * * Copyright (C) 2003 Vivid Solutions * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307, USA. * * For more information, contact: * * Vivid Solutions Suite #1A 2328 Government Street Victoria BC V8T 5G5 Canada * * (250)385-6040 www.vividsolutions.com */ package com.vividsolutions.jump.util.java2xml; import org.apache.log4j.Logger; import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jdom.output.XMLOutputter; import java.io.*; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; public class Java2XML extends XMLBinder { private static Logger LOG = Logger.getLogger(Java2XML.class); public Java2XML() { } public String write(Object object, String rootTagName) throws Exception { StringWriter writer = new StringWriter(); try { write(object, rootTagName, writer); return writer.toString(); } finally { writer.close(); } } public void write(Object object, String rootTagName, File file) throws Exception { FileWriter fileWriter = new FileWriter(file, false); try { BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); try { new Java2XML().write(object, rootTagName, bufferedWriter); bufferedWriter.flush(); fileWriter.flush(); } finally { bufferedWriter.close(); } } finally { fileWriter.close(); } } public void write(Object object, String rootTagName, Writer writer) throws Exception { Document document = new Document(new Element(rootTagName)); write(object, document.getRootElement(), specElements(object.getClass())); XMLOutputter xmlOutputter = new XMLOutputter(); xmlOutputter.setNewlines(true); xmlOutputter.setIndent(true); xmlOutputter.output(document, writer); } private void write(final Object object, final Element tag, List specElements) throws Exception { try { visit(specElements, new SpecVisitor() { public void tagSpecFound(String xmlName, String javaName, List specChildElements) throws Exception { Collection childTags = new ArrayList(); if (javaName != null) { childTags.addAll(writeChildTags(tag, xmlName, getter( object.getClass(), javaName).invoke(object, new Object[]{}), specifyingTypeExplicitly(fieldClass(setter( object.getClass(), javaName))))); } else { Element childTag = new Element(xmlName); tag.addContent(childTag); childTags.add(childTag); } // The parent may specify additional tags for itself in the // children. [Jon Aquino] for (Iterator i = childTags.iterator(); i.hasNext();) { Element childTag = (Element) i.next(); write(object, childTag, specChildElements); } } public void attributeSpecFound(String xmlName, String javaName) throws Exception { writeAttribute(tag, xmlName, getter(object.getClass(), javaName).invoke(object, new Object[]{})); } }, object.getClass()); } catch (Exception e) { LOG.error("Java2XML: Exception writing " + object.getClass()); throw e; } } private void writeAttribute(Element tag, String name, Object value) throws XMLBinderException { if (value == null) { throw new XMLBinderException("Cannot store null value as " + "attribute. Store as element instead. (" + name + ")."); } tag.setAttribute(new Attribute(name, toXML(value))); } private Element writeChildTag(Element tag, String name, Object value, boolean specifyingType) throws Exception { Element childTag = new Element(name); if ((value != null) && specifyingType) { childTag.setAttribute(new Attribute("class", value.getClass() .getName())); } if (value == null) { childTag.setAttribute(new Attribute("null", "true")); } else if (hasCustomConverter(value.getClass())) { childTag.setText(toXML(value)); } else if (value instanceof Map) { for (Iterator i = ((Map) value).keySet().iterator(); i.hasNext();) { Object key = i.next(); Element mappingTag = new Element("mapping"); childTag.addContent(mappingTag); writeChildTag(mappingTag, "key", key, true); writeChildTag(mappingTag, "value", ((Map) value).get(key), true); } } else if (value instanceof Collection) { for (Iterator i = ((Collection) value).iterator(); i.hasNext();) { Object item = i.next(); writeChildTag(childTag, "item", item, true); } } else if (value instanceof QName) { childTag.addContent(value.toString()); } else { write(value, childTag, specElements(value.getClass())); } tag.addContent(childTag); return childTag; } private Collection writeChildTags(Element tag, String name, Object value, boolean specifyingType) throws Exception { ArrayList childTags = new ArrayList(); if (value instanceof Collection) { // Might or might not need to specify type, depending on how // concrete the setter's parameter is. [Jon Aquino] for (Iterator i = ((Collection) value).iterator(); i.hasNext();) { Object item = i.next(); childTags.add(writeChildTag(tag, name, item, specifyingType)); } } else { childTags.add(writeChildTag(tag, name, value, specifyingType)); } return childTags; } private Method getter(Class fieldClass, String field) throws XMLBinderException { Method[] methods = fieldClass.getMethods(); // Exact match first [Jon Aquino] for (int i = 0; i < methods.length; i++) { if (!methods[i].getName().toUpperCase().equals( "GET" + field.toUpperCase()) && !methods[i].getName().toUpperCase().equals( "IS" + field.toUpperCase())) { continue; } if (methods[i].getParameterTypes().length != 0) { continue; } return methods[i]; } for (int i = 0; i < methods.length; i++) { if (!methods[i].getName().toUpperCase().startsWith( "GET" + field.toUpperCase()) && !methods[i].getName().toUpperCase().startsWith( "IS" + field.toUpperCase())) { continue; } if (methods[i].getParameterTypes().length != 0) { continue; } return methods[i]; } throw new XMLBinderException("Could not find getter named like '" + field + "' " + fieldClass); } }