/*
 * 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.tuscany.sca.binding.ws.wsdlgen;

import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.wsdl.Binding;
import javax.wsdl.BindingOperation;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Input;
import javax.wsdl.Message;
import javax.wsdl.OperationType;
import javax.wsdl.Output;
import javax.wsdl.Part;
import javax.wsdl.PortType;
import javax.wsdl.Types;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.schema.Schema;
import javax.wsdl.factory.WSDLFactory;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
import org.apache.tuscany.sca.databinding.DataBinding;
import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint;
import org.apache.tuscany.sca.databinding.XMLTypeHelper;
import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding;
import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.Interface;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
import org.apache.tuscany.sca.interfacedef.java.JavaOperation;
import org.apache.tuscany.sca.interfacedef.util.ElementInfo;
import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
import org.apache.tuscany.sca.interfacedef.util.TypeInfo;
import org.apache.tuscany.sca.interfacedef.util.WrapperInfo;
import org.apache.tuscany.sca.interfacedef.util.XMLType;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.monitor.Problem;
import org.apache.tuscany.sca.monitor.Problem.Severity;
import org.apache.tuscany.sca.monitor.impl.ProblemImpl;
import org.apache.tuscany.sca.xsd.XSDFactory;
import org.apache.tuscany.sca.xsd.XSDefinition;
import org.apache.tuscany.sca.xsd.impl.XSDefinitionImpl;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaException;
import org.apache.ws.commons.schema.utils.NamespaceMap;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @version $Rev: 670103 $ $Date: 2008-06-21 01:35:00 +0100 (Sat, 21 Jun 2008) $
 */
public class Interface2WSDLGenerator {
    private static final Logger logger = Logger.getLogger(Interface2WSDLGenerator.class.getName());
    private static final String SCHEMA_NS = "http://www.w3.org/2001/XMLSchema";
    private static final String SCHEMA_NAME = "schema";
    private static final QName SCHEMA_QNAME = new QName(SCHEMA_NS, SCHEMA_NAME);
    private static final String XMLNS_NS = "http://www.w3.org/2000/xmlns/";
    
    private static final String ANYTYPE_NAME = "anyType";
    private static final QName ANYTYPE_QNAME = new QName(SCHEMA_NS, ANYTYPE_NAME);


    private WSDLFactory factory;
    private DataBindingExtensionPoint dataBindings;
    private WSDLDefinitionGenerator definitionGenerator;
    private boolean requiresSOAP12;
    private ModelResolver resolver;
    private XSDFactory xsdFactory;
    private Monitor monitor;

    public Interface2WSDLGenerator(boolean requiresSOAP12,
                                   ModelResolver resolver,
                                   DataBindingExtensionPoint dataBindings,
                                   XSDFactory xsdFactory,
                                   Monitor monitor) throws WSDLException {
        super();
        this.requiresSOAP12 = requiresSOAP12; 
        this.resolver = resolver; 
        definitionGenerator = new WSDLDefinitionGenerator(requiresSOAP12, false);
        this.dataBindings = dataBindings;
        this.xsdFactory = xsdFactory;
        this.monitor = monitor;
        this.factory = WSDLFactory.newInstance();
    }

    /**
     * Log a warning message.
     * @param problem
     */
    private static void logWarning(Problem problem) {
        Logger problemLogger = Logger.getLogger(problem.getSourceClassName(), problem.getBundleName());
        if (problemLogger != null){
            problemLogger.logp(Level.WARNING, problem.getSourceClassName(), null, problem.getMessageId(), problem.getMessageParams());
        } else {
            logger.severe("Can't get logger " + problem.getSourceClassName()+ " with bundle " + problem.getBundleName());
        }
    }

    /**
     * Report a warning.
     * @param message
     * @param binding
     * @param parameters
     */
    private void warning(String message, Interface interfaze, String... messageParameters) {
        Problem problem = new ProblemImpl(this.getClass().getName(), "wsdlgen-validation-messages", Severity.WARNING, interfaze, message, (Object[])messageParameters);
        if (monitor != null) {
            monitor.problem(problem);
        } else {
            logWarning(problem);
        }
    }

    /**
     * Report a fatal error.
     * @param message
     * @param binding
     * @param parameters
     */
    private void fatal(String message, Interface interfaze, String... messageParameters) {
        Problem problem = new ProblemImpl(this.getClass().getName(), "wsdlgen-validation-messages", Severity.ERROR, interfaze, message, (Object[])messageParameters);
        throw new WSDLGenerationException(problem.toString(), null, problem);
    }
    
    private XMLTypeHelper getTypeHelper(DataType type, Map<String, XMLTypeHelper> helpers) {
        if (type == null) {
            return null;
        }
        String db = type.getDataBinding();
        if (db == null) {
            return null;
        }

        // TUSCANY-3800
        while ("java:array".equals(db)) {
            type = (DataType)type.getLogical();
            db = type.getDataBinding();
        }
        return helpers.get(db);
    }
    
    private boolean inputTypesCompatible(DataType wrapperType, DataType<List<DataType>> inputType, Map<String, XMLTypeHelper> helpers) {
        XMLTypeHelper wrapperHelper = getTypeHelper(wrapperType, helpers);
        for (DataType dt : inputType.getLogical()) {
            if (getTypeHelper(dt, helpers) != wrapperHelper) {
                return false;
            }
        }
        return true;
    }
    
    private boolean outputTypeCompatible(DataType wrapperType, DataType outputType, Map<String, XMLTypeHelper> helpers) {
        if (getTypeHelper(outputType, helpers) != getTypeHelper(wrapperType, helpers)) {
            return false;
        } else {
            return true;
        }
    }
    
    private void addDataType(Map<XMLTypeHelper, List<DataType>> map, DataType type, Map<String, XMLTypeHelper> helpers) {
        if (type == null) {
            return;
        }
        String db = type.getDataBinding();
        if (db == null) {
            return;
        }
        if ("java:array".equals(db)) {
            DataType dt = (DataType)type.getLogical();
            db = dt.getDataBinding();
        }
        XMLTypeHelper helper = helpers.get(db);
        List<DataType> types = map.get(helper);
        if (types == null) {
            types = new ArrayList<DataType>();
            map.put(helper, types);
        }
        types.add(type);
    }
    
    private Map<XMLTypeHelper, List<DataType>> getDataTypes(Interface intf, boolean useWrapper, Map<String, XMLTypeHelper> helpers) {
        Map<XMLTypeHelper, List<DataType>> dataTypes = new HashMap<XMLTypeHelper, List<DataType>>();
        for (Operation op : intf.getOperations()) {
            WrapperInfo inputWrapper = op.getInputWrapper();
            DataType dt1 = null;
            boolean useInputWrapper = useWrapper & inputWrapper != null;
            if (useInputWrapper) {
                dt1 = inputWrapper.getWrapperType();
                useInputWrapper &= inputTypesCompatible(dt1, op.getInputType(), helpers);
            }
            if (useInputWrapper) {
                addDataType(dataTypes, dt1, helpers);
            } else {
                for (DataType dt : op.getInputType().getLogical()) {
                    addDataType(dataTypes, dt, helpers);
                }
            }
            
            DataType dt2 = null;
            WrapperInfo outputWrapper = op.getOutputWrapper();
            boolean useOutputWrapper = useWrapper & outputWrapper != null;
            if (useOutputWrapper) {
                dt2 = outputWrapper.getWrapperType();
                useOutputWrapper &= outputTypeCompatible(dt2, op.getOutputType(), helpers);
            }
            if (useOutputWrapper) {
                addDataType(dataTypes, dt2, helpers);
            } else {
                dt2 = op.getOutputType();
                addDataType(dataTypes, dt2, helpers);
            }
            
            for (DataType<DataType> dt3 : op.getFaultTypes()) {
                DataType dt4 = dt3.getLogical();
                addDataType(dataTypes, dt4, helpers);
            }
        }
        // Adding classes referenced by @XmlSeeAlso in the java interface
        if (intf instanceof JavaInterface) {
            JavaInterface javaInterface = (JavaInterface)intf;
            Class<?>[] seeAlso = getSeeAlso(javaInterface.getJavaClass());
            if (seeAlso != null) {
                for (Class<?> cls : seeAlso) {
                    DataType dt = new DataTypeImpl<XMLType>(JAXBDataBinding.NAME, cls, XMLType.UNKNOWN);
                    addDataType(dataTypes, dt, helpers);
                }
            }
            seeAlso = getSeeAlso(javaInterface.getCallbackClass());
            if (seeAlso != null) {
                for (Class<?> cls : seeAlso) {
                    DataType dt = new DataTypeImpl<XMLType>(JAXBDataBinding.NAME, cls, XMLType.UNKNOWN);
                    addDataType(dataTypes, dt, helpers);
                }
            }
        }
        return dataTypes;
    }
    
    private static Class<?>[] getSeeAlso(Class<?> interfaze) {
        if (interfaze == null) {
            return null;
        }
        XmlSeeAlso seeAlso = interfaze.getAnnotation(XmlSeeAlso.class);
        if (seeAlso == null) {
            return null;
        } else {
            return seeAlso.value();
        }
    }


    public Definition generate(Interface interfaze, WSDLDefinition wsdlDefinition) throws WSDLException {
        if (interfaze == null) {
            return null;
        }
        if (interfaze instanceof WSDLInterface) {
            return ((WSDLInterface)interfaze).getWsdlDefinition().getDefinition();
        }
        JavaInterface iface = (JavaInterface)interfaze;
        if (!interfaze.isRemotable()) {
            fatal("InterfaceNotRemotable", interfaze, iface.getName());
        }
        QName name = getQName(iface);
        Definition definition = factory.newDefinition();
        if (requiresSOAP12) {
            definition.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/");
        } else {
            definition.addNamespace("SOAP", "http://schemas.xmlsoap.org/wsdl/soap/");
        }
        definition.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/");
        definition.addNamespace("xs", SCHEMA_NS);

        String namespaceURI = name.getNamespaceURI();
        definition.setTargetNamespace(namespaceURI);
        definition.setQName(new QName(namespaceURI, name.getLocalPart() + "Service", name.getPrefix()));
        definition.addNamespace(name.getPrefix(), namespaceURI);

        PortType portType = definition.createPortType();
        portType.setQName(name);
        Binding binding = definitionGenerator.createBinding(definition, portType);
        Map<String, XMLTypeHelper> helpers = new HashMap<String, XMLTypeHelper>();
        Map<QName, List<ElementInfo>> wrappers = new HashMap<QName, List<ElementInfo>>();
        for (Operation op : interfaze.getOperations()) {
            javax.wsdl.Operation operation = generateOperation(definition, op, helpers, wrappers);
            portType.addOperation(operation);
            String action = ((JavaOperation)op).getAction();
            if ((action == null || "".equals(action)) && !op.isInputWrapperStyle() && op.getInputWrapper() == null) {
                // Bare style
                action = "urn:" + op.getName();
            }
            BindingOperation bindingOp = definitionGenerator.createBindingOperation(definition, operation, action);
            binding.addBindingOperation(bindingOp);
        }
        portType.setUndefined(false);
        definition.addPortType(portType);
        binding.setUndefined(false);
        definition.addBinding(binding);
        wsdlDefinition.setBinding(binding);
        
        // call each helper in turn to populate the wsdl.types element
        XmlSchemaCollection schemaCollection = new XmlSchemaCollection(); 

        // TUSCANY-3298: enable JAXB wrapper generation
        for (Map.Entry<XMLTypeHelper, List<DataType>> en: getDataTypes(interfaze, true, helpers).entrySet()) {
            XMLTypeHelper helper = en.getKey();
            if (helper == null) {
                continue;
            }
            List<XSDefinition> xsDefinitions = helper.getSchemaDefinitions(xsdFactory, resolver, en.getValue());
            
            for (XSDefinition xsDef: xsDefinitions) {

                Document doc = xsDef.getDocument();
                if (doc != null) {                    
                    // TUSCANY-2757 and TUSCANY-3267 - flip global wrapper elements with nillable 
                    // set true to be set to false.  The JAXB RI seems to be generating this setting
                    // incorrectly according to the JAXB spec.                    
                    NodeList nodes = doc.getFirstChild().getChildNodes();
                    for (int i = 0; i < nodes.getLength(); i++) {
                        Node aNode = nodes.item(i);
                        if (aNode.getLocalName() != null && aNode.getLocalName().equals("element")) {
                            NamedNodeMap attributes = aNode.getAttributes();
                            Node nameAttr = attributes.getNamedItem("name");
                            if (nameAttr != null) { 
                                QName elementName = new QName(xsDef.getNamespace(), nameAttr.getNodeValue());
                                if (wrappers.containsKey(elementName)) {
                                    Node nillable = attributes.getNamedItem("nillable");
                                    if (nillable != null) {
                                        nillable.setNodeValue("false");
                                    }
                                }
                            }
                        }
                    }
                }
                
                loadXSD(schemaCollection, xsDef);
                wsdlDefinition.getXmlSchemas().add(xsDef);
            }
        }

        // remove global wrapper elements with schema definitions from generation list
        for (QName wrapperName: new HashSet<QName>(wrappers.keySet())) {
            if (wsdlDefinition.getXmlSchemaElement(wrapperName) != null) {
                wrappers.remove(wrapperName);
            }
        }
        
        schemaCollection = new XmlSchemaCollection(); 

        // generate schema elements for wrappers that aren't defined in the schemas
        if (wrappers.size() > 0) {
            int i = 0;
            int index = 0;
            Map<String, XSDefinition> wrapperXSDs = new HashMap<String, XSDefinition>();
            Map<Element, Map<String, String>> prefixMaps = new HashMap<Element, Map<String, String>>();
            for (Map.Entry<QName, List<ElementInfo>> entry: wrappers.entrySet()) {
                String targetNS = entry.getKey().getNamespaceURI();
                Document schemaDoc = null;
                Element schema = null;
                XSDefinition xsDef = wrapperXSDs.get(targetNS);
                if (xsDef != null) {
                    schemaDoc = xsDef.getDocument();
                    schema = schemaDoc.getDocumentElement();
                } else {
                    xsDef = wsdlDefinition.getSchema(targetNS);
                    if (xsDef != null) {
                        schemaDoc = xsDef.getDocument();
                        schema = schemaDoc.getDocumentElement();
                        wrapperXSDs.put(targetNS, xsDef);
                        Map<String, String> prefixMap = prefixMaps.get(schema);
                        if (prefixMap == null){
                            prefixMap = new HashMap<String, String>();
                            prefixMaps.put(schema, prefixMap);
                            String [] prefixes = xsDef.getSchema().getNamespaceContext().getDeclaredPrefixes();
                            for (int j = 0; j < prefixes.length; j++){
                                prefixMap.put(xsDef.getSchema().getNamespaceContext().getNamespaceURI(prefixes[j]),
                                              prefixes[j]);
                            }
                        }                        
                    } else {
                        schemaDoc = createDocument();
                        schema = schemaDoc.createElementNS(SCHEMA_NS, "xs:schema");
                        // The elementFormDefault should be set to unqualified, see TUSCANY-2388
                        schema.setAttribute("elementFormDefault", "unqualified");
                        schema.setAttribute("attributeFormDefault", "qualified");
                        schema.setAttribute("targetNamespace", targetNS);
                        schema.setAttributeNS(XMLNS_NS, "xmlns:xs", SCHEMA_NS);
                        schema.setAttributeNS(XMLNS_NS, "xmlns:tns", targetNS);
                        schemaDoc.appendChild(schema);
                        prefixMaps.put(schema, new HashMap<String, String>());
                        xsDef = xsdFactory.createXSDefinition();
                        xsDef.setUnresolved(true);
                        xsDef.setNamespace(targetNS);
                        xsDef.setDocument(schemaDoc);
                        // TUSCANY-2465: Set the system id to avoid schema conflict
                        xsDef.setLocation(URI.create("xsd_" + index + ".xsd"));
                        index++;
                        wrapperXSDs.put(targetNS, xsDef);
                    }  
                }
                Element wrapper = schemaDoc.createElementNS(SCHEMA_NS, "xs:element");
                schema.appendChild(wrapper);
                wrapper.setAttribute("name", entry.getKey().getLocalPart());
                if (entry.getValue().size() == 1 && entry.getValue().get(0).getQName() == null) {
                    // special case for global fault element
                    QName typeName = entry.getValue().get(0).getType().getQName();
                    String nsURI = typeName.getNamespaceURI();
                    if ("".equals(nsURI)) {
                        wrapper.setAttribute("type", typeName.getLocalPart());
                        addSchemaImport(schema, "", schemaDoc);
                    } else if (targetNS.equals(nsURI)) {
                        wrapper.setAttribute("type", typeName.getLocalPart());
                    } else if (SCHEMA_NS.equals(nsURI)) {
                        wrapper.setAttribute("type", "xs:" + typeName.getLocalPart());
                    } else {
                        Map<String, String> prefixMap = prefixMaps.get(schema);
                        String prefix = prefixMap.get(nsURI);
                        if (prefix == null) {
                            prefix = "ns" + i++;
                            while(prefixMap.containsValue(prefix)){
                                prefix = "ns" + i++;
                            }
                            prefixMap.put(nsURI, prefix);
                            schema.setAttributeNS(XMLNS_NS, "xmlns:" + prefix, nsURI);
                            addSchemaImport(schema, nsURI, schemaDoc);
                        }
                        wrapper.setAttribute("type", prefix + ":" + typeName.getLocalPart());
                    }                    
                } else {
                    // normal wrapper containing type definition inline
                    Element complexType = schemaDoc.createElementNS(SCHEMA_NS, "xs:complexType");
                    wrapper.appendChild(complexType);
                    if (entry.getValue().size() > 0) {
                        Element sequence = schemaDoc.createElementNS(SCHEMA_NS, "xs:sequence");
                        complexType.appendChild(sequence);
                        for (ElementInfo element: entry.getValue()) {
                            Element xsElement = schemaDoc.createElementNS(SCHEMA_NS, "xs:element"); 
                            if (element.isMany()) {
                                xsElement.setAttribute("maxOccurs", "unbounded");
                            }
                            xsElement.setAttribute("minOccurs", "0");
                            xsElement.setAttribute("name", element.getQName().getLocalPart());
                            if (element.isNillable()) {
                                xsElement.setAttribute("nillable", "true");
                            }
                            QName typeName = element.getType().getQName();
                            String nsURI = typeName.getNamespaceURI();
                            if ("".equals(nsURI)) {
                                xsElement.setAttribute("type", typeName.getLocalPart());
                                addSchemaImport(schema, "", schemaDoc);
                            } else if (SCHEMA_NS.equals(nsURI)) {
                                xsElement.setAttribute("type", "xs:" + typeName.getLocalPart());
                            } else {
                                Map<String, String> prefixMap = prefixMaps.get(schema);
                                String prefix = prefixMap.get(nsURI);
                                if (prefix == null) {
                                    if (targetNS.equals(nsURI)) {
									    prefix = "tns";
									} else {
                                        prefix = "ns" + i++;
                                        while(prefixMap.containsValue(prefix)){
                                            prefix = "ns" + i++;
                                        }
                                        addSchemaImport(schema, nsURI, schemaDoc);
									}
                                    prefixMap.put(nsURI, prefix);
                                    schema.setAttributeNS(XMLNS_NS, "xmlns:" + prefix, nsURI);
                                }
                                xsElement.setAttribute("type", prefix + ":" + typeName.getLocalPart());
                            }
                            sequence.appendChild(xsElement);
                        }
                    }
                }
            }
 
            // resolve XSDefinitions containing generated wrappers
            for (XSDefinition xsDef: wrapperXSDs.values()) {
                if (wsdlDefinition.getSchema(xsDef.getNamespace()) == null) {
                     wsdlDefinition.getXmlSchemas().add(xsDef);
                }
                
                xsDef.setSchema(null);
                xsDef.setSchemaCollection(null);
                loadXSD(schemaCollection, xsDef);
            }
        }
        
        XSDefinition noNamespaceSchema = null;
        XSDefinition defaultNamespaceSchema = null;     

        for (XSDefinition xsDef: wsdlDefinition.getXmlSchemas()) {
            // only apply these changes if we have a DOM to work with
            // this will generally come from the JAXB generation. SDO
            // just goes straight to generating XmlSchema structures
            Document doc = xsDef.getDocument();
            if (doc != null) {
                // TUSCANY-3283 find any schema that has been generated without a namespace
                //              and any schema using the default WSDL schema so that we can
                //              merge the two together              
                if (xsDef.getNamespace().equals("")){
                    noNamespaceSchema = xsDef;
                }
                if (xsDef.getNamespace().equals(namespaceURI)){
                    defaultNamespaceSchema = xsDef;
                } 
            }
        }    
        
        // useful for debugging DOM issues
        //System.out.println("======================= Schema DOM Pre Merge=======================" );
        //for (XSDefinition xsDef : wsdlDefinition.getXmlSchemas()) {
        //    if (xsDef.getDocument() != null) {
        //        printDOM(xsDef.getDocument());
        //    }
        //}          
        
        // TUSCANY-3283 merge the no namespace schema into the default namespace schema
        if (noNamespaceSchema != null && defaultNamespaceSchema != null){
            // remove the no namespace schema from our list of schema
            wsdlDefinition.getXmlSchemas().remove(noNamespaceSchema);
            // merge the schema with no namespace into the schema with the default namspace for this WSDL
            mergeSchema(noNamespaceSchema, defaultNamespaceSchema, wsdlDefinition.getXmlSchemas());
            
            // useful for debugging DOM issues
            //System.out.println("======================= Schema DOM Post Merge=======================" );
            //for (XSDefinition xsDef : wsdlDefinition.getXmlSchemas()) {
            //    if (xsDef.getDocument() != null) {
            //        printDOM(xsDef.getDocument());
            //    }
            //}            
            
            schemaCollection = new XmlSchemaCollection();
            defaultNamespaceSchema.setSchema(null);
            defaultNamespaceSchema.setSchemaCollection(null);
            loadXSD(schemaCollection, defaultNamespaceSchema);
        }         
        
        // push the schema into the WSDL 
        for (XSDefinition xsDef: wsdlDefinition.getXmlSchemas()){
            addSchemaExtension(xsDef, schemaCollection, wsdlDefinition, definition);
        }
        
        // useful for debugging DOM issues
        //System.out.println("======================= Schema DOM Process End =======================" );
        //for (XSDefinition xsDef : wsdlDefinition.getXmlSchemas()) {
        //    if (xsDef.getDocument() != null) {
        //        printDOM(xsDef.getDocument());
        //    }
        //}        
        
        return definition;
    }        
   
    /**
     * TUSCANY-3283 
     * Merge the no namespace schema into the defualt namespace schema
     * Relies on being called just after the getSchemaDefinitions call when the XSDefinitions 
     * have only the DOM information set
     * 
     * @param noNamespaceSchema
     * @param defaultNamespaceSchema
     * @param xsDefinitions
     */
    private void mergeSchema(XSDefinition noNamespaceSchema, XSDefinition defaultNamespaceSchema, Collection<XSDefinition> xsDefinitions){
        Document fromDoc = noNamespaceSchema.getDocument();
        Document toDoc = defaultNamespaceSchema.getDocument();
          
        // merge namespace definitions from the nonamespace schema into the default namespace schema
        for(int i = 0; i < fromDoc.getDocumentElement().getAttributes().getLength(); i++){
            Attr attribute = (Attr)fromDoc.getDocumentElement().getAttributes().item(i);
            String attribName = attribute.getName();
            if (attribName.startsWith("xmlns:")){
                
                String fromPrefix = attribName.substring(attribName.indexOf(":") + 1);
                
                if (fromPrefix.equals("xs") != true){        
                    // create a new namespace prefix to prevent clashes
                    toDoc.getDocumentElement().setAttributeNS("http://www.w3.org/2000/xmlns/", 
                                                              "xmlns:__" + fromPrefix, 
                                                              attribute.getValue());
                    
                    // fix up any references to the existing namespace prefix
                    fixUpNoNamespaceNamespaces(fromDoc, fromPrefix);
                }
            }
        }
        
        Node toDocFirstChild = toDoc.getDocumentElement().getFirstChild();
        
        // merge types from the no namespace schema into the default namespace schema
        for(int i = 0; i < fromDoc.getDocumentElement().getChildNodes().getLength(); i++){
            // merge the DOM types
            Node node = fromDoc.getDocumentElement().getChildNodes().item(i);
            Node newNode = toDoc.importNode(node, true);
            
            if (newNode.getLocalName() != null && 
                (newNode.getLocalName().equals("import") || 
                 newNode.getLocalName().equals("include") ||
                 newNode.getLocalName().equals("redefine") ||
                 newNode.getLocalName().equals("annotation") )){
            	toDoc.getDocumentElement().insertBefore(newNode, toDocFirstChild);
            } else {
            	toDoc.getDocumentElement().appendChild(newNode);
            }
        }
        
        // fix up any references to the types we've just moved
        for(int i = 0; i < fromDoc.getDocumentElement().getChildNodes().getLength(); i++){
            Node node = fromDoc.getDocumentElement().getChildNodes().item(i);
            
            // correct any references to no name types in other schema
            if (node.getLocalName() != null && 
                node.getLocalName().equals("complexType")){
                Node typeName = node.getAttributes().getNamedItem("name");
                fixUpNoNamespaceReferences(xsDefinitions, typeName.getNodeValue(), defaultNamespaceSchema.getNamespace());
            }
        }
    }
    
    /**
     * TUSCANY-3283 
     * Correct any namespace prefixes in the no namespace schema to prevent them from 
     * clashing when the no namespace schema is merged with the default schema
     * 
     * @param fromSchema
     * @param fromPrefix
     * @param toPrefix
     */   
    private void fixUpNoNamespaceNamespaces(Document fromSchema, String fromPrefix){
        NodeList elements = fromSchema.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema","element");
        for (int k = 0; k < elements.getLength(); k++){
            Element element = (Element) elements.item(k);
            if (element != null && element.getAttributes() != null) {
                Node type = element.getAttributes().getNamedItem("type");
                
                if (type != null &&
                    type.getNodeValue().startsWith(fromPrefix)){
                    type.setNodeValue("__" + type.getNodeValue());
               }
            }
        }
    }

    /**
     * TUSCANY-3283 
     * Correct any references in the schema list that used to point to types in the
     * no namespace schema
     * 
     * @param fromSchema
     * @param toSchema
     */  
    private void fixUpNoNamespaceReferences(Collection<XSDefinition> xsDefinitions, String typeName, String defaultNamespace){
        
        // fix up any references in any other schema that points to this type
        for (XSDefinition xsDef: xsDefinitions) {

        	if (xsDef.getDocument() != null){
	            // look for any imports of the no namespace schema
	            Document refSchema = xsDef.getDocument();
	            NodeList imports = refSchema.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema","import");
	            List<Node> importsToDelete = new ArrayList<Node>();
	            
	            for (int j = 0; j < imports.getLength(); j++){
	                Element _import = (Element)imports.item(j);
	                
	                // Fix up the import
	                if (_import.getAttributes().getLength() == 0){
	                    if (xsDef.getNamespace().equals(defaultNamespace)){
	                        // remove the import
	                        //_import.getParentNode().removeChild(_import);
	                        importsToDelete.add(_import);
	                    } else {
	                        // update the import to refer to the default namespace
	                        _import.setAttribute("namespace", defaultNamespace);
	                    }
	                }
	            }
	            
	            for (Node _import : importsToDelete){
	                _import.getParentNode().removeChild(_import);
	            }
	
	            // look for any type attributes that refer to the 
	            // node being merged
	            NodeList elements = refSchema.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema","element");
	            for (int k = 0; k < elements.getLength(); k++){
	                Element element = (Element) elements.item(k);
	                if (element != null && element.getAttributes() != null) {
	                    Node type = element.getAttributes().getNamedItem("type");
	                    
	                    if (type != null &&
	                        type.getNodeValue().equals(typeName)){
	                        if (xsDef.getNamespace().equals(defaultNamespace)){
	                            // double check that there is a "tns" namespace shortname specified
	                            String tnsNamespace = refSchema.getDocumentElement().getAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:tns");
	                            
	                            if (tnsNamespace == null || tnsNamespace.length() == 0) {
	                                refSchema.getDocumentElement().setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:tns", defaultNamespace);
	                            }
	                            
	                            // just add "tns" in front of the type name as
	                            // we have merged the type into this schema
	                            type.setNodeValue("tns:" + type.getNodeValue());
	                        } else {
	                            // add a namespace 
	                            refSchema.getDocumentElement().setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:__nnns", defaultNamespace);
	
	                            // prefix the type name with the namespace
	                            type.setNodeValue("__nnns:" + type.getNodeValue());
	                        }
	                    }
	                }
	            }
        	}
        }
    }

    /*
     * Just used when debugging DOM problems
     */
    private void printDOM(Document document){
        try {
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            Source source = new DOMSource(document);
            Result result = new StreamResult(System.out);
            transformer.transform(source, result);
        } catch (Exception ex){
            ex.toString();
        }
    }
    
    private static void addSchemaImport(Element schema, String nsURI, Document schemaDoc) {
        Element imp = schemaDoc.createElementNS(SCHEMA_NS, "xs:import");
        if (!"".equals(nsURI)) {
            imp.setAttribute("namespace", nsURI);
        }
        // Scan all xs:import elements to match namespace
        NodeList childNodes = schema.getElementsByTagNameNS(SCHEMA_NS, "import");
        for (int i = 0; i < childNodes.getLength(); i++) {
            Node childNode = childNodes.item(i);
            if (childNode instanceof Element) {
                String ns = ((Element)childNode).getAttributeNS(SCHEMA_NS, "namespace");
                if (nsURI.equals(ns)) {
                    // The xs:import with the same namespace has been declared
                    return;
                }
            }
        }
        // Try to find the first node after the import elements
        Node firstNodeAfterImport = null;
        if (childNodes.getLength() > 0) {
            firstNodeAfterImport = childNodes.item(childNodes.getLength() - 1).getNextSibling();
        } else {
            firstNodeAfterImport = schema.getFirstChild();
        }

        if (firstNodeAfterImport == null) {
            schema.appendChild(imp);
        } else {
            schema.insertBefore(imp, firstNodeAfterImport);
        }
    }

    private void addSchemaExtension(XSDefinition xsDef,
                                    XmlSchemaCollection schemaCollection,
                                    WSDLDefinition wsdlDefinition,
                                    Definition definition) throws WSDLException {
        if (xsDef.getAggregatedDefinitions() != null) {
            for (XSDefinition xsd: xsDef.getAggregatedDefinitions()) {
                addSchemaExtension(xsd, schemaCollection, wsdlDefinition, definition);
            }
        } else {
            String nsURI = xsDef.getNamespace();
            Document document = xsDef.getDocument();
            if (document == null) {
                try {
                    NamespaceMap prefixMap = new NamespaceMap();
                    prefixMap.add("xs", SCHEMA_NS);
                    prefixMap.add("tns", nsURI);
                    XmlSchema schemaDef = xsDef.getSchema();
                    schemaDef.setNamespaceContext(prefixMap);
                    Document[] docs = schemaDef.getAllSchemas();
                    document = docs[docs.length-1];
                    document.setDocumentURI(xsDef.getLocation().toString());
                    xsDef.setDocument(document);
                } catch (XmlSchemaException e) {
                    throw new RuntimeException(e);
                }
            }
            //loadXSD(schemaCollection, xsDef);
            //wsdlDefinition.getXmlSchemas().add(xsDef);
            Element schema = document.getDocumentElement();
            Schema schemaExt = createSchemaExt(definition);
            schemaExt.setDocumentBaseURI(document.getDocumentURI());
            schemaExt.setElement(schema);
        }
    }

    private static void loadXSD(XmlSchemaCollection schemaCollection, XSDefinition definition) {
        if (definition.getSchema() != null) {
            return;
        }
        if (definition.getDocument() != null) {
            String uri = null;
            if (definition.getLocation() != null) {
                uri = definition.getLocation().toString();
            }
            XmlSchema schema = schemaCollection.read(definition.getDocument(), uri, null);
            if (definition.getSchemaCollection() == null) {
                definition.setSchemaCollection(schemaCollection);
            }
            if (definition.getSchema() == null) {
                definition.setSchema(schema);
            }
        }
    }

    public Schema createSchemaExt(Definition definition) throws WSDLException {
        Types types = definition.getTypes();
        if (types == null) {
            types = definition.createTypes();
            definition.setTypes(types);
        }

        Schema schemaExt = createSchema(definition);
        types.addExtensibilityElement(schemaExt);

        return schemaExt;
    }

    public Schema createSchema(Definition definition) throws WSDLException {
        return (Schema)definition.getExtensionRegistry().createExtension(Types.class, SCHEMA_QNAME);
    }

    private DocumentBuilderFactory documentBuilderFactory;

    public Document createDocument() {
        Document document;
        try {
            if (documentBuilderFactory == null) {
                documentBuilderFactory = DocumentBuilderFactory.newInstance();
                documentBuilderFactory.setNamespaceAware(true);
            }
            document = documentBuilderFactory.newDocumentBuilder().newDocument();
        } catch (ParserConfigurationException ex) {
            throw new WSDLGenerationException(ex);
         }
        // document.setDocumentURI("http://");
        return document;
    }

    protected QName getQName(Interface interfaze) {
        JavaInterface iface = (JavaInterface)interfaze;
        QName qname = iface.getQName();
        if (qname != null) {
            return qname;
        } else {
            Class<?> javaClass = iface.getJavaClass();
            return new QName(JavaXMLMapper.getNamespace(javaClass), javaClass.getSimpleName(), "tns");
        }
    }

    public javax.wsdl.Operation generateOperation(Definition definition,
                                                  Operation op,
                                                  Map<String, XMLTypeHelper> helpers,
                                                  Map<QName, List<ElementInfo>> wrappers)
                                              throws WSDLException {
        javax.wsdl.Operation operation = definition.createOperation();
        operation.setName(op.getName());
        operation.setUndefined(false);

        Input input = definition.createInput();
        Message inputMsg = definition.createMessage();
        String namespaceURI = definition.getQName().getNamespaceURI();
        QName inputMsgName = new QName(namespaceURI, op.getName());
        inputMsg.setQName(inputMsgName);
        inputMsg.setUndefined(false);
        definition.addMessage(inputMsg);

        List<ElementInfo> elements = null;
        // FIXME: By default, java interface is mapped to doc-lit-wrapper style WSDL
        if (op.getInputWrapper() != null) {
            // Generate doc-lit-wrapper style
            inputMsg.addPart(generateWrapperPart(definition, op, helpers, wrappers, true));
        } else {
            // Bare style
            int i = 0;
            for (DataType d : op.getInputType().getLogical()) {
                inputMsg.addPart(generatePart(definition, d, "arg" + i));
                elements = new ArrayList<ElementInfo>();
                ElementInfo element = getElementInfo(d.getPhysical(), d, null, helpers);
                elements.add(element);
                QName elementName = ((XMLType)d.getLogical()).getElementName();
                wrappers.put(elementName, elements);
                i++;
            }
        }
        input.setMessage(inputMsg);
        operation.setInput(input);

        if (!op.isNonBlocking()) {
            Output output = definition.createOutput();
            Message outputMsg = definition.createMessage();
            QName outputMsgName = new QName(namespaceURI, op.getName() + "Response");
            outputMsg.setQName(outputMsgName);
            outputMsg.setUndefined(false);
            definition.addMessage(outputMsg);

            if (op.getOutputWrapper() != null) {
                outputMsg.addPart(generateWrapperPart(definition, op, helpers, wrappers, false));
            } else {
                DataType outputType = op.getOutputType();
                if (outputType != null) {
                    outputMsg.addPart(generatePart(definition, outputType, "return"));
                    elements = new ArrayList<ElementInfo>();
                    ElementInfo element = getElementInfo(outputType.getPhysical(), outputType, null, helpers);
                    elements.add(element);
                    QName elementName = ((XMLType)outputType.getLogical()).getElementName();
                    wrappers.put(elementName, elements);
                }
            }
            output.setMessage(outputMsg);

            operation.setOutput(output);
            operation.setStyle(OperationType.REQUEST_RESPONSE);
        } else {
            operation.setStyle(OperationType.ONE_WAY);
        }

        for (DataType<DataType> faultType: op.getFaultTypes()) {
            Fault fault = definition.createFault();
            QName faultName = ((XMLType)faultType.getLogical().getLogical()).getElementName();
            QName faultMsgName = new QName(namespaceURI, faultName.getLocalPart());
            fault.setName(faultName.getLocalPart());
            Message faultMsg = definition.getMessage(faultMsgName);
            if (faultMsg == null) {
                faultMsg = definition.createMessage();
                faultMsg.setQName(faultMsgName);
                faultMsg.setUndefined(false);
                definition.addMessage(faultMsg);
                faultMsg.addPart(generatePart(definition, faultType.getLogical(), faultName.getLocalPart()));
            }
            fault.setMessage(faultMsg);
            operation.addFault(fault);
            if (faultType.getLogical().getPhysical() != faultType.getPhysical()) {
                // create special wrapper for type indirection to real fault bean
                DataType logical = faultType.getLogical();
                elements = new ArrayList<ElementInfo>();
                elements.add(getElementInfo(logical.getPhysical(), logical, null, helpers));
             } else {
                // convert synthesized fault bean to a wrapper type
                for (DataType<XMLType> propDT: op.getFaultBeans().get(faultName)) {
                    XMLType logical = propDT.getLogical();
                    elements = new ArrayList<ElementInfo>();
                    elements.add(getElementInfo(propDT.getPhysical(), propDT, logical.getElementName(), helpers));
                }
            }
            wrappers.put(faultName, elements);
        }

        operation.setUndefined(false);
        return operation;
    }

    public Part generatePart(Definition definition, DataType arg, String partName) {
        Part part = definition.createPart();
        part.setName(partName);
        if (arg != null && arg.getLogical() instanceof XMLType) {
            XMLType xmlType = (XMLType)arg.getLogical();
            QName elementName = xmlType.getElementName();
            part.setElementName(elementName);
            addNamespace(definition, elementName);
            if (xmlType.getElementName() == null) {
                QName typeName = xmlType.getTypeName();
                part.setTypeName(typeName);
                addNamespace(definition, typeName);
            }
        }
        return part;
    }

    public Part generateWrapperPart(Definition definition,
                                    Operation operation,
                                    Map<String, XMLTypeHelper> helpers, 
                                    Map<QName, List<ElementInfo>> wrappers,
                                    boolean input) throws WSDLException {
        Part part = definition.createPart();
        String partName = input ? operation.getName() : (operation.getName() + "Response");
        part.setName(partName);
        WrapperInfo inputWrapperInfo = operation.getInputWrapper();
        WrapperInfo outputWrapperInfo = operation.getOutputWrapper();
        if ((inputWrapperInfo != null) && (outputWrapperInfo != null)) {
            ElementInfo elementInfo =
                input ? inputWrapperInfo.getWrapperElement() : outputWrapperInfo.getWrapperElement();
            List<ElementInfo> elements =
                input ? inputWrapperInfo.getChildElements() : outputWrapperInfo.getChildElements();
            QName wrapperName = elementInfo.getQName();
            part.setElementName(wrapperName);
            addNamespace(definition, wrapperName);
            wrappers.put(wrapperName, elements);

            // FIXME: [rfeng] Ideally, we should try to register the wrappers only. But we are
            // expriencing the problem that we cannot handle XSD imports 
            /*
            Class<?> wrapperClass = input ? opWrapper.getInputWrapperClass() : opWrapper.getOutputWrapperClass();
            DataType wrapperDT = input ? opWrapper.getInputWrapperType() : opWrapper.getOutputWrapperType();
            if (wrapperClass != null) {
                getElementInfo(wrapperClass, wrapperDT, wrapperName, helpers);
                return part;
            }
            */

            Method method = ((JavaOperation)operation).getJavaMethod();
            if (input) {
                Class<?>[] paramTypes = method.getParameterTypes();
                for (int i = 0; i < paramTypes.length; i++) {
                    DataType dataType = operation.getInputType().getLogical().get(i);
                    elements.set(i, getElementInfo(paramTypes[i], dataType, elements.get(i).getQName(), helpers));
                }
            } else {
                Class<?> returnType = method.getReturnType();
                if (returnType != Void.TYPE) {
                    DataType dataType = operation.getOutputType();
                    elements.set(0, getElementInfo(returnType, dataType, elements.get(0).getQName(), helpers));
                }
            }
        }
        return part;
    }

    private ElementInfo getElementInfo(Class javaType,
                                       DataType dataType,
                                       QName name,
                                       Map<String, XMLTypeHelper> helpers) {
        String db = dataType.getDataBinding();
        while ("java:array".equals(db)) {
            dataType = (DataType)dataType.getLogical();
            db = dataType.getDataBinding();
        }
        XMLTypeHelper helper = helpers.get(db);
        if (helper == null) {
            DataBinding dataBinding = dataBindings.getDataBinding(db);
            if (dataBinding == null) {
                QName element = name;
                if (element == null || dataType.getLogical() instanceof XMLType) {
                    XMLType xmlType = (XMLType)dataType.getLogical();
                    if (xmlType.getElementName() != null) {
                        element = xmlType.getElementName();
                    }
                }
                return new ElementInfo(element, new TypeInfo(ANYTYPE_QNAME, false, null));
                // throw new ServiceRuntimeException("No data binding for " + db);
            }

            helper = dataBinding.getXMLTypeHelper();
            if (helper == null) {
                // Default to JAXB
                helper = helpers.get(JAXBDataBinding.NAME);
                if (helper == null) {
                    helper = dataBindings.getDataBinding(JAXBDataBinding.NAME).getXMLTypeHelper();
                    helpers.put(JAXBDataBinding.NAME, helper);
                }
            }
            helpers.put(db, helper);
        }
        TypeInfo typeInfo = helper.getTypeInfo(byte[].class != javaType && javaType.isArray() ? javaType.getComponentType() : javaType,
                                               dataType.getLogical());
        ElementInfo element = new ElementInfo(name, typeInfo);
        element.setMany(byte[].class != javaType && javaType.isArray());
        // TUSCANY-3298: Check the "many" flag set by databinding introspection
        Object logical = dataType.getLogical();
        if (logical instanceof XMLType && ((XMLType)logical).isMany()) {
            element.setMany(true);
        }
        element.setNillable(!javaType.isPrimitive());
        return element;
    }

    private static void addNamespace(Definition definition, QName name) {
        String namespace = name.getNamespaceURI();
        if (definition.getPrefix(namespace) == null) {
            definition.addNamespace("ns" + definition.getNamespaces().size(), namespace);
        }
    }

    /*
    // currently not using the next three methods
    public XmlSchemaType getXmlSchemaType(DataType type) {
        return null;
    }

    // FIXME: WE need to add databinding-specific Java2XSD generation
    public Element generateXSD(DataType dataType) {
        DataBinding dataBinding = dataBindings.getDataBinding(dataType.getDataBinding());
        if (dataBinding != null) {
            // return dataBinding.generateSchema(dataType);
        }
        return null;
    }

    public void generateWrapperElements(Operation op) {
        XmlSchemaCollection collection = new XmlSchemaCollection();
        String ns = getQName(op.getInterface()).getNamespaceURI();
        XmlSchema schema = new XmlSchema(ns, collection);
        schema.setAttributeFormDefault(new XmlSchemaForm(XmlSchemaForm.QUALIFIED));
        schema.setElementFormDefault(new XmlSchemaForm(XmlSchemaForm.QUALIFIED));

        XmlSchemaElement inputElement = new XmlSchemaElement();
        inputElement.setQName(new QName(ns, op.getName()));
        XmlSchemaComplexType inputType = new XmlSchemaComplexType(schema);
        inputType.setName("");
        XmlSchemaSequence inputSeq = new XmlSchemaSequence();
        inputType.setParticle(inputSeq);
        List<DataType> argTypes = op.getInputType().getLogical();
        for (DataType argType : argTypes) {
            XmlSchemaElement child = new XmlSchemaElement();
            Object logical = argType.getLogical();
            if (logical instanceof XMLType) {
                child.setName(((XMLType)logical).getElementName().getLocalPart());
                XmlSchemaType type = getXmlSchemaType(argType);
                child.setType(type);
            }
            inputSeq.getItems().add(child);
        }
        inputElement.setType(inputType);

        XmlSchemaElement outputElement = new XmlSchemaElement();
        outputElement.setQName(new QName(ns, op.getName() + "Response"));
        XmlSchemaComplexType outputType = new XmlSchemaComplexType(schema);
        outputType.setName("");
        XmlSchemaSequence outputSeq = new XmlSchemaSequence();
        outputType.setParticle(outputSeq);
        DataType returnType = op.getOutputType();
        XmlSchemaElement child = new XmlSchemaElement();
        Object logical = returnType.getLogical();
        if (logical instanceof XMLType) {
            child.setName(((XMLType)logical).getElementName().getLocalPart());
            XmlSchemaType type = getXmlSchemaType(returnType);
            child.setType(type);
        }
        outputSeq.getItems().add(child);
        outputElement.setType(outputType);

        schema.getElements().add(inputElement.getQName(), inputElement);
        schema.getElements().add(outputElement.getQName(), outputElement);

    }
    */

    public WSDLFactory getFactory() {
        return factory;
    }

    public void setFactory(WSDLFactory factory) {
        this.factory = factory;
    }

}
