package org.apache.ws.java2wsdl;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.util.StAXUtils;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.java2wsdl.utils.TypeTable;
import org.codehaus.jam.JMethod;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed 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.
*
*/

public class Java2OMBuilder implements Java2WSDLConstants {

    private TypeTable typeTable = null;

    private static int prefixCount = 1;

    private static final String NAMESPACE_PREFIX = "ns";

    private JMethod method [];

    private Collection schemaCollection;

    private String serviceName;

    private String targetNamespace;

    private String targetNamespacePrefix;

    private String schemaTargetNamespace = null;

    private String schemaTargetNamespacePrefix = null;

    private OMNamespace soap;

    private OMNamespace soap12;

    private OMNamespace tns;

    private OMNamespace wsdl;

    private String style;

    private String use;

    private String locationURL;

    public Java2OMBuilder(JMethod[] method, Collection schemaCollection,
                          TypeTable typeTab, String serviceName, String targetNamespace,
                          String targetNamespacePrefix, String style, String use,
                          String locationURL) {
        this.method = method;
        this.schemaCollection = schemaCollection;
        this.typeTable = typeTab;
        if (style == null) {
            this.style = DOCUMENT;
        } else {
            this.style = style;
        }
        if (use == null) {
            this.use = LITERAL;
        } else {
            this.use = use;
        }

        if (locationURL == null) {
            this.locationURL = DEFAULT_LOCATION_URL;
        } else {
            this.locationURL = locationURL;
        }
        this.serviceName = serviceName;

        if (targetNamespace != null && targetNamespace.trim().length() != 0) {
            this.targetNamespace = targetNamespace;
        } else {
            this.targetNamespace = DEFAULT_TARGET_NAMESPACE;
        }

        if (targetNamespacePrefix != null
                && targetNamespacePrefix.trim().length() != 0) {
            this.targetNamespacePrefix = targetNamespacePrefix;
        } else {
            this.targetNamespacePrefix = DEFAULT_TARGET_NAMESPACE_PREFIX;
        }
    }

    public OMElement generateOM() throws Exception {
        OMFactory fac = OMAbstractFactory.getOMFactory();
        wsdl = fac.createOMNamespace(WSDL_NAMESPACE,
                DEFAULT_WSDL_NAMESPACE_PREFIX);
        OMElement ele = fac.createOMElement("definitions", wsdl);

        ele.addAttribute("targetNamespace", targetNamespace, null);
        generateNamespaces(ele);
        generateTypes(fac, ele);
        generateMessages(fac, ele);
        generatePortType(fac, ele);
        generateBinding(fac, ele);
        generateService(fac, ele);
        return ele;
    }

    private void generateNamespaces(OMElement definitions) {
        soap = definitions.declareNamespace(URI_WSDL11_SOAP, SOAP11_PREFIX);
        tns = definitions.declareNamespace(targetNamespace,
                targetNamespacePrefix);
        soap12 = definitions.declareNamespace(URI_WSDL12_SOAP, SOAP12_PREFIX);
        definitions.declareNamespace(HTTP_NAMESPACE, HTTP_PREFIX);
        definitions.declareNamespace(MIME_NAMESPACE, MIME_PREFIX);
        definitions.declareNamespace(getSchemaTargetNamespace(), getSchemaTargetNamespacePrefix());
    }

    private void generateTypes(OMFactory fac, OMElement defintions)
            throws Exception {
        OMElement wsdlTypes = fac.createOMElement("types", wsdl);
        // wrap the Schema elements with this start and end tags to create a
        // document root
        // under which the schemas can fall into

        for (Iterator iterator = schemaCollection.iterator(); iterator.hasNext();) {
            StringWriter writer = new StringWriter();
            XmlSchema xmlSchema = (XmlSchema) iterator.next();
            xmlSchema.write(writer);
            String schemaString = writer.toString();
            if (!"".equals(schemaString)) {
                XMLStreamReader xmlReader = StAXUtils
                        .createXMLStreamReader(new ByteArrayInputStream(schemaString.getBytes()));

                StAXOMBuilder staxOMBuilder = new StAXOMBuilder(fac, xmlReader);
                wsdlTypes.addChild(staxOMBuilder.getDocumentElement());
            }
        }
        defintions.addChild(wsdlTypes);
    }


    private void generateMessages(OMFactory fac, OMElement definitions) {
        Hashtable namespaceMap = new Hashtable();
        String namespacePrefix;
        String namespaceURI;
        QName messagePartType;
        for (int i = 0; i < method.length; i++) {
            JMethod jmethod = method[i];
            if (!jmethod.isPublic()) {
                continue;
            }

            //Request Message
            OMElement requestMessge = fac.createOMElement(
                    MESSAGE_LOCAL_NAME, wsdl);
            requestMessge.addAttribute(ATTRIBUTE_NAME, jmethod
                    .getSimpleName()
                    + MESSAGE_SUFFIX, null);
            definitions.addChild(requestMessge);

            // only if a type for the message part has already been defined
            if ((messagePartType = typeTable.getComplexSchemaType(jmethod
                    .getSimpleName())) != null) {
                namespaceURI = messagePartType.getNamespaceURI();
                // avoid duplicate namespaces
                if ((namespacePrefix = (String) messagePartType.getPrefix()) == null &&
                        (namespacePrefix = (String) namespaceMap.get(namespaceURI)) == null) {
                    namespacePrefix = generatePrefix();
                    namespaceMap.put(namespaceURI, namespacePrefix);
                }

                OMElement requestPart = fac.createOMElement(
                        PART_ATTRIBUTE_NAME, wsdl);
                requestMessge.addChild(requestPart);
                requestPart.addAttribute(ATTRIBUTE_NAME, "part1", null);

                requestPart.addAttribute(ELEMENT_ATTRIBUTE_NAME,
                        namespacePrefix + COLON_SEPARATOR
                                + jmethod.getSimpleName(), null);
            }

            // only if a type for the message part has already been defined
            if ((messagePartType = typeTable.getComplexSchemaType(jmethod
                    .getSimpleName()
                    + RESPONSE)) != null) {
                namespaceURI = messagePartType.getNamespaceURI();
                if ((namespacePrefix = (String) messagePartType.getPrefix()) == null &&
                        (namespacePrefix = (String) namespaceMap.get(namespaceURI)) == null) {
                    namespacePrefix = generatePrefix();
                    namespaceMap.put(namespaceURI, namespacePrefix);
                }
                //Response Message
                OMElement responseMessge = fac.createOMElement(
                        MESSAGE_LOCAL_NAME, wsdl);
                responseMessge.addAttribute(ATTRIBUTE_NAME, jmethod
                        .getSimpleName()
                        + RESPONSE_MESSAGE, null);
                definitions.addChild(responseMessge);
                OMElement responsePart = fac.createOMElement(
                        PART_ATTRIBUTE_NAME, wsdl);
                responseMessge.addChild(responsePart);
                responsePart.addAttribute(ATTRIBUTE_NAME, "part1", null);

                responsePart.addAttribute(ELEMENT_ATTRIBUTE_NAME,
                        namespacePrefix + COLON_SEPARATOR
                                + jmethod.getSimpleName() + RESPONSE, null);
            }

            if (jmethod.getExceptionTypes().length > 0) {
                if ((messagePartType = typeTable.getComplexSchemaType(jmethod.getSimpleName() + "Fault")) != null) {
                    namespaceURI = messagePartType.getNamespaceURI();
                    if ((namespacePrefix = (String) messagePartType.getPrefix()) == null &&
                            (namespacePrefix = (String) namespaceMap.get(namespaceURI)) == null) {
                        namespacePrefix = generatePrefix();
                        namespaceMap.put(namespaceURI, namespacePrefix);
                    }
                    //Response Message
                    OMElement responseMessge = fac.createOMElement(
                            MESSAGE_LOCAL_NAME, wsdl);
                    responseMessge.addAttribute(ATTRIBUTE_NAME, jmethod
                            .getSimpleName()
                            + "Fault", null);
                    definitions.addChild(responseMessge);
                    OMElement responsePart = fac.createOMElement(
                            PART_ATTRIBUTE_NAME, wsdl);
                    responseMessge.addChild(responsePart);
                    responsePart.addAttribute(ATTRIBUTE_NAME, "part1", null);

                    responsePart.addAttribute(ELEMENT_ATTRIBUTE_NAME,
                            namespacePrefix + COLON_SEPARATOR
                                    + jmethod.getSimpleName() + "Fault", null);
                }
            }
        }

        // now add these unique namespaces to the the definitions element
        Enumeration enumeration = namespaceMap.keys();
        while (enumeration.hasMoreElements()) {
            namespaceURI = (String) enumeration.nextElement();
            definitions.declareNamespace(namespaceURI, (String) namespaceMap
                    .get(namespaceURI));
        }
    }


    /**
     * Generate the porttypes
     */
    private void generatePortType(OMFactory fac, OMElement defintions) {
        JMethod jmethod;
        OMElement operation;
        OMElement message;
        OMElement portType = fac.createOMElement(PORT_TYPE_LOCAL_NAME, wsdl);
        defintions.addChild(portType);
        portType.addAttribute(ATTRIBUTE_NAME, serviceName + PORT_TYPE_SUFFIX,
                null);
        //adding message refs
        for (int i = 0; i < method.length; i++) {
            jmethod = method[i];
            if (!jmethod.isPublic()) {
                continue;
            }
            operation = fac.createOMElement(OPERATION_LOCAL_NAME, wsdl);
            portType.addChild(operation);
            operation.addAttribute(ATTRIBUTE_NAME, jmethod.getSimpleName(),
                    null);

            message = fac.createOMElement(IN_PUT_LOCAL_NAME, wsdl);
            message.addAttribute(MESSAGE_LOCAL_NAME, tns.getPrefix()
                    + COLON_SEPARATOR + jmethod.getSimpleName()
                    + MESSAGE_SUFFIX, null);
            operation.addChild(message);

            if (!jmethod.getReturnType().isVoidType()) {
                message = fac.createOMElement(OUT_PUT_LOCAL_NAME, wsdl);
                message.addAttribute(MESSAGE_LOCAL_NAME, tns.getPrefix()
                        + COLON_SEPARATOR + jmethod.getSimpleName()
                        + RESPONSE_MESSAGE, null);
                operation.addChild(message);
            }
            if (jmethod.getExceptionTypes().length > 0) {
                message = fac.createOMElement(FAULT_LOCAL_NAME, wsdl);
                message.addAttribute(MESSAGE_LOCAL_NAME, tns.getPrefix()
                        + COLON_SEPARATOR + jmethod.getSimpleName()
                        + "Fault", null);
                message.addAttribute(ATTRIBUTE_NAME, jmethod.getSimpleName()
                        + "Fault", null);
                operation.addChild(message);
            }
        }

    }

    /**
     * Generate the service
     */
    public void generateService(OMFactory fac, OMElement defintions) {
        OMElement service = fac.createOMElement(SERVICE_LOCAL_NAME, wsdl);
        defintions.addChild(service);
        service.addAttribute(ATTRIBUTE_NAME, serviceName, null);
        OMElement port = fac.createOMElement(PORT, wsdl);
        service.addChild(port);
        port.addAttribute(ATTRIBUTE_NAME, serviceName + SOAP11PORT, null);
        port.addAttribute(BINDING_LOCAL_NAME, tns.getPrefix() + COLON_SEPARATOR
                + serviceName + BINDING_NAME_SUFFIX, null);
        addExtensionElement(fac, port, soap, SOAP_ADDRESS, LOCATION, locationURL
                + serviceName);

        port = fac.createOMElement(PORT, wsdl);
        service.addChild(port);
        port.addAttribute(ATTRIBUTE_NAME, serviceName + SOAP12PORT, null);
        port.addAttribute(BINDING_LOCAL_NAME, tns.getPrefix() + COLON_SEPARATOR
                + serviceName + SOAP12BINDING_NAME_SUFFIX, null);
        addExtensionElement(fac, port, soap12, SOAP_ADDRESS, LOCATION, locationURL
                + serviceName);
    }

    /**
     * Generate the bindings
     */
    private void generateBinding(OMFactory fac, OMElement defintions) {
        generateSoap11Binding(fac, defintions);
        generateSoap12Binding(fac, defintions);
    }

    private void generateSoap11Binding(OMFactory fac, OMElement defintions) {
        OMElement binding = fac.createOMElement(BINDING_LOCAL_NAME, wsdl);
        defintions.addChild(binding);
        binding.addAttribute(ATTRIBUTE_NAME, serviceName + BINDING_NAME_SUFFIX,
                null);
        binding.addAttribute("type", tns.getPrefix() + COLON_SEPARATOR
                + serviceName + PORT_TYPE_SUFFIX, null);

        addExtensionElement(fac, binding, soap, BINDING_LOCAL_NAME, TRANSPORT,
                TRANSPORT_URI, STYLE, style);

        for (int i = 0; i < method.length; i++) {
            JMethod jmethod = method[i];
            if (!jmethod.isPublic()) {
                continue;
            }
            OMElement operation = fac.createOMElement(OPERATION_LOCAL_NAME,
                    wsdl);
            binding.addChild(operation);

            addExtensionElement(fac, operation, soap, OPERATION_LOCAL_NAME,
                    SOAP_ACTION, URN_PREFIX + COLON_SEPARATOR
                    + jmethod.getSimpleName(), STYLE, style);
            operation.addAttribute(ATTRIBUTE_NAME, jmethod.getSimpleName(),
                    null);

            OMElement input = fac.createOMElement(IN_PUT_LOCAL_NAME, wsdl);
            addExtensionElement(fac, input, soap, SOAP_BODY, SOAP_USE, use,
                    "namespace", targetNamespace);
            operation.addChild(input);

            if (!jmethod.getReturnType().isVoidType()) {
                OMElement output = fac.createOMElement(OUT_PUT_LOCAL_NAME, wsdl);
                addExtensionElement(fac, output, soap, SOAP_BODY, SOAP_USE, use,
                        "namespace", targetNamespace);
                operation.addChild(output);
            }

            if (jmethod.getExceptionTypes().length > 0) {

                OMElement fault = fac.createOMElement(FAULT_LOCAL_NAME, wsdl);
                fault.addAttribute(ATTRIBUTE_NAME, jmethod.getSimpleName() + "Fault", null);
                addExtensionElement(fac, fault, soap, SOAP_BODY, SOAP_USE, use,
                        "namespace", targetNamespace);
                operation.addChild(fault);
            }
        }
    }

    private void generateSoap12Binding(OMFactory fac, OMElement defintions) {
        OMElement binding = fac.createOMElement(BINDING_LOCAL_NAME, wsdl);
        defintions.addChild(binding);
        binding.addAttribute(ATTRIBUTE_NAME, serviceName + SOAP12BINDING_NAME_SUFFIX,
                null);
        binding.addAttribute("type", tns.getPrefix() + COLON_SEPARATOR
                + serviceName + PORT_TYPE_SUFFIX, null);

        addExtensionElement(fac, binding, soap12, BINDING_LOCAL_NAME, TRANSPORT,
                TRANSPORT_URI, STYLE, style);

        for (int i = 0; i < method.length; i++) {
            JMethod jmethod = method[i];
            if (!jmethod.isPublic()) {
                continue;
            }
            OMElement operation = fac.createOMElement(OPERATION_LOCAL_NAME,
                    wsdl);
            binding.addChild(operation);
            operation.declareNamespace(URI_WSDL12_SOAP, SOAP12_PREFIX);

            addExtensionElement(fac, operation, soap12, OPERATION_LOCAL_NAME,
                    SOAP_ACTION, URN_PREFIX + COLON_SEPARATOR
                    + jmethod.getSimpleName(), STYLE, style);
            operation.addAttribute(ATTRIBUTE_NAME, jmethod.getSimpleName(),
                    null);

            OMElement input = fac.createOMElement(IN_PUT_LOCAL_NAME, wsdl);
            addExtensionElement(fac, input, soap12, SOAP_BODY, SOAP_USE, use,
                    "namespace", targetNamespace);
            operation.addChild(input);

            if (!jmethod.getReturnType().isVoidType()) {
                OMElement output = fac.createOMElement(OUT_PUT_LOCAL_NAME, wsdl);
                addExtensionElement(fac, output, soap12, SOAP_BODY, SOAP_USE, use,
                        "namespace", targetNamespace);
                operation.addChild(output);
            }
            if (jmethod.getExceptionTypes().length > 0) {

                OMElement fault = fac.createOMElement(FAULT_LOCAL_NAME, wsdl);
                fault.addAttribute(ATTRIBUTE_NAME, jmethod.getSimpleName() + "Fault", null);
                addExtensionElement(fac, fault, soap12, SOAP_BODY, SOAP_USE, use,
                        "namespace", targetNamespace);
                operation.addChild(fault);
            }
        }
    }

    private void addExtensionElement(OMFactory fac, OMElement element, OMNamespace namespace,
                                     String name, String att1Name, String att1Value, String att2Name,
                                     String att2Value) {
        OMElement soapbinding = fac.createOMElement(name, namespace);
        element.addChild(soapbinding);
        soapbinding.addAttribute(att1Name, att1Value, null);
        soapbinding.addAttribute(att2Name, att2Value, null);
    }

    private void addExtensionElement(OMFactory fac, OMElement element, OMNamespace namespace,
                                     String name, String att1Name, String att1Value, String att2Name,
                                     String att2Value, String att3Name,
                                     String att3Value) {
        OMElement soapbinding = fac.createOMElement(name, namespace);
        element.addChild(soapbinding);
        soapbinding.addAttribute(att1Name, att1Value, null);
        soapbinding.addAttribute(att2Name, att2Value, null);
        soapbinding.addAttribute(att3Name, att3Value, null);
    }

    private void addExtensionElement(OMFactory fac, OMElement element, OMNamespace namespace,
                                     String name, String att1Name, String att1Value) {
        OMElement soapbinding = fac.createOMElement(name, namespace);
        element.addChild(soapbinding);
        soapbinding.addAttribute(att1Name, att1Value, null);
    }

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

    public String getSchemaTargetNamespace() {
        return schemaTargetNamespace;
    }

    public void setSchemaTargetNamespace(String schemaTargetNamespace) {
        this.schemaTargetNamespace = schemaTargetNamespace;
    }

    public String getSchemaTargetNamespacePrefix() {
        return schemaTargetNamespacePrefix;
    }

    public void setSchemaTargetNamespacePrefix(String schemaTargetNamespacePrefix) {
        this.schemaTargetNamespacePrefix = schemaTargetNamespacePrefix;
    }

}
