java/sql-dk/src/main/java/info/globalcode/sql/dk/formatting/AbstractXmlFormatter.java
author František Kučera <franta-hg@frantovo.cz>
Thu, 24 Oct 2019 21:43:08 +0200
branchv_0
changeset 250 aae5009bd0af
parent 245 b6ff5b7a8422
permissions -rw-r--r--
fix license version: GNU GPLv3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     1
/**
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     2
 * SQL-DK
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     3
 * Copyright © 2014 František Kučera (frantovo.cz)
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     4
 *
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     6
 * it under the terms of the GNU General Public License as published by
250
aae5009bd0af fix license version: GNU GPLv3
František Kučera <franta-hg@frantovo.cz>
parents: 245
diff changeset
     7
 * the Free Software Foundation, version 3 of the License.
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 *
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 * This program is distributed in the hope that it will be useful,
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    12
 * GNU General Public License for more details.
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    13
 *
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 * You should have received a copy of the GNU General Public License
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    16
 */
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
package info.globalcode.sql.dk.formatting;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    18
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    19
import info.globalcode.sql.dk.ColorfulPrintWriter;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    20
import info.globalcode.sql.dk.ColorfulPrintWriter.TerminalColor;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    21
import java.util.Stack;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    22
import javax.xml.namespace.QName;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    23
import static info.globalcode.sql.dk.Functions.isEmpty;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
import static info.globalcode.sql.dk.Functions.toHex;
206
e2f24eea8543 property annotations (documentation) for particular formatters
František Kučera <franta-hg@frantovo.cz>
parents: 155
diff changeset
    25
import info.globalcode.sql.dk.configuration.PropertyDeclaration;
e2f24eea8543 property annotations (documentation) for particular formatters
František Kučera <franta-hg@frantovo.cz>
parents: 155
diff changeset
    26
import static info.globalcode.sql.dk.formatting.CommonProperties.COLORFUL;
e2f24eea8543 property annotations (documentation) for particular formatters
František Kučera <franta-hg@frantovo.cz>
parents: 155
diff changeset
    27
import static info.globalcode.sql.dk.formatting.CommonProperties.COLORFUL_DESCRIPTION;
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    28
import java.nio.charset.Charset;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
import java.util.EmptyStackException;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
import java.util.HashMap;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
import java.util.LinkedHashMap;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    32
import java.util.Map;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    33
import java.util.Map.Entry;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    34
import java.util.logging.Level;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    35
import java.util.logging.Logger;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    36
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    37
/**
155
eb3676c6929b more JavaDoc
František Kučera <franta-hg@frantovo.cz>
parents: 152
diff changeset
    38
 * <p>
eb3676c6929b more JavaDoc
František Kučera <franta-hg@frantovo.cz>
parents: 152
diff changeset
    39
 * Provides helper methods for printing pretty intended and optionally colorful (syntax highlighted)
eb3676c6929b more JavaDoc
František Kučera <franta-hg@frantovo.cz>
parents: 152
diff changeset
    40
 * XML output.
eb3676c6929b more JavaDoc
František Kučera <franta-hg@frantovo.cz>
parents: 152
diff changeset
    41
 * </p>
eb3676c6929b more JavaDoc
František Kučera <franta-hg@frantovo.cz>
parents: 152
diff changeset
    42
 *
eb3676c6929b more JavaDoc
František Kučera <franta-hg@frantovo.cz>
parents: 152
diff changeset
    43
 * <p>
eb3676c6929b more JavaDoc
František Kučera <franta-hg@frantovo.cz>
parents: 152
diff changeset
    44
 * Must be used with care – bad usage can lead to invalid XML (e.g. using undeclared namespaces).
eb3676c6929b more JavaDoc
František Kučera <franta-hg@frantovo.cz>
parents: 152
diff changeset
    45
 * </p>
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    46
 *
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    47
 * @author Ing. František Kučera (frantovo.cz)
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    48
 */
207
2bba68ef47c1 property annotations: default values
František Kučera <franta-hg@frantovo.cz>
parents: 206
diff changeset
    49
@PropertyDeclaration(name = COLORFUL, defaultValue = "false", type = Boolean.class, description = COLORFUL_DESCRIPTION)
2bba68ef47c1 property annotations: default values
František Kučera <franta-hg@frantovo.cz>
parents: 206
diff changeset
    50
@PropertyDeclaration(name = AbstractXmlFormatter.PROPERTY_INDENT, defaultValue = AbstractXmlFormatter.PROPERTY_INDENT_DEFAULT, type = String.class, description = "tab or sequence of spaces used for indentation of nested elements")
2bba68ef47c1 property annotations: default values
František Kučera <franta-hg@frantovo.cz>
parents: 206
diff changeset
    51
@PropertyDeclaration(name = AbstractXmlFormatter.PROPERTY_INDENT_TEXT, defaultValue = "true", type = Boolean.class, description = "whether text with line breaks should be indented; if not original whitespace will be preserved.")
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    52
public abstract class AbstractXmlFormatter extends AbstractFormatter {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    53
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    54
	private static final Logger log = Logger.getLogger(AbstractXmlFormatter.class.getName());
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    55
	public static final String PROPERTY_INDENT = "indent";
207
2bba68ef47c1 property annotations: default values
František Kučera <franta-hg@frantovo.cz>
parents: 206
diff changeset
    56
	protected static final String PROPERTY_INDENT_DEFAULT = "\t";
130
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
    57
	public static final String PROPERTY_INDENT_TEXT = "indentText";
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    58
	private static final TerminalColor ELEMENT_COLOR = TerminalColor.Magenta;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    59
	private static final TerminalColor ATTRIBUTE_NAME_COLOR = TerminalColor.Green;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    60
	private static final TerminalColor ATTRIBUTE_VALUE_COLOR = TerminalColor.Yellow;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    61
	private static final TerminalColor XML_DECLARATION_COLOR = TerminalColor.Red;
136
c0f9521900bf XML/XHTML formatter – DOCTYPE
František Kučera <franta-hg@frantovo.cz>
parents: 132
diff changeset
    62
	private static final TerminalColor XML_DOCTYPE_COLOR = TerminalColor.Cyan;
245
b6ff5b7a8422 sqldk-relpipe convergence started
František Kučera <franta-hg@frantovo.cz>
parents: 238
diff changeset
    63
	private final Stack<QName> treePosition = new Stack<>();
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    64
	private final ColorfulPrintWriter out;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    65
	private final String indent;
130
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
    66
	private final boolean indentText;
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    67
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    68
	public AbstractXmlFormatter(FormatterContext formatterContext) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    69
		super(formatterContext);
206
e2f24eea8543 property annotations (documentation) for particular formatters
František Kučera <franta-hg@frantovo.cz>
parents: 155
diff changeset
    70
		boolean colorful = formatterContext.getProperties().getBoolean(COLORFUL, false);
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    71
		out = new ColorfulPrintWriter(formatterContext.getOutputStream(), false, colorful);
207
2bba68ef47c1 property annotations: default values
František Kučera <franta-hg@frantovo.cz>
parents: 206
diff changeset
    72
		indent = formatterContext.getProperties().getString(PROPERTY_INDENT, PROPERTY_INDENT_DEFAULT);
130
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
    73
		indentText = formatterContext.getProperties().getBoolean(PROPERTY_INDENT_TEXT, true);
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    74
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    75
		if (!indent.matches("\\s*")) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    76
			log.log(Level.WARNING, "Setting indent to „{0}“ is weird & freaky; in hex: {1}", new Object[]{indent, toHex(indent.getBytes())});
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    77
		}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    78
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    79
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    80
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    81
	protected void printStartDocument() {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    82
		out.print(XML_DECLARATION_COLOR, "<?xml version=\"1.0\" encoding=\"" + Charset.defaultCharset().name() + "\"?>");
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    83
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    84
136
c0f9521900bf XML/XHTML formatter – DOCTYPE
František Kučera <franta-hg@frantovo.cz>
parents: 132
diff changeset
    85
	protected void printDoctype(String doctype) {
c0f9521900bf XML/XHTML formatter – DOCTYPE
František Kučera <franta-hg@frantovo.cz>
parents: 132
diff changeset
    86
		out.print(XML_DOCTYPE_COLOR, "\n<!DOCTYPE " + doctype + ">");
c0f9521900bf XML/XHTML formatter – DOCTYPE
František Kučera <franta-hg@frantovo.cz>
parents: 132
diff changeset
    87
	}
c0f9521900bf XML/XHTML formatter – DOCTYPE
František Kučera <franta-hg@frantovo.cz>
parents: 132
diff changeset
    88
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    89
	protected void printEndDocument() {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    90
		out.println();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    91
		out.flush();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    92
		if (!treePosition.empty()) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    93
			throw new IllegalStateException("Some elements are not closed: " + treePosition);
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    94
		}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    95
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    96
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    97
	protected void printStartElement(QName element) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    98
		printStartElement(element, null);
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    99
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   100
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   101
	protected Map<QName, String> singleAttribute(QName name, String value) {
152
7a3382823fc3 XML formatter: use singleAttribute(qname(""), "")
František Kučera <franta-hg@frantovo.cz>
parents: 136
diff changeset
   102
		Map<QName, String> attributes = new HashMap<>(2);
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   103
		attributes.put(name, value);
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   104
		return attributes;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   105
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   106
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   107
	protected void printStartElement(QName element, Map<QName, String> attributes) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   108
		printStartElement(element, attributes, false);
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   109
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   110
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   111
	/**
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   112
	 * @param empty whether element should be closed <codfe>… /&gt;</code> (has no content, do not
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   113
	 * call {@linkplain #printEndElement()})
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   114
	 */
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   115
	private void printStartElement(QName element, Map<QName, String> attributes, boolean empty) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   116
		printIndent();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   117
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   118
		out.print(ELEMENT_COLOR, "<" + toString(element));
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   119
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   120
		if (attributes != null) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   121
			for (Entry<QName, String> attribute : attributes.entrySet()) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   122
				out.print(" ");
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   123
				out.print(ATTRIBUTE_NAME_COLOR, toString(attribute.getKey()));
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   124
				out.print("=");
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   125
				out.print(ATTRIBUTE_VALUE_COLOR, '"' + escapeXmlAttribute(attribute.getValue()) + '"');
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   126
			}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   127
		}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   129
		if (empty) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   130
			out.print(ELEMENT_COLOR, "/>");
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   131
		} else {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   132
			out.print(ELEMENT_COLOR, ">");
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   133
			treePosition.add(element);
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   134
		}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   135
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   136
		out.flush();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   137
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   138
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   139
	/**
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   140
	 * Prints text node wrapped in given element without indenting the text and adding line breaks
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   141
	 * (useful for short texts).
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   142
	 *
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   143
	 * @param attributes use {@linkplain  LinkedHashMap} to preserve attributes order
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   144
	 */
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   145
	protected void printTextElement(QName element, Map<QName, String> attributes, String text) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   146
		printStartElement(element, attributes);
130
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   147
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   148
		String[] lines = text.split("\\n");
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   149
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   150
		if (indentText && lines.length > 1) {
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   151
			for (String line : lines) {
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   152
				printText(line, true);
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   153
			}
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   154
			printEndElement(true);
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   155
		} else {
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   156
			/*
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   157
			 * line breaks at the end of the text will be eaten – if you need them, use indentText = false
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   158
			 */
132
f785ee7a70a2 XML formatter fix: line breaks at the end of the text will be eaten – if you need them, use indentText = false
František Kučera <franta-hg@frantovo.cz>
parents: 130
diff changeset
   159
			if (lines.length == 1 && text.endsWith("\n")) {
f785ee7a70a2 XML formatter fix: line breaks at the end of the text will be eaten – if you need them, use indentText = false
František Kučera <franta-hg@frantovo.cz>
parents: 130
diff changeset
   160
				text = text.substring(0, text.length() - 1);
f785ee7a70a2 XML formatter fix: line breaks at the end of the text will be eaten – if you need them, use indentText = false
František Kučera <franta-hg@frantovo.cz>
parents: 130
diff changeset
   161
			}
f785ee7a70a2 XML formatter fix: line breaks at the end of the text will be eaten – if you need them, use indentText = false
František Kučera <franta-hg@frantovo.cz>
parents: 130
diff changeset
   162
f785ee7a70a2 XML formatter fix: line breaks at the end of the text will be eaten – if you need them, use indentText = false
František Kučera <franta-hg@frantovo.cz>
parents: 130
diff changeset
   163
			printText(text, false);
130
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   164
			printEndElement(false);
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   165
		}
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   166
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   167
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   168
	protected void printEmptyElement(QName element, Map<QName, String> attributes) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   169
		printStartElement(element, attributes, true);
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   170
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   171
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   172
	protected void printEndElement() {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   173
		printEndElement(true);
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   174
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   175
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   176
	private void printEndElement(boolean indent) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   177
		try {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   178
			QName name = treePosition.pop();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   179
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   180
			if (indent) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   181
				printIndent();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   182
			}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   183
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   184
			out.print(ELEMENT_COLOR, "</" + toString(name) + ">");
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   185
			out.flush();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   186
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   187
		} catch (EmptyStackException e) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   188
			throw new IllegalStateException("No more elements to end.", e);
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   189
		}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   190
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   191
130
8548e21177f9 XML formatter: option for preserve whitespace or indent text with line breaks
František Kučera <franta-hg@frantovo.cz>
parents: 128
diff changeset
   192
	protected void printText(String s, boolean indent) {
128
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   193
		if (indent) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   194
			printIndent();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   195
		}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   196
		out.print(escapeXmlText(s));
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   197
		out.flush();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   198
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   199
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   200
	protected void printIndent() {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   201
		out.println();
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   202
		for (int i = 0; i < treePosition.size(); i++) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   203
			out.print(indent);
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   204
		}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   205
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   206
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   207
	private String toString(QName name) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   208
		if (isEmpty(name.getPrefix(), true)) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   209
			return escapeName(name.getLocalPart());
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   210
		} else {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   211
			return escapeName(name.getPrefix()) + ":" + escapeName(name.getLocalPart());
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   212
		}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   213
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   214
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   215
	private String escapeName(String s) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   216
		// TODO: avoid ugly values in <name name="…"/>		
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   217
		return s;
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   218
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   219
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   220
	private static String escapeXmlText(String s) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   221
		return s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   222
		// Not needed:
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   223
		// return s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   224
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   225
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   226
	/**
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   227
	 * Expects attribute values enclosed in "quotes" not 'apostrophes'.
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   228
	 */
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   229
	private static String escapeXmlAttribute(String s) {
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   230
		return s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;");
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   231
	}
67f5ff139da0 XML formatter: abstract + part of basic XML formatter
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   232
}