XMLStreamWriterImpl.java 8.76 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.internal.xmp.utils;

import com.adobe.internal.xmp.impl.Utils;
import com.adobe.internal.xmp.options.SerializeOptions;
import java.io.IOException;
import java.io.Writer;
import java.util.HashSet;
import java.util.Stack;

public class XMLStreamWriterImpl {
    private static final String DEFAULTNS = "";
    private Writer writer;
    private boolean startElementOpened = false;
    private boolean emptyElement = false;
    private Stack qNameStack = new Stack();
    private char[] newLineStr = new char[]{'\r'};
    private int baseIndent = 0;
    private char[] indentStr = new char[]{' ', ' '};
    private int indentLevel = 0;
    private boolean charIndent = false;
    private boolean namespaceLF = true;
    private boolean preventWhitespace = false;
    private boolean preventNextLF = true;
    private final HashSet registeredPrefixes = new HashSet();
    private boolean escapeWhitespaces = true;

    public XMLStreamWriterImpl(Writer writer, SerializeOptions options) {
        this(writer);
        this.newLineStr = options.getNewline().toCharArray();
        this.indentStr = options.getIndent().toCharArray();
        this.baseIndent = options.getBaseIndent();
    }

    public XMLStreamWriterImpl(Writer writer) {
        this.writer = writer;
    }

    public void writeStartElement(String qname) throws IOException {
        if (qname == null) {
            throw new IllegalArgumentException("The element name may not be null");
        }
        this.closeStartElement();
        this.writeNewLine();
        this.write("<");
        this.write(qname);
        this.startElementOpened = true;
        this.qNameStack.push(qname);
    }

    public void writeEmptyElement(String qname) throws IOException {
        this.writeStartElement(qname);
        this.emptyElement = true;
    }

    public void writeEndElement() throws IOException {
        if (this.startElementOpened) {
            this.qNameStack.pop();
            this.write("/>");
            this.startElementOpened = false;
            if (this.emptyElement) {
                this.writeCloseElement();
                this.emptyElement = false;
            }
        } else {
            this.writeCloseElement();
        }
    }

    public void close() throws IOException {
        this.flush();
        this.writer.close();
    }

    public void flush() throws IOException {
        this.writer.flush();
    }

    public void writeEndDocument() throws IOException {
        while (!this.qNameStack.isEmpty()) {
            this.writeEndElement();
        }
    }

    public void writeAttribute(String qname, String value) throws IOException {
        if (!this.startElementOpened) {
            throw new IOException("A start element must be written before an attribute");
        }
        this.write(" ");
        this.write(qname);
        this.write("=\"");
        this.writeCharactersInternal(value.toCharArray(), 0, value.length(), true);
        this.write("\"");
    }

    public void writeNamespace(String prefix, String namespaceURI) throws IOException {
        if (!this.startElementOpened) {
            throw new IOException("A start element must be written before a namespace");
        }
        if (prefix == null || "".equals(prefix) || "xmlns".equals(prefix)) {
            this.writeDefaultNamespace(namespaceURI);
            return;
        }
        if (this.needToWriteNamespace(prefix)) {
            if (this.namespaceLF) {
                ++this.indentLevel;
                this.writeNewLine();
                --this.indentLevel;
            } else {
                this.write(' ');
            }
            this.write("xmlns:");
            this.write(prefix);
            this.write("=\"");
            this.write(namespaceURI);
            this.write("\"");
        }
    }

    public void writeDefaultNamespace(String namespaceURI) throws IOException {
        if (!this.startElementOpened) {
            throw new IOException("A start element must be written before the default namespace");
        }
        if (this.needToWriteNamespace("")) {
            this.write(" xmlns");
            this.write("=\"");
            this.write(namespaceURI);
            this.write("\"");
        }
    }

    public void writeComment(String comment) throws IOException {
        this.closeStartElement();
        this.write("<!--");
        if (comment != null) {
            this.write(comment);
        }
        this.write("-->");
    }

    public void writeProcessingInstruction(String target) throws IOException {
        this.closeStartElement();
        this.writeProcessingInstruction(target, null);
    }

    public void writeProcessingInstruction(String target, String text) throws IOException {
        this.closeStartElement();
        this.writeNewLine();
        this.write("<?");
        if (target != null) {
            this.write(target);
        }
        if (text != null) {
            this.write(' ');
            this.write(text);
        }
        this.write("?>");
    }

    public void writeDTD(String dtd) throws IOException {
        this.writeNewLine();
        this.write(dtd);
    }

    public void writeCData(String data) throws IOException {
        this.closeStartElement();
        this.write("<![CDATA[");
        if (data != null) {
            this.write(data);
        }
        this.write("]]>");
    }

    public void writeEntityRef(String name) throws IOException {
        this.closeStartElement();
        this.write("&");
        this.write(name);
        this.write(";");
    }

    public void writeStartDocument() throws IOException {
        this.writeNewLine();
        this.write("<?xml version='1.0' encoding='utf-8'?>");
    }

    public void writeStartDocument(String version) throws IOException {
        this.writeNewLine();
        this.write("<?xml version='");
        this.write(version);
        this.write("'?>");
    }

    public void writeStartDocument(String encoding, String version) throws IOException {
        this.writeNewLine();
        this.write("<?xml version='");
        this.write(version);
        this.write("' encoding='");
        this.write(encoding);
        this.write("'?>");
    }

    public void writeCharacters(String text) throws IOException {
        this.writeCharacters(text.toCharArray(), 0, text.length());
    }

    public void writeCharacters(char[] buffer, int off, int length) throws IOException {
        boolean openStartElement = this.startElementOpened;
        this.closeStartElement();
        if (openStartElement) {
            if (this.charIndent) {
                this.writeNewLine();
            } else {
                this.preventWhitespace = true;
            }
        }
        this.writeCharactersInternal(buffer, off, length, false);
    }

    public void setEscapeWhitespaces(boolean escapeWhitespaces) {
        this.escapeWhitespaces = escapeWhitespaces;
    }

    private void write(String str) throws IOException {
        this.writer.write(str);
    }

    private void write(char ch) throws IOException {
        this.writer.write(ch);
    }

    private void write(char[] buffer) throws IOException {
        this.writer.write(buffer);
    }

    private void writeCharactersInternal(char[] buffer, int off, int length, boolean isAttributeValue) throws IOException {
        ++this.indentLevel;
        String value = Utils.escapeXML(new String(buffer, off, length), isAttributeValue, this.escapeWhitespaces);
        this.writer.write(value);
        --this.indentLevel;
    }

    private void closeStartElement() throws IOException {
        if (this.startElementOpened) {
            if (!this.emptyElement) {
                this.write(">");
            } else {
                this.qNameStack.pop();
                this.write("/>");
                this.emptyElement = false;
                --this.indentLevel;
            }
            this.startElementOpened = false;
            ++this.indentLevel;
        }
    }

    private void writeCloseElement() throws IOException {
        --this.indentLevel;
        String qname = (String)this.qNameStack.pop();
        this.writeNewLine();
        this.write("</");
        this.write(qname);
        this.write(">");
        this.preventWhitespace = false;
    }

    private void writeNewLine() throws IOException {
        if (!this.preventNextLF && !this.preventWhitespace) {
            this.write(this.newLineStr);
        }
        if (!this.preventWhitespace) {
            for (int i = this.baseIndent + this.indentLevel; i > 0; --i) {
                this.writer.write(this.indentStr);
            }
        }
        this.preventNextLF = false;
    }

    private boolean needToWriteNamespace(String prefix) {
        if (!this.registeredPrefixes.contains(prefix)) {
            this.registeredPrefixes.add(prefix);
            return true;
        }
        return false;
    }
}