/*
 * 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.apache.ode.jbi.util;

import java.net.URI;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Import;
import javax.wsdl.Input;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.Output;
import javax.wsdl.Part;
import javax.wsdl.PortType;
import javax.wsdl.Types;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.schema.SchemaImport;
import javax.wsdl.factory.WSDLFactory;
import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ibm.wsdl.extensions.schema.SchemaImpl;

public class WSDLFlattener {

    private static Log __log = LogFactory.getLog(WSDLFlattener.class);

    private Definition _definition;
    private SchemaCollection _schemas;
    private Map<QName, Definition> _flattened;
    private boolean _initialized;


    public WSDLFlattener(Definition definition) {
        this(definition, null);
    }

    public WSDLFlattener(Definition definition, SchemaCollection schemas) {
        if (definition == null)
            throw new NullPointerException("Null definition!");
        this._definition = definition;
        this._flattened = new ConcurrentHashMap<QName, Definition>();
        this._schemas = schemas;
    }

    /**
     * Parse the schemas referenced by the definition.
     * @throws Exception if an error occurs
     */
    public void initialize() throws Exception {
        if (!_initialized) {
            if (_schemas == null) {
                this._schemas = new SchemaCollection(getUri(_definition.getDocumentBaseURI()));
            }
            parseSchemas(this._definition);
            _initialized = true;
        }
    }

    /**
     * Retrieve a flattened definition for a given port type name.
     * @param portType the port type to create a flat definition for
     * @return a flat definition for the port type
     * @throws Exception if an error occurs
     */
    public Definition getDefinition(QName portType) throws Exception {
        Definition def = (Definition) _flattened.get(portType);
        if (def == null) {
            def = flattenDefinition(portType);
            _flattened.put(portType, def);
        }
        return def;
    }

    /**
     * @return Returns the definition.
     */
    public Definition getDefinition() {
        return _definition;
    }

    /**
     * @param definition The definition to set.
     */
    public void setDefinition(Definition definition) {
        this._definition = definition;
    }

    /**
     * @return Returns the schemas.
     */
    public SchemaCollection getSchemas() throws Exception {
        return _schemas;
    }

    /**
     * @param schemas The schemas to set.
     */
    public void setSchemas(SchemaCollection schemas) {
        this._schemas = schemas;
    }

    private Definition flattenDefinition(QName name) throws Exception {
        // Check that schemas have been loaded
        initialize();
        // Create new definition
        Definition flat = WSDLFactory.newInstance().newDefinition();
        flat.setTargetNamespace(name.getNamespaceURI());
        addNamespaces(flat, _definition);
        // Create port type
        PortType defPort = _definition.getPortType(name);
        PortType flatPort = flat.createPortType();
        flatPort.setQName(defPort.getQName());
        flatPort.setUndefined(false);
        // Import all operations and related messages
        for (Iterator itOper = defPort.getOperations().iterator(); itOper.hasNext();) {
            Operation defOper = (Operation) itOper.next();
            Operation flatOper = flat.createOperation();
            flatOper.setName(defOper.getName());
            flatOper.setStyle(defOper.getStyle());
            flatOper.setUndefined(false);
            if (defOper.getInput() != null) {
                Input flatInput = flat.createInput();
                flatInput.setName(defOper.getInput().getName());
                if (defOper.getInput().getMessage() != null) {
                    Message flatInputMsg = copyMessage(defOper.getInput().getMessage(), flat);
                    flatInput.setMessage(flatInputMsg);
                    flat.addMessage(flatInputMsg);
                }
                flatOper.setInput(flatInput);
            }
            if (defOper.getOutput() != null) {
                Output flatOutput = flat.createOutput();
                flatOutput.setName(defOper.getOutput().getName());
                if (defOper.getOutput().getMessage() != null) {
                    Message flatOutputMsg = copyMessage(defOper.getOutput().getMessage(), flat);
                    flatOutput.setMessage(flatOutputMsg);
                    flat.addMessage(flatOutputMsg);
                }
                flatOper.setOutput(flatOutput);
            }
            for (Iterator itFault = defOper.getFaults().values().iterator(); itFault.hasNext();) {
                Fault defFault = (Fault) itFault.next();
                Fault flatFault = flat.createFault();
                flatFault.setName(defFault.getName());
                if (defFault.getMessage() != null) {
                    Message flatFaultMsg = copyMessage(defFault.getMessage(), flat);
                    flatFault.setMessage(flatFaultMsg);
                    flat.addMessage(flatFaultMsg);
                }
                flatOper.addFault(flatFault);
            }
            flatPort.addOperation(flatOper);
        }

        // Import schemas in definition
        if (_schemas.getSize() > 0) {
           Types types = flat.createTypes();
           for (Iterator it = _schemas.getSchemas().iterator(); it.hasNext();) {
              javax.wsdl.extensions.schema.Schema imp = new SchemaImpl();
              imp.setElement(((Schema)it.next()).getRoot());
              imp.setElementType(new QName("http://www.w3.org/2001/XMLSchema", "schema"));
              types.addExtensibilityElement(imp);
           }
           flat.setTypes(types);
        }

        flat.addPortType(flatPort);
        return flat;
    }

    private void parseSchemas(Definition def) throws Exception {
        if (def.getTypes() != null && def.getTypes().getExtensibilityElements() != null) {
            for (Iterator iter = def.getTypes().getExtensibilityElements().iterator(); iter.hasNext();) {
                ExtensibilityElement element = (ExtensibilityElement) iter.next();
                if (element instanceof javax.wsdl.extensions.schema.Schema) {
                    javax.wsdl.extensions.schema.Schema schema = (javax.wsdl.extensions.schema.Schema) element;
                    if (schema.getElement() != null) {
                        _schemas.read(schema.getElement(), getUri(schema.getDocumentBaseURI()));
                    }
                    for (Iterator itImp = schema.getImports().values().iterator(); itImp.hasNext();) {
                        Collection imps = (Collection) itImp.next();
                        for (Iterator itSi = imps.iterator(); itSi.hasNext();) {
                            SchemaImport imp = (SchemaImport) itSi.next();
                            _schemas.read(imp.getSchemaLocationURI(), getUri(def.getDocumentBaseURI()));
                        }
                    }
                }
            }
        }
        if (def.getImports() != null) {
            for (Iterator itImp = def.getImports().values().iterator(); itImp.hasNext();) {
                Collection imps = (Collection) itImp.next();
                for (Iterator iter = imps.iterator(); iter.hasNext();) {
                    Import imp = (Import) iter.next();
                    parseSchemas(imp.getDefinition());
                }
            }
        }
    }

    private void addNamespaces(Definition flat, Definition def) {
        for (Iterator itImport = def.getImports().values().iterator(); itImport.hasNext();) {
            List defImports = (List) itImport.next();
            for (Iterator iter = defImports.iterator(); iter.hasNext();) {
                Import defImport = (Import) iter.next();
                addNamespaces(flat, defImport.getDefinition());
            }
        }
        for (Iterator itNs = def.getNamespaces().keySet().iterator(); itNs.hasNext();) {
            String key = (String) itNs.next();
            String val = def.getNamespace(key);
            flat.addNamespace(key, val);
        }
    }

    private Message copyMessage(Message defMessage, Definition flat) {
        Message flatMsg = flat.createMessage();
        flatMsg.setUndefined(false);
        if (defMessage.getQName() != null) {
            flatMsg.setQName(new QName(flat.getTargetNamespace(), defMessage.getQName().getLocalPart()));
        }
        for (Iterator itPart = defMessage.getParts().values().iterator(); itPart.hasNext();) {
            Part defPart = (Part) itPart.next();
            Part flatPart = flat.createPart();
            flatPart.setName(defPart.getName());
            flatPart.setElementName(defPart.getElementName());
            flatMsg.addPart(flatPart);
        }
        return flatMsg;
    }

    private URI getUri(String str) {
        if (str != null) {
            str = str.replaceAll(" ", "%20");
            return URI.create(str);
        }
        return null;
    }

}
