All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xmlparser.XmlWriter Maven / Gradle / Ivy

There is a newer version: 3.2.0
Show newest version
package xmlparser;

import xmlparser.annotations.XmlMapTagIsKey;
import xmlparser.annotations.XmlMapWithAttributes;
import xmlparser.annotations.XmlMapWithChildNodes;
import xmlparser.error.InvalidAnnotation;
import xmlparser.model.XmlElement;
import xmlparser.model.XmlElement.XmlTextElement;
import xmlparser.parsing.ObjectSerializer;
import xmlparser.utils.Interfaces.AccessSerializers;
import xmlparser.utils.Interfaces.ParserConfiguration;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import static xmlparser.utils.Constants.*;
import static xmlparser.utils.Reflection.*;
import static xmlparser.utils.Validator.multipleAreTrue;
import static xmlparser.utils.XML.*;

public interface XmlWriter extends AccessSerializers, ParserConfiguration {

    default String toXml(final Object o) {
        final StringWriter output = new StringWriter();

        try { writeObject(output, toName(o.getClass()), o, EMPTY); }
        catch (IllegalArgumentException | IllegalAccessException | IOException e) { /* can't happen */ }

        return output.toString();
    }
    default void toXml(final Object o, final Writer writer) throws IOException {
        try { writeObject(writer, toName(o.getClass()), o, EMPTY); }
        catch (IllegalArgumentException | IllegalAccessException e) { /* can't happen */ }
    }

    default String domToXml(final XmlElement node) {
        final StringWriter output = new StringWriter();

        try { domToXml(node, output); }
        catch (IOException e) { /* can't happen */ }

        return output.toString();
    }
    default void domToXml(final XmlElement node, final Writer writer) throws IOException {
        domToXml(node, writer, "");
    }
    default void domToXml(final XmlElement node, final Writer writer, final String indent) throws IOException {
        final String text = node.getText();
        if (text == null && node.children.isEmpty()) {
            writeIndent(writer, indent);
            writeSelfClosingTag(writer, node.name, attributesToXml(node.attributes, shouldEncodeUTF8()));
            writeNewLine(writer);
        } else if (!node.hasNonTextChildren() && node.attributes.isEmpty()) {
            writeIndent(writer, indent);
            writeOpeningAndClosingTag(writer, node.name, text);
            writeNewLine(writer);
        } else {
            writeIndent(writer, indent);
            writeOpeningTag(writer, node.name, attributesToXml(node.attributes, shouldEncodeUTF8()));
            writeNewLine(writer);
            for (final XmlElement child : node.children) {
                if (child instanceof XmlTextElement) continue;

                domToXml(child, writer, INDENT+indent);
            }
            if (text != null) {
                writeIndent(writer, indent);
                writer.append(escapeXml(text, shouldEncodeUTF8()));
            }
            writeIndent(writer, indent);
            writeClosingTag(writer, node.name);
            writeNewLine(writer);
        }
    }


    private void writeSimple(final Writer writer, final String name, final Object value, final String indent) throws IOException {
        writeIndent(writer, indent);
        writeTag(writer, name, escapeXml(getSerializer(value.getClass()).convert(value), shouldEncodeUTF8()));
        writeNewLine(writer);
    }

    private void writeSimple(final Writer writer, final String name, final Object value, final List attributes
            , final Object text, final String indent) throws IOException, IllegalAccessException {
        writeIndent(writer, indent);
        writeTag(writer, name, attributesToXml(attributes, value, shouldEncodeUTF8()),
                escapeXml(getSerializer(text.getClass()).convert(text), shouldEncodeUTF8()));
        writeNewLine(writer);
    }

    private void writeList(final Writer writer, final Field field, final String name, final Object o, final String indent)
            throws IllegalArgumentException, IllegalAccessException, IOException {
        for (final Object item : (List) o) {
            writeField(item.getClass(), field, writer, name, item, indent);
        }
    }

    private void writeArray(final Writer writer, final Field field, final String name, final Object o, final String indent)
            throws IllegalArgumentException, IllegalAccessException, IOException {
        for (final Object item : (Object[]) o) {
            writeField(item.getClass(), field, writer, name, item, indent);
        }
    }

    private void writeSet(final Writer writer, final Field field, final String name, final Object o, final String indent)
            throws IllegalArgumentException, IllegalAccessException, IOException {
        for (final Object item : (Set) o) {
            writeField(item.getClass(), field, writer, name, item, indent);
        }
    }

    private void writeMap(final Writer writer, final Field field, final String name, final Object o, final String indent)
            throws IllegalArgumentException, IllegalAccessException, IOException {

        final boolean isXmlMapTagIsKey = field.isAnnotationPresent(XmlMapTagIsKey.class);
        final boolean isXmlMapWithAttributes = field.isAnnotationPresent(XmlMapWithAttributes.class);
        final boolean isXmlMapWithChildNodes = field.isAnnotationPresent(XmlMapWithChildNodes.class);

        if (multipleAreTrue(isXmlMapTagIsKey, isXmlMapWithAttributes, isXmlMapWithChildNodes))
            throw new InvalidAnnotation("Only one of XmlMapTagIsKey, XmlMapWithAttributes and XmlMapWithChildNodes is allowed per field");

        final ParameterizedType type = (ParameterizedType) field.getGenericType();
        final Map map = (Map) o;
        final ObjectSerializer convKey = getSerializer(toClassOfMapKey(type));
        final ObjectSerializer convVal = getSerializer(toClassOfMapValue(type));

        if (isXmlMapWithAttributes) {
            final XmlMapWithAttributes annotation = field.getAnnotation(XmlMapWithAttributes.class);
            final String keyName = annotation.keyName();
            final String valueName = annotation.valueName();

            for (final Entry entry : map.entrySet()) {
                writeIndent(writer, indent);
                if (valueName.isEmpty()) {
                    final StringBuilder builder = new StringBuilder();
                    addAttribute(builder, keyName, escapeXml(convKey.convert(entry.getKey()), shouldEncodeUTF8()));
                    writeTag(writer, name, builder.toString(), escapeXml(convVal.convert(entry.getValue()), shouldEncodeUTF8()));
                } else {
                    final StringBuilder builder = new StringBuilder();
                    addAttribute(builder, keyName, escapeXml(convKey.convert(entry.getKey()), shouldEncodeUTF8()));
                    addAttribute(builder, valueName, escapeXml(convVal.convert(entry.getValue()), shouldEncodeUTF8()));
                    writeSelfClosingTag(writer, name, builder.toString());
                }
                writeNewLine(writer);
            }
            return;
        }

        if (isXmlMapWithChildNodes) {
            final XmlMapWithChildNodes annotation = field.getAnnotation(XmlMapWithChildNodes.class);
            final String keyName = annotation.keyName();
            final String valueName = annotation.valueName();

            for (final Entry entry : map.entrySet()) {
                writeIndent(writer, indent);
                writeOpeningTag(writer, name);
                writeNewLine(writer);
                writeField(entry.getKey().getClass(), field, writer, keyName, entry.getKey(), indent+INDENT);
                if (valueName.isEmpty()) {
                    writeIndent(writer, indent+INDENT);
                    writer.append(escapeXml(convVal.convert(entry.getValue()), shouldEncodeUTF8()));
                    writeNewLine(writer);
                } else {
                    writeField(entry.getValue().getClass(), field, writer, valueName, entry.getValue(), indent+INDENT);
                }
                writeIndent(writer, indent);
                writeClosingTag(writer, name);
                writeNewLine(writer);
            }
            return;
        }

        writeIndent(writer, indent);
        writeOpeningTag(writer, name);
        writeNewLine(writer);
        for (final Entry entry : map.entrySet()) {
            writeField(entry.getValue().getClass(), field, writer, entry.getKey().toString(), entry.getValue(), indent+INDENT);
        }
        writeIndent(writer, indent);
        writeClosingTag(writer, name);
        writeNewLine(writer);
    }

    private void writeEnum(final Writer writer, final String name, final Object o, final String indent) throws IOException {
        writeIndent(writer, indent);
        writeTag(writer, name, escapeXml(toEnumName(o), shouldEncodeUTF8()));
        writeNewLine(writer);
    }

    private void writeObject(final Writer writer, final String name, final Object o, final String indent)
            throws IllegalArgumentException, IllegalAccessException, IOException {
        final List attributes = new LinkedList<>();
        final List childNodes = new LinkedList<>();
        final Field textNode = determineTypeOfFields(o.getClass(), o, attributes, childNodes);

        if (childNodes.isEmpty()) {
            if (textNode == null) {
                writeIndent(writer, indent);
                writeSelfClosingTag(writer, name, attributesToXml(attributes, o, shouldEncodeUTF8()));
                writeNewLine(writer);
            }
            else
                writeSimple(writer, name, o, attributes, textNode.get(o), indent);
            return;
        }

        writeIndent(writer, indent);
        writeOpeningTag(writer, name, attributesToXml(attributes, o, shouldEncodeUTF8()));
        writeNewLine(writer);

        for (final Field f : childNodes) {
            boolean isWrapped = isWrapped(f);
            if (isWrapped) {
                writeIndent(writer, indent+INDENT);
                writeOpeningTag(writer, toWrappedName(f));
                writeNewLine(writer);
                writeField(f.getType(), f, writer, toName(f), f.get(o), indent+INDENT+INDENT);
                writeIndent(writer, indent+INDENT);
                writeClosingTag(writer, toWrappedName(f));
                writeNewLine(writer);
            } else {
                writeField(f.getType(), f, writer, toName(f), f.get(o), indent+INDENT);
            }
        }
        if (textNode != null) {
            writeIndent(writer, indent);
            writer.append(escapeXml(textNode.get(o).toString(), shouldEncodeUTF8()));
            writeNewLine(writer);
        }
        writeIndent(writer, indent);
        writeClosingTag(writer, name);
        writeNewLine(writer);
    }

    private void writeField(final Class c, final Field field, final Writer writer,
            final String name, final Object value, final String indent)
            throws IllegalArgumentException, IllegalAccessException, IOException {
        switch (toClassType(c, this)) {
            case SIMPLE -> writeSimple(writer, name, value, indent);
            case ARRAY -> writeArray(writer, field, name, value, indent);
            case LIST -> writeList(writer, field, name, value, indent);
            case SET -> writeSet(writer, field, name, value, indent);
            case MAP -> writeMap(writer, field, name, value, indent);
            case ENUM -> writeEnum(writer, name, value, indent);
            default -> writeObject(writer, name, value, indent);
        }
    }

    private void writeIndent(final Writer writer, final String indent) throws IOException {
        if (shouldPrettyPrint()) writer.append(indent);
    }
    private void writeNewLine(final Writer writer) throws IOException {
        if (shouldPrettyPrint()) writer.append(NEW_LINE);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy