package org.rrd4j.core; import java.awt.Color; import java.awt.Font; import java.io.File; import java.io.OutputStream; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.Stack; import java.util.TimeZone; /** * Extremely simple utility class used to create XML documents. */ public class XmlWriter { static final String INDENT_STR = " "; private static final String STYLE = "style"; private static final ThreadLocal<SimpleDateFormat> ISOLIKE = new ThreadLocal<SimpleDateFormat>() { @Override protected SimpleDateFormat initialValue() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ", Locale.ENGLISH); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); return sdf; } }; private final PrintWriter writer; private final StringBuilder indent = new StringBuilder(""); private final Stack<String> openTags = new Stack<String>(); /** * Creates XmlWriter with the specified output stream to send XML code to. * * @param stream Output stream which receives XML code */ public XmlWriter(OutputStream stream) { writer = new PrintWriter(stream, true); } /** * Creates XmlWriter with the specified output stream to send XML code to. * * @param stream Output stream which receives XML code * @param autoFlush is the stream to be flushed automatically */ public XmlWriter(OutputStream stream, boolean autoFlush) { writer = new PrintWriter(stream, autoFlush); } /** * Opens XML tag * * @param tag XML tag name */ public void startTag(String tag) { writer.println(indent + "<" + tag + ">"); openTags.push(tag); indent.append(INDENT_STR); } /** * Closes the corresponding XML tag */ public void closeTag() { String tag = openTags.pop(); indent.setLength(indent.length() - INDENT_STR.length()); writer.println(indent + "</" + tag + ">"); } /** * Writes <tag>value</tag> to output stream * * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, Object value) { if (value != null) { writer.println(indent + "<" + tag + ">" + escape(value.toString()) + "</" + tag + ">"); } else { writer.println(indent + "<" + tag + "></" + tag + ">"); } } /** * Writes <tag>value</tag> to output stream * * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, int value) { writeTag(tag, Integer.toString(value)); } /** * Writes <tag>value</tag> to output stream * * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, long value) { writeTag(tag, Long.toString(value)); } /** * Writes <tag>value</tag> to output stream * * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> * @param nanString a {@link java.lang.String} object. */ public void writeTag(String tag, double value, String nanString) { writeTag(tag, Util.formatDouble(value, nanString, true)); } /** * Writes <tag>value</tag> to output stream * * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, double value) { writeTag(tag, Util.formatDouble(value, true)); } /** * Writes <tag>value</tag> to output stream * * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, boolean value) { writeTag(tag, Boolean.toString(value)); } /** * Writes <tag>value</tag> to output stream * * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, Color value) { int rgb = value.getRGB() & 0xFFFFFF; writeTag(tag, "#" + Integer.toHexString(rgb).toUpperCase()); } /** * Writes <tag>value</tag> to output stream * * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, Font value) { startTag(tag); writeTag("name", value.getName()); int style = value.getStyle(); if ((style & Font.BOLD) != 0 && (style & Font.ITALIC) != 0) { writeTag(STYLE, "BOLDITALIC"); } else if ((style & Font.BOLD) != 0) { writeTag(STYLE, "BOLD"); } else if ((style & Font.ITALIC) != 0) { writeTag(STYLE, "ITALIC"); } else { writeTag(STYLE, "PLAIN"); } writeTag("size", value.getSize()); closeTag(); } /** * Writes <tag>value</tag> to output stream * * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, File value) { writeTag(tag, value.getPath()); } /** * Flushes the output stream */ public void flush() { writer.flush(); } /** * Writes XML comment to output stream * * @param comment comment string */ public void writeComment(Object comment) { if (comment instanceof Date) { comment = ISOLIKE.get().format((Date) comment); } writer.println(indent + "<!-- " + escape(comment.toString()) + " -->"); } private static String escape(String s) { return s.replaceAll("<", "<").replaceAll(">", ">"); } }