/*
 * 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.axis2.description;

import com.ibm.wsdl.util.xml.DOM2Writer;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.AddressingHelper;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.addressing.EndpointReferenceHelper;
import org.apache.axis2.addressing.wsdl.WSDL11ActionHelper;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.util.LoggingControl;
import org.apache.axis2.util.PolicyUtil;
import org.apache.axis2.util.XMLUtils;
import org.apache.axis2.wsdl.SOAPHeaderMessage;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.axis2.wsdl.WSDLUtil;
import org.apache.axis2.wsdl.util.WSDLDefinitionWrapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.neethi.Constants;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyReference;
import org.apache.ws.commons.schema.utils.NamespaceMap;
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;
import org.xml.sax.SAXException;

import javax.wsdl.Binding;
import javax.wsdl.BindingFault;
import javax.wsdl.BindingInput;
import javax.wsdl.BindingOperation;
import javax.wsdl.BindingOutput;
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.OperationType;
import javax.wsdl.Output;
import javax.wsdl.Part;
import javax.wsdl.Port;
import javax.wsdl.PortType;
import javax.wsdl.Service;
import javax.wsdl.Types;
import javax.wsdl.WSDLException;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.UnknownExtensibilityElement;
import javax.wsdl.extensions.http.HTTPAddress;
import javax.wsdl.extensions.http.HTTPBinding;
import javax.wsdl.extensions.http.HTTPOperation;
import javax.wsdl.extensions.http.HTTPUrlEncoded;
import javax.wsdl.extensions.mime.MIMEContent;
import javax.wsdl.extensions.mime.MIMEMimeXml;
import javax.wsdl.extensions.mime.MIMEMultipartRelated;
import javax.wsdl.extensions.mime.MIMEPart;
import javax.wsdl.extensions.schema.Schema;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap.SOAPBody;
import javax.wsdl.extensions.soap.SOAPHeader;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.wsdl.extensions.soap12.SOAP12Address;
import javax.wsdl.extensions.soap12.SOAP12Binding;
import javax.wsdl.extensions.soap12.SOAP12Body;
import javax.wsdl.extensions.soap12.SOAP12Header;
import javax.wsdl.extensions.soap12.SOAP12Operation;
import javax.wsdl.xml.WSDLLocator;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

public class WSDL11ToAxisServiceBuilder extends WSDLToAxisServiceBuilder {

    public static final int COMPONENT_PORT_TYPE = 1;
    public static final int COMPONENT_MESSAGE = 2;
    public static final int COMPONENT_BINDING = 3;

    /**
     * Parameter used on {@link AxisMessage} objects to track the value of the <tt>name</tt>
     * attribute of the <tt>wsdl:fault</tt>. Note that this is more like a workaround. The problem
     * is that {@link AxisMessage} stores the faults as a simple list. A better fix would be to
     * replace that by a map with the fault name as key, similar to what WSDL4J does (see
     * {@link Operation#getFaults()}).
     */
    private static final String FAULT_NAME = "faultName";
    
    protected static final Log log = LogFactory
            .getLog(WSDL11ToAxisServiceBuilder.class);
    private static final boolean isTraceEnabled = log.isTraceEnabled();

    protected String portName;

    private static final String BINDING = "Binding";

    private static final String SERVICE = "Service";

    private static final String PORT = "Port";

    private static final String PORT_TYPE = "PortType";

    private static final String PORT_TYPE_OPERATION = "PortType.Operation";

    private static final String PORT_TYPE_OPERATION_INPUT = "PortType.Operation.Input";

    private static final String PORT_TYPE_OPERATION_OUTPUT = "PortType.Operation.Output";

    private static final String PORT_TYPE_OPERATION_FAULT = "PortType.Operation.Fault";

    private static final String BINDING_OPERATION = "Binding.Operation";

    private static final String BINDING_OPERATION_INPUT = "Binding.Operation.Input";

    private static final String BINDING_OPERATION_OUTPUT = "Binding.Operation.Output";

    protected Definition wsdl4jDefinition = null;
    protected String     wsdlBaseDocumentURI = null;

    private WSDLLocator customWSDLResolver;

    public static final String RPC_STYLE = "rpc";

    public static final String DOCUMENT_STYLE = "document";

    public static final String ENCODED_USE = "encoded";

    /**
     * List of BindingOperationEntry objects.
     * Each object in the list may require a wrapped schema element for 
     * the input/output or both.
     */
    private List wrappableBOEs = new ArrayList();
    // used to keep the binding type of the selected binding
    private String bindingType;

    public static final String WRAPPED_OUTPUTNAME_SUFFIX = "Response";

    public static final String XML_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/";

    public static final String NAMESPACE_DECLARATION_PREFIX = "xmlns:";

    private static int prefixCounter = 0;

    public static final String NAMESPACE_URI = "namespace";

    public static final String TRAGET_NAMESPACE = "targetNamespace";

    public static final String BINDING_TYPE_SOAP = "soap";
    public static final String BINDING_TYPE_HTTP = "http";

    /**
     * keep track of whether setup code related to the entire wsdl is complete.
     * Note that WSDL11ToAllAxisServices will call setup multiple times, so this
     * field is used to make subsequent calls no-ops.
     */
    private boolean setupComplete = false;

    private Map schemaMap = null;

    private static final String JAVAX_WSDL_VERBOSE_MODE_KEY = "javax.wsdl.verbose";

    // As bindings are processed add it to this array so that we dont process the same binding twice
    private Map processedBindings;

    private boolean isAllPorts;

    /**
     * constructor taking in the service name and the port name
     *
     * @param in - InputStream for the WSDL
     * @param serviceName - The service Name
     * @param portName - The port name
     */
    public WSDL11ToAxisServiceBuilder(InputStream in, QName serviceName,
                                      String portName) {
        super(in, serviceName);
        this.portName = portName;
    }

    /**
     * @param def - The WSDL4J Definition object
     * @param serviceName - The service Name
     * @param portName - The port name
     */
    public WSDL11ToAxisServiceBuilder(Definition def, QName serviceName,
                                      String portName) {
        super(null, serviceName);
        this.wsdl4jDefinition = def;
        this.portName = portName;
        this.isAllPorts = false;
    }

    /**
     * @param def - The WSDL4J Definition object
     * @param serviceName - The service Name
     * @param portName - The port name
     * @param isAllPorts - boolean representing whether to generate code for all ports or not
     */
    public WSDL11ToAxisServiceBuilder(Definition def,
                                      QName serviceName,
                                      String portName,
                                      boolean isAllPorts) {
        this(def, serviceName, portName);
        this.isAllPorts = isAllPorts;
    }


    /**
     * @param in
     * @param service
     */
    public WSDL11ToAxisServiceBuilder(InputStream in, AxisService service) {
        super(in, service);
    }

    /**
     * @param in
     */
    public WSDL11ToAxisServiceBuilder(InputStream in) {
        this(in, null, null);
    }


    /**
     * sets a custom WSDL locator
     *
     * @param customResolver
     */
    public void setCustomWSDLResolver(WSDLLocator customResolver) {
        this.customWSDLResolver = customResolver;
        setDocumentBaseUri(this.customWSDLResolver.getBaseURI());
    }


    /**
     * Sets the URI to the base document associated with the WSDL definition.
     * This identifies the origin of the Definition and allows the
     * Definition to be reloaded.  Note that this is the URI of the base
     * document, not the imports.
     *
     * @param baseUri
     */
    public void setDocumentBaseUri(String baseUri) {
        if (wsdl4jDefinition != null) {
            wsdl4jDefinition.setDocumentBaseURI(baseUri);
        }
        wsdlBaseDocumentURI = baseUri;
    }

    /**
     * Gets the URI to the base document associated with the WSDL definition.
     * This identifies the origin of the Definition and allows the
     * Definition to be reloaded.  Note that this is the URI of the base
     * document, not the imports.
     *
     */
    public String getDocumentBaseUri() {
        return wsdlBaseDocumentURI;
    }




    /**
     * Populates a given service.
     *
     * @throws AxisFault
     */
    public AxisService populateService() throws AxisFault {
        try {
            setup();

            // NOTE: set the axisService with the Parameter for the WSDL
            // Definition after the rest of the work

            if (wsdl4jDefinition == null) {
                return null;
            }

            // setting target name space
            axisService.setTargetNamespace(wsdl4jDefinition.getTargetNamespace());
            axisService.setNamespaceMap(new NamespaceMap(wsdl4jDefinition.getNamespaces()));
            
            Map importsMap = wsdl4jDefinition.getImports();
            
            if (importsMap != null) {
                List imports = new ArrayList(importsMap.keySet());
                axisService.setImportedNamespaces(imports);
            }
            
            //TODO : find the service also in imported wsdls
            Service wsdl4jService = findService(wsdl4jDefinition);

            Binding binding = findBinding(wsdl4jDefinition, wsdl4jService);
            Definition bindingWSDL = getParentDefinition(wsdl4jDefinition,
                    binding.getQName(), COMPONENT_BINDING, new HashSet());
            
            //do not search for wsdl where port type is defined, this search is depth-first
            //and might lead to a wsdl where the port is only referenced but undefined
            //instead look up the port type in the wsdl and only if not found fall back to binding's port type
            PortType portType = wsdl4jDefinition.getPortType(binding.getPortType().getQName());
            if (portType == null) {
                //TODO in case of recursive imports, binding's port type will contain operations with null input message 
                //requires fix for http://sourceforge.net/p/wsdl4j/bugs/39
                portType = binding.getPortType();
            }

            if (portType == null) {
                throw new AxisFault("There is no port type associated with the binding");
            }

            // create new Schema extensions element for wrapping
            // (if its present)
            Element[] schemaElements = generateWrapperSchema(schemaMap, binding, portType);

            processTypes(wsdl4jDefinition, axisService);

            // add the newly created schemas
            if (schemaElements != null && schemaElements.length > 0) {
                for (int i = 0; i < schemaElements.length; i++) {
                    Element schemaElement = schemaElements[i];
                    if (schemaElement != null) {
                        axisService.addSchema(getXMLSchema(schemaElement, null));
                    }
                }
            }
            // copy the documentation element content to the description
            Element documentationElement = wsdl4jDefinition.getDocumentationElement();
            addDocumentation(axisService, documentationElement);

            axisService.setName(wsdl4jService.getQName().getLocalPart());
            populateEndpoints(binding, bindingWSDL,wsdl4jService, portType);
            processPoliciesInDefintion(wsdl4jDefinition);
            axisService.getPolicyInclude().setPolicyRegistry(registry);


            // Setting wsdl4jdefintion to the axisService parameter include list,
            // so if someone needs to use the definition directly,
            // he can do that by getting the parameter
            Parameter wsdlDefinitionParameter = new Parameter();
            wsdlDefinitionParameter.setName(WSDLConstants.WSDL_4_J_DEFINITION);

            if (!(wsdl4jDefinition instanceof WSDLDefinitionWrapper)) {
                AxisConfiguration ac = axisService.getAxisConfiguration();
                if (ac == null) {
                    ac = this.axisConfig;
                }
                WSDLDefinitionWrapper wrapper = new WSDLDefinitionWrapper(wsdl4jDefinition, ac);
                wsdlDefinitionParameter.setValue(wrapper);
            } else {
                wsdlDefinitionParameter.setValue(wsdl4jDefinition);
            }

            axisService.addParameter(wsdlDefinitionParameter);
            axisService.setWsdlFound(true);
            axisService.setCustomWsdl(true);


            return axisService;

        } catch (WSDLException e) {
            if(log.isDebugEnabled()){
                log.debug(e.getMessage(), e);
            }
            throw AxisFault.makeFault(e);
        } catch (Exception e) {
            if(log.isDebugEnabled()){
                log.debug(e.getMessage(), e);
            }
            throw AxisFault.makeFault(e);
        }
    }

    private void processTypes(Definition wsdlDefinition, AxisService axisService)
            throws AxisFault {
        processTypes(wsdlDefinition, axisService, new HashSet());
    }

    private void processTypes(Definition wsdlDefinition,
                              AxisService axisService,
                              Set visitedWSDLs)
            throws AxisFault {
        visitedWSDLs.add(wsdlDefinition.getDocumentBaseURI());
        // process all the types in all the wsdls
        Types types = wsdlDefinition.getTypes();
        if (types != null) {
            copyExtensibleElements(types.getExtensibilityElements(),
                                   wsdlDefinition,
                                   axisService,
                                   TYPES);
        }

        // process the types in other wsdls
        Iterator iter = wsdlDefinition.getImports().values().iterator();
        Vector values = null;
        Import wsdlImport = null;
        for (; iter.hasNext();) {
            values = (Vector) iter.next();
            for (Iterator valuesIter = values.iterator(); valuesIter.hasNext();) {
                wsdlImport = (Import) valuesIter.next();
                // process the types recuresiveilt
                Definition innerDefinition = wsdlImport.getDefinition();
                if(!visitedWSDLs.contains(innerDefinition.getDocumentBaseURI())){
                    processTypes(innerDefinition, axisService, visitedWSDLs);
                }
            }
        }
    }

    private void addDocumentation(AxisDescription axisDescription, Element documentationElement) {
        if ((documentationElement != null) && (documentationElement.getFirstChild() != null)) {
            Node firstChild = documentationElement.getFirstChild();
            String documentation = DOM2Writer.nodeToString(firstChild);
            if (!"".equals(documentation)) {
                axisDescription.setDocumentation(documentation);
            }
        }
    }

    /**
     * @param binding
     * @param wsdl4jService must have atlease one port
     * @throws AxisFault
     */
    private void populateEndpoints(Binding binding,
                                   Definition bindingWSDL,
                                   Service wsdl4jService,
                                   PortType portType) throws AxisFault {

        Map wsdl4jPorts = wsdl4jService.getPorts();
        QName bindingName = binding.getQName();

        Port port;
        AxisEndpoint axisEndpoint = null;

        processedBindings = new HashMap();

        // process the port type for this binding
        // although we support multiports they must be belongs to same port type and should have the
        // same soap style
        populatePortType(portType);

        Binding currentBinding;
        Definition currentBindingWSDL = null;

        for (Iterator iterator = wsdl4jPorts.values().iterator(); iterator.hasNext();) {
            port = (Port) iterator.next();
            // if the user has picked a port then we have to process only that port
            if ((this.portName == null) || (this.portName.equals(port.getName()))) {
                // we process the port only if it has the same port type as the selected binding
                currentBindingWSDL = getParentDefinition(wsdl4jDefinition,
                        port.getBinding().getQName(), COMPONENT_BINDING, new HashSet());
                currentBinding = currentBindingWSDL.getBinding(port.getBinding().getQName());

                if (currentBinding.getPortType().getQName().equals(binding.getPortType().getQName())) {
                    axisEndpoint = new AxisEndpoint();
                    axisEndpoint.setName(port.getName());

                    if (axisService.getEndpointName() == null &&
                            bindingName.equals(port.getBinding().getQName())) {
                        populateEndpoint(axisEndpoint, port, currentBinding,
                                bindingWSDL, portType, true);
                        axisService.setEndpointName(axisEndpoint.getName());
                        axisService.setBindingName(axisEndpoint.getBinding().getName().getLocalPart());
                    } else {
                        populateEndpoint(axisEndpoint, port, currentBinding,
                                bindingWSDL, portType, false);
                    }

                    axisEndpoint.setParent(axisService);
                    axisService.addEndpoint(port.getName(), axisEndpoint);
                }
            }
        }
    }

    /**
     * setting message qname is a binding dependent process for an example message element depends on the
     * soap style (rpc or document) and parts elememet of the soap body
     * On the otherhand we keep only one set of axis operations belongs to a selected port type in axis service
     * So setting qname refetences done only with the selected binding processing
     *
     * @param axisEndpoint
     * @param wsdl4jPort
     * @param isSetMessageQNames
     * @throws AxisFault
     */
    private void populateEndpoint(AxisEndpoint axisEndpoint,
                                  Port wsdl4jPort,
                                  Binding wsdl4jBinding,
                                  Definition bindingWSDL,
                                  PortType portType,
                                  boolean isSetMessageQNames)
            throws AxisFault {

        copyExtensibleElements(wsdl4jPort.getExtensibilityElements(), wsdl4jDefinition,
                               axisEndpoint, BINDING);
        processEmbeddedEPR(wsdl4jPort.getExtensibilityElements(), axisEndpoint);
        addDocumentation(axisEndpoint, wsdl4jPort.getDocumentationElement());
        if (processedBindings.containsKey(wsdl4jBinding.getQName())) {
            axisEndpoint.setBinding(
                    (AxisBinding) processedBindings.get(wsdl4jBinding.getQName()));
        } else {
            AxisBinding axisBinding = new AxisBinding();
            axisBinding.setName(wsdl4jBinding.getQName());
            axisBinding.setParent(axisEndpoint);
            axisEndpoint.setBinding(axisBinding);
            axisBinding.setParent(axisEndpoint);
            populateBinding(axisBinding,
                    wsdl4jBinding,
                    bindingWSDL,
                    portType,
                    isSetMessageQNames);
            processedBindings.put(wsdl4jBinding.getQName(), axisBinding);
        }
    }

    private void processEmbeddedEPR(List extensibilityElements, AxisEndpoint axisEndpoint) {
    	Iterator eelts = extensibilityElements.iterator();
    	while(eelts.hasNext()){
    		ExtensibilityElement ee = (ExtensibilityElement)eelts.next();
    		if(AddressingConstants.Final.WSA_ENDPOINT_REFERENCE.equals(ee.getElementType())){
    			try {
    				Element elt = ((UnknownExtensibilityElement)ee).getElement();
    				OMElement eprOMElement = XMLUtils.toOM(elt);
    				EndpointReference epr = EndpointReferenceHelper.fromOM(eprOMElement);
    				Map referenceParameters = epr.getAllReferenceParameters();
    				if(referenceParameters != null){
    					axisEndpoint.addParameter(AddressingConstants.REFERENCE_PARAMETER_PARAMETER, new ArrayList(referenceParameters.values()));
    				}
    				for (OMElement extensibleElement : epr.getExtensibleElements()) {
    				    if (AddressingConstants.QNAME_IDENTITY.equals(extensibleElement.getQName())) {
    				        axisEndpoint.addParameter(AddressingConstants.ADDRESSING_IDENTITY_PARAMETER, extensibleElement.cloneOMElement());
    				        break;
    				    }
    				}
    			} catch (Exception e) {
    				if(log.isDebugEnabled()){
    					log.debug("Exception encountered processing embedded wsa:EndpointReference", e);
    				}
    			}
    		}
    	}
    }

	private void populatePortType(PortType wsdl4jPortType) throws AxisFault {
		copyExtensionAttributes(wsdl4jPortType.getExtensionAttributes(),
				axisService, PORT_TYPE);
        List wsdl4jOperations = wsdl4jPortType.getOperations();

        // Added to use in ?wsdl2 as the interface name
        axisService.addParameter(new Parameter(WSDL2Constants.INTERFACE_LOCAL_NAME,
                                               wsdl4jPortType.getQName().getLocalPart()));
        if (wsdl4jOperations.size() < 1) {
            throw new AxisFault("No operation found in the portType element");
        }

        AxisOperation axisOperation;
        List operationNames = new ArrayList();

        QName opName;
        Operation wsdl4jOperation;

        for (Iterator iterator = wsdl4jOperations.iterator(); iterator.hasNext();) {
            wsdl4jOperation = (Operation) iterator.next();

            axisOperation = populateOperations(wsdl4jOperation, wsdl4jPortType);
            addDocumentation(axisOperation, wsdl4jOperation.getDocumentationElement());
            if (wsdl4jOperation.getInput() != null) {
                addMessageDocumentation(axisOperation, wsdl4jOperation.getInput().getDocumentationElement(), WSDLConstants.MESSAGE_LABEL_IN_VALUE);
            }
            if (wsdl4jOperation.getOutput() != null) {
                addMessageDocumentation(axisOperation, wsdl4jOperation.getOutput().getDocumentationElement(), WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
            }
            axisOperation.setParent(axisService);
            axisService.addChild(axisOperation);
            operationNames.add(axisOperation.getName());
        }

        // this is used only in codegen to preserve operation order
        if (isCodegen) {
            axisService.setOperationsNameList(operationNames);
        }

    }

    /**
     * This method is used for adding documentation for the message types of the service operations
     * eg: input message
     *     output message
     *     fault messages 
     *
     * @param axisOperation
     * @param documentationElement
     * @param messageLabel
     */
    private void addMessageDocumentation(AxisOperation axisOperation, Element documentationElement, String messageLabel) {
        if ((documentationElement != null) && (documentationElement.getFirstChild() != null)) {
            Node firstChild = documentationElement.getFirstChild();
            String documentation = DOM2Writer.nodeToString(firstChild);

            if (!"".equals(documentation)) {
                (axisOperation.getMessage(messageLabel)).setDocumentation(documentation);
            }
        }
    }
    
    private void populateBinding(AxisBinding axisBinding,
                                 Binding wsdl4jBinding,
                                 Definition bindingWSDL,
                                 PortType portType,
                                 boolean isSetMessageQNames)
            throws AxisFault {

        copyExtensibleElements(wsdl4jBinding.getExtensibilityElements(), bindingWSDL,
                               axisBinding, BINDING);

        List wsdl4jBidingOperations = wsdl4jBinding.getBindingOperations();

        if (wsdl4jBidingOperations.size() < 1) {
            throw new AxisFault("No operation found for the binding");
        }

        addDocumentation(axisBinding, wsdl4jBinding.getDocumentationElement());

        AxisOperation axisOperation;
        Operation wsdl4jOperation;

        AxisBindingOperation axisBindingOperation;
        BindingOperation wsdl4jBindingOperation;

        Map httpLocationMap = createHttpLocationTable();
        String httpLocation = null;

        for (Iterator iterator = wsdl4jBidingOperations.iterator(); iterator.hasNext();) {

            axisBindingOperation = new AxisBindingOperation();
            wsdl4jBindingOperation = (BindingOperation) iterator.next();
            wsdl4jOperation = findOperation(portType, wsdl4jBindingOperation);

            axisBindingOperation.setName(new QName(bindingWSDL.getTargetNamespace(), wsdl4jBindingOperation.getName()));
            addDocumentation(axisBindingOperation, wsdl4jBindingOperation.getDocumentationElement());

            axisOperation = axisService.getOperation(new QName(portType.getQName().getNamespaceURI(), wsdl4jOperation.getName()));
            axisBindingOperation.setAxisOperation(axisOperation);

            // process ExtensibilityElements of the wsdl4jBinding
            copyExtensibleElements(wsdl4jBindingOperation.getExtensibilityElements(),
                                   wsdl4jDefinition, axisBindingOperation, BINDING_OPERATION);

            httpLocation =
                    (String) axisBindingOperation.getProperty(WSDL2Constants.ATTR_WHTTP_LOCATION);
            String httpMethod =
                    (String) axisBindingOperation.getProperty(WSDL2Constants.ATTR_WHTTP_METHOD);
            if (httpMethod == null || "".equals(httpMethod)) {
                httpMethod = HTTPConstants.HEADER_POST;
            }
            if (httpLocation != null) {
                httpLocationMap.put(WSDLUtil.getConstantFromHTTPLocation(httpLocation, httpMethod),
                                    axisBindingOperation.getAxisOperation());
            }

            BindingInput wsdl4jBindingInput = wsdl4jBindingOperation.getBindingInput();

            if (isServerSide) {
                if (wsdl4jBindingInput != null &&
                        WSDLUtil.isInputPresentForMEP(axisOperation.getMessageExchangePattern())) {
                    AxisBindingMessage axisBindingInMessage = new AxisBindingMessage();
                    axisBindingInMessage.setParent(axisBindingOperation);
                    addDocumentation(axisBindingInMessage, wsdl4jBindingInput.getDocumentationElement());
                    copyExtensibleElements(wsdl4jBindingInput.getExtensibilityElements(),
                            wsdl4jDefinition,
                            axisBindingInMessage, BINDING_OPERATION_INPUT);

                    AxisMessage axisInMessage =
                            axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
                    //This is a hack to get AXIS2-2771 working , I had to copy soap headers
                    //  from binding message to AxisMessage
                    List soapHeaders = (List) axisBindingInMessage.getProperty(
                            WSDL2Constants.ATTR_WSOAP_HEADER);
                    if (soapHeaders != null) {
                        for (int i = 0; i < soapHeaders.size(); i++) {
                            SOAPHeaderMessage headerMessage = (SOAPHeaderMessage) soapHeaders.get(i);
                            axisInMessage.addSoapHeader(headerMessage);
                        }
                    }

                    if (isSetMessageQNames) {
                        BindingOperationEntry boe = find(wrappableBOEs, wsdl4jBindingOperation);
                        boolean isWrapped = (boe == null) ? false : boe.isWrappedInput();
                        addQNameReference(axisInMessage, wsdl4jOperation,
                                wsdl4jBindingInput,
                                isWrapped);
                    }

                    axisBindingInMessage.setAxisMessage(axisInMessage);
                    axisBindingInMessage.setName(axisInMessage.getName());
                    axisBindingInMessage.setDirection(axisInMessage.getDirection());

                    axisBindingOperation
                            .addChild(WSDLConstants.MESSAGE_LABEL_IN_VALUE, axisBindingInMessage);
                }
            } else {
                if (wsdl4jBindingInput != null &&
                        WSDLUtil.isOutputPresentForMEP(axisOperation.getMessageExchangePattern())) {
                    AxisBindingMessage axisBindingOutMessage = new AxisBindingMessage();
                    axisBindingOutMessage.setParent(axisBindingOperation);
                    addDocumentation(axisBindingOutMessage, wsdl4jBindingInput.getDocumentationElement());
                    copyExtensibleElements(wsdl4jBindingInput.getExtensibilityElements(),
                            wsdl4jDefinition,
                            axisBindingOutMessage, BINDING_OPERATION_OUTPUT);

                    AxisMessage axisOutMessage =
                            axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
                    //This is a hack to get AXIS2-2771 working , I had to copy soap headers
                    //  from binding message to AxisMessage
                    List soapHeaders = (List) axisBindingOutMessage.getProperty(
                            WSDL2Constants.ATTR_WSOAP_HEADER);
                    if (soapHeaders != null) {
                        for (int i = 0; i < soapHeaders.size(); i++) {
                            SOAPHeaderMessage headerMessage = (SOAPHeaderMessage) soapHeaders.get(i);
                            axisOutMessage.addSoapHeader(headerMessage);
                        }
                    }

                    if (isSetMessageQNames) {
                        BindingOperationEntry boe = find(wrappableBOEs, wsdl4jBindingOperation);
                        boolean isWrapped = (boe == null) ? false : boe.isWrappedInput();
                        addQNameReference(axisOutMessage, wsdl4jOperation,
                                wsdl4jBindingInput,
                                isWrapped);
                    }

                    axisBindingOutMessage.setAxisMessage(axisOutMessage);
                    axisBindingOutMessage.setName(axisOutMessage.getName());
                    axisBindingOutMessage.setDirection(axisOutMessage.getDirection());

                    axisBindingOperation
                            .addChild(WSDLConstants.MESSAGE_LABEL_OUT_VALUE, axisBindingOutMessage);
                }
            }

            BindingOutput wsdl4jBindingOutput = wsdl4jBindingOperation.getBindingOutput();

            if (isServerSide) {
                if (wsdl4jBindingOutput != null &&
                        WSDLUtil.isOutputPresentForMEP(axisOperation.getMessageExchangePattern())) {

                    AxisBindingMessage axisBindingOutMessage = new AxisBindingMessage();
                    axisBindingOutMessage.setParent(axisBindingOperation);
                    addDocumentation(axisBindingOutMessage, wsdl4jBindingOutput.getDocumentationElement());
                    AxisMessage axisOutMessage =
                            axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);

                    copyExtensibleElements(wsdl4jBindingOutput.getExtensibilityElements(),
                            wsdl4jDefinition,
                            axisBindingOutMessage, BINDING_OPERATION_OUTPUT);

                    //This is a hack to get AXIS2-2771 working , I had to copy soap headers
                    //  from binding message to AxisMessage
                    List soapHeaders =
                            (List) axisBindingOutMessage.getProperty(WSDL2Constants.ATTR_WSOAP_HEADER);
                    if (soapHeaders != null) {
                        for (int i = 0; i < soapHeaders.size(); i++) {
                            SOAPHeaderMessage headerMessage = (SOAPHeaderMessage) soapHeaders.get(i);
                            axisOutMessage.addSoapHeader(headerMessage);
                        }
                    }

                    if (isSetMessageQNames) {
                        BindingOperationEntry boe = find(wrappableBOEs, wsdl4jBindingOperation);
                        boolean isWrapped = (boe == null) ? false : boe.isWrappedOutput();
                        axisOutMessage.setWrapped(isWrapped);
                        addQNameReference(axisOutMessage, wsdl4jOperation,
                                wsdl4jBindingOutput,
                                isWrapped);
                    }


                    axisBindingOutMessage.setAxisMessage(axisOutMessage);
                    axisBindingOutMessage.setName(axisOutMessage.getName());
                    axisBindingOutMessage.setDirection(axisOutMessage.getDirection());

                    axisBindingOperation
                            .addChild(WSDLConstants.MESSAGE_LABEL_OUT_VALUE, axisBindingOutMessage);
                }
            } else {
                if (wsdl4jBindingOutput != null &&
                        WSDLUtil.isInputPresentForMEP(axisOperation.getMessageExchangePattern())) {

                    AxisBindingMessage axisBindingInMessage = new AxisBindingMessage();
                    axisBindingInMessage.setParent(axisBindingOperation);
                    addDocumentation(axisBindingInMessage, wsdl4jBindingOutput.getDocumentationElement());
                    AxisMessage axisInMessage =
                            axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);

                    copyExtensibleElements(wsdl4jBindingOutput.getExtensibilityElements(),
                            wsdl4jDefinition,
                            axisBindingInMessage, BINDING_OPERATION_INPUT);

                    //This is a hack to get AXIS2-2771 working , I had to copy soap headers
                    //  from binding message to AxisMessage
                    List soapHeaders =
                            (List) axisBindingInMessage.getProperty(WSDL2Constants.ATTR_WSOAP_HEADER);
                    if (soapHeaders != null) {
                        for (int i = 0; i < soapHeaders.size(); i++) {
                            SOAPHeaderMessage headerMessage = (SOAPHeaderMessage) soapHeaders.get(i);
                            axisInMessage.addSoapHeader(headerMessage);
                        }
                    }

                    if (isSetMessageQNames) {
                        BindingOperationEntry boe = find(wrappableBOEs, wsdl4jBindingOperation);
                        boolean isWrapped = (boe == null) ? false : boe.isWrappedOutput();
                        axisInMessage.setWrapped(isWrapped);
                        addQNameReference(axisInMessage, wsdl4jOperation,
                                wsdl4jBindingOutput,
                                isWrapped);
                    }


                    axisBindingInMessage.setAxisMessage(axisInMessage);
                    axisBindingInMessage.setName(axisInMessage.getName());
                    axisBindingInMessage.setDirection(axisInMessage.getDirection());

                    axisBindingOperation
                            .addChild(WSDLConstants.MESSAGE_LABEL_IN_VALUE, axisBindingInMessage);
                }
            }

            Map bindingFaultsMap = wsdl4jBindingOperation.getBindingFaults();

            /* process the binding faults */
            for (Iterator bindingFaults = bindingFaultsMap.values().iterator();
                 bindingFaults.hasNext();) {

                BindingFault bindingFault = (BindingFault) bindingFaults.next();
                if (bindingFault.getName() == null) {
                    throw new AxisFault("Binding name is null for the binding fault in " +
                            " binding operation ==> " + wsdl4jBindingOperation.getName());
                } else {
                    Fault wsdl4jFault = wsdl4jOperation.getFault(bindingFault.getName());
                    if (wsdl4jFault == null){
                        throw new AxisFault("Can not find the corresponding fault element in " +
                                "wsdl operation " + wsdl4jOperation.getName() + " for the fault" +
                                " name " + bindingFault.getName());
                    } else {
                        Message wsdl4jFaultMessge = wsdl4jFault.getMessage();

                        AxisMessage faultMessage = findFaultMessage(
                                wsdl4jFault.getName(),
                                axisOperation.getFaultMessages());

                        AxisBindingMessage axisBindingFaultMessage = new AxisBindingMessage();
                        addDocumentation(axisBindingFaultMessage, wsdl4jFaultMessge.getDocumentationElement());
                        axisBindingFaultMessage.setFault(true);
                        axisBindingFaultMessage.setAxisMessage(faultMessage);
                        axisBindingFaultMessage.setName(faultMessage.getName());
                        axisBindingFaultMessage.setParent(axisBindingOperation);

                        axisBindingOperation.addFault(axisBindingFaultMessage);
                        if (isSetMessageQNames) {
                            addQNameReference(faultMessage, wsdl4jFault.getMessage());
                        }
                    }
                }
            }

            axisBindingOperation.setParent(axisBinding);
            axisBinding.addChild(axisBindingOperation.getName(), axisBindingOperation);
        }
        axisBinding.setProperty(WSDL2Constants.HTTP_LOCATION_TABLE, httpLocationMap);
    }

    /**
     * contains all code which gathers non-service specific information from the
     * wsdl. <p/> After all the setup completes successfully, the setupComplete
     * field is set so that any subsequent calls to setup() will result in a
     * no-op. Note that subclass WSDL11ToAllAxisServicesBuilder will call
     * populateService for each port in the WSDL. Separating the non-service
     * specific information here allows WSDL11ToAllAxisServicesBuilder to only
     * do this work 1 time per WSDL, instead of for each port on each service.
     *
     * @throws WSDLException if readInTheWSDLFile fails
     */
    protected void setup() throws WSDLException {
        if (setupComplete) { // already setup, just do nothing and return
            return;
        }
        if (wsdl4jDefinition == null) {
            wsdl4jDefinition = readInTheWSDLFile(in);
        }
        if (wsdl4jDefinition == null) {
            return; // can't continue without wsdl
        }


        // setup the schemaMap
        this.schemaMap = new HashMap();
        populateSchemaMap(wsdl4jDefinition, new HashSet());

        setPolicyRegistryFromService(axisService);

        setupComplete = true; // if any part of setup fails, don't mark
        // setupComplete
    }


    /**
     * Populate a map of targetNamespace vs DOM schema element This is used to
     * grab the correct schema element when adding a new element
     *
     * @param definition
     */

    private void populateSchemaMap(Definition definition, Set visitedWSDLs) {
        visitedWSDLs.add(definition.getDocumentBaseURI());
        // first process the types in the given wsdl
        Types types = definition.getTypes();
        Object extensibilityElement;
        if (types != null) {
            for (Iterator iterator = types.getExtensibilityElements().iterator(); iterator.hasNext();)
            {
                extensibilityElement = iterator.next();
                if (extensibilityElement instanceof Schema) {
                    Element schemaElement = ((Schema) extensibilityElement).getElement();
                    schemaMap.put(schemaElement.getAttribute(XSD_TARGETNAMESPACE), schemaElement);
                }
            }
        }

        // popualte the imports as well
        Iterator iter = definition.getImports().values().iterator();
        Vector values = null;
        Import wsdlImport = null;
        for (; iter.hasNext();) {
            values = (Vector) iter.next();
            for (Iterator valuesIter = values.iterator(); valuesIter.hasNext();) {
                wsdlImport = (Import) valuesIter.next();
                Definition innerDefinition = wsdlImport.getDefinition();
                if(!visitedWSDLs.contains(innerDefinition.getDocumentBaseURI())) {
                    populateSchemaMap(innerDefinition, visitedWSDLs);
                }
            }
        }
    }


    /**
     * return the service to process
     * if user has specified we check whether it exists
     * else pick a random service and throws an exception if not found any thing
     *
     * @param definition
     * @return service to process
     * @throws AxisFault
     */

    private Service findService(Definition definition) throws AxisFault {
        Map services = definition.getServices();
        Service service = null;
        if (serviceName != null) {
            // i.e if a user has specified a pirticular port
            service = (Service) services.get(serviceName);
            if (service == null) {
                throw new AxisFault("Service " + serviceName
                                    + " was not found in the WSDL");
            }
        } else {
            if (services.size() > 0) {
                for (Iterator iter = services.values().iterator(); iter.hasNext();) {
                    service = (Service) iter.next();
                    if (service.getPorts().size() > 0) {
                        //i.e we have found a service with ports
                        break;
                    }
                }
                if ((service == null) || (service.getPorts().size() == 0)) {
                    throw new AxisFault("there is no service with ports to pick");
                }

            } else {
                throw new AxisFault("No services found in the WSDL at " +
                                    definition.getDocumentBaseURI()
                                    + " with targetnamespace "
                                    + definition.getTargetNamespace());
            }
        }
        return service;
    }

    /**
     * Look for the relevant binding!
     * if user has spcifed a port get it
     * otherwise find first soap port or pick random one if there is no soap port
     *
     * @param dif
     * @param service service can not be null
     * @throws AxisFault
     */
    private Binding findBinding(Definition dif, Service service) throws AxisFault {

        Binding binding = null;
        Port port = null;
        copyExtensibleElements(service.getExtensibilityElements(), dif, axisService, SERVICE);
        if (portName != null) {
            // i.e if user has specified a service
            port = service.getPort(portName);
            if (port == null) {
                throw new AxisFault("No port found for the given name :" + portName);
            }
        } else {
            Map ports = service.getPorts();
            if (ports != null && ports.size() > 0) {
                // pick the port with the SOAP address as the default port
                port = findPort(ports);
                if (port == null) {
                    // a SOAP port was not found - log a warning
                    // and use the first port in the list
                    log.info("A SOAP port was not found - "
                             + "picking a random port!");
                    port = (Port) ports.values().toArray()[0];
                }

                if (port != null) {
                    // i.e we have find a correct port
                    // this is only use full in codegen time.
                    if (this.isCodegen && !this.isAllPorts) {
                        // if user has not set all option
                        // we have to generate code only for that option.
                        this.portName = port.getName();
                    }
                }
            }
        }

        axisService.setName(service.getQName().getLocalPart());

        if (port != null) {
            copyExtensibleElements(port.getExtensibilityElements(), dif,
                                   axisService, PORT);
            Definition parentDefinition = getParentDefinition(dif,
                    port.getBinding().getQName(), COMPONENT_BINDING, new HashSet());
            binding = parentDefinition.getBinding(port.getBinding().getQName());
            if (binding == null) {
                binding = port.getBinding();
            }
        }

        return binding;
    }

    /**
     * Finds a SOAP port given the port map
     */
    private Port findPort(Map ports) {
        Port port;
        Port returnPort = null;
        for (Iterator portsIterator = ports.values().iterator(); portsIterator.hasNext();) {
            port = (Port) portsIterator.next();
            List extensibilityElements = port.getExtensibilityElements();
            for (int i = 0; i < extensibilityElements.size(); i++) {
                Object extElement = extensibilityElements.get(i);
                if (extElement instanceof SOAP12Address) {
                    // SOAP 1.2 address found - keep this and loop until http address is found
                    returnPort = port;
                    String location = ((SOAP12Address)extElement).getLocationURI().trim();
                    if ((location != null) && location.startsWith("http:")){
                        // i.e we have found an http port so return from here
                       break;
                    }
                }
            }
        }

        if (returnPort != null){
            return returnPort;
        }

        for (Iterator portsIterator = ports.values().iterator(); portsIterator
                .hasNext();) {
            port = (Port) portsIterator.next();
            List extensibilityElements = port.getExtensibilityElements();
            for (int i = 0; i < extensibilityElements.size(); i++) {
                Object extElement = extensibilityElements.get(i);
                if (extElement instanceof SOAPAddress) {
                    // SOAP 1.1 address found - keep this and loop until http address is found
                    returnPort = port;
                    String location = ((SOAPAddress)extElement).getLocationURI().trim();
                    if ((location != null) && location.startsWith("http:")){
                        // i.e we have found an http port so return from here
                       break;
                    }
                }
            }
        }

        if (returnPort != null){
            return returnPort;
        }

        for (Iterator portsIterator = ports.values().iterator(); portsIterator
                .hasNext();) {
            port = (Port) portsIterator.next();
            List extensibilityElements = port.getExtensibilityElements();
            for (int i = 0; i < extensibilityElements.size(); i++) {
                Object extElement = extensibilityElements.get(i);
                if (extElement instanceof HTTPAddress) {
                    // HTTP address found - keep this and loop until http address is found
                    returnPort = port;
                    String location = ((HTTPAddress)extElement).getLocationURI().trim();
                    if ((location != null) && location.startsWith("http:")){
                        // i.e we have found an http port so return from here
                       break;
                    }
                }
            }
        }
        return returnPort;
    }

    private Operation findOperation(PortType portType,
                                    BindingOperation wsdl4jBindingOperation) {
        Operation op = wsdl4jBindingOperation.getOperation();
        String input = null;
        if (op != null && op.getInput() != null) {
            input = op.getInput().getName();
            if (":none".equals(input)) {
                input = null;
            }
        }
        String output = null;
        if (op != null && op.getOutput() != null) {
            output = op.getOutput().getName();
            if (":none".equals(output)) {
                output = null;
            }
        }
        Operation op2 = portType.getOperation(op.getName(), input, output);
        return ((op2 == null) ? op : op2);
    }

    /**
     * Find the fault message relevant to a given name from the fault message
     * list
     *
     * @param name
     * @param faultMessages
     */
    private AxisMessage findFaultMessage(String name, ArrayList faultMessages) {
        AxisMessage tempMessage;
        for (int i = 0; i < faultMessages.size(); i++) {
            tempMessage = (AxisMessage) faultMessages.get(i);
            if (name.equals(tempMessage.getParameterValue(FAULT_NAME))) {
                return tempMessage;
            }

        }
        return null;
    }

    /**
     * Add the QName for the binding input
     *
     * @param inMessage
     * @param wsdl4jOperation
     * @param bindingInput
     * @param isWrapped       - basically whether the operation is soap/rpc or not
     */
    private void addQNameReference(AxisMessage inMessage,
                                   Operation wsdl4jOperation, BindingInput bindingInput,
                                   boolean isWrapped) {

        List extensibilityElements = bindingInput.getExtensibilityElements();
        Message wsdl4jMessage = wsdl4jOperation.getInput().getMessage();

        addQNameReference(inMessage,
                          wsdl4jOperation,
                          isWrapped,
                          extensibilityElements,
                          wsdl4jMessage,
                          wsdl4jOperation.getName());
    }

    /**
     * Add the QName for the binding output
     *
     * @param outMessage
     * @param wsdl4jOperation
     * @param isWrapped
     */
    private void addQNameReference(AxisMessage outMessage,
                                   Operation wsdl4jOperation, BindingOutput bindingOutput,
                                   boolean isWrapped) {

        if (bindingOutput != null) {
            List extensibilityElements = bindingOutput.getExtensibilityElements();
            if (wsdl4jOperation.getOutput() == null) {
                return;
            }
            Message wsdl4jMessage = wsdl4jOperation.getOutput().getMessage();

            addQNameReference(outMessage,
                              wsdl4jOperation,
                              isWrapped,
                              extensibilityElements,
                              wsdl4jMessage,
                              wsdl4jOperation.getName() + WRAPPED_OUTPUTNAME_SUFFIX);
        }
    }

    private void addQNameReference(AxisMessage message,
                                   Operation wsdl4jOperation,
                                   boolean isWrapped,
                                   List extensibilityElements,
                                   Message wsdl4jMessage,
                                   String rpcOperationName) {
        if (isWrapped) {
            // we have already validated and process the qname references
            // so set it here
            // The schema for this should be already made ! Find the
            // QName from
            // the list and add it - the name for this is just the
            message.setElementQName((QName) resolvedRpcWrappedElementMap
                    .get(rpcOperationName));
            message.getAxisOperation().getAxisService().addMessageElementQNameToOperationMapping(
                    (QName) resolvedRpcWrappedElementMap.get(rpcOperationName),
                    message.getAxisOperation());
        } else {
            // now we are sure this is an document literal type element
            List bindingPartsList = getPartsListFromSoapBody(extensibilityElements);
            if (bindingPartsList == null) {
                // i.e user has not given any part list so we go to message and pick the firest part if
                // available
                if ((wsdl4jMessage.getParts() != null) && (wsdl4jMessage.getParts().size() > 0)) {
                    if (wsdl4jMessage.getParts().size() == 1) {
                        Part part = (Part) wsdl4jMessage.getParts().values().iterator().next();
                        QName elementName = part.getElementName();
                        if (elementName != null) {
                            message.setElementQName(elementName);
                            message.setMessagePartName(part.getName());
                            AxisOperation operation = message.getAxisOperation();
                            AxisService service = operation.getAxisService();
                            service.addMessageElementQNameToOperationMapping(elementName,
                                                                             operation);
                        } else {
                            throw new WSDLProcessingException(
                                    "No element type is defined for message " +
                                    wsdl4jMessage.getQName().getLocalPart() + " (see WS-I BP 1.0, R2204)");
                        }
                    } else {
                        // user has specified more than one parts with out specifing a part in
                        // soap body
                        throw new WSDLProcessingException("More than one part for message " +
                                                          wsdl4jMessage.getQName().getLocalPart());
                    }
                } else {
                    // This is allowed in the spec in this case element qname is null and nothing is send
                    // in the soap body.  This is true for Doc/Lit/Bare operations that do not have any paramaters.
                    // In this case, add a mapping of the operation to a null key so the empty body can be routed on
                    // (for example in SOAPMessageBodyBasedDispatcher).
                    message.setElementQName(null);
                    AxisOperation operation = message.getAxisOperation();
                    AxisService service = operation.getAxisService();
                    service.addMessageElementQNameToOperationMapping(null, operation);
                }
            } else {
                if (bindingPartsList.size() == 0) {
                    // we donot have to set the element qname
                    message.setElementQName(null);
                } else if (bindingPartsList.size() == 1) {
                    Part part = wsdl4jMessage.getPart((String) bindingPartsList.get(0));
                    if (part != null) {
                        QName elementName = part.getElementName();
                        if (elementName != null) {
                            message.setElementQName(elementName);
                            message.setMessagePartName(part.getName());
                            AxisOperation operation = message.getAxisOperation();
                            AxisService service = operation.getAxisService();
                            service.addMessageElementQNameToOperationMapping(elementName,
                                                                             operation);
                        } else {
                            throw new WSDLProcessingException(
                                    "No element type is defined for message " +
                                    wsdl4jMessage.getQName().getLocalPart() + " (see WS-I BP 1.0, R2204)");
                        }
                    } else {
                        throw new WSDLProcessingException("Missing part named "
                                                          + bindingPartsList.get(0) + " ");
                    }

                } else {
                    // i.e more than one part specified in this case we have
                    // to send an exception
                    throw new WSDLProcessingException(
                            "More than one element part is not allwed in document literal " +
                            " type binding operation " + wsdl4jOperation.getName());
                }
            }

        }

    }

    /**
     * Add the QName for the binding output
     */
    private void addQNameReference(AxisMessage faultMessage,
                                   Message wsdl4jMessage) throws AxisFault {

        // for a fault this is trivial - All faults are related directly to a
        // message by the name and are supposed to have a single part. So it is
        // a matter of copying the right QName from the message part

        // get the part
        Map parts = wsdl4jMessage.getParts();
        if (parts == null || parts.size() == 0) {
            String message = "There are no parts"
                             + " for fault message : "
                             + wsdl4jMessage.getQName();
            log.error(message);
            throw new WSDLProcessingException(message);
        }
        Part wsdl4jMessagePart = (Part) parts.values()
                .toArray()[0];
        if (wsdl4jMessagePart == null) {
            throw new WSDLProcessingException();
        }
        QName name = wsdl4jMessagePart.getElementName();
        if (name == null) {
            String message = "Part '"
                             + wsdl4jMessagePart.getName()
                             + "' of fault message '"
                             + wsdl4jMessage.getQName()
                             + "' must be defined with 'element=QName' and not 'type=QName'";
            log.error(message);
            throw new AxisFault(message);
        }

        faultMessage.setMessagePartName(wsdl4jMessagePart.getName());
        faultMessage.setElementQName(name);
    }

    /**
     * A util method that returns the SOAP style included in the binding
     * operation
     *
     * @param bindingOp
     */
    private String getSOAPStyle(BindingOperation bindingOp) {
        List extensibilityElements = bindingOp.getExtensibilityElements();
        for (int i = 0; i < extensibilityElements.size(); i++) {
            Object extElement = extensibilityElements.get(i);
            if (extElement instanceof SOAPOperation) {
                return ((SOAPOperation) extElement).getStyle();
            } else if (extElement instanceof SOAP12Operation) {
                return ((SOAP12Operation) extElement).getStyle();
            }

        }
        return null;
    }

    /**
     * Copy the component from the operation
     *
     * @param wsdl4jOperation
     * @param dif
     * @throws AxisFault
     */
    private AxisOperation populateOperations(Operation wsdl4jOperation,
                                             PortType wsdl4jPortType)
            throws AxisFault {
        QName opName = new QName(wsdl4jPortType.getQName().getNamespaceURI(), wsdl4jOperation.getName());
        // Copy Name Attribute
        AxisOperation axisOperation = axisService.getOperation(opName);
        if (axisOperation == null) {
            String MEP = getMEP(wsdl4jOperation);
            axisOperation = AxisOperationFactory.getOperationDescription(MEP);
            axisOperation.setName(opName);

            // setting the PolicyInclude property of the AxisOperation
            PolicyInclude policyInclude = new PolicyInclude(axisOperation);
            axisOperation.setPolicyInclude(policyInclude);
        }

        copyExtensionAttributes(wsdl4jOperation.getExtensionAttributes(), 
                               axisOperation, PORT_TYPE_OPERATION);

        Input wsdl4jInputMessage = wsdl4jOperation.getInput();

        if (isServerSide) {
            if (null != wsdl4jInputMessage) {
                AxisMessage inMessage = axisOperation
                        .getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
                Message message = wsdl4jInputMessage.getMessage();
                if (null != message) {
                    inMessage.setName(message.getQName().getLocalPart());
                    copyExtensionAttributes(wsdl4jInputMessage.getExtensionAttributes(),
                                           inMessage, PORT_TYPE_OPERATION_INPUT);

                }
                // Check if the action is already set as we don't want to
                // override it
                // with the Default Action Pattern
                ArrayList inputActions = axisOperation.getWSAMappingList();
                String action = null;
                if (inputActions == null || inputActions.size() == 0) {
                    action = WSDL11ActionHelper
                            .getActionFromInputElement(wsdl4jDefinition, wsdl4jPortType,
                                                       wsdl4jOperation, wsdl4jInputMessage);
                }
                if (action != null) {
                    if (inputActions == null) {
                        inputActions = new ArrayList();
                        axisOperation.setWsamappingList(inputActions);
                    }
                    inputActions.add(action);
                    axisService.mapActionToOperation(action, axisOperation);
                }
            }
            // Create an output message and add
            Output wsdl4jOutputMessage = wsdl4jOperation.getOutput();
            if (null != wsdl4jOutputMessage) {
                AxisMessage outMessage = axisOperation
                        .getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
                Message message = wsdl4jOutputMessage.getMessage();
                if (null != message) {

                    outMessage.setName(message.getQName().getLocalPart());
                    copyExtensionAttributes(wsdl4jOutputMessage.getExtensionAttributes(),
                                           outMessage, PORT_TYPE_OPERATION_OUTPUT);

                    // wsdl:portType -> wsdl:operation -> wsdl:output
                }
                // Check if the action is already set as we don't want to
                // override it
                // with the Default Action Pattern
                String action = axisOperation.getOutputAction();
                if (action == null) {
                    action = WSDL11ActionHelper.getActionFromOutputElement(wsdl4jDefinition,
                                                                           wsdl4jPortType,
                                                                           wsdl4jOperation,
                                                                           wsdl4jOutputMessage);
                }
                if (action != null) {
                    axisOperation.setOutputAction(action);
                }
            }
        } else {

            // for the client side we have to do something that is a bit
            // weird. The in message is actually taken from the output
            // and the output is taken from the in

            if (null != wsdl4jInputMessage) {
                AxisMessage inMessage = axisOperation
                        .getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
                Message message = wsdl4jInputMessage.getMessage();
                if (null != message) {

                    inMessage.setName(message.getQName().getLocalPart());
                    copyExtensionAttributes(wsdl4jInputMessage.getExtensionAttributes(),
                                           inMessage, PORT_TYPE_OPERATION_OUTPUT);

                }
                // Check if the action is already set as we don't want to
                // override it
                // with the Default Action Pattern
                String action = axisOperation.getOutputAction();
                if (action == null) {
                    action = WSDL11ActionHelper
                            .getActionFromInputElement(wsdl4jDefinition, wsdl4jPortType,
                                                       wsdl4jOperation, wsdl4jInputMessage);
                }
                if (action != null) {
                    axisOperation.setOutputAction(action);
                }
            }
            // Create an output message and add
            Output wsdl4jOutputMessage = wsdl4jOperation.getOutput();
            if (null != wsdl4jOutputMessage) {
                AxisMessage outMessage = axisOperation
                        .getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
                Message message = wsdl4jOutputMessage.getMessage();
                if (null != message) {

                    outMessage.setName(message.getQName().getLocalPart());
                    copyExtensionAttributes(wsdl4jOutputMessage.getExtensionAttributes(),
                                           outMessage, PORT_TYPE_OPERATION_INPUT);

                    // wsdl:portType -> wsdl:operation -> wsdl:output
                }
                // Check if the action is already set as we don't want to
                // override it
                // with the Default Action Pattern
                ArrayList inputActions = axisOperation.getWSAMappingList();
                String action = null;
                if (inputActions == null || inputActions.size() == 0) {
                    action = WSDL11ActionHelper.getActionFromOutputElement(wsdl4jDefinition,
                                                                           wsdl4jPortType,
                                                                           wsdl4jOperation,
                                                                           wsdl4jOutputMessage);
                }
                if (action != null) {
                    if (inputActions == null) {
                        inputActions = new ArrayList();
                        axisOperation.setWsamappingList(inputActions);
                    }
                    inputActions.add(action);
                }
            }
        }

        Map faults = wsdl4jOperation.getFaults();
        Iterator faultKeyIterator = faults.keySet().iterator();

        while (faultKeyIterator.hasNext()) {
            Fault fault = (Fault) faults.get(faultKeyIterator.next());
            AxisMessage axisFaultMessage = new AxisMessage();
            addDocumentation(axisFaultMessage,fault.getDocumentationElement());
            axisFaultMessage.addParameter(FAULT_NAME, fault.getName());
            Message faultMessage = fault.getMessage();
            if (null != faultMessage) {
                axisFaultMessage
                        .setName(faultMessage.getQName().getLocalPart());

                copyExtensibleElements(faultMessage.getExtensibilityElements(),
                                       wsdl4jDefinition, axisFaultMessage, PORT_TYPE_OPERATION_FAULT);

            }

            // Check if the action is already set as we don't want to override
            // it
            // with the Default Action Pattern
            String action = axisOperation.getFaultAction(fault.getName());
            if (action == null) {
                action = WSDL11ActionHelper.getActionFromFaultElement(wsdl4jDefinition,
                                                                      wsdl4jPortType,
                                                                      wsdl4jOperation, fault);
            }
            if (action != null) {
                axisOperation.addFaultAction(fault.getName(), action);
            }
            
            // Also add mapping from Exception name to fault action
            String faultMessageName = axisFaultMessage.getName();
            if (null != faultMessageName) {
                char firstChar = faultMessageName.charAt(0);
                String upperChar = String.valueOf(firstChar).toUpperCase();
                String nameWithoutFirstChar = faultMessageName.substring(1);
                String exceptionClassName = upperChar.concat(nameWithoutFirstChar);
                if (log.isDebugEnabled()) {
                    log.debug("Searching for fault action using faultMessageName = "+faultMessageName+", exceptionClassName = "+exceptionClassName);
                }
            
                String faultAction = axisOperation.getFaultAction(exceptionClassName);
                if (faultAction == null) {
                    faultAction = WSDL11ActionHelper.getActionFromFaultElement(wsdl4jDefinition,
                                                                          wsdl4jPortType,
                                                                          wsdl4jOperation, fault);
                    if (log.isDebugEnabled()) {
                        log.debug("Fault action didn't previously exist, getting it from WSDL: "+faultAction);
                    }
                }
                if (faultAction != null) {
                    axisOperation.addFaultAction(exceptionClassName, faultAction);
                    axisOperation.addFaultAction(exceptionClassName+"_Exception", faultAction);
                    if (log.isDebugEnabled()) {
                        log.debug("Adding fault action entry: "+exceptionClassName+"="+faultAction);
                        log.debug("Adding fault action entry: "+exceptionClassName+"_Exception"+"="+faultAction);
                    }
                }
            }
            
            axisOperation.setFaultMessages(axisFaultMessage);
        }
        return axisOperation;
    }

    /**
     * Generates a list of wrapper schemas
     *
     * @param wsdl4jBinding
     */
    private Element[] generateWrapperSchema(Map schemaMap,
                                            Binding wsdl4jBinding,
                                            PortType portType) {

        List schemaElementList = new ArrayList();
        // target namespace for this should be the namespace URI for
        // the porttype
        String porttypeNamespaceURI = portType.getQName().getNamespaceURI();

        // //////////////////////////////////////////////////////////////////////
        // if there are any bindings present then we have to process them. we
        // have to generate a schema per wsdl4jBinding (that is the safest
        // option).
        // if not we just resolve to
        // the good old port type
        // list, in which case we'll generate a schema per porttype
        // //////////////////////////////////////////////////////////////////////

        // findwrappable operations return either the rpc soap operations or
        // Http binding operations

        List wrappableBOEList = findWrappableBindingOperations(wsdl4jBinding);

        // this method returns all the new schemas created when processing the rpc messages
        Map newSchemaMap = createSchemaForPorttype(porttypeNamespaceURI,
                                                   wrappableBOEList,
                                                   schemaMap);

        schemaElementList.addAll(newSchemaMap.values());
        return (Element[]) schemaElementList
                .toArray(new Element[schemaElementList.size()]);
    }

    /**
     * Create a schema by looking at the port type
     *
     * @param namespaceURI - namespace of the porttype uri.
     *  we use this only if a user has not specified a namespace in soap:body
     * @param boeListToProcess - List of BindingOperationEntry objects which require wrappering
     *                     
     * @return null if there is no element
     */
    private Map createSchemaForPorttype(String namespaceURI,
                                        List boeListToProcess,
                                        Map existingSchemaMap) {

        // this map is used to keep the newly added schemas
        Map newSchemaMap = new HashMap();
        // first of all look at the operations list
        // we can return immediately if we get the operations list
        // as empty
        if (boeListToProcess.isEmpty()) {
            return newSchemaMap;
        }

        // loop through the messages. We'll populate thins map with the relevant
        // messages
        // from the operations
        Map messageQnameToMessageMap = new HashMap();
        Map boeToInputMessageMap = new HashMap();
        Map boeToOutputMessageMap = new HashMap();

        // this contains the required namespace imports. the key in this
        // map would be the namaspace URI
        Map namespaceImportsMap = null;
        // list namespace prefix map. This map will include uri -> prefix
        Map namespacePrefixMap = null;

        // //////////////////////////////////////////////////////////////////////////////////////////////////
        // First thing is to populate the message map with the messages to
        // process.
        // //////////////////////////////////////////////////////////////////////////////////////////////////

        // we really need to do this for a single porttype!
        BindingOperationEntry boe;
        for (int k = 0; k < boeListToProcess.size(); k++) {
            boe = (BindingOperationEntry) boeListToProcess.get(k);
            Input input = boe.getBindingOperation().getOperation().getInput();
            Message message;
            if (input != null) {
                message = input.getMessage();
                messageQnameToMessageMap.put(message.getQName(), message);
                boeToInputMessageMap.put(boe, message);
            }

            Output output = boe.getBindingOperation().getOperation().getOutput();
            if (output != null) {
                message = output.getMessage();
                messageQnameToMessageMap.put(message.getQName(), message);
                boeToOutputMessageMap.put(boe, message);
            }

            // we do not want to process fault messages since they can only be used as document type
            // see basic profile 4.4.2
        }

        // find the xsd prefix
        String xsdPrefix = findSchemaPrefix();
        // DOM document that will be the ultimate creator
        Document document = getDOMDocumentBuilder().newDocument();

        Element elementDeclaration;

        //loop through the input op map and generate the elements
        BindingOperationEntry boEntry;
        for (Iterator boeIter = boeToInputMessageMap.keySet().iterator();
             boeIter.hasNext();) {

            boEntry = (BindingOperationEntry) boeIter.next();
            elementDeclaration = document.createElementNS(
                    XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
                                             + XML_SCHEMA_ELEMENT_LOCAL_NAME);
            elementDeclaration.setAttribute(XSD_NAME, boEntry.getBindingOperation().getName());

            //when creating the inner complex type we have to find the parts list from the binding input
            BindingInput bindingInput = boEntry.getBindingOperation().getBindingInput();
            Message message = (Message) boeToInputMessageMap.get(boEntry);

            if (bindingInput != null) {

                Collection partsCollection = null;
                if (BINDING_TYPE_SOAP.equals(this.bindingType)) {
                    // first see the body parts list
                    List bodyPartsList =
                        getPartsListFromSoapBody(bindingInput.getExtensibilityElements());
                    partsCollection = message.getOrderedParts(bodyPartsList);
                } else {
                    // i.e http binding
                    partsCollection = message.getParts().values();
                }

                List parameterOrder = 
                   boEntry.getBindingOperation().getOperation().getParameterOrdering();
                namespaceImportsMap = new HashMap();
                namespacePrefixMap = new HashMap();

                Node newComplexType = getNewComplextType(document,
                                                         xsdPrefix,
                                                         partsCollection,
                                                         parameterOrder,
                                                         false,
                                                         namespaceImportsMap,
                                                         namespacePrefixMap, 
                                                         boEntry);

                elementDeclaration.appendChild(newComplexType);
                String namespaceToUse = namespaceURI;

                if (BINDING_TYPE_SOAP.equals(this.bindingType)) {
                    String bodyNamespace =
                            getNamespaceFromSoapBody(bindingInput.getExtensibilityElements());
                    namespaceToUse = bodyNamespace != null ? bodyNamespace : namespaceURI;
                }

                if (existingSchemaMap.containsKey(namespaceToUse)) {
                    // i.e this namespace is already exists with the original wsdl schemas
                    addElementToAnExistingSchema((Element) existingSchemaMap.get(namespaceToUse),
                                                 elementDeclaration,
                                                 namespacePrefixMap,
                                                 namespaceImportsMap,
                                                 namespaceToUse);
                } else if (newSchemaMap.containsKey(namespaceToUse)) {
                    // i.e this namespace is with a newly created schema
                    addElementToAnExistingSchema((Element) newSchemaMap.get(namespaceToUse),
                                                 elementDeclaration,
                                                 namespacePrefixMap,
                                                 namespaceImportsMap,
                                                 namespaceToUse);
                } else {
                    // i.e this element namespace has not found yet so
                    // we have to create new schema for it
                    Element newSchema = createNewSchemaWithElement(elementDeclaration,
                                                                   namespacePrefixMap,
                                                                   namespaceImportsMap,
                                                                   namespaceToUse,
                                                                   document,
                                                                   xsdPrefix);
                    newSchemaMap.put(namespaceToUse, newSchema);
                }
                resolvedRpcWrappedElementMap.put(boEntry.getBindingOperation().getName(), new QName(
                        namespaceToUse, boEntry.getBindingOperation().getName(), AXIS2WRAPPED));

            } else {
                throw new WSDLProcessingException(
                        "No binding input is defiend for binding operation ==> "
                        + boEntry.getBindingOperation().getName());
            }

        }

        // loop through the output to map and generate the elements
        for (Iterator boeIterator = boeToOutputMessageMap.keySet().iterator();
             boeIterator.hasNext();) {
            boEntry = (BindingOperationEntry) boeIterator.next();
            String baseoutputOpName = boEntry.getBindingOperation().getName();
            // see basic profile 4.7.19
            String outputOpName = baseoutputOpName + WRAPPED_OUTPUTNAME_SUFFIX;
            elementDeclaration = document.createElementNS(
                    XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
                                             + XML_SCHEMA_ELEMENT_LOCAL_NAME);
            elementDeclaration.setAttribute(XSD_NAME, outputOpName);

            BindingOutput bindingOutput = boEntry.getBindingOperation().getBindingOutput();
            Message message = (Message) boeToOutputMessageMap.get(boEntry);

            if (bindingOutput != null) {
                Collection partsCollection = null;
                if (BINDING_TYPE_SOAP.equals(this.bindingType)) {
                    // first see the body parts list
                    List bodyPartsList =
                        getPartsListFromSoapBody(bindingOutput.getExtensibilityElements());
                    partsCollection = message.getOrderedParts(bodyPartsList);

                } else {
                    // i.e if http binding
                    partsCollection = message.getParts().values();
                }

                List parameterOrder = 
                    boEntry.getBindingOperation().getOperation().getParameterOrdering();

                // we have to initialize the hash maps always since we add the elements onece we
                // generate it
                namespacePrefixMap = new HashMap();
                namespaceImportsMap = new HashMap();

                Node newComplexType = getNewComplextType(document,
                                                         xsdPrefix,
                                                         partsCollection,
                                                         parameterOrder,
                                                         true,
                                                         namespaceImportsMap,
                                                         namespacePrefixMap,
                                                         boEntry);
                elementDeclaration.appendChild(newComplexType);

                String namespaceToUse = namespaceURI;

                if (BINDING_TYPE_SOAP.equals(this.bindingType)) {
                    String bodyNamespace =
                            getNamespaceFromSoapBody(bindingOutput.getExtensibilityElements());
                    namespaceToUse = bodyNamespace != null ? bodyNamespace : namespaceURI;
                }

                if (existingSchemaMap.containsKey(namespaceToUse)) {
                    // i.e this namespace is already exists with the original wsdl schemas
                    addElementToAnExistingSchema((Element) existingSchemaMap.get(namespaceToUse),
                                                 elementDeclaration,
                                                 namespacePrefixMap,
                                                 namespaceImportsMap,
                                                 namespaceToUse);
                } else if (newSchemaMap.containsKey(namespaceToUse)) {
                    // i.e this namespace is with a newly created schema
                    addElementToAnExistingSchema((Element) newSchemaMap.get(namespaceToUse),
                                                 elementDeclaration,
                                                 namespacePrefixMap,
                                                 namespaceImportsMap,
                                                 namespaceToUse);
                } else {
                    // i.e this element namespace has not found yet so
                    // we have to create new schema for it
                    Element newSchema = createNewSchemaWithElement(elementDeclaration,
                                                                   namespacePrefixMap,
                                                                   namespaceImportsMap,
                                                                   namespaceToUse,
                                                                   document,
                                                                   xsdPrefix);
                    newSchemaMap.put(namespaceToUse, newSchema);
                }
                resolvedRpcWrappedElementMap.put(outputOpName, new QName(
                        namespaceToUse, outputOpName, AXIS2WRAPPED));

            } else {
                throw new WSDLProcessingException(
                        "No binding out put is defined for binding operation ==>" +
                        boEntry.getBindingOperation().getName());
            }
        }

        return newSchemaMap;
    }

    private void addElementToAnExistingSchema(Element schemaElement,
                                              Element newElement,
                                              Map namespacePrefixMap,
                                              Map namespaceImportsMap,
                                              String targetNamespace) {

        Document ownerDocument = schemaElement.getOwnerDocument();

        String newElementName = newElement.getAttribute(XSD_NAME);

        // check whether this element already exists.
        NodeList nodeList = schemaElement.getChildNodes();
        Element nodeElement = null;
        for (int i = 1; i < nodeList.getLength(); i++) {
            if (nodeList.item(i) instanceof Element){
                nodeElement = (Element) nodeList.item(i);
                if (nodeElement.getLocalName().equals(XML_SCHEMA_ELEMENT_LOCAL_NAME)){
                    if (nodeElement.getAttribute(XSD_NAME).equals(newElementName)){
                        // if the element already exists we do not add this element
                        // and just return.
                        return;
                    }
                }
            }

        }

        // loop through the namespace declarations first and add them
        String[] nameSpaceDeclarationArray = (String[]) namespacePrefixMap
                .keySet().toArray(new String[namespacePrefixMap.size()]);
        for (int i = 0; i < nameSpaceDeclarationArray.length; i++) {
            String s = nameSpaceDeclarationArray[i];
            checkAndAddNamespaceDeclarations(s, namespacePrefixMap,
                                             schemaElement);
        }

        // add imports - check whether it is the targetnamespace before
        // adding
        Element[] namespaceImports = (Element[]) namespaceImportsMap
                .values().toArray(new Element[namespaceImportsMap.size()]);
        for (int i = 0; i < namespaceImports.length; i++) {
            if (!targetNamespace.equals(namespaceImports[i]
                    .getAttribute(NAMESPACE_URI))) {
                schemaElement.appendChild(ownerDocument.importNode(
                        namespaceImports[i], true));
            }
        }

        schemaElement.appendChild(ownerDocument.importNode(newElement, true));

    }

    private Element createNewSchemaWithElement(Element newElement,
                                               Map namespacePrefixMap,
                                               Map namespaceImportsMap,
                                               String targetNamespace,
                                               Document document,
                                               String xsdPrefix) {

        Element schemaElement = document.createElementNS(
                XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
                                         + XML_SCHEMA_LOCAL_NAME);

        // loop through the namespace declarations first
        String[] nameSpaceDeclarationArray = (String[]) namespacePrefixMap
                .keySet().toArray(new String[namespacePrefixMap.size()]);
        for (int i = 0; i < nameSpaceDeclarationArray.length; i++) {
            String s = nameSpaceDeclarationArray[i];
            schemaElement.setAttributeNS(XML_NAMESPACE_URI,
                                         NAMESPACE_DECLARATION_PREFIX
                                         + namespacePrefixMap.get(s).toString(), s);
        }

        if (schemaElement.getAttributeNS(XML_NAMESPACE_URI, xsdPrefix).length() == 0) {
            schemaElement.setAttributeNS(XML_NAMESPACE_URI,
                                         NAMESPACE_DECLARATION_PREFIX + xsdPrefix,
                                         XMLSCHEMA_NAMESPACE_URI);
        }

        // add the targetNamespace
        schemaElement.setAttributeNS(XML_NAMESPACE_URI, XMLNS_AXIS2WRAPPED, targetNamespace);
        schemaElement.setAttribute(XSD_TARGETNAMESPACE, targetNamespace);
        schemaElement.setAttribute(XSD_ELEMENT_FORM_DEFAULT, XSD_UNQUALIFIED);

        // add imports
        Element[] namespaceImports = (Element[]) namespaceImportsMap
                .values().toArray(new Element[namespaceImportsMap.size()]);
        for (int i = 0; i < namespaceImports.length; i++) {
            schemaElement.appendChild(namespaceImports[i]);

        }

        schemaElement.appendChild(newElement);
        return schemaElement;
    }

    private List getPartsListFromSoapBody(List extensibilityElements) {
        List partsList = null;
        ExtensibilityElement extElement;
        for (Iterator iter = extensibilityElements.iterator(); iter.hasNext();) {
            
            
            extElement = (ExtensibilityElement) iter.next();
            
            if (log.isDebugEnabled()) {
                log.debug("Extensibility Element type is:" + extElement.getElementType());
                log.debug("Extensibility Element class is:" + extElement.getClass().getName());
            }
            // SOAP 1.1 body element found!
            if (extElement instanceof SOAPBody) {
                SOAPBody soapBody = (SOAPBody) extElement;
                partsList = soapBody.getParts();
            } else if (extElement instanceof SOAP12Body) {
                SOAP12Body soapBody = (SOAP12Body) extElement;
                partsList = soapBody.getParts();
            } else if (extElement instanceof MIMEMultipartRelated) {
                MIMEMultipartRelated minMimeMultipartRelated = (MIMEMultipartRelated) extElement;
                List mimePartsList = minMimeMultipartRelated.getMIMEParts();
                MIMEPart mimePart = null;
                Object object;
                List mimePartElements;
                ExtensibilityElement mimePartExtensibilityElement;
                for (Iterator mimePartsIter = mimePartsList.iterator(); mimePartsIter.hasNext();) {
                    object = mimePartsIter.next();
                    if (object instanceof MIMEPart) {
                        mimePart = (MIMEPart) object;
                        mimePartElements = mimePart.getExtensibilityElements();
                        for (Iterator mimePartElementsIter = mimePartElements.iterator(); mimePartElementsIter.hasNext();)
                        {
                            mimePartExtensibilityElement = (ExtensibilityElement) mimePartElementsIter.next();
                            if (mimePartExtensibilityElement instanceof SOAPBody) {
                                SOAPBody soapBody = (SOAPBody) mimePartExtensibilityElement;
                                partsList = soapBody.getParts();
                            } else if (mimePartExtensibilityElement instanceof SOAP12Body) {
                                SOAP12Body soapBody = (SOAP12Body) mimePartExtensibilityElement;
                                partsList = soapBody.getParts();
                            }
                        }
                    }
                }
            } 
        }
        if (partsList == null) {
            log.debug("SOAP body parts have not been set. All the parts in the message were added to the message.");
        }
        return partsList;
    }

    private String getNamespaceFromSoapBody(List extensibilityElements) {

        ExtensibilityElement extElement;
        String namespace = null;
        for (Iterator iter = extensibilityElements.iterator(); iter.hasNext();) {
            extElement = (ExtensibilityElement) iter.next();
            // SOAP 1.1 body element found!
            if (extElement instanceof SOAPBody) {
                SOAPBody soapBody = (SOAPBody) extElement;
                namespace = soapBody.getNamespaceURI();
            } else if (extElement instanceof SOAP12Body) {
                SOAP12Body soapBody = (SOAP12Body) extElement;
                namespace = soapBody.getNamespaceURI();
            }
        }
        return namespace;
    }

    /**
     * creates a new shema complex element according to the elements sequence difined
     * this parts list is always for a message refering from the
     * soap rpc type operation
     *
     * @param document
     * @param xsdPrefix
     * @param partsCollection     - parts to be added
     * @param parameterOrder      - param Order list if it is given
     * @param isOutMessage
     * @param namespaceImportsMap
     * @param namespacePrefixMap
     * @param boe BindingOperationEntry for this partCollection
     * @return new element
     */
    private Element getNewComplextType(Document document,
                                       String xsdPrefix,
                                       Collection partsCollection,
                                       List parameterOrder,
                                       boolean isOutMessage,
                                       Map namespaceImportsMap,
                                       Map namespacePrefixMap,
                                       BindingOperationEntry boe) {
        // add the complex type
        Element newComplexType = document.createElementNS(
                XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
                                         + XML_SCHEMA_COMPLEX_TYPE_LOCAL_NAME);

        Element cmplxTypeSequence = document.createElementNS(
                XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
                                         + XML_SCHEMA_SEQUENCE_LOCAL_NAME);

        Part part;
        if ((parameterOrder == null) || (parameterOrder.size() == 0)) {
            // no parameter order then just add the elements in the parts collection
            for (Iterator partsIter = partsCollection.iterator(); partsIter.hasNext();) {
                part = (Part) partsIter.next();
                // the part name
                addPartToElement(part,
                                 document,
                                 xsdPrefix,
                                 namespaceImportsMap,
                                 namespacePrefixMap,
                                 cmplxTypeSequence,
                                 isOutMessage,
                                 boe);

            }
        } else {
            // i.e an parts order is given
            // first populate all the parts to a map
            Map partsMap = new HashMap();
            for (Iterator partsIter = partsCollection.iterator(); partsIter.hasNext();) {
                part = (Part) partsIter.next();
                partsMap.put(part.getName(), part);
            }

            String partName;
            for (Iterator paramOrderIter = parameterOrder.iterator(); paramOrderIter.hasNext();) {
                partName = (String) paramOrderIter.next();
                part = (Part) partsMap.get(partName);
                if (part != null) {
                    addPartToElement(part,
                                     document,
                                     xsdPrefix,
                                     namespaceImportsMap,
                                     namespacePrefixMap,
                                     cmplxTypeSequence, 
                                     isOutMessage,
                                     boe);
                    partsMap.remove(partName);
                }
            }
            // if this is an output message then we have to set the
            // return type if exists
            if (isOutMessage) {
                if (partsMap.size() > 0) {
                    if (partsMap.size() == 1) {
                        part = (Part) partsMap.values().iterator().next();
                        // change the name of this part
                        // this is the return type and its name should be result
                        // part.setName("result");
                        addPartToElement(part,
                                         document,
                                         xsdPrefix,
                                         namespaceImportsMap,
                                         namespacePrefixMap,
                                         cmplxTypeSequence,
                                         isOutMessage,
                                         boe);
                    } else {
                        throw new WSDLProcessingException("the parameter order can left atmost" +
                                                          " one part");
                    }
                }
            }
        }

        newComplexType.appendChild(cmplxTypeSequence);
        return newComplexType;
    }

    /**
     * @param part
     * @param document
     * @param xsdPrefix
     * @param namespaceImportsMap
     * @param namespacePrefixMap
     * @param cmplxTypeSequence
     * @param isOutMessage (true is part is referenced by the output clause)
     * @param boe BindingOperationEntry that caused the creation of this part.
     */
    private void addPartToElement(Part part,
                                  Document document,
                                  String xsdPrefix,
                                  Map namespaceImportsMap,
                                  Map namespacePrefixMap,
                                  Element cmplxTypeSequence,
                                  boolean isOutMessage,
                                  BindingOperationEntry boe) {
        Element child;
        String elementName = part.getName();

        // the type name
        QName schemaTypeName = part.getTypeName();

        if (schemaTypeName != null) {

            child = document.createElementNS(XMLSCHEMA_NAMESPACE_URI,
                                             xsdPrefix + ":" + XML_SCHEMA_ELEMENT_LOCAL_NAME);
            // always child attribute should be in no namespace
            child.setAttribute("form", "unqualified");
            child.setAttribute("nillable", "true");

            String prefix;
            if (XMLSCHEMA_NAMESPACE_URI.equals(schemaTypeName.getNamespaceURI())) {
                prefix = xsdPrefix;
                if(log.isDebugEnabled()) {
                    log.debug("Unable to find a namespace for " + xsdPrefix + ". Creating a new namespace attribute");
                }
                cmplxTypeSequence.setAttributeNS("http://www.w3.org/2000/xmlns/",
                        "xmlns:" + xsdPrefix,
                        XMLSCHEMA_NAMESPACE_URI);
            } else {
                // this schema is a third party one. So we need to have
                // an import statement in our generated schema
                String uri = schemaTypeName.getNamespaceURI();
                if (!namespaceImportsMap.containsKey(uri)) {
                    // create Element for namespace import
                    Element namespaceImport = document.createElementNS(
                            XMLSCHEMA_NAMESPACE_URI, xsdPrefix + ":"
                                                     + XML_SCHEMA_IMPORT_LOCAL_NAME);
                    namespaceImport.setAttribute(NAMESPACE_URI, uri);
                    // add this to the map
                    namespaceImportsMap.put(uri, namespaceImport);
                    // we also need to associate this uri with a prefix
                    // and include that prefix
                    // in the schema's namspace declarations. So add
                    // theis particular namespace to the
                    // prefix map as well
                    prefix = getTemporaryNamespacePrefix();
                    namespacePrefixMap.put(uri, prefix);
                } else {
                    // this URI should be already in the namspace prefix
                    // map
                    prefix = (String) namespacePrefixMap.get(uri);
                }

            }

            child.setAttribute(XSD_NAME, elementName);
            child.setAttribute(XSD_TYPE, prefix + ":" + schemaTypeName.getLocalPart());
            cmplxTypeSequence.appendChild(child);

        } else {
            String bindingOperationName = boe.getBindingOperation().getName();
            String partName = part.getName();
            if (boe.isRPC()) {
                // see the basic profile 4.4.1 for rpc-literal.
                // messages parts can have only types
                throw new WSDLProcessingException(
                   "The binding operation " + bindingOperationName + " is RPC/literal. " +
                   "The message parts for this operation must use the type " +
                   "attribute as specificed by " +
                   "WS-I Basic Profile specification (4.4.1).  Message part, " + 
                   partName + ", violates" +
                   "this rule.  Please remove the element attribute " +
                   "and use the type attribute.");
            } else {
                // The presense of an element means that a wrapper xsd element is not needed.
                boe.setWrappedOutput(false);
                if (log.isDebugEnabled()) {
                    log.debug("The binding operation " + bindingOperationName + 
                              " references message part " +
                              partName + ".  This part does not use the " +
                              "type attribute, so a wrappering element is not added.");
                }
            }
            
        }
    }

    /**
     * @param prefixMap
     */
    private void checkAndAddNamespaceDeclarations(String namespace,
                                                  Map prefixMap, Element schemaElement) {
        // get the attribute for the current namespace
        String prefix = (String) prefixMap.get(namespace);
        // A prefix must be found at this point!
        String existingURL = schemaElement.getAttributeNS(XML_NAMESPACE_URI,
                                                          NAMESPACE_DECLARATION_PREFIX + prefix);
        if (existingURL == null || existingURL.length() == 0) {
            // there is no existing URL by that prefix - declare a new namespace
            schemaElement.setAttributeNS(XML_NAMESPACE_URI,
                                         NAMESPACE_DECLARATION_PREFIX + prefix, namespace);
        } else if (existingURL.equals(namespace)) {
            // this namespace declaration is already there with the same prefix
            // ignore it
        } else {
            // there is a different namespace declared in the given prefix
            // change the prefix in the prefix map to a new one and declare it

            // create a prefix
            String generatedPrefix = "ns" + prefixCounter++;
            while (prefixMap.containsKey(generatedPrefix)) {
                generatedPrefix = "ns" + prefixCounter++;
            }
            schemaElement.setAttributeNS(XML_NAMESPACE_URI,
                                         NAMESPACE_DECLARATION_PREFIX + generatedPrefix, namespace);
            // add to the map
            prefixMap.put(namespace, generatedPrefix);
        }

    }

    /**
     * Read the WSDL file given the inputstream for the WSDL source
     *
     * @param in
     * @throws WSDLException
     */
    private Definition readInTheWSDLFile(InputStream in) throws WSDLException {

    	WSDLReader reader = WSDLUtil.newWSDLReaderWithPopulatedExtensionRegistry();

        // switch off the verbose mode for all usecases
        reader.setFeature(JAVAX_WSDL_VERBOSE_MODE_KEY, false);
        reader.setFeature("javax.wsdl.importDocuments", true);

        Definition def;
        // if the custem resolver is present then use it
        if (customWSDLResolver != null) {
            // make sure the wsdl definition has the URI for the base document set
            def = reader.readWSDL(customWSDLResolver);
            def.setDocumentBaseURI(customWSDLResolver.getBaseURI());
            return def;
        } else {
            Document doc;
            try {
                doc = XMLUtils.newDocument(in);
            } catch (ParserConfigurationException e) {
                throw new WSDLException(WSDLException.PARSER_ERROR,
                                        "Parser Configuration Error", e);
            } catch (SAXException e) {
                throw new WSDLException(WSDLException.PARSER_ERROR,
                                        "Parser SAX Error", e);

            } catch (IOException e) {
                throw new WSDLException(WSDLException.INVALID_WSDL, "IO Error",
                                        e);
            }

            // Log when and from where the WSDL is loaded.
            if (log.isDebugEnabled()) {
                log.debug("Reading 1.1 WSDL with base uri = " + getBaseUri());
                log.debug("  the document base uri = " + getDocumentBaseUri());
                log.trace("  the stack at this point is: " + stackToString());
            }
            def = reader.readWSDL(getBaseUri(), doc);
            def.setDocumentBaseURI(getDocumentBaseUri());
            return def;
        }
    }

    /**
     * Get the Extensible elements form wsdl4jExtensibleElements
     * <code>Vector</code> if any and copy them to <code>Component</code>
     * <p/> Note - SOAP body extensible element will be processed differently
     *
     * @param wsdl4jExtensibleElements
     * @param description                   where is the ext element (port , portype , biding)
     * @param wsdl4jDefinition
     * @param originOfExtensibilityElements -
     *                                      this will indicate the place this extensibility element came
     *                                      from.
     */
    private void copyExtensibleElements(List wsdl4jExtensibleElements,
                                        Definition wsdl4jDefinition, AxisDescription description,
                                        String originOfExtensibilityElements) throws AxisFault {

        ExtensibilityElement wsdl4jExtensibilityElement;

        for (Iterator iterator = wsdl4jExtensibleElements.iterator(); iterator.hasNext();) {

            wsdl4jExtensibilityElement = (ExtensibilityElement) iterator.next();

            if (wsdl4jExtensibilityElement instanceof UnknownExtensibilityElement) {

                UnknownExtensibilityElement unknown =
                        (UnknownExtensibilityElement) (wsdl4jExtensibilityElement);
                QName type = unknown.getElementType();
                
                // <wsp:Policy>
                if (Constants.isPolicyElement(type)) {
                    if (isTraceEnabled) {
                        log.trace("copyExtensibleElements:: PolicyElement found " + unknown);
                    }
                    Policy policy = (Policy) PolicyUtil.getPolicyComponent(unknown.getElement());
                    description.getPolicySubject().attachPolicy(policy);
                    
//                    int attachmentScope =
//                            getPolicyAttachmentPoint(description, originOfExtensibilityElements);
//                    if (attachmentScope > -1) {
//                        description.getPolicyInclude().addPolicyElement(
//                                attachmentScope, policy);
//                    }
                    // <wsp:PolicyReference>
                } else if (Constants.isPolicyRef(type)) {
                    if (isTraceEnabled) {
                        log.trace("copyExtensibleElements:: PolicyReference found " + unknown);
                    }
                    PolicyReference policyReference = (PolicyReference) PolicyUtil
                            .getPolicyComponent(unknown.getElement());
                    description.getPolicySubject().attachPolicyReference(policyReference);
                    
//                    int attachmentScope =
//                            getPolicyAttachmentPoint(description, originOfExtensibilityElements);
//                    if (attachmentScope > -1) {
//                        description.getPolicyInclude().addPolicyRefElement(
//                                attachmentScope, policyReference);
//                    }
                } else if (AddressingConstants.Final.WSAW_USING_ADDRESSING
                        .equals(type)
                           || AddressingConstants.Submission.WSAW_USING_ADDRESSING
                        .equals(unknown.getElementType())) {
                    if (isTraceEnabled) {
                        log.trace("copyExtensibleElements:: wsaw:UsingAddressing found " + unknown);
                    }
                    // FIXME We need to set this the appropriate Axis Description AxisEndpoint or
                    // AxisBinding .
                    if (originOfExtensibilityElements.equals(PORT)
                        || originOfExtensibilityElements.equals(BINDING)) {
                        if (Boolean.TRUE.equals(unknown.getRequired())) {
                        	AddressingHelper.setAddressingRequirementParemeterValue(axisService, AddressingConstants.ADDRESSING_REQUIRED);
                        } else {
                        	AddressingHelper.setAddressingRequirementParemeterValue(axisService, AddressingConstants.ADDRESSING_OPTIONAL);
                        }
                    }

                }    else if (wsdl4jExtensibilityElement.getElementType() != null &&
                        wsdl4jExtensibilityElement.getElementType().getNamespaceURI().equals(
                                org.apache.axis2.namespace.Constants.FORMAT_BINDING)) {
                    Element typeMapping = unknown.getElement();
                    
                    NodeList typeMaps = typeMapping.getElementsByTagNameNS(
                            org.apache.axis2.namespace.Constants.FORMAT_BINDING,
                            "typeMap");
                    int count = typeMaps.getLength();
                    HashMap typeMapper = new HashMap();
                    for (int index = 0; index < count; index++) {
                        Node node = typeMaps.item(index);
                        NamedNodeMap attributes = node.getAttributes();
                        Node typeName = attributes.getNamedItem("typeName");

                        if (typeName != null) {
                            String prefix = getPrefix(typeName.getNodeValue());

                            if (prefix != null) {
                                String ns = (String) wsdl4jDefinition.getNamespaces().get(prefix);
                                if (ns != null) {
                                    Node formatType = attributes.getNamedItem("formatType");
                                    typeMapper.put(new QName(ns, getTypeName(
                                            typeName.getNodeValue())), formatType.getNodeValue());
                                }

                            }
                        }
                    }
                } else if (wsdl4jExtensibilityElement.getElementType() != null &&
                        wsdl4jExtensibilityElement.getElementType().getNamespaceURI().equals(
                                org.apache.axis2.namespace.Constants.JAVA_NS)) {
                    Element unknowJavaElement = unknown.getElement();
                    if (unknowJavaElement.getLocalName().equals("address") ) {
                        NamedNodeMap nameAttributes = unknowJavaElement.getAttributes();
                        Node node = nameAttributes.getNamedItem("className");
                        Parameter serviceClass = new Parameter();
                        serviceClass.setName("className");
                        serviceClass.setValue(node.getNodeValue());
                        axisService.addParameter(serviceClass);
                        Parameter transportName = new Parameter();
                        transportName.setName("TRANSPORT_NAME");
                        transportName.setValue("java");
                        axisService.addParameter(transportName);
                    }
                }  else {
                    // Ignore this element - it is a totally unknown element
                    if (isTraceEnabled) {
                        log.trace("copyExtensibleElements:: Unknown Extensibility Element found " +
                                  unknown);
                    }
                }

            } else if (wsdl4jExtensibilityElement instanceof SOAP12Address) {
                SOAP12Address soapAddress = (SOAP12Address) wsdl4jExtensibilityElement;
                if (description instanceof AxisEndpoint) {
                	setEndpointURL((AxisEndpoint) description, soapAddress.getLocationURI());
                }

            } else if (wsdl4jExtensibilityElement instanceof SOAPAddress) {
                SOAPAddress soapAddress = (SOAPAddress) wsdl4jExtensibilityElement;
                if (description instanceof AxisEndpoint) {
                	setEndpointURL((AxisEndpoint) description, soapAddress.getLocationURI());
                }
            } else if (wsdl4jExtensibilityElement instanceof HTTPAddress) {
                HTTPAddress httpAddress = (HTTPAddress) wsdl4jExtensibilityElement;
                if (description instanceof AxisEndpoint) {
                	setEndpointURL((AxisEndpoint) description, httpAddress.getLocationURI());
                }

            } else if (wsdl4jExtensibilityElement instanceof Schema) {
                Schema schema = (Schema) wsdl4jExtensibilityElement;
                // just add this schema - no need to worry about the imported
                // ones
                axisService.addSchema(getXMLSchema(schema.getElement(), schema
                        .getDocumentBaseURI()));

            } else if (wsdl4jExtensibilityElement instanceof SOAP12Operation) {
                SOAP12Operation soapOperation = (SOAP12Operation) wsdl4jExtensibilityElement;
                AxisBindingOperation axisBindingOperation = (AxisBindingOperation) description;

                String style = soapOperation.getStyle();
                if (style != null) {
                    axisBindingOperation.setProperty(WSDLConstants.WSDL_1_1_STYLE, style);
                }

                String soapActionURI = soapOperation.getSoapActionURI();
                
                if (this.isCodegen && ((soapActionURI == null) || (soapActionURI.equals("")))) {
                    soapActionURI = axisBindingOperation.getAxisOperation().getInputAction();
                }
                
                if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled())
                    log.debug("WSDL Binding Operation: " + axisBindingOperation.getName() +
                            ", SOAPAction: " + soapActionURI);
                
                if (soapActionURI != null && !soapActionURI.equals("")) {
                    axisBindingOperation
                            .setProperty(WSDL2Constants.ATTR_WSOAP_ACTION, soapActionURI);
                    axisBindingOperation.getAxisOperation().setSoapAction(soapActionURI);
                    if (!isServerSide) {
                        axisBindingOperation.getAxisOperation().setOutputAction(soapActionURI);
                    }

                    axisService.mapActionToOperation(soapActionURI,
                                                     axisBindingOperation.getAxisOperation());
                }

            } else if (wsdl4jExtensibilityElement instanceof SOAPOperation) {
                SOAPOperation soapOperation = (SOAPOperation) wsdl4jExtensibilityElement;
                AxisBindingOperation axisBindingOperation = (AxisBindingOperation) description;

                String style = soapOperation.getStyle();
                if (style != null) {
                    axisBindingOperation.setProperty(WSDLConstants.WSDL_1_1_STYLE, style);
                }

                String soapAction = soapOperation.getSoapActionURI();
                if (this.isCodegen && ((soapAction == null) || (soapAction.equals("")))) {
                    soapAction = axisBindingOperation.getAxisOperation().getInputAction();
                }
                
                if (LoggingControl.debugLoggingAllowed && log.isDebugEnabled())
                    log.debug("WSDL Binding Operation: " + axisBindingOperation.getName() +
                            ", SOAPAction: " + soapAction);
                
                if (soapAction != null && !soapAction.equals("")) {
                    axisBindingOperation.setProperty(WSDL2Constants.ATTR_WSOAP_ACTION, soapAction);
                    axisBindingOperation.getAxisOperation().setSoapAction(soapAction);
                    if (!isServerSide) {
                        axisBindingOperation.getAxisOperation().setOutputAction(soapAction);
                    }

                    axisService.mapActionToOperation(soapAction,
                                                     axisBindingOperation.getAxisOperation());
                }
            } else if (wsdl4jExtensibilityElement instanceof HTTPOperation) {
                HTTPOperation httpOperation = (HTTPOperation) wsdl4jExtensibilityElement;
                AxisBindingOperation axisBindingOperation = (AxisBindingOperation) description;

                String httpLocation = httpOperation.getLocationURI();
                if (httpLocation != null) {
                    // change the template to make it same as WSDL 2 template
                    httpLocation = httpLocation.replaceAll("\\(", "{");
                    httpLocation = httpLocation.replaceAll("\\)", "}");
                    axisBindingOperation
                            .setProperty(WSDL2Constants.ATTR_WHTTP_LOCATION, httpLocation);

                }
                axisBindingOperation.setProperty(WSDL2Constants.ATTR_WHTTP_INPUT_SERIALIZATION,
                                                 HTTPConstants.MEDIA_TYPE_TEXT_XML);


            } else if (wsdl4jExtensibilityElement instanceof SOAP12Header) {

                SOAP12Header soapHeader = (SOAP12Header) wsdl4jExtensibilityElement;
                SOAPHeaderMessage headerMessage = new SOAPHeaderMessage();

                headerMessage.setNamespaceURI(soapHeader.getNamespaceURI());
                headerMessage.setUse(soapHeader.getUse());

                Boolean required = soapHeader.getRequired();

                if (required != null) {
                    headerMessage.setRequired(required.booleanValue());
                }

                if (wsdl4jDefinition != null) {
                    // find the relevant schema part from the messages
                    Message msg = wsdl4jDefinition.getMessage(soapHeader
                            .getMessage());

                    if (msg == null) {
                        msg = getMessage(wsdl4jDefinition, soapHeader
                            .getMessage(), new HashSet());
                    }
                    
                    if (msg == null) {
                        // TODO i18n this
                        throw new AxisFault("message "
                                            + soapHeader.getMessage()
                                            + " not found in the WSDL ");
                    }
                    Part msgPart = msg.getPart(soapHeader.getPart());

                    if (msgPart == null) {
                        // TODO i18n this
                        throw new AxisFault("message part "
                                            + soapHeader.getPart()
                                            + " not found in the WSDL ");
                    }
                    // see basic profile 4.4.2 Bindings and Faults header, fault and headerfaults
                    // can only have elements
                    headerMessage.setElement(msgPart.getElementName());
                }

                headerMessage.setMessage(soapHeader.getMessage());
                headerMessage.setPart(soapHeader.getPart());

                if (description instanceof AxisBindingMessage) {
                    AxisBindingMessage bindingMessage = (AxisBindingMessage) description;
                    List soapHeaders =
                            (List) bindingMessage.getProperty(WSDL2Constants.ATTR_WSOAP_HEADER);
                    if (soapHeaders == null) {
                        soapHeaders = new ArrayList();
                        bindingMessage.setProperty(WSDL2Constants.ATTR_WSOAP_HEADER, soapHeaders);
                    }
                    soapHeaders.add(headerMessage);
                }

            } else if (wsdl4jExtensibilityElement instanceof SOAPHeader) {

                SOAPHeader soapHeader = (SOAPHeader) wsdl4jExtensibilityElement;
                SOAPHeaderMessage headerMessage = new SOAPHeaderMessage();
                headerMessage.setNamespaceURI(soapHeader.getNamespaceURI());
                headerMessage.setUse(soapHeader.getUse());
                Boolean required = soapHeader.getRequired();
                if (null != required) {
                    headerMessage.setRequired(required.booleanValue());
                }
                if (null != wsdl4jDefinition) {
                    // find the relevant schema part from the messages
                    Message msg = wsdl4jDefinition.getMessage(soapHeader
                            .getMessage());
                    
                    if (msg == null) {
                        msg = getMessage(wsdl4jDefinition, soapHeader
                            .getMessage(), new HashSet());
                    }

                    if (msg == null) {
                        // todo i18n this
                        throw new AxisFault("message "
                                            + soapHeader.getMessage()
                                            + " not found in the WSDL ");
                    }
                    Part msgPart = msg.getPart(soapHeader.getPart());
                    if (msgPart == null) {
                        // todo i18n this
                        throw new AxisFault("message part "
                                            + soapHeader.getPart()
                                            + " not found in the WSDL ");
                    }
                    headerMessage.setElement(msgPart.getElementName());
                }
                headerMessage.setMessage(soapHeader.getMessage());

                headerMessage.setPart(soapHeader.getPart());

                if (description instanceof AxisBindingMessage) {
                    AxisBindingMessage bindingMessage = (AxisBindingMessage) description;
                    List soapHeaders =
                            (List) bindingMessage.getProperty(WSDL2Constants.ATTR_WSOAP_HEADER);
                    if (soapHeaders == null) {
                        soapHeaders = new ArrayList();
                        bindingMessage.setProperty(WSDL2Constants.ATTR_WSOAP_HEADER, soapHeaders);
                    }
                    soapHeaders.add(headerMessage);
                }
            } else if (wsdl4jExtensibilityElement instanceof SOAPBinding) {

                SOAPBinding soapBinding = (SOAPBinding) wsdl4jExtensibilityElement;
                AxisBinding axisBinding = (AxisBinding) description;

                axisBinding.setType(soapBinding.getTransportURI());

                axisBinding.setProperty(WSDL2Constants.ATTR_WSOAP_VERSION,
                                        SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);

                String style = soapBinding.getStyle();
                if (style != null) {
                    axisBinding.setProperty(WSDLConstants.WSDL_1_1_STYLE, style);
                }

            } else if (wsdl4jExtensibilityElement instanceof SOAP12Binding) {

                SOAP12Binding soapBinding = (SOAP12Binding) wsdl4jExtensibilityElement;
                AxisBinding axisBinding = (AxisBinding) description;

                axisBinding.setProperty(WSDL2Constants.ATTR_WSOAP_VERSION,
                                        SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);

                String style = soapBinding.getStyle();
                if (style != null) {
                    axisBinding.setProperty(WSDLConstants.WSDL_1_1_STYLE, style);
                }

                String transportURI = soapBinding.getTransportURI();
                axisBinding.setType(transportURI);

            } else if (wsdl4jExtensibilityElement instanceof HTTPBinding) {
                HTTPBinding httpBinding = (HTTPBinding) wsdl4jExtensibilityElement;
                AxisBinding axisBinding = (AxisBinding) description;
                // set the binding style same as the wsd2 to process smoothly
                axisBinding.setType(WSDL2Constants.URI_WSDL2_HTTP);
                axisBinding.setProperty(WSDL2Constants.ATTR_WHTTP_METHOD, httpBinding.getVerb());
            } else if (wsdl4jExtensibilityElement instanceof MIMEContent) {
                if (description instanceof AxisBindingMessage) {
                    MIMEContent mimeContent = (MIMEContent) wsdl4jExtensibilityElement;
                    String messageSerialization = mimeContent.getType();
                    AxisBindingMessage bindingMessage = (AxisBindingMessage) description;
                    setMessageSerialization(
                        (AxisBindingOperation)bindingMessage.getParent(),
                        originOfExtensibilityElements, messageSerialization);
                }
            } else if (wsdl4jExtensibilityElement instanceof MIMEMimeXml) {
                if (description instanceof AxisBindingMessage) {
                    AxisBindingMessage bindingMessage = (AxisBindingMessage) description;
                    setMessageSerialization(
                        (AxisBindingOperation)bindingMessage.getParent(),
                        originOfExtensibilityElements,
                        HTTPConstants.MEDIA_TYPE_TEXT_XML);
                }
            } else if (wsdl4jExtensibilityElement instanceof HTTPUrlEncoded) {
                if (description instanceof AxisBindingMessage) {
                    AxisBindingMessage bindingMessage = (AxisBindingMessage) description;
                    setMessageSerialization(
                        (AxisBindingOperation)bindingMessage.getParent(),
                        originOfExtensibilityElements,
                        HTTPConstants.MEDIA_TYPE_X_WWW_FORM);
                }
            }
        }
    }
    
    private static void setMessageSerialization(AxisBindingOperation bindingOperation,
                                                String originOfExtensibilityElements, 
                                                String messageSerialization) {
        if (bindingOperation != null) {
            if (BINDING_OPERATION_INPUT.equals(originOfExtensibilityElements)) {
                bindingOperation.setProperty(
                    WSDL2Constants.ATTR_WHTTP_INPUT_SERIALIZATION,
                    messageSerialization);
            } else if (BINDING_OPERATION_OUTPUT.equals(originOfExtensibilityElements)) {
                bindingOperation.setProperty(
                    WSDL2Constants.ATTR_WHTTP_OUTPUT_SERIALIZATION,
                    messageSerialization);
            }
        }
    }
    
    /**
     * Look deeper in the imports to find the requested Message. Use a HashSet to make 
     * sure we don't traverse the same Definition object twice (avoid recursion).
     * 
     * @param definition
     * @param message
     * @param instances
     * @return
     */
    private Message getMessage(Definition definition, QName message, Set seen) {
        
        Message msg = definition.getMessage(message);
        
        if (msg != null) { 
            if (log.isDebugEnabled()) {
                log.debug("getMessage returning = " + ((message.getLocalPart() != null) ? message.getLocalPart(): "NULL"));
            }

            return msg;
        }
        
        seen.add(definition);
        
        Iterator iter = definition.getImports().values().iterator();
        
        while (iter.hasNext()) {
            Vector values = (Vector) iter.next();
            for (Iterator valuesIter = values.iterator(); valuesIter.hasNext();) {
                Import wsdlImport = (Import) valuesIter.next();
                Definition innerDefinition = wsdlImport.getDefinition();
                
                if (seen.contains(innerDefinition)) { 
                    continue; // Skip seen
                }
                Message result = getMessage(innerDefinition, message, seen);
                if (result != null) { 
                    return result;
                }
            }
        }

        if (log.isDebugEnabled()) {
            log.debug("getMessage: Unable to find message, returning NULL");
        }

        return null;
    }
 
    
    
    
    private int getPolicyAttachmentPoint(AxisDescription description,
                                         String originOfExtensibilityElements) {
        int result = -1; // Attachment Point Not Identified

        if (SERVICE.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.SERVICE_POLICY;
        } else if (PORT.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.PORT_POLICY;
        } else if (BINDING.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.BINDING_POLICY;
        } else if (BINDING_OPERATION.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.BINDING_OPERATION_POLICY;
        } else if (BINDING_OPERATION_INPUT.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.BINDING_INPUT_POLICY;
        } else if (BINDING_OPERATION_OUTPUT.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.BINDING_OUTPUT_POLICY;
        } else if (PORT_TYPE.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.PORT_TYPE_POLICY;
        } else if (PORT_TYPE_OPERATION.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.OPERATION_POLICY;
        } else if (PORT_TYPE_OPERATION_INPUT.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.INPUT_POLICY;
        } else if (PORT_TYPE_OPERATION_OUTPUT.equals(originOfExtensibilityElements)) {
            result = PolicyInclude.OUTPUT_POLICY;
        }

        if (isTraceEnabled) {
            log.trace("getPolicyAttachmentPoint:: axisDescription=" + description +
                      " extensibilityPoint=" + originOfExtensibilityElements + " result=" + result);
        }

        return result;
    }

    /**
     * Look for the wrappable operations depending on the style
     *
     * @param binding
     * @return List of BindingOperationEntry objects
     */
    private List findWrappableBindingOperations(Binding binding) {
        // first find the global style declaration.
        // for a SOAP binding this can be only rpc or document
        // as per the WSDL spec (section 3.4) the default style is document

        // now we have to handle the http bindings case as well
        //

        boolean isRPC = false;
        boolean isSOAPBinding = false;
        boolean isHttpBinding = false;

        List extElements = binding.getExtensibilityElements();
        for (int i = 0; i < extElements.size(); i++) {
            if (extElements.get(i) instanceof SOAPBinding) {
                // we have a global SOAP binding!
                isSOAPBinding = true;
                SOAPBinding soapBinding = (SOAPBinding) extElements.get(i);
                if (RPC_STYLE.equals(soapBinding.getStyle())) {
                    // set the global style to rpc
                    isRPC = true;
                }
                this.bindingType = BINDING_TYPE_SOAP;
                break;
            } else if (extElements.get(i) instanceof SOAP12Binding) {
                // we have a global SOAP binding!
                isSOAPBinding = true;
                SOAP12Binding soapBinding = (SOAP12Binding) extElements.get(i);
                if (RPC_STYLE.equals(soapBinding.getStyle())) {
                    // set the global style to rpc
                    isRPC = true;
                }
                this.bindingType = BINDING_TYPE_SOAP;
                break;
            } else if (extElements.get(i) instanceof HTTPBinding) {
                isHttpBinding = true;
                this.bindingType = BINDING_TYPE_HTTP;
            }
        }
        
        if (log.isDebugEnabled()) {
            log.debug("Binding Name    =" + binding.getQName());
            log.debug("  isSOAPBinding =" + isSOAPBinding );
            log.debug("  isHttpBinding =" + isHttpBinding );
            log.debug("  isRPC         =" + isRPC );
        }

        // go through every operation and get their styles.
        // each one can have a style override from the global
        // styles. Depending on the style add the relevant operations
        // to the return list
        List returnList = new ArrayList();

        if (isHttpBinding || isSOAPBinding) {
            BindingOperation bindingOp;
            for (Iterator bindingOperationsIterator =
                    binding.getBindingOperations().iterator(); bindingOperationsIterator.hasNext();)
            {
                bindingOp = (BindingOperation) bindingOperationsIterator.next();
                
                if (log.isDebugEnabled()) {
                    log.debug("  Binding Operation  =" + bindingOp.getName());
                }
                if (isSOAPBinding) {
                    String style = getSOAPStyle(bindingOp);
                    if (log.isDebugEnabled()) {
                        log.debug("    SOAPStyle  =" + style);
                    }
                    if (style == null) {
                        // no style specified
                        // use the global style to determine whether to put this one or
                        // not
                        if (isRPC) {
                            if (log.isDebugEnabled()) {
                                log.debug("    schema wrappering required");
                            }
                            BindingOperationEntry boe = 
                                new BindingOperationEntry(bindingOp, 
                                                          true, 
                                                          false,
                                                          style,
                                                          true);
                            returnList.add(boe);
                        }
                    } else if (RPC_STYLE.equals(style)) {
                        // add to the list
                        if (log.isDebugEnabled()) {
                            log.debug("    schema wrappering required");
                        }
                        BindingOperationEntry boe = 
                            new BindingOperationEntry(bindingOp, 
                                                      true, 
                                                      false,
                                                      style,
                                                      true);
                        returnList.add(boe);
                    }
                    // if not RPC we just leave it - default is doc
                } else {
                    // i.e an http binding then we have to add the operation any way
                    if (log.isDebugEnabled()) {
                        log.debug("    schema wrappering required");
                    }
                    BindingOperationEntry boe = 
                        new BindingOperationEntry(bindingOp, 
                                                  false, 
                                                  true,
                                                  null,
                                                  false);
                    returnList.add(boe);
                }
            }
        }

        // if the binding is not either soap or http binding then we return and empty list

        // set this to the global list
        wrappableBOEs = returnList;
        return returnList;
    }

    /**
     * Guess the MEP based on the order of messages
     *
     * @param operation
     * @throws AxisFault
     */
    private String getMEP(Operation operation) throws AxisFault {
        OperationType operationType = operation.getStyle();
        if (isServerSide) {
            if (operationType != null) {
                if (operationType.equals(OperationType.REQUEST_RESPONSE)) {
                    return WSDL2Constants.MEP_URI_IN_OUT;
                }

                if (operationType.equals(OperationType.ONE_WAY)) {
                    if (operation.getFaults().size() > 0) {
                        return WSDL2Constants.MEP_URI_ROBUST_IN_ONLY;
                    }
                    return WSDL2Constants.MEP_URI_IN_ONLY;
                }

                if (operationType.equals(OperationType.NOTIFICATION)) {
                    return WSDL2Constants.MEP_URI_OUT_ONLY;
                }

                if (operationType.equals(OperationType.SOLICIT_RESPONSE)) {
                    return WSDL2Constants.MEP_URI_OUT_IN;
                }
                throw new AxisFault("Cannot Determine the MEP");
            }
        } else {
            if (operationType != null) {
                if (operationType.equals(OperationType.REQUEST_RESPONSE)) {
                    return WSDL2Constants.MEP_URI_OUT_IN;
                }

                if (operationType.equals(OperationType.ONE_WAY)) {
                    return WSDL2Constants.MEP_URI_OUT_ONLY;
                }

                if (operationType.equals(OperationType.NOTIFICATION)) {
                    return WSDL2Constants.MEP_URI_IN_ONLY;
                }

                if (operationType.equals(OperationType.SOLICIT_RESPONSE)) {
                    return WSDL2Constants.MEP_URI_IN_OUT;
                }
                throw new AxisFault("Cannot Determine the MEP");
            }
        }
        throw new AxisFault("Cannot Determine the MEP");
    }

    /**
     * Copies the extension attributes
     *
     * @param extAttributes
     * @param description
     * @param origin
     */
    private void copyExtensionAttributes(Map extAttributes,
			AxisDescription description, String origin) {

		QName key;
		QName value;

		for (Iterator iterator = extAttributes.keySet().iterator(); iterator
				.hasNext();) {
			key = (QName) iterator.next();

			if (Constants.URI_POLICY_NS.equals(key.getNamespaceURI())
					&& "PolicyURIs".equals(key.getLocalPart())) {

				value = (QName) extAttributes.get(key);
				String policyURIs = value.getLocalPart();

				if (policyURIs.length() != 0) {
					String[] uris = policyURIs.split(" ");

					PolicyReference ref;
					for (int i = 0; i < uris.length; i++) {
						ref = new PolicyReference();
						ref.setURI(uris[i]);

						if (PORT_TYPE.equals(origin)
						        || PORT_TYPE_OPERATION.equals(origin)
						        || PORT_TYPE_OPERATION_INPUT.equals(origin) 
						        || PORT_TYPE_OPERATION_OUTPUT.equals(origin)) {
                      
						    if (description != null) {
						        PolicySubject subject = description.getPolicySubject();
                             
						        if (subject != null) {
						            subject.attachPolicyReference(ref);
						        }
						    }
						}
					}
				}
			}
		}
	}

    /**
	 * Process the policy definitions
	 * 
	 * @param definition
	 */
    private void processPoliciesInDefintion(Definition definition) {
        processPoliciesInDefintion(definition, new HashSet());
    }

    /**
	 * Process the policy definitions
	 * 
	 * @param definition
	 */
    private void processPoliciesInDefintion(Definition definition, Set visitedWSDLs) {
        visitedWSDLs.add(definition.getDocumentBaseURI());
        List extElements = definition.getExtensibilityElements();
        ExtensibilityElement extElement;
        UnknownExtensibilityElement unknown = null;
        Policy policy = null;

        for (Iterator iterator = extElements.iterator(); iterator.hasNext();) {
            extElement = (ExtensibilityElement) iterator.next();

            if (extElement instanceof UnknownExtensibilityElement) {
                unknown = (UnknownExtensibilityElement) extElement;
                if (Constants.isPolicyElement(unknown.getElementType())) {

                    policy = (Policy) PolicyUtil.getPolicyComponent(unknown.getElement());
                    String key;
                    if ((key = policy.getName()) != null || (key = policy.getId()) != null) {
                    	axisService.registerPolicy(key, policy);
//                        registry.register(key, policy);
//                        registry.register("#" + key, policy);
                    }

                }
            }
        }
        // include policices in other imported wsdls
        Iterator iter = definition.getImports().values().iterator();
        Vector values = null;
        Import wsdlImport = null;
        for (; iter.hasNext();) {
            values = (Vector) iter.next();
            for (Iterator valuesIter = values.iterator(); valuesIter.hasNext();) {
                wsdlImport = (Import) valuesIter.next();
                Definition innerDefinition = wsdlImport.getDefinition();
                // find the binding recursively
                if(!visitedWSDLs.contains(innerDefinition.getDocumentBaseURI())) {
                    processPoliciesInDefintion(innerDefinition, visitedWSDLs);
                }
            }
        }
    }
    
    private void setEndpointURL(AxisEndpoint axisEndpoint, String endpointURL) throws AxisFault {
    	axisEndpoint.setEndpointURL(endpointURL);
    	try {
    		URL url = new URL(endpointURL);
    		axisEndpoint.setTransportInDescription(url.getProtocol());
    	} catch (Exception e) {
    		log.debug(e.getMessage(),e);
		}    	
    }


    /**
     * Inner class declaration for the processing exceptions
     */
    public static class WSDLProcessingException extends RuntimeException {
        public WSDLProcessingException() {
        }

        public WSDLProcessingException(String message) {
            super(message);
        }

        public WSDLProcessingException(Throwable cause) {
            super(cause);
        }

        public WSDLProcessingException(String message, Throwable cause) {
            super(message, cause);
        }

    }

    public boolean isAllPorts() {
        return isAllPorts;
    }

    public void setAllPorts(boolean allPorts) {
        isAllPorts = allPorts;
    }

//    private void processPoliciesInDefinition() {
//
//        Object obj;
//        for (Iterator iterator = wsdl4jDefinition.getExtensibilityElements().iterator(); iterator.hasNext();) {
//            obj = iterator.next();
//
//            if (obj instanceof UnknownExtensibilityElement) {
//                Element e = ((UnknownExtensibilityElement) obj).getElement();
//                if (WSDLConstants.WSDL11Constants.POLICY.getNamespaceURI().equals(e.getNamespaceURI()) &&
//                        WSDLConstants.WSDL11Constants.POLICY.getLocalPart().equals(e.getLocalName())) {
//                    Policy p = (Policy) PolicyUtil.getPolicyComponent(e);
//                    reg.register(p.getId(), p);
//                }
//            }
//        }
//    }

    /**
     * This method is to split attribute like abc:cde and get the prefix part of it
     * so the method will retuen abc if the ":" is present in the the string else it
     * will return null
     *
     * @param attributeValue  : String
     * @return String
     */
    public static String getPrefix(String attributeValue) {
        if (attributeValue != null) {
            int splitIdex = attributeValue.indexOf(':');
            if (splitIdex > 0) {
                return attributeValue.substring(0, splitIdex);
            }
        }
        return null;
    }

    public static String getTypeName(String attributeValue) {
        if (attributeValue != null) {
            int splitIdex = attributeValue.indexOf(':');
            if (splitIdex > 0) {
                return attributeValue.substring(splitIdex + 1);
            } else {
                return attributeValue;
            }
        }
        return null;
    }

    /**
     * returns the wsld defintion for the given component.
     * @param definition
     * @param qname
     * @param componentType
     * @param visitedWSDLs
     * @return definition containing the component.
     */
    private Definition getParentDefinition(Definition definition,
                                           QName qname,
                                           int componentType,
                                           Set visitedWSDLs){
        visitedWSDLs.add(definition.getDocumentBaseURI());
        Definition newParentDefinition = null;
        // first find through imports
        Iterator iter = definition.getImports().values().iterator();
        Vector values = null;
        Import wsdlImport = null;
        for (; iter.hasNext();) {
            values = (Vector) iter.next();
            for (Iterator valuesIter = values.iterator(); valuesIter.hasNext();) {
                wsdlImport = (Import) valuesIter.next();
                Definition innerDefinition = wsdlImport.getDefinition();
                if (!visitedWSDLs.contains(innerDefinition.getDocumentBaseURI())){
                    newParentDefinition = getParentDefinition(innerDefinition,qname,componentType,visitedWSDLs);
                    if (newParentDefinition != null){
                        break;
                    }
                }
            }
            if (newParentDefinition != null) {
                break;
            }
        }

        // if it not available in imports we check for the current definition.
        if (newParentDefinition == null) {
            // this can be in a imported wsdl
            if (isComponetAvailable(definition, qname, componentType)) {
                newParentDefinition = definition;
            }
        }

        return newParentDefinition;
    }

    private boolean isComponetAvailable(Definition definition,
                                        QName qname,
                                        int componentType){
        boolean isAvailable = false;
        switch (componentType){
            case COMPONENT_BINDING : {
                isAvailable = (definition.getBinding(qname) != null) &&
                        (definition.getBinding(qname).getPortType() != null);
                break;
            }
            case COMPONENT_PORT_TYPE : {
                isAvailable = (definition.getPortType(qname) != null);
                break;
            }
            case COMPONENT_MESSAGE : {
                isAvailable = (definition.getMessage(qname) != null);
                break;
            }
        }
        return isAvailable;
    }
    
    /**
     * Find BindingOperationEntry
     * @param boes List of BindingOperationEntry
     * @param bo BindingOperation 
     * @return BindingOperation or null
     */
    private BindingOperationEntry find(List boes, BindingOperation bo) {
        for (int i=0; i < boes.size(); i++) {
            BindingOperationEntry boe = (BindingOperationEntry) boes.get(i);
            if (boe.getBindingOperation() == bo) {
                return boe;
            }
        }
        return null;
    }
    /**
     * BindingOperation plus state information
     */
    class BindingOperationEntry {
        
        private BindingOperation bindingOperation;
        private boolean isSOAPBinding;
        private boolean isHTTPBinding;
        private String soapStyle;
        private boolean isRPC;
        private boolean wrappedInput = true;
        private boolean wrappedOutput = true;
        
        public BindingOperationEntry(BindingOperation bindingOperation, boolean isSOAPBinding, boolean isHTTPBinding, String soapStyle, boolean isRPC) {
            super();
            this.bindingOperation = bindingOperation;
            this.isSOAPBinding = isSOAPBinding;
            this.isHTTPBinding = isHTTPBinding;
            this.soapStyle = soapStyle;
            this.isRPC = isRPC;
        }
        
        public boolean isHTTPBinding() {
            return isHTTPBinding;
        }
        public boolean isSOAPBinding() {
            return isSOAPBinding;
        }
        public String getSoapStyle() {
            return soapStyle;
        }
        
        public boolean isRPC() {
            return isRPC;
        }
        public BindingOperation getBindingOperation() {
            return bindingOperation;
        }

        /**
         * @return true if wrapper xsd is used
         */
        public boolean isWrappedInput() {
            return wrappedInput;
        }

        /**
         * @param wrappedInput indicate if wrapper xsd is needed
         */
        public void setWrappedInput(boolean wrappedInput) {
            this.wrappedInput = wrappedInput;
        }

        /**
         * @return true if wrapper xsd is needed for the output message
         */
        public boolean isWrappedOutput() {
            return wrappedOutput;
        }

        /**
         * @param wrappedOutput indicate if wrapper xsd is needed on the output message
         */
        public void setWrappedOutput(boolean wrappedOutput) {
            this.wrappedOutput = wrappedOutput;
        }
    }
}
