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

com.espertech.esper.event.xml.SchemaUtil Maven / Gradle / Ivy

The newest version!
/*
 ***************************************************************************************
 *  Copyright (C) 2006 EsperTech, Inc. All rights reserved.                            *
 *  http://www.espertech.com/esper                                                     *
 *  http://www.espertech.com                                                           *
 *  ---------------------------------------------------------------------------------- *
 *  The software in this package is published under the terms of the GPL license       *
 *  a copy of which has been included with this distribution in the license.txt file.  *
 ***************************************************************************************
 */
package com.espertech.esper.event.xml;

import com.espertech.esper.client.EPException;
import com.espertech.esper.client.PropertyAccessException;
import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
import org.w3c.dom.*;

import javax.xml.namespace.QName;
import javax.xml.xpath.XPathConstants;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.Map;

/**
 * Utility class for querying schema information via Xerces implementation classes.
 *
 * @author pablo
 */
public class SchemaUtil {

    private static Map typeMap;

    static {
        typeMap = new HashMap();
        Object[][] types = new Object[][]{
                {"nonPositiveInteger", Integer.class},
                {"nonNegativeInteger", Integer.class},
                {"negativeInteger", Integer.class},
                {"positiveInteger", Integer.class},
                {"long", Long.class},
                {"unsignedLong", Long.class},
                {"int", Integer.class},
                {"unsignedInt", Integer.class},
                {"decimal", Double.class},
                {"integer", Integer.class},
                {"float", Float.class},
                {"double", Double.class},
                {"string", String.class},
                {"short", Short.class},
                {"unsignedShort", Short.class},
                {"byte", Byte.class},
                {"unsignedByte", Byte.class},
                {"boolean", Boolean.class},
                {"dateTime", String.class},
                {"date", String.class},
                {"time", String.class}};
        for (int i = 0; i < types.length; i++) {
            typeMap.put(types[i][0].toString(), (Class) types[i][1]);
        }
    }

    /**
     * Returns the Class-type of the schema item.
     *
     * @param item to to determine type for
     * @return type
     */
    public static Class toReturnType(SchemaItem item) {
        if (item instanceof SchemaItemAttribute) {
            SchemaItemAttribute att = (SchemaItemAttribute) item;
            return SchemaUtil.toReturnType(att.getXsSimpleType(), att.getTypeName(), null);
        } else if (item instanceof SchemaElementSimple) {
            SchemaElementSimple simple = (SchemaElementSimple) item;
            Class returnType = SchemaUtil.toReturnType(simple.getXsSimpleType(), simple.getTypeName(), simple.getFractionDigits());
            if (simple.isArray()) {
                returnType = Array.newInstance(returnType, 0).getClass();
            }
            return returnType;
        } else if (item instanceof SchemaElementComplex) {
            SchemaElementComplex complex = (SchemaElementComplex) item;
            if (complex.getOptionalSimpleType() != null) {
                return SchemaUtil.toReturnType(complex.getOptionalSimpleType(), complex.getOptionalSimpleTypeName(), null);
            }
            if (complex.isArray()) {
                return NodeList.class;
            }
            return Node.class;
        } else {
            throw new PropertyAccessException("Invalid schema return type:" + item);
        }
    }

    /**
     * Returns the type for a give short type and type name.
     *
     * @param xsType                 XSSimplyType type
     * @param typeName               type name in XML standard
     * @param optionalFractionDigits fraction digits if any are defined
     * @return equivalent native type
     */
    public static Class toReturnType(short xsType, String typeName, Integer optionalFractionDigits) {
        if (typeName != null) {
            Class result = typeMap.get(typeName);
            if (result != null) {
                return result;
            }
        }

        switch (xsType) {
            case XSSimpleType.PRIMITIVE_BOOLEAN:
                return Boolean.class;
            case XSSimpleType.PRIMITIVE_STRING:
                return String.class;
            case XSSimpleType.PRIMITIVE_DECIMAL:
                if ((optionalFractionDigits != null) && (optionalFractionDigits > 0)) {
                    return Double.class;
                }
                return Integer.class;
            case XSSimpleType.PRIMITIVE_FLOAT:
                return Float.class;
            case XSSimpleType.PRIMITIVE_DOUBLE:
                return Double.class;
            default:
                return String.class;
        }
    }

    /**
     * Returns the native type based on XPathConstants qname and an optional cast-to type, if provided.
     *
     * @param resultType         qname
     * @param optionalCastToType null or cast-to type
     * @return return type
     */
    public static Class toReturnType(QName resultType, Class optionalCastToType) {
        if (optionalCastToType != null) {
            return optionalCastToType;
        }

        if (resultType.equals(XPathConstants.NODESET))
            return NodeList.class;
        if (resultType.equals(XPathConstants.NODE))
            return Node.class;
        if (resultType.equals(XPathConstants.BOOLEAN))
            return Boolean.class;
        if (resultType.equals(XPathConstants.NUMBER))
            return Double.class;
        if (resultType.equals(XPathConstants.STRING))
            return String.class;

        return String.class;
    }

    /**
     * Returns the XPathConstants type for a given Xerces type definition.
     *
     * @param type is the type
     * @return XPathConstants type
     */
    public static QName simpleTypeToQName(short type) {
        switch (type) {
            case XSSimpleType.PRIMITIVE_BOOLEAN:
                return XPathConstants.BOOLEAN;
            case XSSimpleType.PRIMITIVE_DOUBLE:
                return XPathConstants.NUMBER;
            case XSSimpleType.PRIMITIVE_STRING:
                return XPathConstants.STRING;
            case XSSimpleType.PRIMITIVE_DECIMAL:
                return XPathConstants.NUMBER;
            case XSSimpleType.PRIMITIVE_FLOAT:
                return XPathConstants.NUMBER;
            case XSSimpleType.PRIMITIVE_DATETIME:
                return XPathConstants.STRING;
            case XSSimpleType.PRIMITIVE_DATE:
                return XPathConstants.STRING;
            case XSSimpleType.PRIMITIVE_TIME:
                return XPathConstants.STRING;
            default:
                throw new EPException("Unexpected schema simple type encountered '" + type + "'");
        }
    }

    /**
     * Returns the root element for a given schema given a root element name and namespace.
     *
     * @param schema      is the schema to interrogate
     * @param namespace   is the namespace of the root element
     * @param elementName is the name of the root element
     * @return declaration of root element
     */
    public static SchemaElementComplex findRootElement(SchemaModel schema, String namespace, String elementName) {
        if ((namespace != null) && namespace.length() != 0) {
            for (SchemaElementComplex complexElement : schema.getComponents()) {
                if ((complexElement.getNamespace().equals(namespace)) && (complexElement.getName().equals(elementName))) {
                    return complexElement;
                }
            }
        } else {
            for (SchemaElementComplex complexElement : schema.getComponents()) {
                if (complexElement.getName().equals(elementName)) {
                    return complexElement;
                }
            }
        }

        if (elementName.startsWith("//")) {
            elementName = elementName.substring(2);
            for (SchemaElementComplex complexElement : schema.getComponents()) {
                SchemaElementComplex match = recursiveDeepMatch(complexElement, namespace, elementName);
                if (match != null) {
                    return match;
                }
            }
        }

        String text = "Could not find root element declaration in schema for element name '" + elementName + '\'';
        if (namespace != null) {
            text = text + " in namespace '" + namespace + '\'';
        }
        throw new EPException(text);
    }

    private static SchemaElementComplex recursiveDeepMatch(SchemaElementComplex parent, String namespace, String elementName) {
        if ((namespace != null) && namespace.length() != 0) {
            for (SchemaElementComplex complexElement : parent.getChildren()) {
                if ((complexElement.getNamespace().equals(namespace)) && (complexElement.getName().equals(elementName))) {
                    return complexElement;
                }
            }
        } else {
            for (SchemaElementComplex complexElement : parent.getChildren()) {
                if (complexElement.getName().equals(elementName)) {
                    return complexElement;
                }
            }
        }

        for (SchemaElementComplex complexElement : parent.getChildren()) {
            SchemaElementComplex found = recursiveDeepMatch(complexElement, namespace, elementName);
            if (found != null) {
                return found;
            }
        }

        return null;
    }


    /**
     * Finds an apropiate definition for the given property, starting at the * given definition.
     * First look if the property es an attribute. If not, look at simple and then child element
     * definitions.
     *
     * @param def      the definition to start looking
     * @param property the property to look for
     * @return schema element or null if not found
     */
    public static SchemaItem findPropertyMapping(SchemaElementComplex def, String property) {

        for (SchemaItemAttribute attribute : def.getAttributes()) {
            if (attribute.getName().equals(property)) {
                return attribute;
            }
        }

        for (SchemaElementSimple simple : def.getSimpleElements()) {
            if (simple.getName().equals(property)) {
                return simple;
            }
        }

        for (SchemaElementComplex complex : def.getChildren()) {
            if (complex.getName().equals(property)) {
                return complex;
            }
        }

        //property not found in schema
        return null;
    }

    /**
     * Serialize the given node.
     *
     * @param doc node to serialize
     * @return serialized node string
     */
    public static String serialize(Node doc) {
        StringWriter writer = new StringWriter();
        try {
            serializeNode(doc, "", writer);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        writer.flush();
        return writer.toString();
    }

    private static void serializeNode(Node node, String
            indentLevel, StringWriter writer) throws IOException {
        switch (node.getNodeType()) {
            case Node.DOCUMENT_NODE:
                Document doc = (Document) node;
                writer.write("\n");

                NodeList nodes = node.getChildNodes();
                if (nodes != null) {
                    for (int i = 0; i < nodes.getLength(); i++) {
                        serializeNode(nodes.item(i), "", writer);
                    }
                }
                break;
            case Node.ELEMENT_NODE:
                String name = node.getNodeName();
                writer.write(indentLevel + "<" + name);
                NamedNodeMap attributes = node.getAttributes();
                for (int i = 0; i < attributes.getLength(); i++) {
                    Node current = attributes.item(i);
                    writer.write(" " + current.getNodeName() + "=\"");
                    print(current.getNodeValue(), writer);
                    writer.write("\"");
                }
                writer.write(">");

                NodeList children = node.getChildNodes();
                if (children != null) {
                    if ((children.item(0) != null) && (children.item(0).getNodeType() == Node.ELEMENT_NODE)) {
                        writer.write("\n");
                    }

                    for (int i = 0; i < children.getLength(); i++) {
                        serializeNode(children.item(i), indentLevel, writer);
                    }

                    if ((children.item(0) != null)
                            && (children.item(children.getLength() - 1).getNodeType() == Node.ELEMENT_NODE)) {
                        writer.write(indentLevel);
                    }
                }

                writer.write("\n");
                break;
            case Node.TEXT_NODE:
                print(node.getNodeValue(), writer);
                break;
            case Node.CDATA_SECTION_NODE:
                writer.write("CDATA");
                print(node.getNodeValue(), writer);
                writer.write("");
                break;
            case Node.COMMENT_NODE:
                writer.write(indentLevel + "\n");
                break;
            case Node.PROCESSING_INSTRUCTION_NODE:
                writer.write("\n");
                break;
            case Node.ENTITY_REFERENCE_NODE:
                writer.write("&" + node.getNodeName() + ";");
                break;
            case Node.DOCUMENT_TYPE_NODE:
                DocumentType docType = (DocumentType) node;
                String publicId = docType.getPublicId();
                String systemId = docType.getSystemId();
                String internalSubset = docType.getInternalSubset();
                writer.write("\n");
                break;
            default:
                break;
        }
    }

    private static void print(String s, Writer writer) throws IOException {
        if (s == null) {
            return;
        }
        for (int i = 0, len = s.length(); i < len; i++) {
            char c = s.charAt(i);
            switch (c) {
                case '<':
                    writer.write("<");
                    break;
                case '>':
                    writer.write(">");
                    break;
                case '&':
                    writer.write("&");
                    break;
                case '\r':
                    writer.write("
");
                    break;
                default:
                    writer.write(c);
            }
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy