package net.sf.jasperreports.engine.util; import java.awt.Color; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import net.sf.jasperreports.engine.JRExpression; public class JRXmlWriteHelper { private final Writer writer; private final List indents; private int indent; private final List elementStack; private StringBuffer buffer; private StackElement lastElement; protected static class Attribute { String name; String value; Attribute(String name, String value) { this.name = name; this.value = value; } } protected static class StackElement { String name; List atts; boolean hasChildren; StackElement(String name) { this.name = name; this.atts = new ArrayList(); this.hasChildren = false; } void addAttribute(String attName, String value) { this.atts.add(new JRXmlWriteHelper.Attribute(attName, value)); } } public JRXmlWriteHelper(Writer writer) { this.writer = writer; this.indents = new ArrayList(); this.indent = 0; this.elementStack = new ArrayList(); this.lastElement = null; clearBuffer(); } public void writeProlog(String encoding) throws IOException { this.writer.write("\n"); } public void writePublicDoctype(String rootElement, String description, String dtdLocation) throws IOException { this.writer.write("\n\n"); } public void startElement(String name) { this.indent++; this.lastElement = new StackElement(name); this.elementStack.add(this.lastElement); } protected void writeParents(boolean content) throws IOException { int stackSize = this.elementStack.size(); int startWrite = stackSize - 1; while (startWrite >= 0) { StackElement element = this.elementStack.get(startWrite); if (element.hasChildren) break; if (startWrite < stackSize - 1) { element.hasChildren = true; } else { element.hasChildren |= content; } startWrite--; } for (int i = startWrite + 1; i < stackSize; i++) { StackElement element = this.elementStack.get(i); writeElementAttributes(element, i); } } public void writeCDATA(String data) throws IOException { if (data != null) { writeParents(true); this.buffer.append(getIndent(this.indent)); this.buffer.append("\n"); flushBuffer(); } } public void writeCDATAElement(String name, String data) throws IOException { if (data != null) { writeParents(true); this.buffer.append(getIndent(this.indent)); this.buffer.append('<'); this.buffer.append(name); this.buffer.append(">\n"); flushBuffer(); } } public void writeCDATAElement(String name, String data, String attName, String attValue) throws IOException { writeCDATAElement(name, data, attName, attValue); } public void writeCDATAElement(String name, String data, String attName, Object attValue) throws IOException { if (data != null) { writeParents(true); this.buffer.append(getIndent(this.indent)); this.buffer.append('<'); this.buffer.append(name); if (attValue != null) { this.buffer.append(' '); this.buffer.append(attName); this.buffer.append("=\""); this.buffer.append(attValue); this.buffer.append("\""); } this.buffer.append(">\n"); flushBuffer(); } } protected void writeElementAttributes(StackElement element, int level) throws IOException { this.buffer.append(getIndent(level)); this.buffer.append('<'); this.buffer.append(element.name); for (Iterator i = element.atts.iterator(); i.hasNext(); ) { Attribute att = i.next(); this.buffer.append(' '); this.buffer.append(att.name); this.buffer.append("=\""); this.buffer.append(att.value); this.buffer.append('"'); } if (element.hasChildren) { this.buffer.append(">\n"); } else { this.buffer.append("/>\n"); } flushBuffer(); } public void closeElement() throws IOException { closeElement(false); } public void closeElement(boolean skipIfEmpty) throws IOException { this.indent--; if (skipIfEmpty && this.lastElement.atts.size() == 0 && !this.lastElement.hasChildren) { clearBuffer(); } else { writeParents(false); if (this.lastElement.hasChildren) { this.buffer.append(getIndent(this.indent)); this.buffer.append("\n"); flushBuffer(); } } this.elementStack.remove(this.indent); this.lastElement = (this.indent > 0) ? this.elementStack.get(this.indent - 1) : null; } protected char[] getIndent(int level) { if (level >= this.indents.size()) for (int i = this.indents.size(); i <= level; i++) { char[] str = new char[i]; Arrays.fill(str, '\t'); this.indents.add(str); } return this.indents.get(level); } protected void flushBuffer() throws IOException { this.writer.write(this.buffer.toString()); clearBuffer(); } protected void clearBuffer() { this.buffer = new StringBuffer(); } public void writeExpression(String name, JRExpression expression, boolean writeClass) throws IOException { writeExpression(name, expression, writeClass, null); } public void writeExpression(String name, JRExpression expression, boolean writeClass, String defaultClassName) throws IOException { if (expression != null) if (writeClass && (defaultClassName == null || !defaultClassName.equals(expression.getValueClassName()))) { writeCDATAElement(name, expression.getText(), "class", expression.getValueClassName()); } else { writeCDATAElement(name, expression.getText()); } } protected void writeAttribute(String name, String value) { this.lastElement.addAttribute(name, value); } public void addAttribute(String name, String value) { if (value != null) writeAttribute(name, value); } public void addEncodedAttribute(String name, String value) { if (value != null) writeAttribute(name, JRStringUtil.xmlEncode(value)); } public void addAttribute(String name, String value, String defaultValue) { if (value != null && !value.equals(defaultValue)) writeAttribute(name, value); } public void addEncodedAttribute(String name, String value, String defaultValue) { if (value != null && !value.equals(defaultValue)) writeAttribute(name, JRStringUtil.xmlEncode(value)); } public void addAttribute(String name, Object value) { if (value != null) writeAttribute(name, String.valueOf(value)); } public void addAttribute(String name, int value) { writeAttribute(name, String.valueOf(value)); } public void addAttributePositive(String name, int value) { if (value > 0) writeAttribute(name, String.valueOf(value)); } public void addAttribute(String name, float value) { writeAttribute(name, String.valueOf(value)); } public void addAttribute(String name, float value, float defaultValue) { if (value != defaultValue) writeAttribute(name, String.valueOf(value)); } public void addAttribute(String name, double value) { writeAttribute(name, String.valueOf(value)); } public void addAttribute(String name, double value, double defaultValue) { if (value != defaultValue) writeAttribute(name, String.valueOf(value)); } public void addAttribute(String name, int value, int defaultValue) { if (value != defaultValue) addAttribute(name, value); } public void addAttribute(String name, boolean value) { writeAttribute(name, String.valueOf(value)); } public void addAttribute(String name, boolean value, boolean defaultValue) { if (value != defaultValue) addAttribute(name, value); } public void addAttribute(String name, Color color) { if (color != null) writeAttribute(name, "#" + JRColorUtil.getColorHexa(color)); } public void addAttribute(String name, Color value, Color defaultValue) { if (value != null && value.getRGB() != defaultValue.getRGB()) addAttribute(name, value); } public void addAttribute(String name, byte value, Map xmlValues) { String xmlValue = (String)xmlValues.get(new Byte(value)); writeAttribute(name, xmlValue); } public void addAttribute(String name, int value, Map xmlValues) { String xmlValue = (String)xmlValues.get(new Integer(value)); writeAttribute(name, xmlValue); } public void addAttribute(String name, byte value, Map xmlValues, byte defaultValue) { if (value != defaultValue) addAttribute(name, value, xmlValues); } public void addAttribute(String name, Object value, Map xmlValues) { if (value != null) { String xmlValue = (String)xmlValues.get(value); writeAttribute(name, xmlValue); } } public void addAttribute(String name, Object value, Map xmlValues, Object defaultValue) { if (!value.equals(defaultValue)) addAttribute(name, value, xmlValues); } }