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

com.citytechinc.cq.component.xml.XmlWriter Maven / Gradle / Ivy

There is a newer version: 7.0.0
Show newest version
package com.citytechinc.cq.component.xml;

import org.codehaus.plexus.util.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

public class XmlWriter {

    private static final DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();

    private static final TransformerFactory transformerFactory = TransformerFactory.newInstance();

    private static final List DO_NOT_CALL = Arrays.asList("getNameSpace", "getContainedElements",
        "getFieldName", "getClass", "getRanking");

    /**
     * Widget field types that require special prefixes for correct JCR values.
     */
    private static final Set TYPES_WITH_PREFIXES;

    static {
        TYPES_WITH_PREFIXES = new HashSet();
        TYPES_WITH_PREFIXES.add(Double.class);
        TYPES_WITH_PREFIXES.add(Long.class);
        TYPES_WITH_PREFIXES.add(Boolean.class);
    }

    private XmlWriter() {
    }

    public static void writeXml(XmlElement rootXmlElement, OutputStream outputStream)
        throws ParserConfigurationException, TransformerException, IllegalArgumentException, SecurityException,
        IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        Document xmlDocument = makeDocument(rootXmlElement);

        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

        DOMSource domSource = new DOMSource(xmlDocument);

        StreamResult resultStream = new StreamResult(outputStream);

        transformer.transform(domSource, resultStream);
    }

    @SuppressWarnings({ "all" })
    private static Element createElement(XmlElement xmlElement, Document document) throws IllegalArgumentException,
        IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException {
        Class xmlClass = xmlElement.getClass();
        Method namespaceMethod = xmlClass.getMethod("getNameSpace", null);
        String namespace = (String) namespaceMethod.invoke(xmlElement, null);
        Method fieldNameMethod = xmlClass.getMethod("getFieldName", null);
        String fieldName = sanitize((String) fieldNameMethod.invoke(xmlElement, null));
        Method containedElementsMethod = xmlClass.getMethod("getContainedElements", null);
        List containedElementsReturn = (List) containedElementsMethod.invoke(xmlElement, null);
        Element createdElement;
        if (StringUtils.isEmpty(namespace)) {
            createdElement = document.createElement(fieldName);
        } else {
            createdElement = document.createElementNS(namespace, fieldName);
        }
        Method[] methods = xmlElement.getClass().getMethods();
        for (Method method : methods) {
            String methodName = method.getName();
            if (!DO_NOT_CALL.contains(methodName) && (methodName.startsWith("get") || methodName.startsWith("is"))) {
                Object methodReturn = method.invoke(xmlElement, null);
                if (methodReturn != null) {
                    if (methodReturn instanceof Map) {
                        Map returnMap = (Map) methodReturn;
                        for (Entry entry : returnMap.entrySet()) {
                            String key = entry.getKey().toString();
                            Object value = entry.getValue();
                            if (value instanceof NameSpacedAttribute) {
                                NameSpacedAttribute nsa = (NameSpacedAttribute) value;
                                setPropertyOnElement(createdElement, nsa.getNameSpace(), nsa.getNameSpacePrefix(),
                                    StringUtils.isNotEmpty(nsa.getName()) ? nsa.getName() : key, nsa.getValue());
                            } else {
                                setPropertyOnElement(createdElement, null, null, key, value);
                            }
                        }
                    } else if (methodReturn instanceof NameSpacedAttribute) {
                        NameSpacedAttribute nsa = (NameSpacedAttribute) methodReturn;
                        Object nsaObject = nsa.getValue();
                        if (nsaObject != null) {
                            if (nsaObject instanceof List) {
                                List listReturn = (List) nsaObject;
                                nsaObject = generateStringFromList(listReturn);
                            } else if (nsaObject.getClass().isArray()) {
                                Object[] arrayReturn = (Object[]) nsaObject;
                                nsaObject = generateStringFromArray(arrayReturn);
                            }
                            setPropertyOnElementForMethod(createdElement, nsa.getNameSpace(), nsa.getNameSpacePrefix(),
                                StringUtils.isNotEmpty(nsa.getName()) ? nsa.getName() : methodName, nsaObject);
                        }
                    } else if (methodReturn instanceof List) {
                        List listReturn = (List) methodReturn;
                        setPropertyOnElementForMethod(createdElement, null, null, methodName,
                            generateStringFromList(listReturn));
                    } else if (methodReturn.getClass().isArray()) {
                        Object[] arrayReturn = (Object[]) methodReturn;
                        setPropertyOnElementForMethod(createdElement, null, null, methodName,
                            generateStringFromArray(arrayReturn));
                    } else {
                        setPropertyOnElementForMethod(createdElement, null, null, methodName, methodReturn);
                    }
                }
            }
        }
        if (containedElementsReturn != null && containedElementsReturn.size() > 0) {
            for (XmlElement de : containedElementsReturn) {
                createdElement.appendChild(createElement(de, document));
            }
        }
        return createdElement;
    }

    private static Document makeDocument(XmlElement rootXmlElement) throws ParserConfigurationException,
        IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException,
        NoSuchMethodException {

        DocumentBuilder documentBuilder = docFactory.newDocumentBuilder();

        Document document = documentBuilder.newDocument();

        Element jcrRootElement = createElement(rootXmlElement, document);

        document.appendChild(jcrRootElement);

        return document;
    }

    private static String sanitize(String uncleanString) {
        uncleanString = uncleanString.replaceAll("[^A-Za-z0-9:_.-]", "");
        if (uncleanString.matches("^(\\d(.*)|(?i)XML|:(.*)|\\.(.*))")) {
            uncleanString = UUID.randomUUID().toString().replaceAll("-", "").replaceAll("[0-9]", "") + uncleanString;
        }
        return uncleanString;
    }

    private static void setPropertyOnElementForMethod(Element element, String nameSpace, String nameSpacePrefix,
        String methodName, Object methodReturn) {
        String propertyName = null;
        if (methodName.startsWith("get")) {
            propertyName = StringUtils.lowercaseFirstLetter(methodName.substring(3));
        } else if (methodName.startsWith("is")) {
            propertyName = StringUtils.lowercaseFirstLetter(methodName.substring(2));
        } else {
            propertyName = methodName;
        }
        setPropertyOnElement(element, nameSpace, nameSpacePrefix, propertyName, methodReturn);
    }

    private static void setPropertyOnElement(Element element, String nameSpace, String nameSpacePrefix, String name,
        Object value) {
        if (value != null) {
            String propertyValue = value.toString();

            Class clazz = value.getClass();

            if (TYPES_WITH_PREFIXES.contains(clazz)) {
                propertyValue = "{" + clazz.getSimpleName() + "}" + propertyValue;
            }

            if (StringUtils.isEmpty(nameSpace)) {
                element.setAttribute(name, propertyValue);
            } else {
                if (StringUtils.isNotEmpty(nameSpacePrefix)) {
                    element.setAttributeNS(nameSpace, nameSpacePrefix + ":" + name, propertyValue);
                } else {
                    element.setAttributeNS(nameSpace, name, propertyValue);
                }
            }
        }
    }

    private static String generateStringFromList(List list) {
        StringBuilder sb = new StringBuilder();
        sb.append("[").append(StringUtils.join(list.toArray(), ",")).append("]");
        return sb.toString();
    }

    private static String generateStringFromArray(Object[] array) {
        StringBuilder sb = new StringBuilder();
        sb.append("[").append(StringUtils.join(array, ",")).append("]");
        return sb.toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy