/* This file is part of Green.
*
* Copyright (C) 2005 The Research Foundation of State University of New York
* All Rights Under Copyright Reserved, The Research Foundation of S.U.N.Y.
*
* Green is free software, licensed under the terms of the Eclipse
* Public License, version 1.0. The license is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package edu.buffalo.cse.green.xml;
import static edu.buffalo.cse.green.constants.XMLConstants.XML_TAB;
import java.util.Map;
import java.util.Stack;
/**
* Creates XML code and decodes XML strings.
*
* @author bcmartin
*/
public class XMLConverter {
private StringBuffer _buf = new StringBuffer();
private Stack<XMLNode> _headers = new Stack<XMLNode>();
/**
* @param xml - The contents of the XML file.
* @return The node representation of the XML.
* @throws ArrayIndexOutOfBoundsException
* @author bcmartin
* @author zgwang
*/
public XMLNode getDecodedXML(String xml)
throws ArrayIndexOutOfBoundsException {
int pos;
String line;
XMLNode node = new XMLNode("!root");
XMLNode currentNode = node;
while (true) {
pos = xml.indexOf('>');
if (pos == -1) break;
pos++; //Account for position of line break character (/n)
line = xml.substring(0, pos);
xml = xml.substring(pos + 1);
//Trims off remaining /n before tags
while(xml.length() > 0 && xml.charAt(0) == '\n')
xml = xml.substring(1);
if (line.length() < 3) continue;
currentNode = addLineToNode(currentNode, line);
}
return node;
}
/**
* @return The encoded XML.
*/
public String getEncodedXML() {
_headers.clear();
return _buf.toString();
}
/**
* Adds a header to the stack.
*
* @param header - The node to add.
*/
public void pushHeader(XMLNode header) {
appendToBuffer("<" + header + ">");
_headers.push(header);
}
/**
* Adds a header to the stack. A node with the given name will be created
* and added to the stack.
*
* @param header - The name of the node to create and add.
*/
public void pushHeader(String header) {
pushHeader(new XMLNode(header));
}
/**
* Creates an open header
* @param header - The name of the header.
* @param value - The value to assign to the header.
*/
public void openHeader(String header, String value) {
appendToBuffer("<" + header + "=\"" + value + "\">");
_headers.push(new XMLNode(header));
}
/**
* Removes a header from the stack.
*/
public void popHeader() {
appendToBuffer("</" + _headers.pop() + ">");
}
/**
* Writes a closed XML header with the specified name and value.
*
* @param header - The name.
* @param value - The value.
*/
public void writeKey(String header, Object value) {
appendToBuffer("<" + header + "=\"" + value + "\"/>");
}
/**
* Writes all key-value pairs in the given map as closed XML headers.
*
* @param map - The map.
*/
public void writeMap(Map<String, String> map) {
for (String key : map.keySet()) {
writeKey(key, map.get(key).toString());
}
}
/**
* Writes the given string to the buffer, appending tabs as appropriate.
*
* @param appendString - The string to append.
*/
private void appendToBuffer(String appendString) {
for (int x = 0; x < _headers.size(); x++)
_buf.append(XML_TAB);
_buf.append(appendString + "\n");
}
/**
* Adds the given line of text to the current node, manipulating headers as
* appropriate.
*
* @param node - The node.
* @param line - The text.
* @return - The new node.
*/
private XMLNode addLineToNode(XMLNode node, String line) {
line = line.substring(line.indexOf("<")).trim();
if (line.substring(0, 2).equals("</")) {
// close header
return _headers.pop();
} else {
int len = line.length();
if (line.substring(len - 2, len).equals("/>")) {
// write value to map
int pos = line.indexOf("=");
String key = line.substring(1, pos);
String val = line.substring(pos + 2, len - 3);
node.getAttributes().put(key, val);
return node;
} else {
// open header
pushHeader(node);
String name = line.substring(1, len - 1);
XMLNode newNode = new XMLNode(name);
node.addChild(newNode);
return newNode;
}
}
}
}