/*
Copyright (c) 2009 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS..
*/
package org.clothocore.util.xml;
import java.io.*;
import java.util.Collection;
import java.util.HashMap;
import org.openide.util.Exceptions;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
/**
* XmlGenerator is called from an objBase to recursively turn the entire
* series of linked objects into an XML file. This is not a generic xml-generating
* class--it specifically generates a Clotho XML representation of an object.
*
* @author J.Christopher Anderson
* @author Douglas Densmore
*/
public class XmlGenerator {
public XmlGenerator(HashMap<String, HashMap<String, Object>> data) {
write(data);
}
///////////////////////////////////////////////////////////////////
//// private methods ////
private void write(HashMap<String, HashMap<String, Object>> data) {
_dataHash = data;
try {
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = builderFactory.newDocumentBuilder();
//creating a new instance of a DOM to build a DOM tree.
_theDocument = docBuilder.newDocument();
Element root = _theDocument.createElement("output");
//adding a node after the last child node of the specified node.
_theDocument.appendChild(root);
parseOutHashMap(root);
finalizer();
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
}
}
private void parseOutHashMap(Element root) {
//For each ClothoObject in the hash, write its xml
for(String uuid: _dataHash.keySet()) {
//Create the object node for each ClothoObject
Element anelement = _theDocument.createElement("ClothoObject");
root.appendChild(anelement);
HashMap<String, Object> objectHash = _dataHash.get(uuid);
// System.out.println("Working on " + uuid + " has hash of length " + objectHash.size());
for(String field: objectHash.keySet()) {
Object value = objectHash.get(field);
if(value==null) {
addNullElement(anelement, field);
continue;
}
//If it's a String, call the terminal subroutine
try {
String stringValue = (String) value;
addStringElement(anelement, field, stringValue);
continue;
} catch (java.lang.ClassCastException ex) {
}
//If it's a list, call recursion on it
try {
Collection subArray = (Collection) value;
addListElements(anelement, field, subArray);
continue;
} catch (java.lang.ClassCastException ex2) {
}
}
}
}
/**Terminal method of recursive document generation...this adds a field node
* and its string value
* @param root
* @param afield
* @param stringValue
*/
private void addStringElement(Element root, String afield, String stringValue) {
Element anelement;
Text theText;
Element child1 = _theDocument.createElement(afield);
root.appendChild(child1);
Text text = _theDocument.createTextNode(stringValue);
child1.appendChild(text);
}
private void addNullElement(Element root, String field) {
Element anelement;
Text theText;
Element child1 = _theDocument.createElement(field);
root.appendChild(child1);
}
private void addListElements(Element root, String passedField, Collection passedArray) {
String afield = passedField;
Element listNode = _theDocument.createElement(afield);
root.appendChild(listNode);
for(Object value: passedArray) {
//If it's a String, call the terminal subroutine
try {
String stringValue = (String) value;
addStringElement(listNode, "list", stringValue);
} catch (java.lang.ClassCastException ex) {
}
}
}
private void finalizer() {
try {
//TransformerFactory instance is used to create Transformer objects.
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
// create string from xml tree
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(_theDocument);
transformer.transform(source, result);
String xmlString = sw.toString();
File file = new File("../newxml.xml");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
bw.write(xmlString);
bw.flush();
bw.close();
} catch (Exception ex) {
}
}
///////////////////////////////////////////////////////////////////
//// protected variables ////
/*The HashMap contains fieldname, fielddata, and the fielddata can be recursive*/
protected HashMap<String, HashMap<String, Object>> _dataHash; //HashMap of type <String, (ArrayList, HashMap, or String )>
protected Document _theDocument;
}