org.testng.reporters.XMLStringBuffer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of testng Show documentation
Show all versions of testng Show documentation
Testing framework for Java
package org.testng.reporters;
import org.testng.internal.Nullable;
import java.io.Writer;
import java.util.Properties;
import java.util.Stack;
import java.util.regex.Pattern;
/**
* This class allows you to generate an XML text document by pushing
* and popping tags from a stack maintained internally.
*
* @author Cedric Beust Jul 21, 2003
*/
public class XMLStringBuffer {
/** End of line, value of 'line.separator' system property or '\n' */
private static final String EOL = System.getProperty("line.separator", "\n");
/** Tab space indent for XML document */
private static final String DEFAULT_INDENT_INCREMENT = " ";
/** The buffer to hold the xml document */
private IBuffer m_buffer;
/** The stack of tags to make sure XML document is well formed. */
private final Stack m_tagStack = new Stack();
/** 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. Note that this constructor will also insert
* an ").append(EOL);
}
/**
* Set the doctype for this document.
*
* @param docType The DOCTYPE string, without the "<!DOCTYPE " ">"
*/
public void setDocType(String docType) {
m_buffer.append("" + EOL);
}
/**
* 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, @Nullable String schema, @Nullable Properties attributes) {
XMLUtils.xmlOpen(m_buffer, m_currentIndent, tagName + schema, attributes);
m_tagStack.push(new Tag(m_currentIndent, tagName, attributes));
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, @Nullable 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, @Nullable Properties attributes) {
push(tagName, "", attributes);
}
public void push(String tagName, String... attributes) {
push(tagName, createProperties(attributes));
}
private Properties createProperties(String[] attributes) {
Properties result = new Properties();
if (attributes == null) {
return result;
}
if (attributes.length % 2 != 0) {
throw new IllegalArgumentException("Arguments 'attributes' length must be even. Actual: " + attributes.length);
}
for (int i = 0; i < attributes.length; i += 2) {
result.put(attributes[i], attributes[i + 1]);
}
return result;
}
/**
* 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,
XMLUtils.extractComment(tagName, t.properties));
}
/**
* 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, @Nullable String value) {
addRequired(tagName, value, (Properties) 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, @Nullable String value, @Nullable Properties attributes) {
XMLUtils.xmlRequired(m_buffer, m_currentIndent, tagName, value, attributes);
}
public void addRequired(String tagName, @Nullable String value, String... attributes) {
addRequired(tagName, value, createProperties(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, @Nullable String value, @Nullable Properties attributes) {
if (value != null) {
XMLUtils.xmlOptional(m_buffer, m_currentIndent, tagName, value, attributes);
}
}
public void addOptional(String tagName, @Nullable String value, String... attributes) {
if (value != null) {
XMLUtils.xmlOptional(m_buffer, m_currentIndent, tagName, value, createProperties(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, @Nullable String value) {
addOptional(tagName, value, (Properties) 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, @Nullable Boolean value, @Nullable 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
*/
public void addOptional(String tagName, @Nullable Boolean value) {
addOptional(tagName, value, null);
}
/**
* Add an empty element tag (e.g. )
*
* @param tagName The name of the tag
*
*/
public void addEmptyElement(String tagName) {
addEmptyElement(tagName, (Properties) null);
}
/**
* Add an empty element tag (e.g. )
* @param tagName The name of the tag
* @param attributes A Properties file containing the attributes (or null)
*/
public void addEmptyElement(String tagName, @Nullable Properties attributes) {
m_buffer.append(m_currentIndent).append("<").append(tagName);
XMLUtils.appendAttributes(m_buffer, attributes);
m_buffer.append("/>").append(EOL);
}
public void addEmptyElement(String tagName, String... attributes) {
addEmptyElement(tagName, createProperties(attributes));
}
public void addComment(String comment) {
m_buffer.append(m_currentIndent).append("\n");
}
public void addString(String s) {
m_buffer.append(s);
}
private static void ppp(String s) {
System.out.println("[XMLStringBuffer] " + s);
}
/**
* Add a CDATA tag.
*/
public void addCDATA(String content) {
if (content == null) {
content = "null";
}
if (content.indexOf("]]>") > -1) {
String[] subStrings = content.split("]]>");
m_buffer.append(m_currentIndent).append("");
for (int i = 1; i < subStrings.length - 1; i++) {
m_buffer.append("").append(subStrings[i]).append("]]]]>");
}
m_buffer.append("").append(subStrings[subStrings.length - 1]).append("]]>");
if (content.endsWith("]]>")) {
m_buffer.append("").append("]]>");
}
m_buffer.append(EOL);
} else {
m_buffer.append(m_currentIndent).append("" + EOL);
}
}
/**
*
* @return The StringBuffer used to create the document.
*/
public IBuffer getStringBuffer() {
return m_buffer;
}
private static final Pattern INVALID_XML_CHARS =
Pattern.compile("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\uD800\uDC00-\uDBFF\uDFFF]");
/**
* @return The String representation of the XML for this XMLStringBuffer.
*/
public String toXML() {
return INVALID_XML_CHARS.matcher(m_buffer.toString()).replaceAll("");
}
public static void main(String[] argv) {
IBuffer result = Buffer.create();
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 ("" + EOL + "true " + EOL + "true " + EOL + " " + EOL)
.equals(result.toString());
}
public String getCurrentIndent() {
return m_currentIndent;
}
public void toWriter(Writer fw) {
m_buffer.toWriter(fw);
}
}
////////////////////////
class Tag {
public final String tagName;
public final String indent;
public final Properties properties;
public Tag(String ind, String n, Properties p) {
tagName = n;
indent = ind;
properties = p;
}
@Override
public String toString() {
return tagName;
}
}