org.fireflow.model.io.service.ServiceParser.java Source code

Java tutorial

Introduction

Here is the source code for org.fireflow.model.io.service.ServiceParser.java

Source

/**
 * Copyright 2007-2011 ?
 * All rights reserved. 
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses. *
 */
package org.fireflow.model.io.service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;
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.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.lang.StringUtils;
import org.fireflow.model.InvalidModelException;
import org.fireflow.model.data.Expression;
import org.fireflow.model.data.Input;
import org.fireflow.model.data.Output;
import org.fireflow.model.data.impl.ExpressionImpl;
import org.fireflow.model.data.impl.InputImpl;
import org.fireflow.model.data.impl.OutputImpl;
import org.fireflow.model.io.DeserializerException;
import org.fireflow.model.io.ModelElementNames;
import org.fireflow.model.io.SerializerException;
import org.fireflow.model.io.Util4Deserializer;
import org.fireflow.model.io.Util4Serializer;
import org.fireflow.model.servicedef.InterfaceDef;
import org.fireflow.model.servicedef.OperationDef;
import org.fireflow.model.servicedef.ServiceDef;
import org.fireflow.model.servicedef.impl.AbstractServiceDef;
import org.fireflow.model.servicedef.impl.CommonInterfaceDef;
import org.fireflow.model.servicedef.impl.OperationDefImpl;
import org.firesoa.common.schema.NameSpaces;
import org.firesoa.common.util.ScriptLanguages;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 
 * @author ? www.firesoa.com
 * 
 * 
 */
public abstract class ServiceParser implements ModelElementNames {
    protected static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    private static String CDATA_SECTION_ELEMENT_LIST = "";
    public static final String JDK_TRANSFORMER_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";

    protected static boolean useJDKTransformerFactory = false;//??bug

    static {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        if (JDK_TRANSFORMER_CLASS.equals(transformerFactory.getClass().getName())) {
            useJDKTransformerFactory = true;
        }
        documentBuilderFactory.setNamespaceAware(true);
        StringBuffer buf = new StringBuffer();
        buf.append("{").append(ModelElementNames.SERVICE_NS_URI).append("}").append(ModelElementNames.DESCRIPTION)
                .append(" ").append("{").append(ModelElementNames.SERVICE_NS_URI).append("}")
                .append(ModelElementNames.BODY).append(" ")

                .append("{").append(ModelElementNames.RESOURCE_NS_URI).append("}")
                .append(ModelElementNames.DESCRIPTION).append(" ").append("{")
                .append(ModelElementNames.RESOURCE_NS_URI).append("}").append(ModelElementNames.BODY).append(" ");
        CDATA_SECTION_ELEMENT_LIST = buf.toString();
    }
    private static Map<String, ServiceParser> parserCache = new HashMap<String, ServiceParser>();

    public abstract ServiceDef deserializeService(Element element) throws DeserializerException;

    private static final String DEFAULT_CHARSET = "UTF-8";

    /**
     * service??elementelementparentElement?
     * 
     * @param service
     * @param parentElement
     * @throws SerializerException
     */
    public abstract void serializeService(ServiceDef service, Element parentElement) throws SerializerException;

    /**
     * service??ServiceDef
     * 
     * @param in
     * @return
     * @throws IOException
     * @throws InvalidModelException
     */
    public static List<ServiceDef> deserialize(InputStream in)
            throws IOException, DeserializerException, InvalidModelException {
        DocumentBuilder documentBuilder = null;
        try {
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document document = documentBuilder.parse(in);
            return deserialize(document);
        } catch (ParserConfigurationException e) {
            throw new DeserializerException(e);
        } catch (SAXException e) {
            throw new DeserializerException(e);
        }

    }

    public static List<ServiceDef> deserialize(Document document)
            throws DeserializerException, InvalidModelException {
        Element servicesElem = document.getDocumentElement();
        List<ServiceDef> result = new ArrayList<ServiceDef>();
        loadServices(result, servicesElem);
        return result;
    }

    public static Document serializeToDOM(List<ServiceDef> services)
            throws InvalidModelException, SerializerException {
        try {
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document document = documentBuilder.newDocument();
            Element servicesElement = document.createElementNS(SERVICE_NS_URI, SERVICE_NS_PREFIX + ":" + SERVICES);
            document.appendChild(servicesElement);

            // servicesElement.addNamespace(SERVICE_NS_PREFIX, SERVICE_NS_URI);
            // servicesElement.addNamespace(XSD_NS_PREFIX, XSD_URI);
            // servicesElement.addNamespace(XSI_NS_PREFIX, XSI_URI);

            // QName qname = df.createQName("schemaLocation", "xsi", XSI_URI);
            // servicesElement.addAttribute(qname, SERVICE_SCHEMA_LOCATION);

            for (ServiceDef svc : services) {
                ServiceParser parser = ServiceParser.getInstance(svc);
                parser.serializeService(svc, servicesElement);
            }

            return document;
        } catch (ParserConfigurationException e) {
            throw new SerializerException(e);
        } finally {

        }
    }

    public static String serializeToXmlString(List<ServiceDef> services, String charset)
            throws InvalidModelException, SerializerException {

        ByteArrayOutputStream out = new ByteArrayOutputStream();

        try {
            serialize(services, out, charset);
        } catch (IOException e) {
            throw new SerializerException(e);
        }
        return out.toString();
    }

    public static String serializeToXmlString(List<ServiceDef> services)
            throws InvalidModelException, SerializerException {
        return serializeToXmlString(services, DEFAULT_CHARSET);

    }

    public static void writeServices(List<ServiceDef> services, Element parentElement)
            throws SerializerException, InvalidModelException {
        Document document = parentElement.getOwnerDocument();
        Element servicesElement = document.createElementNS(SERVICE_NS_URI, SERVICE_NS_PREFIX + ":" + SERVICES);
        parentElement.appendChild(servicesElement);

        for (ServiceDef svc : services) {
            ServiceParser parser = ServiceParser.getInstance(svc);
            parser.serializeService(svc, servicesElement);
        }
    }

    public static void serialize(List<ServiceDef> services, OutputStream out, String charset)
            throws IOException, InvalidModelException, SerializerException {
        try {
            Document document = serializeToDOM(services);

            TransformerFactory transformerFactory = TransformerFactory.newInstance();

            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.ENCODING, charset);
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, CDATA_SECTION_ELEMENT_LIST);
            transformer.transform(new DOMSource(document), new StreamResult(out));
            out.flush();
        } catch (TransformerConfigurationException e) {
            throw new SerializerException(e);
        } catch (TransformerException e) {
            throw new SerializerException(e);
        } finally {

        }
    }

    public static void serialize(List<ServiceDef> services, OutputStream out)
            throws IOException, InvalidModelException, SerializerException {

        serialize(services, out, DEFAULT_CHARSET);
    }

    public static void loadServices(List<ServiceDef> servicesList, Element servicesElement)
            throws DeserializerException, InvalidModelException {
        if (servicesElement == null)
            return;
        servicesList.clear();

        NodeList children = servicesElement.getChildNodes();
        int length = children.getLength();
        for (int i = 0; i < length; i++) {
            Node node = children.item(i);
            if (node.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            Element svcElm = (Element) node;
            ServiceParser parser = ServiceParser.getInstance(svcElm);
            ServiceDef svcDef = parser.deserializeService(svcElm);

            servicesList.add(svcDef);
        }
    }

    public static ServiceParser getInstance(Element element) throws InvalidModelException {
        String parserClass = element.getAttribute(PARSER_CLASS_NAME);
        if (StringUtils.isEmpty(parserClass)) {
            throw new InvalidModelException("Can not find the parser-class from the service element.");
        }

        return getConcretServiceParser(parserClass);
    }

    public static ServiceParser getInstance(ServiceDef service) throws InvalidModelException {
        String parserClass = service.getParserClassName();
        if (StringUtils.isEmpty(parserClass)) {
            throw new InvalidModelException("Parser class of the Service can NOT be empty.");
        }
        return getConcretServiceParser(parserClass);
    }

    protected static ServiceParser getConcretServiceParser(String parserClassName) throws InvalidModelException {
        ServiceParser parser = parserCache.get(parserClassName);
        if (parser != null)
            return parser;
        try {
            Class clz = Class.forName(parserClassName);
            parser = (ServiceParser) clz.newInstance();
            parserCache.put(parserClassName, parser);
            return parser;
        } catch (ClassNotFoundException e) {
            throw new InvalidModelException(e);
        } catch (InstantiationException e) {
            throw new InvalidModelException(e);
        } catch (IllegalAccessException e) {
            throw new InvalidModelException(e);
        } finally {

        }

    }

    protected void writeCommonServiceAttribute(AbstractServiceDef service, Element svcElem) {
        svcElem.setAttribute(ID, service.getId());
        svcElem.setAttribute(NAME, service.getName());
        svcElem.setAttribute(BIZ_CATEGORY, service.getBizCategory());
        svcElem.setAttribute(DISPLAY_NAME, service.getDisplayName());
        svcElem.setAttribute(TARGET_NAMESPACE, service.getTargetNamespaceUri());

        if (!StringUtils.isEmpty(service.getInvokerBeanName())) {
            svcElem.setAttribute(INVOKER_BEAN_NAME, service.getInvokerBeanName());
        }

        else if (!StringUtils.isEmpty(service.getInvokerClassName())) {
            svcElem.setAttribute(INVOKER_CLASS_NAME, service.getInvokerClassName());
        }

        svcElem.setAttribute(PARSER_CLASS_NAME, service.getParserClassName());
        this.writeDescription(svcElem, service.getDescription());

    }

    protected void loadCommonServiceAttribute(AbstractServiceDef absService, Element svcElem) {
        absService.setName(svcElem.getAttribute(NAME));
        absService.setDisplayName(svcElem.getAttribute(DISPLAY_NAME));
        absService.setBizCategory(svcElem.getAttribute(BIZ_CATEGORY));
        absService.setDescription(this.loadCDATA(Util4Deserializer.child(svcElem, DESCRIPTION)));
        String beanName = svcElem.getAttribute(INVOKER_BEAN_NAME);
        if (!StringUtils.isEmpty(beanName)) {
            absService.setInvokerBeanName(beanName);
        }
        String className = svcElem.getAttribute(INVOKER_CLASS_NAME);
        if (!StringUtils.isEmpty(className)) {
            absService.setInvokerClassName(className);
        }
        absService.setParserClassName(svcElem.getAttribute(PARSER_CLASS_NAME));

        absService.setTargetNamespaceUri(svcElem.getAttribute(TARGET_NAMESPACE));
        Element extendedAttributesElement = Util4Deserializer.child(svcElem, EXTENDED_ATTRIBUTES);
        this.loadExtendedAttributes(absService.getExtendedAttributes(), extendedAttributesElement);
    }

    /**
     * common interface???
     */
    protected InterfaceDef loadCommonInterface(ServiceDef service, Element element) {
        CommonInterfaceDef _interface = new CommonInterfaceDef();

        _interface.setName(element.getAttribute(NAME));

        List<OperationDef> operations = _interface.getOperations();

        List<Element> operationElements = Util4Deserializer.children(element, OPERATION);

        if (operationElements != null) {
            for (Element operationElm : operationElements) {
                OperationDefImpl op = new OperationDefImpl();
                op.setOperationName(operationElm.getAttribute(NAME));

                // ?inputs
                List<Input> inputs = op.getInputs();
                Element inputsElement = Util4Deserializer.child(operationElm, INPUTS);
                List<Element> inputElements = Util4Deserializer.children(inputsElement, INPUT);
                if (inputElements != null) {
                    for (Element inputElm : inputElements) {
                        InputImpl input = new InputImpl();
                        input.setName(inputElm.getAttribute(NAME));
                        input.setDisplayName(inputElm.getAttribute(DISPLAY_NAME));
                        input.setDefaultValueAsString(inputElm.getAttribute(DEFAULT_VALUE));
                        input.setDataPattern(inputElm.getAttribute(DATA_PATTERN));

                        String dataTypeStr = inputElm.getAttribute(DATA_TYPE);
                        if (dataTypeStr.charAt(0) == '{') {
                            input.setDataType(javax.xml.namespace.QName.valueOf(dataTypeStr));
                        } else {
                            //TODO ? 
                            //                     service.getXmlSchemaCollection().getXmlSchemas()[0].get
                            //                     int index = dataTypeStr.indexOf(":");
                            //                     String prefix = dataTypeStr.substring(0, index);
                            //                     String localName = dataTypeStr.substring(index + 1);
                            //                     inputElm.getOwnerDocument().getn
                            //                     Namespace dom4jNs = inputElm
                            //                           .getNamespaceForPrefix(prefix);
                            //                     input.setDataType(new javax.xml.namespace.QName(
                            //                           dom4jNs.getURI(), localName, dom4jNs
                            //                                 .getPrefix()));

                        }

                        inputs.add(input);
                    }
                }

                // ?output
                List<Output> outputs = op.getOutputs();
                Element outputsElement = Util4Deserializer.child(operationElm, OUTPUTS);
                List<Element> outputElements = Util4Deserializer.children(outputsElement, OUTPUT);
                if (outputElements != null) {
                    for (Element outputElm : outputElements) {
                        OutputImpl output = new OutputImpl();
                        output.setName(outputElm.getAttribute(NAME));
                        output.setDisplayName(outputElm.getAttribute(DISPLAY_NAME));

                        String dataTypeStr = outputElm.getAttribute(DATA_TYPE);
                        if (dataTypeStr.charAt(0) == '{') {
                            output.setDataType(javax.xml.namespace.QName.valueOf(dataTypeStr));
                        } else {
                            //?
                            //                     int index = dataTypeStr.indexOf(":");
                            //                     String prefix = dataTypeStr.substring(0, index);
                            //                     String localName = dataTypeStr.substring(index + 1);
                            //                     Namespace dom4jNs = outputElm
                            //                           .getNamespaceForPrefix(prefix);
                            //                     output.setDataType(new javax.xml.namespace.QName(
                            //                           dom4jNs.getURI(), localName, dom4jNs
                            //                                 .getPrefix()));

                        }

                        outputs.add(output);
                    }
                }

                operations.add(op);
            }
        }

        return _interface;
    }

    /**
     * common interface?
     */
    protected Element writeCommonInterface(InterfaceDef _interface, Element svcElem) {
        CommonInterfaceDef commonInterface = (CommonInterfaceDef) _interface;

        Element element = Util4Serializer.addElement(svcElem, INTERFACE_COMMON);

        element.setAttribute(NAME, commonInterface.getName());
        List<OperationDef> operations = commonInterface.getOperations();
        if (operations != null) {
            for (OperationDef op : operations) {
                Element opElm = Util4Serializer.addElement(element, OPERATION);
                opElm.setAttribute(NAME, op.getOperationName());

                List<Input> inputs = op.getInputs();
                if (inputs != null) {
                    Element inputsElm = Util4Serializer.addElement(opElm, INPUTS);
                    for (Input in : inputs) {
                        Element inElm = Util4Serializer.addElement(inputsElm, INPUT);

                        inElm.setAttribute(NAME, in.getName());
                        if (!StringUtils.isEmpty(in.getDisplayName())) {
                            inElm.setAttribute(DISPLAY_NAME, in.getDisplayName());
                        }
                        if (!StringUtils.isEmpty(in.getDataPattern())) {
                            inElm.setAttribute(DATA_PATTERN, in.getDataPattern());
                        }
                        if (!StringUtils.isEmpty(in.getDefaultValueAsString())) {
                            inElm.setAttribute(DEFAULT_VALUE, in.getDefaultValueAsString());
                        }
                        if (in.getDataType() != null) {
                            inElm.setAttribute(DATA_TYPE, in.getDataType().toString());
                        }

                    }
                }

                List<Output> outputs = op.getOutputs();
                if (outputs != null) {
                    Element outputsElm = Util4Serializer.addElement(opElm, OUTPUTS);
                    for (Output out : outputs) {
                        Element outElm = Util4Serializer.addElement(outputsElm, OUTPUT);

                        outElm.setAttribute(NAME, out.getName());
                        if (!StringUtils.isEmpty(out.getDisplayName())) {
                            outElm.setAttribute(DISPLAY_NAME, out.getDisplayName());
                        }

                        if (out.getDataType() != null) {
                            outElm.setAttribute(DATA_TYPE, out.getDataType().toString());
                        }
                    }
                }
            }
        }

        return element;
    }

    protected void loadExtendedAttributes(Map<String, String> extendedAttributes,
            Element extendedAttributesElement) {
        if (extendedAttributesElement != null) {
            List<Element> children = Util4Deserializer.children(extendedAttributesElement, EXTENDED_ATTRIBUTE);
            for (Element propElem : children) {
                extendedAttributes.put(propElem.getAttribute(NAME), propElem.getAttribute(VALUE));
            }
        }
    }

    protected void writeExtendedAttributes(Map<String, String> extendedAttributes, Element serviceElement) {
        if (extendedAttributes == null || extendedAttributes.isEmpty()) {
            return;
        }

        Element extendedAttributesElement = Util4Serializer.addElement(serviceElement, EXTENDED_ATTRIBUTES);

        Iterator<String> iterator = extendedAttributes.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            Element propElm = Util4Serializer.addElement(extendedAttributesElement, EXTENDED_ATTRIBUTE);
            propElm.setAttribute(NAME, key);
            propElm.setAttribute(VALUE, extendedAttributes.get(key));

        }
    }

    protected Expression createExpression(Element expressionElement) {
        if (expressionElement != null) {
            ExpressionImpl exp = new ExpressionImpl();
            exp.setLanguage(expressionElement.getAttribute(LANGUAGE));
            exp.setName(expressionElement.getAttribute(NAME));
            exp.setDisplayName(expressionElement.getAttribute(DISPLAY_NAME));
            String dataTypeStr = expressionElement.getAttribute(DATA_TYPE);
            QName qname = QName.valueOf(dataTypeStr);
            exp.setDataType(qname);
            Element bodyElement = Util4Deserializer.child(expressionElement, BODY);

            if (bodyElement == null) {
                exp.setBody("");
            } else {
                exp.setBody(this.loadCDATA(bodyElement));
            }

            Element namespacePrefixUriMapElem = Util4Deserializer.child(expressionElement,
                    NAMESPACE_PREFIX_URI_MAP);

            if (namespacePrefixUriMapElem != null) {
                List<Element> children = Util4Deserializer.children(namespacePrefixUriMapElem, ENTRY);
                if (children != null && children.size() > 0) {
                    for (Element elem : children) {
                        String prefix = elem.getAttribute(NAME);
                        String uri = elem.getAttribute(VALUE);
                        exp.getNamespaceMap().put(prefix, uri);
                    }
                }
            }
            return exp;
        } else {
            ExpressionImpl exp = new ExpressionImpl();
            exp.setLanguage(ScriptLanguages.UNIFIEDJEXL.name());
            exp.setDataType(
                    new QName(NameSpaces.JAVA.getUri(), String.class.getName(), NameSpaces.JAVA.getPrefix()));
            exp.setName("WorkItemSubject");
            exp.setDisplayName("");// 
            exp.setBody("");
            return exp;
        }
    }

    protected void writeExpression(Expression exp, Element parent) {
        if (exp == null)
            return;
        Element expressionElem = Util4Serializer.addElement(parent, EXPRESSION);
        if (exp.getName() != null && !exp.getName().trim().equals("")) {
            expressionElem.setAttribute(NAME, exp.getName());
        }
        if (exp.getDisplayName() != null && !exp.getDisplayName().trim().equals("")) {
            expressionElem.setAttribute(DISPLAY_NAME, exp.getDisplayName());
        }
        expressionElem.setAttribute(LANGUAGE, exp.getLanguage());
        Document doc = parent.getOwnerDocument();
        String body = exp.getBody() == null ? "" : exp.getBody();
        CDATASection cdata = doc.createCDATASection(useJDKTransformerFactory ? (" " + body) : body);
        Element bodyElem = Util4Serializer.addElement(expressionElem, BODY);
        bodyElem.appendChild(cdata);

        if (exp.getNamespaceMap() != null && exp.getNamespaceMap().size() > 0) {

            Element namespaceMapElem = Util4Serializer.addElement(expressionElem, NAMESPACE_PREFIX_URI_MAP);
            Iterator<Map.Entry<String, String>> entrys = exp.getNamespaceMap().entrySet().iterator();
            while (entrys.hasNext()) {
                Map.Entry<String, String> entry = entrys.next();
                Element entryElem = Util4Serializer.addElement(namespaceMapElem, ENTRY);
                entryElem.setAttribute(NAME, entry.getKey());
                entryElem.setAttribute(VALUE, entry.getValue());
            }
        }

    }

    protected static boolean equalStrings(String s1, String s2) {
        if (s1 == s2) {
            return true;
        }
        s1 = s1 == null ? "" : s1.trim();
        s2 = s2 == null ? "" : s2.trim();
        return s1.equals(s2);
    }

    protected String loadCDATA(Element cdataElement) {
        if (cdataElement == null) {
            return "";
        } else {
            String data = cdataElement.getTextContent();
            if (data == null)
                return data;
            else {
                if (useJDKTransformerFactory) {
                    if (data.startsWith(" ")) {
                        return data.substring(1);//
                    }
                }
                return data;
            }
        }
    }

    protected void writeDescription(Element parent, String desc) {
        if (desc == null || desc.trim().equals(""))
            return;
        Document doc = parent.getOwnerDocument();
        Element descElem = Util4Serializer.addElement(parent, DESCRIPTION);

        CDATASection cdata = doc.createCDATASection(useJDKTransformerFactory ? (" " + desc) : desc);
        descElem.appendChild(cdata);
    }
}