blob: 289d9e8a2e483326984726349ad62edec5e6364d [file] [log] [blame]
package org.testng.reporters;
import java.util.Properties;
import java.util.Stack;
/**
* This class allows you to generate an XML text document by pushing
* and popping tags from a stack maintained internally.
*
* @author <a href="mailto:cedric@beust.com">Cedric Beust</a> Jul 21, 2003
* TODO CQ have a method to set the XML version and encoding
*/
public class XMLStringBuffer {
/** End of line */
private static final String EOL = System.getProperty("line.separator");
/** Tab space indent for XML document */
private static final String DEFAULT_INDENT_INCREMENT = " ";
/** The buffer to hold the xml document */
private final StringBuffer m_buffer;
/** The stack of tags to make sure XML document is well formed. */
private final Stack<Tag> m_tagStack = new Stack<Tag>();
/** A string of space character representing the current indentation. */
private String m_currentIndent = "";
/**
*
* @param start A string of spaces indicating the indentation at which
* to start the generation.
*/
public XMLStringBuffer(String start) {
this(new StringBuffer(), start);
}
/**
* Set the doctype for this document.
*
* @param docType The DOCTYPE string, without the "&lt;!DOCTYPE " "&gt;"
*/
public void setDocType(String docType) {
m_buffer.append("<!DOCTYPE " + docType + ">" + EOL);
}
/**
*
* @param buffer The StringBuffer to use internally to represent the
* document.
* @param start A string of spaces indicating the indentation at which
* to start the generation.
*/
public XMLStringBuffer(StringBuffer buffer, String start) {
m_buffer = buffer;
m_currentIndent = start;
}
/**
* Push a new tag. Its value is stored and will be compared against the parameter
* passed to pop().
*
* @param tagName The name of the tag.
* @param schema The schema to use (can be null or an empty string).
* @param attributes A Properties file representing the attributes (or null)
*/
public void push(String tagName, String schema, Properties attributes) {
XMLUtils.xmlOpen(m_buffer, m_currentIndent, tagName + schema, attributes);
m_tagStack.push(new Tag(m_currentIndent, tagName));
m_currentIndent += DEFAULT_INDENT_INCREMENT;
}
/**
* Push a new tag. Its value is stored and will be compared against the parameter
* passed to pop().
*
* @param tagName The name of the tag.
* @param schema The schema to use (can be null or an empty string).
*/
public void push(String tagName, String schema) {
push(tagName, schema, null);
}
/**
* Push a new tag. Its value is stored and will be compared against the parameter
* passed to pop().
*
* @param tagName The name of the tag.
* @param attributes A Properties file representing the attributes (or null)
*/
public void push(String tagName, Properties attributes) {
push(tagName, "", attributes);
}
/**
* Push a new tag. Its value is stored and will be compared against the parameter
* passed to pop().
*
* @param tagName The name of the tag.
*/
public void push(String tagName) {
push(tagName, "");
}
/**
* Pop the last pushed element without verifying it if matches the previously
* pushed tag.
*/
public void pop() {
pop(null);
}
/**
* Pop the last pushed element and throws an AssertionError if it doesn't
* match the corresponding tag that was pushed earlier.
*
* @param tagName The name of the tag this pop() is supposed to match.
*/
public void pop(String tagName) {
m_currentIndent = m_currentIndent.substring(DEFAULT_INDENT_INCREMENT.length());
Tag t = m_tagStack.pop();
if (null != tagName) {
if (!tagName.equals(t.tagName)) {
// TODO Is it normal to throw an Error here?
throw new AssertionError(
"Popping the wrong tag: " + t.tagName + " but expected " + tagName);
}
}
XMLUtils.xmlClose(m_buffer, m_currentIndent, t.tagName);
}
/**
* Add a required element to the current tag. An opening and closing tag
* will be generated even if value is null.
* @param tagName The name of the tag
* @param value The value for this tag
*/
public void addRequired(String tagName, String value) {
addRequired(tagName, value, null);
}
/**
* Add a required element to the current tag. An opening and closing tag
* will be generated even if value is null.
* @param tagName The name of the tag
* @param value The value for this tag
* @param attributes A Properties file containing the attributes (or null)
*/
public void addRequired(String tagName, String value, Properties attributes) {
XMLUtils.xmlRequired(m_buffer, m_currentIndent, tagName, value, attributes);
}
/**
* Add an optional String element to the current tag. If value is null, nothing is
* added.
* @param tagName The name of the tag
* @param value The value for this tag
* @param attributes A Properties file containing the attributes (or null)
*/
public void addOptional(String tagName, String value, Properties attributes) {
XMLUtils.xmlOptional(m_buffer, m_currentIndent, tagName, value, attributes);
}
/**
* Add an optional String element to the current tag. If value is null, nothing is
* added.
* @param tagName The name of the tag
* @param value The value for this tag
*/
public void addOptional(String tagName, String value) {
addOptional(tagName, value, null);
}
/**
* Add an optional Boolean element to the current tag. If value is null, nothing is
* added.
* @param tagName The name of the tag
* @param value The value for this tag
* @param attributes A Properties file containing the attributes (or null)
*/
public void addOptional(String tagName, Boolean value, Properties attributes) {
if (null != value) {
XMLUtils.xmlOptional(m_buffer, m_currentIndent, tagName, value.toString(), attributes);
}
}
/**
* Add an optional Boolean element to the current tag. If value is null, nothing is
* added.
* @param tagName The name of the tag
* @param value The value for this tag
* @param attributes A Properties file containing the attributes (or null)
*/
public void addOptional(String tagName, Boolean value) {
addOptional(tagName, value, null);
}
/**
* Add an empty element tag (e.g. <foo/>)
*
* @param tagName The name of the tag
*
*/
public void addEmptyElement(String tagName) {
addEmptyElement(tagName, null);
}
/**
* Add an empty element tag (e.g. <foo/>)
* @param tagName The name of the tag
* @param attributes A Properties file containing the attributes (or null)
*/
public void addEmptyElement(String tagName, Properties attributes) {
m_buffer.append(m_currentIndent).append("<").append(tagName);
XMLUtils.appendAttributes(m_buffer, attributes);
m_buffer.append("/>").append(EOL);
}
private static void ppp(String s) {
System.out.println("[XMLStringBuffer] " + s);
}
/**
* Add a CDATA tag.
*/
public void addCDATA(String content) {
m_buffer.append(m_currentIndent).append("<![CDATA[").append(content).append("]]>" + EOL);
}
/**
*
* @return The StringBuffer used to create the document.
*/
public StringBuffer getStringBuffer() {
return m_buffer;
}
/**
*
* @return The String representation of the XML for this XMLStringBuffer.
*/
public String toXML() {
return m_buffer.toString();
}
public static void main(String[] argv) {
StringBuffer result = new StringBuffer();
XMLStringBuffer sb = new XMLStringBuffer(result, "");
sb.push("family");
Properties p = new Properties();
p.setProperty("prop1", "value1");
p.setProperty("prop2", "value2");
sb.addRequired("cedric", "true", p);
sb.addRequired("alois", "true");
sb.addOptional("anne-marie", (String) null);
sb.pop();
System.out.println(result.toString());
assert ("<family>" + EOL + "<cedric>true</cedric>" + EOL + "<alois>true</alois>" + EOL + "</family>" + EOL)
.equals(result.toString());
}
}
////////////////////////
class Tag {
public final String tagName;
public final String indent;
public Tag(String ind, String n) {
tagName = n;
indent = ind;
}
}