Package org.wso2.carbon.rulecep.service

Source Code of org.wso2.carbon.rulecep.service.ServiceWSDLBuilder

/*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you under the Apache License, Version 2.0 (the
*  "License"); you may not use this file except in compliance
*  with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing,
*  software distributed under the License is distributed on an
*   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
*  specific language governing permissions and limitations
*  under the License.
*/
package org.wso2.carbon.rulecep.service;

import org.apache.axis2.description.AxisMessage;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.java2wsdl.DefaultNamespaceGenerator;
import org.apache.axis2.description.java2wsdl.Java2WSDLConstants;
import org.apache.axis2.description.java2wsdl.NamespaceGenerator;
import org.apache.axis2.description.java2wsdl.TypeTable;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.*;
import org.apache.ws.commons.schema.utils.NamespaceMap;
import org.apache.ws.commons.schema.utils.NamespacePrefixList;
import org.wso2.carbon.rulecep.adapters.InputAdapterFactory;
import org.wso2.carbon.rulecep.adapters.OutputAdapterFactory;
import org.wso2.carbon.rulecep.adapters.impl.OMElementResourceAdapter;
import org.wso2.carbon.rulecep.commons.LoggedRuntimeException;
import org.wso2.carbon.rulecep.commons.descriptions.ResourceDescription;
import org.wso2.carbon.rulecep.commons.descriptions.service.ServiceDescription;

import javax.xml.namespace.QName;
import java.util.*;

/**
* TODO Some Code are copied from axis2 - need to review
* Creates a WSDL for a Rule Service
*/
public class ServiceWSDLBuilder implements Java2WSDLConstants {

    private static final Log log = LogFactory.getLog(ServiceWSDLBuilder.class);
    public static final String NAME_SPACE_PREFIX = "rsns";// axis2 name space
    private int prefixCount = 1;
    private Map<String, String> targetNamespacePrefixMap = new Hashtable<String, String>();
    private XmlSchemaCollection xmlSchemaCollection = new XmlSchemaCollection();
    private AxisService service;
    private Map<String, XmlSchema> schemaMap = new HashMap<String, XmlSchema>();
    private TypeTable typeTable = new TypeTable();
    private String schemaTargetNameSpace;
    private String schema_namespace_prefix;
    private String attrFormDefault = null;
    private String elementFormDefault = null;
    private boolean useWSDLTypesNamespace = false;
    private Map<String, String> pkg2nsmap = null;
    private NamespaceGenerator nsGen = null;
    private String targetNamespace = null;
    private boolean isGenerateWrappedArrayTypes = false;
    final List<String> names = new ArrayList<String>();
    private ServiceDescription serviceDescription;

    public ServiceWSDLBuilder(AxisService service,
                              ServiceDescription serviceDescription) {
        this.service = service;
        this.serviceDescription = serviceDescription;
    }

    /**
     * Starts the WSDL building process by setting target namespace , prefix , etc
     */
    public void startBuild() {

        this.targetNamespace = serviceDescription.getTargetNamespace();
        this.schemaTargetNameSpace = serviceDescription.getTargetNamespace();
        this.schema_namespace_prefix = serviceDescription.getTargetNSPrefix();

        if (this.targetNamespace == null) {
            this.targetNamespace = service.getTargetNamespace();
        }
        if (this.schemaTargetNameSpace == null) {
            this.schemaTargetNameSpace = service.getTargetNamespace();
        }
//        this.schema_namespace_prefix = service.getSchemaTargetNamespacePrefix();

        Parameter generateWrappedArrayTypes = service.getParameter("generateWrappedArrayTypes");
        if ((generateWrappedArrayTypes != null) &&
                JavaUtils.isTrue(generateWrappedArrayTypes.getValue())) {
            isGenerateWrappedArrayTypes = true;
        }
        getXmlSchema(schemaTargetNameSpace);
    }

    /**
     * Builds the WSDL In message part for the given operation.
     *
     * @param axisOperation <code>AxisOperation</code> instance
     * @param facts         A list of facts that defines the arguments of the WSDL In message
     * @param factory       <code>InputAdapterFactory</code> to be used to find registered fact adapters
     */
    public void buildInMessage(AxisOperation axisOperation,
                               List<ResourceDescription> facts,
                               InputAdapterFactory factory) {
        try {
            String methodName = axisOperation.getName().getLocalPart();
            String partQName = methodName + Java2WSDLConstants.MESSAGE_SUFFIX;
            AxisMessage inMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
            inMessage.setName(partQName);
            XmlSchemaSequence sequence = generateSchema(facts,
                    partQName, factory.getInputAdapters(), "parameter");
            XmlSchemaComplexType methodSchemaType =
                    createSchemaTypeForMethodPart(partQName);
            if (sequence != null) {
                methodSchemaType.setParticle(sequence);
            }
            QName elementQName = typeTable.getQNamefortheType(partQName);
            setParentElementQName(facts, elementQName);
            inMessage.setElementQName(elementQName);
            service.addMessageElementQNameToOperationMapping(methodSchemaType.getQName(),
                    axisOperation);
        } catch (Exception e) {
            throw new LoggedRuntimeException("Error when preparing in-message " +
                    "of operation : " + axisOperation.getName(), e, log);
        }
    }

    /**
     * Builds the WSDL out message part for the given operation.
     *
     * @param axisOperation <code>AxisOperation</code> instance
     * @param results       A list of results that defines the arguments of the WSDL out message
     * @param factory       <code>OutputAdapterFactory</code> to be used to find registered result adapters
     */
    public void buildOutMessage(AxisOperation axisOperation,
                                List<ResourceDescription> results,
                                OutputAdapterFactory factory) {
        try {
            ResourceDescription firstDescription = results.get(0);
            if (!OMElementResourceAdapter.TYPE.equals(firstDescription.getType())) {
                throw new LoggedRuntimeException("Invalid result !! result type is invalid", log);
            }
            String methodName = axisOperation.getName().getLocalPart();
            String partQName = methodName + RESPONSE;
            AxisMessage outMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
            outMessage.setName(partQName);
            XmlSchemaSequence sequence = generateSchema(firstDescription.getChildResources(),
                    partQName, factory.getOutputAdapters(), "item");
             XmlSchemaComplexType methodSchemaType =
                    createSchemaTypeForMethodPart(partQName);
            if(sequence != null){
                methodSchemaType.setParticle(sequence);
            }
            QName elementQName = typeTable.getQNamefortheType(partQName);
            setParentElementQName((List)results.get(0).getChildResources(), elementQName);
            outMessage.setElementQName(elementQName);
            firstDescription.setElementQName(elementQName);
            service.addMessageElementQNameToOperationMapping(methodSchemaType.getQName(),
                    axisOperation);
        } catch (Exception e) {
            throw new LoggedRuntimeException("Error when preparing out-message " +
                    "of operation : " + axisOperation.getName(), e, log);
        }
    }

    /**
     * Ends the WSDL building process
     */
    public void endBuild() {
        service.addSchema(schemaMap.values());
    }

    /**
     * Helper method to generate WSDL message parts and required schema from a given
     * a list of resource descriptions
     *
     * @param descriptions a list of resource descriptions
     * @param partName     part name of the WSDL message
     * @param types        a set of registered adapter types
     * @param id           default id to be used to named elements in the parts
     * @return <code> XmlSchemaComplexType</code> for a operation
     */
    private XmlSchemaSequence generateSchema(Collection<ResourceDescription> descriptions,
                                             String partName,
                                             Collection<String> types, String id) {

        if (descriptions.isEmpty()) {
            if (log.isDebugEnabled()) {
                log.debug("There is no resources to generate schema types for part name :" +
                        partName);
            }
            return null;
        }

        int number = 0;
        XmlSchemaSequence sequence = new XmlSchemaSequence();
        for (ResourceDescription description : descriptions) {

            if (description == null) {
                continue;
            }

            String name = description.getName();
            if (!types.contains(description.getType())) {
                String className = description.getType();
                if (className == null) {
                    continue;
                }

                description.setTypeTable(typeTable);
                description.setResourceClassLoader(service.getClassLoader());
                boolean isSimpleType = (typeTable.getSimpleSchemaTypeName(className) != null);
                if (!names.contains(className) && !isSimpleType) {
                    generateSchemaFroClass(className);
                    names.add(className);
                }

                if (name == null || "".equals(name)) {
                    String cName = className;
                    if (cName.indexOf(".") != -1) {
                        name = cName.substring(cName.lastIndexOf('.') + 1,
                                cName.length());
//                            String firstChar = Character.toString(name.charAt(0)).toLowerCase();
//                            name = firstChar + name.substring(1);
                    }
                }

                if (name == null || "".equals(name)) {
                    name = id + number;
                    number++;
                }

                XmlSchemaElement el = new XmlSchemaElement();
                if (isSimpleType) {
                    el.setSchemaTypeName(typeTable.getSimpleSchemaTypeName(className));
                } else {
                    setSchemaTypeOnElement(el, className);
                }
                sequence.getItems().add(el);
                description.setElementQName(
                        new QName(schemaTargetNameSpace, name, schema_namespace_prefix));
                el.setName(name);
                el.setMinOccurs(0);
                el.setMaxOccurs(Long.MAX_VALUE);
            } else {
                XmlSchemaAny el = new XmlSchemaAny();
                sequence.getItems().add(el);
            }
        }

        return sequence;

    }

    /**
     * Sets the Schema Type Name to the given  XmlSchemaElement
     *
     * @param el        <code >XmlSchemaElement</code>
     * @param className Class name to be used to find the  ComplexSchemaType using type-table
     */
    private void setSchemaTypeOnElement(XmlSchemaElement el, String className) {
        Collection<XmlSchema> xmlSchemas = schemaMap.values();
        for (XmlSchema schema : xmlSchemas) {
            Iterator<?> iterator = schema.getItems().getIterator();
            while (iterator.hasNext()) {

                XmlSchemaObject object = (XmlSchemaObject) iterator.next();
                if (!(object instanceof XmlSchemaType)) {
                    continue;
                }

                QName qName =
                        ((XmlSchemaType) object).getQName();
                if (qName == null) {
                    continue;
                }

                if (qName.equals(typeTable.getComplexSchemaType(className))) {
                    el.setSchemaTypeName(qName);
                    addImport(getXmlSchema(schemaTargetNameSpace), qName);
                    return;
                } else if (qName.equals(typeTable.getSimpleSchemaTypeName(className))) {
                    el.setSchemaTypeName(qName);
                    addImport(getXmlSchema(schemaTargetNameSpace), qName);
                    return;
                }
            }
        }
    }

    private void addImport(XmlSchema xmlSchema, QName schemaTypeName) {
        NamespacePrefixList map = xmlSchema.getNamespaceContext();
        if (map == null ||
                ((map instanceof NamespaceMap) && ((NamespaceMap) map).values() == null) ||
                schemaTypeName == null) {
            return;
        }
        if (map instanceof NamespaceMap && !((NamespaceMap) map).values().
                contains(schemaTypeName.getNamespaceURI())) {
            XmlSchemaImport importElement = new XmlSchemaImport();
            importElement.setNamespace(schemaTypeName.getNamespaceURI());
            xmlSchema.getItems().add(importElement);
            ((NamespaceMap) xmlSchema.getNamespaceContext()).
                    put(generatePrefix(), schemaTypeName.getNamespaceURI());
        }
    }

    /**
     * Helper method to generate a schema for a Java Type
     *
     * @param className Java Type
     */
    private void generateSchemaFroClass(String className) {
        try {
            POJO2SchemaGenerator schemaGenerator = new POJO2SchemaGenerator(
                    service.getClassLoader(),
                    className, null, null, service);
            schemaGenerator.generateSchema();
            Map map = schemaGenerator.getTypeTable().getComplexSchemaMap();
            for (Object typeName : map.keySet()) {
                typeTable.addComplexSchema((String) typeName, (QName) map.get(typeName));
            }
            mergeTwoSchemaTypes(schemaGenerator.getSchemaMap());
        } catch (Exception e) {
            throw new LoggedRuntimeException("Error generating schema", e, log);
        }
    }

    /**
     * Helper methods to merge two schema types
     *
     * @param xmlSchemaMap XmlSchema types map to be merged into main XmlSchema map
     */
    private void mergeTwoSchemaTypes(Map<String, XmlSchema> xmlSchemaMap) {
        for (String ns : xmlSchemaMap.keySet()) {

            XmlSchema tobeAdd = xmlSchemaMap.get(ns);
            if (!schemaMap.containsKey(ns)) {
                schemaMap.put(ns, tobeAdd);
                continue;
            }

            XmlSchema xmlSchema = schemaMap.get(ns);
            Iterator<?> iterator = tobeAdd.getItems().getIterator();
            while (iterator.hasNext()) {

                XmlSchemaObject object = (XmlSchemaObject) iterator.next();
                if (!(object instanceof XmlSchemaType)) {
                    continue;
                }

                XmlSchemaType xmlSchemaType = (XmlSchemaType) object;
                QName qName = xmlSchemaType.getQName();

                boolean canAdd = false;
                XmlSchemaObjectCollection collection = xmlSchema.getItems();
                Iterator<?> it = collection.getIterator();
                while (it.hasNext()) {
                    XmlSchemaObject schemaObject = (XmlSchemaObject) it.next();
                    if (!(schemaObject instanceof XmlSchemaType)) {
                        continue;
                    }

                    XmlSchemaType type = (XmlSchemaType) schemaObject;
                    if (!qName.equals(type.getQName())) {
                        canAdd = true;
                        break;
                    }
                }
                if (canAdd) {
                    collection.add(object);
                }
            }
        }
    }

    private void setParentElementQName(List<ResourceDescription> descriptions, QName parent) {
        for (ResourceDescription description : descriptions) {
            if (description != null) {
                description.setParentElementQName(parent);
            }
        }
    }

    /**
     * * Following all Code copied from the Axis2 - TODO**
     */

    private XmlSchemaComplexType createSchemaTypeForMethodPart(String localPartName) {

        XmlSchema xmlSchema = getXmlSchema(schemaTargetNameSpace);
        QName elementName =
                new QName(this.schemaTargetNameSpace, localPartName, this.schema_namespace_prefix);
        XmlSchemaComplexType
                complexType = getComplexTypeForElement(xmlSchema, elementName);
        if (complexType == null) {
            complexType = new XmlSchemaComplexType(xmlSchema);
            XmlSchemaElement globalElement = new XmlSchemaElement();
            globalElement.setSchemaType(complexType);
            globalElement.setName(localPartName);
            globalElement.setQName(elementName);
            xmlSchema.getItems().add(globalElement);
            xmlSchema.getElements().add(elementName, globalElement);
        }
        typeTable.addComplexSchema(localPartName, elementName);

        return complexType;
    }

    private XmlSchemaComplexType createComplexTypeForWrapper(String localPartName) {

        XmlSchema xmlSchema = getXmlSchema(schemaTargetNameSpace);
        QName elementName =
                new QName(this.schemaTargetNameSpace, localPartName, this.schema_namespace_prefix);
        XmlSchemaComplexType
                complexType = getComplexTypeForElement(xmlSchema, elementName);
        if (complexType == null) {
            complexType = new XmlSchemaComplexType(xmlSchema);
            complexType.setName(localPartName);
            xmlSchema.getItems().add(complexType);
        }
        typeTable.addComplexSchema(localPartName, elementName);

        return complexType;
    }

    private XmlSchema getXmlSchema(String targetNamespace) {
        XmlSchema xmlSchema;

        if ((xmlSchema = schemaMap.get(targetNamespace)) == null) {
            String targetNamespacePrefix;

            if (targetNamespace.equals(schemaTargetNameSpace) &&
                    schema_namespace_prefix != null) {
                targetNamespacePrefix = schema_namespace_prefix;
            } else {
                targetNamespacePrefix = generatePrefix();
            }
            xmlSchema = new XmlSchema(targetNamespace, xmlSchemaCollection);
            xmlSchema.setAttributeFormDefault(getAttrFormDefaultSetting());
            xmlSchema.setElementFormDefault(getElementFormDefaultSetting());

            targetNamespacePrefixMap.put(targetNamespace, targetNamespacePrefix);
            schemaMap.put(targetNamespace, xmlSchema);

            NamespaceMap prefixmap = new NamespaceMap();
            prefixmap.put(DEFAULT_SCHEMA_NAMESPACE_PREFIX, URI_2001_SCHEMA_XSD);
            prefixmap.put(targetNamespacePrefix, targetNamespace);
            xmlSchema.setNamespaceContext(prefixmap);
        }
        return xmlSchema;
    }

    private String generatePrefix() {
        return NAME_SPACE_PREFIX + prefixCount++;
    }

    private String getAttrFormDefault() {
        return attrFormDefault;
    }

    private String getElementFormDefault() {
        return elementFormDefault;
    }

    private XmlSchemaForm getAttrFormDefaultSetting() {
        if (FORM_DEFAULT_UNQUALIFIED.equals(getAttrFormDefault())) {
            return new XmlSchemaForm(XmlSchemaForm.UNQUALIFIED);
        } else {
            return new XmlSchemaForm(XmlSchemaForm.QUALIFIED);
        }
    }

    private XmlSchemaForm getElementFormDefaultSetting() {
        if (FORM_DEFAULT_UNQUALIFIED.equals(getElementFormDefault())) {
            return new XmlSchemaForm(XmlSchemaForm.UNQUALIFIED);
        } else {
            return new XmlSchemaForm(XmlSchemaForm.QUALIFIED);
        }
    }

    private NamespaceGenerator getNsGen() throws Exception {
        if (nsGen == null) {
            nsGen = new DefaultNamespaceGenerator();
        }
        return nsGen;
    }

    private String resolveSchemaNamespace(String packageName) throws Exception {
        //if all types must go into the wsdl types schema namespace
        if (useWSDLTypesNamespace) {
            //return schemaTargetNameSpace;
            return pkg2nsmap.get("all");
        } else {
            if (pkg2nsmap != null && !pkg2nsmap.isEmpty()) {
                //if types should go into namespaces that are mapped against the package name for the type
                if (pkg2nsmap.get(packageName) != null) {
                    //return that mapping
                    return pkg2nsmap.get(packageName);
                } else {
                    return getNsGen().schemaNamespaceFromPackageName(packageName).toString();
                }
            } else {
                // if  pkg2nsmap is null and if not default schema ns found for the custom bean
                return getNsGen().schemaNamespaceFromPackageName(packageName).toString();
            }
        }
    }

    private XmlSchemaComplexType getComplexTypeForElement(XmlSchema xmlSchema, QName name) {
        Iterator<XmlSchemaObject> iterator = xmlSchema.getItems().getIterator();
        while (iterator.hasNext()) {
            XmlSchemaObject object = iterator.next();
            if (object instanceof XmlSchemaElement
                    && ((XmlSchemaElement) object).getQName().equals(name)) {
                return (XmlSchemaComplexType) ((XmlSchemaElement) object).getSchemaType();
            } else if (object instanceof XmlSchemaComplexType
                    && ((XmlSchemaComplexType) object).getQName().equals(name)) {
                //return (XmlSchemaComplexType) ((XmlSchemaElement) object).getSchemaType();
                return (XmlSchemaComplexType) object;
            }

        }
        return null;
    }
}
TOP

Related Classes of org.wso2.carbon.rulecep.service.ServiceWSDLBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.