/*
 * 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.wsdl.codegen.emitter;

import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.description.AxisBinding;
import org.apache.axis2.description.AxisBindingMessage;
import org.apache.axis2.description.AxisBindingOperation;
import org.apache.axis2.description.AxisEndpoint;
import org.apache.axis2.description.AxisMessage;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.WSDL20DefaultValueHolder;
import org.apache.axis2.description.WSDL2Constants;
import org.apache.axis2.util.CommandLineOptionConstants;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.util.PolicyUtil;
import org.apache.axis2.util.Utils;
import org.apache.axis2.util.XSLTUtils;
import org.apache.axis2.wsdl.HTTPHeaderMessage;
import org.apache.axis2.wsdl.SOAPHeaderMessage;
import org.apache.axis2.wsdl.SOAPModuleMessage;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.axis2.wsdl.WSDLUtil;
import org.apache.axis2.wsdl.codegen.CodeGenConfiguration;
import org.apache.axis2.wsdl.codegen.CodeGenerationException;
import org.apache.axis2.wsdl.codegen.writer.AntBuildWriter;
import org.apache.axis2.wsdl.codegen.writer.CallbackHandlerWriter;
import org.apache.axis2.wsdl.codegen.writer.ExceptionWriter;
import org.apache.axis2.wsdl.codegen.writer.FileWriter;
import org.apache.axis2.wsdl.codegen.writer.InterfaceImplementationWriter;
import org.apache.axis2.wsdl.codegen.writer.InterfaceWriter;
import org.apache.axis2.wsdl.codegen.writer.MessageReceiverWriter;
import org.apache.axis2.wsdl.codegen.writer.SchemaWriter;
import org.apache.axis2.wsdl.codegen.writer.ServiceXMLWriter;
import org.apache.axis2.wsdl.codegen.writer.SkeletonInterfaceWriter;
import org.apache.axis2.wsdl.codegen.writer.SkeletonWriter;
import org.apache.axis2.wsdl.codegen.writer.TestClassWriter;
import org.apache.axis2.wsdl.codegen.writer.WSDL11Writer;
import org.apache.axis2.wsdl.codegen.writer.WSDL20Writer;
import org.apache.axis2.wsdl.databinding.TypeMapper;
import org.apache.axis2.wsdl.util.Constants;
import org.apache.axis2.wsdl.util.MessagePartInformationHolder;
import org.apache.axis2.wsdl.util.TypeTesterUtil;
import org.apache.axis2.wsdl.util.XSLTIncludeResolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.neethi.Policy;
import org.apache.ws.commons.schema.XmlSchema;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
import java.util.ArrayList;
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.lang.reflect.Constructor;


public class AxisServiceBasedMultiLanguageEmitter implements Emitter {

    protected static final String CALL_BACK_HANDLER_SUFFIX = "CallbackHandler";
    protected static final String STUB_SUFFIX = "Stub";
    protected static final String TEST_SUFFIX = "Test";
    protected static final String SKELETON_CLASS_SUFFIX = "Skeleton";
    protected static final String SKELETON_CLASS_SUFFIX_BACK = "Impl";
    protected static final String SKELETON_INTERFACE_SUFFIX = "SkeletonInterface";
    // keep a seperate variable for  SKELETON_INTERFACE_SUFFIX_BACK although it is
    // "" to accomadate any future changes easily.
    protected static final String SKELETON_INTERFACE_SUFFIX_BACK = "";
    protected static final String STUB_INTERFACE_SUFFIX_BACK = "Stub";
    protected static final String MESSAGE_RECEIVER_SUFFIX = "MessageReceiver";
    protected static final String DATABINDING_SUPPORTER_NAME_SUFFIX = "DatabindingSupporter";

    protected static Map mepToClassMap;
    protected static Map mepToSuffixMap;

    protected AxisBinding axisBinding;
    protected AxisEndpoint axisEndpoint;

    protected int uniqueFaultNameCounter = 0;
    /**
     * Field constructorMap
     */
    protected static HashMap constructorMap = new HashMap(50);

    //~--- static initializers ------------------------------------------------

    static {

        // Type maps to a valid initialization value for that type
        // Type var = new Type(arg)
        // Where "Type" is the key and "new Type(arg)" is the string stored
        // Used in emitting test cases and server skeletons.
        constructorMap.put("int", "0");
        constructorMap.put("float", "0");
        constructorMap.put("boolean", "true");
        constructorMap.put("double", "0");
        constructorMap.put("byte", "(byte)0");
        constructorMap.put("short", "(short)0");
        constructorMap.put("long", "0");
        constructorMap.put("java.lang.Boolean", "new java.lang.Boolean(false)");
        constructorMap.put("java.lang.Byte", "new java.lang.Byte((byte)0)");
        constructorMap.put("java.lang.Double", "new java.lang.Double(0)");
        constructorMap.put("java.lang.Float", "new java.lang.Float(0)");
        constructorMap.put("java.lang.Integer", "new java.lang.Integer(0)");
        constructorMap.put("java.lang.Long", "new java.lang.Long(0)");
        constructorMap.put("java.lang.Short", "new java.lang.Short((short)0)");
        constructorMap.put("java.math.BigDecimal", "new java.math.BigDecimal(0)");
        constructorMap.put("java.math.BigInteger", "new java.math.BigInteger(\"0\")");
        constructorMap.put("java.lang.Object", "new java.lang.String()");
        constructorMap.put("byte[]", "new byte[0]");
        constructorMap.put("java.util.Calendar", "java.util.Calendar.getInstance()");
        constructorMap.put("javax.xml.namespace.QName",
                "new javax.xml.namespace.QName(\"http://foo\", \"bar\")");

        //populate the MEP -> class map
        mepToClassMap = new HashMap();
        mepToClassMap.put(WSDL2Constants.MEP_URI_IN_ONLY,
                "org.apache.axis2.receivers.AbstractInMessageReceiver");
        mepToClassMap.put(WSDL2Constants.MEP_URI_ROBUST_IN_ONLY,
                "org.apache.axis2.receivers.AbstractMessageReceiver");
        mepToClassMap.put(WSDL2Constants.MEP_URI_IN_OUT,
                "org.apache.axis2.receivers.AbstractInOutMessageReceiver");

        //populate the MEP -> suffix map
        mepToSuffixMap = new HashMap();
        mepToSuffixMap.put(WSDLConstants.WSDL20_2004_Constants.MEP_URI_IN_ONLY,
                MESSAGE_RECEIVER_SUFFIX + "InOnly");
        mepToSuffixMap.put(WSDLConstants.WSDL20_2006Constants.MEP_URI_IN_ONLY,
                MESSAGE_RECEIVER_SUFFIX + "InOnly");
        mepToSuffixMap.put(WSDL2Constants.MEP_URI_IN_ONLY,
                MESSAGE_RECEIVER_SUFFIX + "InOnly");
        mepToSuffixMap.put(WSDLConstants.WSDL20_2004_Constants.MEP_URI_ROBUST_IN_ONLY,
                MESSAGE_RECEIVER_SUFFIX + "RobustInOnly");
        mepToSuffixMap.put(WSDLConstants.WSDL20_2006Constants.MEP_URI_ROBUST_IN_ONLY,
                MESSAGE_RECEIVER_SUFFIX + "RobustInOnly");
        mepToSuffixMap.put(WSDL2Constants.MEP_URI_ROBUST_IN_ONLY,
                MESSAGE_RECEIVER_SUFFIX + "RobustInOnly");
        mepToSuffixMap.put(WSDLConstants.WSDL20_2004_Constants.MEP_URI_IN_OUT,
                MESSAGE_RECEIVER_SUFFIX + "InOut");
        mepToSuffixMap.put(WSDLConstants.WSDL20_2006Constants.MEP_URI_IN_OUT,
                MESSAGE_RECEIVER_SUFFIX + "InOut");
        mepToSuffixMap.put(WSDL2Constants.MEP_URI_IN_OUT,
                MESSAGE_RECEIVER_SUFFIX + "InOut");
        //register the other types as necessary
    }

    //~--- fields -------------------------------------------------------------
    protected static final Log log = LogFactory.getLog(AxisServiceBasedMultiLanguageEmitter.class);
    protected URIResolver resolver;

    // this is used to keep the current service infoHolder
    protected Map infoHolder;
    // this is used to keep infoHolders for all services
    protected Map allServiceInfoHolder;

    protected CodeGenConfiguration codeGenConfiguration;

    protected TypeMapper mapper;

    protected AxisService axisService;

    protected List axisServices;

    //a map to keep the fault classNames
    protected Map fullyQualifiedFaultClassNameMap = new HashMap();
    protected Map faultClassNameMap = new HashMap();
    protected Map faultElementQNameMap = new HashMap();

    protected Map instantiatableMessageClassNames = new HashMap();

    protected static final String TEST_SRC_DIR_NAME = "test";

    protected boolean useHolderClass_jaxws = false;
    protected boolean wrapped_jaxws = false;


    /**
     * default constructor - builds
     */
    public AxisServiceBasedMultiLanguageEmitter() {
        infoHolder = new HashMap();
        allServiceInfoHolder = new HashMap();
    }

    /**
     * Sets the relevant codegen configuration
     *
     * @param configuration
     * @see Emitter#setCodeGenConfiguration(org.apache.axis2.wsdl.codegen.CodeGenConfiguration)
     */
    public void setCodeGenConfiguration(CodeGenConfiguration configuration) {
        this.codeGenConfiguration = configuration;
        this.axisServices = codeGenConfiguration.getAxisServices();
        this.axisService = codeGenConfiguration.getAxisService();
        this.axisEndpoint = axisService.getEndpoint(axisService.getEndpointName());
        this.axisBinding = axisEndpoint.getBinding();
        resolver = new XSLTIncludeResolver(codeGenConfiguration);
    }

    /**
     * Sets the type mapper
     *
     * @param mapper
     * @see Emitter#setMapper(org.apache.axis2.wsdl.databinding.TypeMapper)
     */
    public void setMapper(TypeMapper mapper) {
        this.mapper = mapper;
    }

    protected Object getBindingPropertyFromOperation(String name, QName qName) {

        // Get the correct AxisBindingOperation coresponding to the AxisOperation
        AxisBindingOperation axisBindingOperation = null;
        if (axisBinding != null) {
            axisBindingOperation = (AxisBindingOperation) axisBinding.getChild(qName);
        }

        Object property = null;

        if (axisBindingOperation != null) {
            property = axisBindingOperation.getProperty(name);
        }

        if ((property == null) && (axisBinding != null)) {
            property = axisBinding.getProperty(name);
        }

        if (property == null) {
            property = WSDL20DefaultValueHolder.getDefaultValue(name);
        }

        return property;
    }

    protected Policy getBindingPolicyFromMessage(AxisBindingOperation axisBindingOperation,
                                                 String key) {
        AxisBindingMessage axisBindingMessage = null;

        if (axisBindingOperation != null) {

            axisBindingMessage = (AxisBindingMessage) axisBindingOperation.getChild(key);
            if (axisBindingMessage != null) {
                try {
                    return axisBindingMessage.getEffectivePolicy();
                } catch (RuntimeException ex){
                    log.error(ex.getMessage(), ex);
                }
            }
        }
        return null;
    }

    protected Object getBindingPropertyFromMessage(String name, QName qName, String key) {

        Object property = null;
        // Get the correct AxisBindingOperation coresponding to the AxisOperation
        AxisBindingOperation axisBindingOperation = null;
        if (axisBinding != null) {
            axisBindingOperation = (AxisBindingOperation) axisBinding.getChild(qName);

        }

        AxisBindingMessage axisBindingMessage = null;
        if (axisBindingOperation != null) {
            axisBindingMessage = (AxisBindingMessage) axisBindingOperation.getChild(key);
            if (axisBindingMessage != null) {
                property = axisBindingMessage.getProperty(name);
            }

            if (property == null) {
                property = axisBindingOperation.getProperty(name);
            }
        }


        if ((property == null) && (axisBinding != null)) {
            property = axisBinding.getProperty(name);
        }

        if (property == null) {
            property = WSDL20DefaultValueHolder.getDefaultValue(name);
        }

        return property;
    }

    protected Object getBindingPropertyFromMessageFault(String name, QName qName, String key) {

        Object property = null;
        // Get the correct AxisBindingOperation coresponding to the AxisOperation
        AxisBindingOperation axisBindingOperation =
                (AxisBindingOperation) axisBinding.getChild(qName);

        AxisBindingMessage axisBindingMessageFault = null;
        AxisBindingMessage axisBindingFault = null;
        if (axisBindingOperation != null) {
            axisBindingMessageFault = (AxisBindingMessage) axisBindingOperation.getFault(key);

            if (axisBindingMessageFault != null) {
                property = axisBindingMessageFault.getProperty(name);
            }

            if (property == null) {
                axisBindingFault = axisBinding.getFault(key);
                property = axisBindingFault.getProperty(name);
            }
        }

        if (property == null) {
            property = WSDL20DefaultValueHolder.getDefaultValue(name);
        }

        return property;
    }


    /**
     * Update mapper for the stub
     */
    protected void updateMapperForStub() {
        updateMapperClassnames(getFullyQualifiedStubName());
    }

    /**
     * Returns the fully qualified Stub name reused in many methods
     *
     * @return classname
     */
    protected String getFullyQualifiedStubName() {
        String packageName = codeGenConfiguration.getPackageName();
        String localPart = null;
        if (this.axisService.getEndpoints().size() > 1) {
            localPart = makeJavaClassName(axisService.getName() + axisService.getEndpointName());
        } else {
            localPart = makeJavaClassName(axisService.getName());
        }
        return packageName + "." + localPart + STUB_SUFFIX;
    }

    /**
     * rests the fault name maps
     */
    protected void resetFaultNames() {
        fullyQualifiedFaultClassNameMap.clear();
        faultClassNameMap.clear();
        faultElementQNameMap.clear();
    }

    /**
     * Populate a map of fault class names
     */
    protected void generateAndPopulateFaultNames() {
        //loop through and find the faults
        Iterator operations = axisService.getOperations();
        AxisOperation operation;
        AxisMessage faultMessage;
        while (operations.hasNext()) {
            operation = (AxisOperation) operations.next();
            ArrayList faultMessages = operation.getFaultMessages();
            for (int i = 0; i < faultMessages.size(); i++) {
                faultMessage = (AxisMessage) faultMessages.get(i);
                //make a unique name and put that in the hashmap
                if (!fullyQualifiedFaultClassNameMap.
                        containsKey(faultMessage.getName())) {
                    //make a name
                    String className = makeJavaClassName(faultMessage.getName());
                    QName faultQName = new QName(codeGenConfiguration.getTargetNamespace(), faultMessage.getName());
                    if (this.mapper.getQNameToMappingObject(faultQName) != null) {
                        // i.e we already have an entry
                        className = makeJavaClassName(className + "Exception");
                    }
                    while (fullyQualifiedFaultClassNameMap.containsValue(className)) {
                        className = makeJavaClassName(className + (uniqueFaultNameCounter++));
                    }

                    fullyQualifiedFaultClassNameMap.put(
                            faultMessage.getName(),
                            className);
                    //we've to keep track of the fault base names seperately
                    faultClassNameMap.put(faultMessage.getName(),
                            className);

                    faultElementQNameMap.put(faultMessage.getName(),
                            faultMessage.getElementQName());

                }
            }

        }
    }

    /**
     * Emits the stubcode with bindings.
     *
     * @throws CodeGenerationException
     * @see Emitter#emitStub()
     */
    public void emitStub() throws CodeGenerationException {
        try {

            //first keep a seperate copy of the original map to use in
            // every iteration
            // for every iteration  qName2NameMap is changed in updateMapperForStub
            // method if in the packing mode
            Map originalTypeMap = getNewCopy(mapper.getAllMappedNames());

            for (Iterator axisServicesIter = this.axisServices.iterator();
                 axisServicesIter.hasNext();) {
                this.axisService = (AxisService) axisServicesIter.next();
                //we have to generate the code for each bininding
                //for the moment lets genrate the stub name with the service name and end point name
                this.axisBinding = axisService.getEndpoint(axisService.getEndpointName()).getBinding();

                if (!codeGenConfiguration.isPackClasses()) {
                    // write the call back handlers
                    writeCallBackHandlers();
                }

                Map endpoints = this.axisService.getEndpoints();
                for (Iterator endPointsIter = endpoints.values().iterator();
                     endPointsIter.hasNext();) {
                    // set the end point details.
                    this.axisEndpoint = (AxisEndpoint) endPointsIter.next();
                    this.axisBinding = this.axisEndpoint.getBinding();
                    axisService.setEndpointName(this.axisEndpoint.getName());
                    axisService.setBindingName(
                            this.axisEndpoint.getBinding().getName().getLocalPart());

                    // see the comment at updateMapperClassnames for details and reasons for
                    // calling this method
                    if (mapper.isObjectMappingPresent()) {
                        // initialize the map to original one
                        copyMap(originalTypeMap, mapper.getAllMappedNames());
                        updateMapperForStub();
                    } else {
                        copyToFaultMap();
                    }

                    //generate and populate the fault names before hand. We need that for
                    //the smooth opration of the thing
                    //first reset the fault names and recreate it
                    resetFaultNames();
                    generateAndPopulateFaultNames();
                    updateFaultPackageForStub();

                    // write the inteface
                    // feed the binding information also
                    // note that we do not create this interface if the user switched on the wrap classes mode
                    // this interface also depends on the binding
                    if (!codeGenConfiguration.isPackClasses()) {
                        writeInterface(false);
                    }

                    if (codeGenConfiguration.isPackClasses()) {
                        // write the call back handlers
                        writeCallBackHandlers();
                    }

                    // write the Exceptions
                    writeExceptions();

                    // write interface implementations
                    writeInterfaceImplementation();

                    // write the test classes
                    writeTestClasses();

                }

            }

            // save back type map
            if (this.mapper.isObjectMappingPresent()) {
                copyMap(originalTypeMap, this.mapper.getAllMappedNames());
            }

            if (!codeGenConfiguration.isSkipBuildXML()) {
                // write an ant build file
                // Note that ant build is generated only once
                // and that has to happen here only if the
                // client side code is required
                if (!codeGenConfiguration.isGenerateAll()) {
                    //our logic for the build xml is that it will
                    //only be written when not flattened
                    if (!codeGenConfiguration.isFlattenFiles()) {
                        writeAntBuild();
                    }
                }
            }
        } catch (CodeGenerationException ce) {
            throw ce;
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        }
    }

    public Map getNewCopy(Map copyFormMap) {
        Map copyToMap = new HashMap();
        Object key;
        for (Iterator iter = copyFormMap.keySet().iterator(); iter.hasNext();) {
            key = iter.next();
            copyToMap.put(key, copyFormMap.get(key));
        }
        return copyToMap;
    }

    public void copyMap(Map copyFormMap, Map copyToMap) {
        Object key;
        for (Iterator iter = copyFormMap.keySet().iterator(); iter.hasNext();) {
            key = iter.next();
            copyToMap.put(key, copyFormMap.get(key));
        }
    }


    /**
     * Writes the Ant build.
     *
     * @throws Exception
     */
    protected void writeAntBuild() throws Exception {

        // Write the service xml in a folder with the
        Document skeletonModel = createDOMDocumentForAntBuild();
        debugLogDocument("Document for ant build:", skeletonModel);
        AntBuildWriter antBuildWriter = new AntBuildWriter(codeGenConfiguration.getOutputLocation(),
                codeGenConfiguration.getOutputLanguage());

        antBuildWriter.setDatabindingFramework(codeGenConfiguration.getDatabindingType());
        antBuildWriter.setOverride(codeGenConfiguration.isOverride());
        writeFile(skeletonModel, antBuildWriter);
        codeGenConfiguration.addXmlFileName(antBuildWriter.getOutputFile().getAbsolutePath());//$NON-SEC-3
    }

    /**
     * Creates the DOM tree for the Ant build. Uses the interface.
     */
    protected Document createDOMDocumentForAntBuild() {
        Document doc = getEmptyDocument();
        Element rootElement = doc.createElement("ant");
        String serviceName = makeJavaClassName(axisService.getName());
        String packageName = codeGenConfiguration.getPackageName();
        String[] dotSeparatedValues = packageName.split("\\.");

        addAttribute(doc, "package", dotSeparatedValues[0], rootElement);
        addAttribute(doc, "name", serviceName, rootElement);
        addAttribute(doc, "servicename", serviceName, rootElement);
        addAttribute(doc, "src", codeGenConfiguration.getSourceLocation(), rootElement);
        addAttribute(doc, "resource", codeGenConfiguration.getResourceLocation(), rootElement);

        if (codeGenConfiguration.getAxisServices().size() > 1){
            addAttribute(doc, "artifactname", "Services", rootElement);
        } else {
            addAttribute(doc, "artifactname", this.axisService.getName() , rootElement);
        }

        if (!codeGenConfiguration.isWriteTestCase()) {
            addAttribute(doc, "testOmit", "true", rootElement);
        }

        if (codeGenConfiguration.isServerSide()) {
            addAttribute(doc,
                    "isserverside",
                    "yes",
                    rootElement);
        }

        doc.appendChild(rootElement);

        //////////////////////////////////////////////////////////
//        System.out.println(DOM2Writer.nodeToString(rootElement));
        ////////////////////////////////////////////////////////////

        return doc;
    }

    /**
     * Write the test classes
     */
    protected void writeTestClasses() throws Exception {
        if (codeGenConfiguration.isWriteTestCase()) {
            Document classModel = createDOMDocumentForTestCase();
            debugLogDocument("Document for test case:", classModel);
            TestClassWriter callbackWriter =
                    new TestClassWriter(
                            codeGenConfiguration.isFlattenFiles() ?
                                    getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                            null) :
                                    getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                            TEST_SRC_DIR_NAME),
                            codeGenConfiguration.getOutputLanguage());
            callbackWriter.setOverride(codeGenConfiguration.isOverride());
            writeFile(classModel, callbackWriter);
        }
    }

    /**
     * Creates the XML Model for the test case
     *
     * @return DOM document
     */
    protected Document createDOMDocumentForTestCase() {
        String coreClassName = makeJavaClassName(axisService.getName());
        Document doc = getEmptyDocument();
        Element rootElement = doc.createElement("class");

        addAttribute(doc, "package", codeGenConfiguration.getPackageName(), rootElement);
        if (this.axisService.getEndpoints().size() > 1) {
            addAttribute(doc, "name",
                    makeJavaClassName(axisService.getName() + axisService.getEndpointName())
                            + TEST_SUFFIX, rootElement);
        } else {
            addAttribute(doc, "name", makeJavaClassName(axisService.getName())
                    + TEST_SUFFIX, rootElement);
        }

        //todo is this right ???
        addAttribute(doc, "namespace", axisService.getTargetNamespace(), rootElement);
        addAttribute(doc, "interfaceName", coreClassName, rootElement);
        if (codeGenConfiguration.isPackClasses()) {
            if (this.axisService.getEndpoints().size() > 1) {
                addAttribute(doc, "callbackname", makeJavaClassName(
                        axisService.getName() + axisService.getEndpointName())
                        + CALL_BACK_HANDLER_SUFFIX, rootElement);
            } else {
                addAttribute(doc, "callbackname", makeJavaClassName(axisService.getName())
                        + CALL_BACK_HANDLER_SUFFIX, rootElement);
            }

        } else {
            addAttribute(doc, "callbackname", coreClassName + CALL_BACK_HANDLER_SUFFIX,
                    rootElement);
        }
        if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
            addAttribute(doc, "stubname",
                    makeJavaClassName(axisService.getBindingName()) + STUB_SUFFIX,
                    rootElement);
        } else {
            if (this.axisService.getEndpoints().size() > 1) {
                addAttribute(doc, "stubname", makeJavaClassName(
                        axisService.getName() + axisService.getEndpointName())
                        + STUB_SUFFIX, rootElement);
            } else {
                addAttribute(doc, "stubname", makeJavaClassName(axisService.getName())
                        + STUB_SUFFIX, rootElement);
            }

        }

        //add backwordcompatibility attribute
        addAttribute(doc, "isbackcompatible",
                String.valueOf(codeGenConfiguration.isBackwordCompatibilityMode()),
                rootElement);

        fillSyncAttributes(doc, rootElement);
        loadOperations(doc, rootElement, null);

        // add the databind supporters. Now the databind supporters are completly contained inside
        // the stubs implementation and not visible outside
        rootElement.appendChild(createDOMElementforDatabinders(doc, false));
        doc.appendChild(rootElement);
        //////////////////////////////////////////////////////////
//        System.out.println(DOM2Writer.nodeToString(rootElement));
        ////////////////////////////////////////////////////////////

        return doc;
    }

    /**
     * Writes the implementations.
     *
     * @throws Exception
     */
    protected void writeInterfaceImplementation() throws Exception {

        // first check for the policies in this service and write them
        Document interfaceImplModel = createDOMDocumentForInterfaceImplementation();
        debugLogDocument("Document for interface implementation:", interfaceImplModel);
        InterfaceImplementationWriter writer =
                new InterfaceImplementationWriter(
                        codeGenConfiguration.isFlattenFiles() ?
                                getOutputDirectory(codeGenConfiguration.getOutputLocation(), null) :
                                getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                        codeGenConfiguration.getSourceLocation()),
                        codeGenConfiguration.getOutputLanguage());

        writer.setOverride(codeGenConfiguration.isOverride());
        writeFile(interfaceImplModel, writer);


    }

    /**
     * Creates the DOM tree for implementations.
     */
    protected Document createDOMDocumentForInterfaceImplementation() throws Exception {

        String packageName = codeGenConfiguration.getPackageName();
        String localPart = makeJavaClassName(axisService.getName());
        String stubName = makeJavaClassName(axisService.getName() + axisService.getEndpointName()) +
                STUB_SUFFIX;
        Document doc = getEmptyDocument();
        Element rootElement = doc.createElement("class");

        addAttribute(doc, "package", packageName, rootElement);

        addAttribute(doc, "servicename", localPart, rootElement);
        //The target nemespace is added as the namespace for this service
        addAttribute(doc, "namespace", axisService.getTargetNamespace(), rootElement);
        if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
            addAttribute(doc, "interfaceName",
                    makeJavaClassName(axisService.getEndpointName()) +
                            STUB_INTERFACE_SUFFIX_BACK,
                    rootElement);
            addAttribute(doc, "name", makeJavaClassName(axisService.getBindingName()) + STUB_SUFFIX,
                    rootElement);
        } else {
            if (this.axisService.getEndpoints().size() > 1) {
                addAttribute(doc, "interfaceName",
                        makeJavaClassName(
                                axisService.getName() + axisService.getEndpointName()),
                        rootElement);
                addAttribute(doc, "name", stubName, rootElement);
            } else {
                addAttribute(doc, "interfaceName",
                        makeJavaClassName(axisService.getName()),
                        rootElement);
                addAttribute(doc, "name", makeJavaClassName(axisService.getName()) + STUB_SUFFIX,
                        rootElement);
            }

        }

        if (codeGenConfiguration.isPackClasses()) {
            if (this.axisService.getEndpoints().size() > 1) {
                addAttribute(doc, "callbackname",
                        makeJavaClassName(
                                axisService.getName() + axisService.getEndpointName()) +
                                CALL_BACK_HANDLER_SUFFIX, rootElement);
            } else {
                addAttribute(doc, "callbackname",
                        makeJavaClassName(axisService.getName()) +
                                CALL_BACK_HANDLER_SUFFIX, rootElement);
            }

        } else {
            addAttribute(doc, "callbackname", localPart + CALL_BACK_HANDLER_SUFFIX, rootElement);
        }
        //add backwordcompatibility attribute
        addAttribute(doc, "isbackcompatible",
                String.valueOf(codeGenConfiguration.isBackwordCompatibilityMode()),
                rootElement);

        // add the wrap classes flag
        if (codeGenConfiguration.isPackClasses()) {
            addAttribute(doc, "wrapped", "yes", rootElement);
        }

        // add SOAP version
        addSoapVersion(doc, rootElement);

        // add the end point
        addEndpoint(doc, rootElement);

        // set the sync/async attributes
        fillSyncAttributes(doc, rootElement);

        // ###########################################################################################
        // this block of code specifically applies to the integration of databinding code into the
        // generated classes tightly (probably as inner classes)
        // ###########################################################################################
        // check for the special models in the mapper and if they are present process them
        if (mapper.isObjectMappingPresent()) {

            // add an attribute to the root element showing that the writing has been skipped
            addAttribute(doc, "skip-write", "yes", rootElement);

            // process the mapper objects
            processModelObjects(mapper.getAllMappedObjects(), rootElement, doc);
        }

        // #############################################################################################

        // load the operations
        loadOperations(doc, rootElement, null);

        // add the databind supporters. Now the databind supporters are completly contained inside
        // the stubs implementation and not visible outside
        rootElement.appendChild(createDOMElementforDatabinders(doc, false));

        Object moduleCodegenPolicyExtensionElement;

        //if some extension has added the stub methods property, add them to the
        //main document
        if ((moduleCodegenPolicyExtensionElement =
                codeGenConfiguration.getProperty("module-codegen-policy-extensions")) != null) {
            rootElement.appendChild(
                    doc.importNode((Element) moduleCodegenPolicyExtensionElement, true));
        }

        //add another element to have the unique list of faults
        rootElement.appendChild(getUniqueListofFaults(doc));


        doc.appendChild(rootElement);

        //////////////////////////////////////////////////////////
//        System.out.println(DOM2Writer.nodeToString(rootElement));
        ////////////////////////////////////////////////
        return doc;
    }

    /**
     * A util method that returns a unique list of faults
     *
     * @param doc
     * @return DOM element
     */
    protected Element getUniqueListofFaults(Document doc) {
        Element rootElement = doc.createElement("fault-list");
        Element faultElement;
        String key;
        Iterator iterator = fullyQualifiedFaultClassNameMap.keySet().iterator();
        while (iterator.hasNext()) {
            faultElement = doc.createElement("fault");
            key = (String) iterator.next();

            //as for the name of a fault, we generate an exception
            addAttribute(doc, "name",
                    (String) fullyQualifiedFaultClassNameMap.get(key),
                    faultElement);
            addAttribute(doc, "shortName",
                    (String) faultClassNameMap.get(key),
                    faultElement);

            //the type represents the type that will be wrapped by this
            //name
            String typeMapping =
                    this.mapper.getTypeMappingName((QName) faultElementQNameMap.get(key));
            addAttribute(doc, "type", (typeMapping == null)
                    ? ""
                    : typeMapping, faultElement);
            String attribValue = (String) instantiatableMessageClassNames.
                    get(key);

            addAttribute(doc, "instantiatableType",
                    attribValue == null ? "" : attribValue,
                    faultElement);

            // add an extra attribute to say whether the type mapping is
            // the default
            if (mapper.getDefaultMappingName().equals(typeMapping)) {
                addAttribute(doc, "default", "yes", faultElement);
            }
            addAttribute(doc, "value", getParamInitializer(typeMapping),
                    faultElement);


            rootElement.appendChild(faultElement);
        }
        return rootElement;
    }

    /**
     * add the qNames of the operation fault message names to faultMessages Mep
     *
     * @param operationFaultMessages
     * @param faultMessagesToMep
     */

    protected void addFaultMessages(List operationFaultMessages, Set faultMessagesToMep) {

        AxisMessage faultMessage;
        for (Iterator iter = operationFaultMessages.iterator(); iter.hasNext();) {
            faultMessage = (AxisMessage) iter.next();
            faultMessagesToMep.add(faultMessage.getName());
        }

    }

    /**
     * A util method that returns a unique list of faults for a given mep
     *
     * @param doc
     * @return DOM element
     */
    protected Element getUniqueListofFaultsofMep(Document doc, String mep) {

        //  list to keep fault message qnames for this mep
        Set faultListForMep = new HashSet();

        Iterator iter = this.axisService.getOperations();
        AxisOperation axisOperation;

        for (; iter.hasNext();) {
            axisOperation = (AxisOperation) iter.next();
            if (mep == null) {
                // add the fault messages
                addFaultMessages(axisOperation.getFaultMessages(), faultListForMep);
            } else {
                if (mep.equals(axisOperation.getMessageExchangePattern())) {
                    // add the fault messages
                    addFaultMessages(axisOperation.getFaultMessages(), faultListForMep);
                }
            }
        }

        Element rootElement = doc.createElement("fault-list");
        Element faultElement;
        String key;
        Iterator iterator = faultListForMep.iterator();
        while (iterator.hasNext()) {
            faultElement = doc.createElement("fault");
            key = (String) iterator.next();

            //as for the name of a fault, we generate an exception
            addAttribute(doc, "name",
                    (String) fullyQualifiedFaultClassNameMap.get(key),
                    faultElement);
            addAttribute(doc, "shortName",
                    (String) faultClassNameMap.get(key),
                    faultElement);

            //the type represents the type that will be wrapped by this
            //name
            String typeMapping =
                    this.mapper.getTypeMappingName((QName) faultElementQNameMap.get(key));
            addAttribute(doc, "type", (typeMapping == null)
                    ? ""
                    : typeMapping, faultElement);
            String attribValue = (String) instantiatableMessageClassNames.
                    get(key);

            addAttribute(doc, "instantiatableType",
                    attribValue == null ? "" : attribValue,
                    faultElement);

            String exceptionName = ((QName) faultElementQNameMap.get(key)).getLocalPart();
            addAttribute(doc, "localname",
                    exceptionName == null ? "" : exceptionName,
                    faultElement);

            // add an extra attribute to say whether the type mapping is
            // the default
            if (mapper.getDefaultMappingName().equals(typeMapping)) {
                addAttribute(doc, "default", "yes", faultElement);
            }
            addAttribute(doc, "value", getParamInitializer(typeMapping),
                    faultElement);


            rootElement.appendChild(faultElement);
        }
        return rootElement;
    }

    /**
     * Adds the endpoint to the document.
     *
     * @param doc
     * @param rootElement
     */
    protected void addEndpoint(Document doc, Element rootElement) throws Exception {

        Element endpointElement = doc.createElement("endpoint");

        String endpoint = this.axisEndpoint.getEndpointURL();
        Text text = doc.createTextNode((endpoint != null)
                ? endpoint
                : "");

        endpointElement.appendChild(text);
        rootElement.appendChild(endpointElement);
    }

    /**
     * Looks for the SOAPVersion and adds it.
     *
     * @param doc
     * @param rootElement
     */
    protected void addSoapVersion(Document doc, Element rootElement) {
        // loop through the extensibility elements to get to the bindings element
        addAttribute(doc, "soap-version",
                (String) axisBinding.getProperty(WSDL2Constants.ATTR_WSOAP_VERSION),
                rootElement);
    }

    /**
     * Writes the exceptions.
     */
    protected void writeExceptions() throws Exception {
        Element faultElement;
        String key;
        Iterator iterator = fullyQualifiedFaultClassNameMap.keySet().iterator();
        while (iterator.hasNext()) {
            Document doc = getEmptyDocument();

            faultElement = doc.createElement("fault");

            addAttribute(doc, "package", codeGenConfiguration.getPackageName(), faultElement);

            key = (String) iterator.next();

            //as for the name of a fault, we generate an exception
            addAttribute(doc, "name",
                    (String) faultClassNameMap.get(key),
                    faultElement);
            addAttribute(doc, "shortName",
                    (String) faultClassNameMap.get(key),
                    faultElement);

            //added the base exception class name
            if (this.codeGenConfiguration.getExceptionBaseClassName() != null) {
                addAttribute(doc, "exceptionBaseClass",
                        this.codeGenConfiguration.getExceptionBaseClassName(), faultElement);
                try {
                    addConstructorDetails(doc, faultElement, this.codeGenConfiguration.getExceptionBaseClassName());
                } catch (ClassNotFoundException e) {
                    log.warn("Can not load the Exception base class");
                }
            } else {
                addAttribute(doc, "exceptionBaseClass", Exception.class.getName(), faultElement);
            }

            //the type represents the type that will be wrapped by this
            //name
            String typeMapping =
                    this.mapper.getTypeMappingName((QName) faultElementQNameMap.get(key));
            addAttribute(doc, "type", (typeMapping == null)
                    ? ""
                    : typeMapping, faultElement);
            String attribValue = (String) instantiatableMessageClassNames.
                    get(key);
            addAttribute(doc, "instantiatableType",
                    attribValue == null ? "" : attribValue,
                    faultElement);

            // add an extra attribute to say whether the type mapping is
            // the default
            if (mapper.getDefaultMappingName().equals(typeMapping)) {
                addAttribute(doc, "default", "yes", faultElement);
            }
            addAttribute(doc, "value", getParamInitializer(typeMapping),
                    faultElement);
            ExceptionWriter exceptionWriter =
                    new ExceptionWriter(
                            codeGenConfiguration.isFlattenFiles() ?
                                    getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                            null) :
                                    getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                            codeGenConfiguration.getSourceLocation()),
                            codeGenConfiguration.getOutputLanguage());

            doc.appendChild(faultElement);
            //////////////////////////////////////////////////////////
//            System.out.println(DOM2Writer.nodeToString(doc));
            ////////////////////////////////////////////////////////////
            exceptionWriter.setOverride(codeGenConfiguration.isOverride());
            writeFile(doc, exceptionWriter);
        }
    }

    private void addConstructorDetails(Document doc,
                                       Element faultElement,
                                       String exceptionClassName) throws ClassNotFoundException {
        Class exceptionClass = Class.forName(exceptionClassName);
        Constructor[] constructors =  exceptionClass.getConstructors();
        for (int i = 0; i < constructors.length; i++) {
            Element constructorElement = doc.createElement("constructor");
            faultElement.appendChild(constructorElement);
            Class[] parameters = constructors[i].getParameterTypes();
            for (int j = 0; j < parameters.length; j++){
                Element parameterElement = doc.createElement("param");
                constructorElement.appendChild(parameterElement);
                addAttribute(doc, "type",
                        parameters[j].getName(), parameterElement);
                addAttribute(doc, "name",
                        getParameterName(parameters[j].getName()), parameterElement);

            }
        }
    }

    private String getParameterName(String className){
       if (className.lastIndexOf(".") > 0){
           className = className.substring(className.lastIndexOf(".") + 1);
       }
       return JavaUtils.xmlNameToJavaIdentifier(className);
    }

    /**
     * Generates the model for the callbacks.
     */
    protected Document createDOMDocumentForException() {
        Document doc = getEmptyDocument();
        Element rootElement = doc.createElement("callback");

        addAttribute(doc, "package", codeGenConfiguration.getPackageName(), rootElement);
        addAttribute(doc, "name",
                makeJavaClassName(axisService.getName()) + CALL_BACK_HANDLER_SUFFIX,
                rootElement);

        // TODO JAXRPC mapping support should be considered here ??
        this.loadOperations(doc, rootElement, null);

        doc.appendChild(rootElement);
        return doc;
    }


    /**
     * Writes the callback handlers.
     */
    protected void writeCallBackHandlers() throws Exception {
        if (codeGenConfiguration.isAsyncOn()) {
            Document interfaceModel = createDOMDocumentForCallbackHandler();
            debugLogDocument("Document for callback handler:", interfaceModel);
            CallbackHandlerWriter callbackWriter =
                    new CallbackHandlerWriter(
                            codeGenConfiguration.isFlattenFiles() ?
                                    getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                            null) :
                                    getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                            codeGenConfiguration.getSourceLocation()),
                            codeGenConfiguration.getOutputLanguage());
            callbackWriter.setOverride(codeGenConfiguration.isOverride());
            writeFile(interfaceModel, callbackWriter);
        }
    }

    /**
     * Generates the model for the callbacks.
     */
    protected Document createDOMDocumentForCallbackHandler() {
        Document doc = getEmptyDocument();
        Element rootElement = doc.createElement("callback");

        addAttribute(doc, "package", codeGenConfiguration.getPackageName(), rootElement);
        if (codeGenConfiguration.isPackClasses() && this.axisService.getEndpoints().size() > 1) {
            addAttribute(doc, "name",
                    makeJavaClassName(axisService.getName() + axisService.getEndpointName())
                            + CALL_BACK_HANDLER_SUFFIX, rootElement);
        } else {
            addAttribute(doc, "name",
                    makeJavaClassName(axisService.getName()) + CALL_BACK_HANDLER_SUFFIX,
                    rootElement);
        }

        // TODO JAXRPC mapping support should be considered here ??
        this.loadOperations(doc, rootElement, null);

        doc.appendChild(rootElement);
        return doc;
    }

    /**
     * Writes the interfaces.
     *
     * @throws Exception
     */
    protected void writeInterface(boolean writeDatabinders) throws Exception {
        Document interfaceModel = createDOMDocumentForInterface(writeDatabinders);
        debugLogDocument("Document for interface:", interfaceModel);
        InterfaceWriter interfaceWriter =
                new InterfaceWriter(
                        codeGenConfiguration.isFlattenFiles() ?
                                getOutputDirectory(codeGenConfiguration.getOutputLocation(), null) :
                                getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                        codeGenConfiguration.getSourceLocation()),
                        this.codeGenConfiguration.getOutputLanguage());
        interfaceWriter.setOverride(codeGenConfiguration.isOverride());
        writeFile(interfaceModel, interfaceWriter);
    }

    /**
     * Creates the DOM tree for the interface creation. Uses the interface.
     */
    protected Document createDOMDocumentForInterface(boolean writeDatabinders) {
        Document doc = getEmptyDocument();
        Element rootElement = doc.createElement("interface");
        String localPart = null;
        if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
            localPart =
                    makeJavaClassName(axisService.getEndpointName() + STUB_INTERFACE_SUFFIX_BACK);
        } else {
            if (this.axisService.getEndpoints().size() > 1) {
                localPart =
                        makeJavaClassName(axisService.getName() + axisService.getEndpointName());
            } else {
                localPart = makeJavaClassName(axisService.getName());
            }
        }

        addAttribute(doc, "package", codeGenConfiguration.getPackageName(), rootElement);
        addAttribute(doc, "name", localPart, rootElement);

        addAttribute(doc, "callbackname",
                makeJavaClassName(axisService.getName()) + CALL_BACK_HANDLER_SUFFIX,
                rootElement);

        //add backwordcompatibility attribute
        addAttribute(doc, "isbackcompatible",
                String.valueOf(codeGenConfiguration.isBackwordCompatibilityMode()),
                rootElement);
        fillSyncAttributes(doc, rootElement);
        loadOperations(doc, rootElement, null);

        // ###########################################################################################
        // this block of code specifically applies to the integration of databinding code into the
        // generated classes tightly (probably as inner classes)
        // ###########################################################################################
        // check for the special models in the mapper and if they are present process them
        if (writeDatabinders) {
            if (mapper.isObjectMappingPresent()) {

                // add an attribute to the root element showing that the writing has been skipped
                addAttribute(doc, "skip-write", "yes", rootElement);

                // process the mapper objects
                processModelObjects(mapper.getAllMappedObjects(), rootElement, doc);
            }
        }

        // #############################################################################################
        doc.appendChild(rootElement);

        return doc;
    }


    /**
     * Update mapper for message receiver
     */
    protected void updateMapperForMessageReceiver() {
        updateMapperClassnames(getFullyQualifiedMessageReceiverName());
    }

    /**
     * @return fully qualified MR name
     */
    protected String getFullyQualifiedMessageReceiverName() {
        String packageName = codeGenConfiguration.getPackageName();
        String localPart = makeJavaClassName(axisService.getName());
        return packageName + "." + localPart + MESSAGE_RECEIVER_SUFFIX;
    }

    /**
     * @return fully qualified skeleton name
     */
    protected String getFullyQualifiedSkeletonName() {
        String packageName = codeGenConfiguration.getPackageName();
        String localPart = makeJavaClassName(axisService.getName());
        String skeltonName;
        if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
            skeltonName = packageName + "." + makeJavaClassName(axisService.getBindingName()) +
                    SKELETON_CLASS_SUFFIX_BACK;
        } else {
            skeltonName = packageName + "." + localPart + SKELETON_CLASS_SUFFIX;
        }
        return skeltonName;
    }

    /**
     * @return fully qualified skeleton interface name
     */
    protected String getFullyQualifiedSkeletonInterfaceName() {
        String packageName = codeGenConfiguration.getPackageName();
        String localPart = makeJavaClassName(axisService.getName());
        String skeltonInterfaceName;
        if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
            skeltonInterfaceName = packageName + "." +
                    makeJavaClassName(axisService.getEndpointName()) +
                    SKELETON_INTERFACE_SUFFIX_BACK;
        } else {
            skeltonInterfaceName = packageName + "." + localPart + SKELETON_INTERFACE_SUFFIX;
        }
        return skeltonInterfaceName;
    }

    /**
     * Emits the skeleton
     *
     * @throws CodeGenerationException
     */
    public void emitSkeleton() throws CodeGenerationException {

        try {

            allServiceInfoHolder = new HashMap();
            Map originalMap = getNewCopy(this.mapper.getAllMappedNames());
            // we are going to generate following files seperately per service
            for (Iterator axisServicesIter = this.axisServices.iterator();
                 axisServicesIter.hasNext();) {
                // create a new hash map for each service
                this.infoHolder = new HashMap();
                this.axisService = (AxisService) axisServicesIter.next();
                this.axisBinding =
                        axisService.getEndpoint(axisService.getEndpointName()).getBinding();

                // see the comment at updateMapperClassnames for details and reasons for
                // calling this method
                if (mapper.isObjectMappingPresent()) {
                    copyMap(originalMap, this.mapper.getAllMappedNames());
                    updateMapperForMessageReceiver();
                } else {
                    copyToFaultMap();
                }

                //handle faults
                generateAndPopulateFaultNames();

                //
                if (codeGenConfiguration.isServerSideInterface()) {
                    //write skeletonInterface
                    writeSkeletonInterface();
                }

                // write skeleton only if the used has
                // asked for the deployment descriptor in the interface mode
                // else write it anyway :)
                if (codeGenConfiguration.isServerSideInterface()) {
                    if (codeGenConfiguration.isGenerateDeployementDescriptor()) {
                        writeSkeleton();
                    }
                } else {
                    writeSkeleton();
                }

                if (!codeGenConfiguration.isSkipMessageReceiver()) {
                    // write a MessageReceiver for this particular service.
                    writeMessageReceiver();
                }

                // write the Exceptions
                writeExceptions();

                if (!codeGenConfiguration.isSkipWriteWSDLs()) {
                    //for the server side codegen
                    //we need to serialize the WSDL's
                    writeWSDLFiles();
                }
                // save the info holder with the service
                allServiceInfoHolder.put(this.axisService.getName(),this.infoHolder);
            }

            // save back type map
            if (this.mapper.isObjectMappingPresent()) {
                copyMap(originalMap, this.mapper.getAllMappedNames());
            }

            // write service xml
            // if asked
            if (codeGenConfiguration.isGenerateDeployementDescriptor()) {
                writeServiceXml();
            }

            if (!codeGenConfiguration.isSkipBuildXML()) {
                //write the ant build
                //we skip this for the flattened case
                if (!codeGenConfiguration.isFlattenFiles()) {
                    writeAntBuild();
                }
            }


        } catch (CodeGenerationException cgExp) {
            throw cgExp;
        } catch (Exception e) {
            throw new CodeGenerationException(e);
        }
    }

    /**
     * Write out the WSDL files (and the schemas) writing the WSDL (and schemas) is somewhat special
     * so we cannot follow the usual pattern of using the class writer
     */
    protected void writeWSDLFiles() {

        //first modify the schema names (and locations) so that
        //they have unique (flattened) names and the schema locations
        //are adjusted to suit it
        axisService.setCustomSchemaNamePrefix("");//prefix with nothing
        axisService.setCustomSchemaNameSuffix(".xsd");//suffix with .xsd - the file name extension
        //force the mappings to be reconstructed
        axisService.setSchemaLocationsAdjusted(false);
        //when generating the code we should copy all the schemas to
        // resource folder.
        Map changedMap = axisService.populateSchemaMappings(this.codeGenConfiguration.isOverrideAbsoluteAddress());

        // add these two attribute to use the user defined wsdl to use.
        try {
            axisService.addParameter(new Parameter("useOriginalwsdl", "true"));
            axisService.addParameter(new Parameter("modifyUserWSDLPortAddress", "false"));
        } catch (AxisFault axisFault) {
            // there is no way to get this excpetion while in codegeneration
        }

        //now get the schema list and write it out
        SchemaWriter schemaWriter = new SchemaWriter(
                codeGenConfiguration.isFlattenFiles() ?
                        getOutputDirectory(codeGenConfiguration.getOutputLocation(), null) :
                        getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                codeGenConfiguration.getResourceLocation()));

        // first write all the schmas.
        // then use the changedMap got above to adjust the names.
        Map schemaMappings = axisService.getSchemaMappingTable();
        Iterator keys = schemaMappings.keySet().iterator();
        String key = null;
        while (keys.hasNext()) {
            key = (String) keys.next();
            if (!key.startsWith("http")){
               schemaWriter.writeSchema((XmlSchema) schemaMappings.get(key), key);
            }
        }

        //switch between the correct writer
        if (CommandLineOptionConstants.WSDL2JavaConstants.WSDL_VERSION_2.
                equals(codeGenConfiguration.getWSDLVersion())) {
            // Woden cannot serialize the WSDL as yet, so lets serialize the axisService for now.

            WSDL20Writer wsdl20Writer = new WSDL20Writer(
                    codeGenConfiguration.isFlattenFiles() ?
                            getOutputDirectory(codeGenConfiguration.getOutputLocation(), null) :
                            getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                    codeGenConfiguration.getResourceLocation()));
            wsdl20Writer.writeWSDL(axisService);

        } else {
            // here we are going to write the wsdl and its imports
            // with out using the axis service.

            WSDL11Writer wsdl11Writer = new WSDL11Writer(
                    codeGenConfiguration.isFlattenFiles() ?
                            getOutputDirectory(codeGenConfiguration.getOutputLocation(), null) :
                            getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                    codeGenConfiguration.getResourceLocation()));
            wsdl11Writer.writeWSDL(axisService,
                    codeGenConfiguration.getWsdlDefinition(),
                    changedMap);

        }
    }

    /**
     * Utility method to copy the faults to the correct map
     */
    protected void copyToFaultMap() {
        Map classNameMap = mapper.getAllMappedNames();
        Iterator keys = classNameMap.keySet().iterator();
        while (keys.hasNext()) {
            Object key = keys.next();
            instantiatableMessageClassNames.put(key,
                    classNameMap.get(key));
        }
    }

    /**
     * Change the fault classnames to go with the package and stub
     */
    protected void updateFaultPackageForStub() {
        Iterator faultClassNameKeys = fullyQualifiedFaultClassNameMap.keySet().iterator();
        while (faultClassNameKeys.hasNext()) {
            Object key = faultClassNameKeys.next();
            String className = (String) fullyQualifiedFaultClassNameMap.get(key);
            //append the skelton name
            String fullyQualifiedStubName = getFullyQualifiedStubName();
            fullyQualifiedFaultClassNameMap.put(key, codeGenConfiguration.getPackageName() + "."
                    + className);
        }
    }

    /**
     * Writes the message receiver
     *
     * @throws Exception
     */
    protected void writeMessageReceiver() throws Exception {
        //loop through the meps and generate code for each mep
        Iterator it = mepToClassMap.keySet().iterator();
        while (it.hasNext()) {
            String mep = (String) it.next();
            Document classModel = createDocumentForMessageReceiver(
                    mep,
                    codeGenConfiguration.isServerSideInterface());
            debugLogDocument("Document for message receiver (mep=" + mep +
                    "):", classModel);
            //write the class only if any methods are found
            if (Boolean.TRUE.equals(infoHolder.get(mep))) {
                MessageReceiverWriter writer =
                        new MessageReceiverWriter(
                                codeGenConfiguration.isFlattenFiles() ?
                                        getOutputDirectory(
                                                codeGenConfiguration.getOutputLocation(),
                                                null) :
                                        getOutputDirectory(
                                                codeGenConfiguration.getOutputLocation(),
                                                codeGenConfiguration.getSourceLocation()),
                                codeGenConfiguration.getOutputLanguage());
                writer.setOverride(codeGenConfiguration.isOverride());
                writeFile(classModel, writer);

            }
        }
    }

    /**
     * Creates the XML model for the message receiver
     *
     * @param mep
     * @param isServerSideInterface
     * @return DOM Document
     */
    protected Document createDocumentForMessageReceiver(String mep, boolean isServerSideInterface) {

        Document doc = getEmptyDocument();
        Element rootElement = doc.createElement("interface");

        addAttribute(doc, "package", codeGenConfiguration.getPackageName(), rootElement);

        String localPart = makeJavaClassName(axisService.getName());

        addAttribute(doc, "name", localPart + mepToSuffixMap.get(mep), rootElement);

        if (this.codeGenConfiguration.isLowerCaseMethodName()){
           addAttribute(doc, "isLowerCaseMethodName", "true", rootElement); 
        }
        //add backwordcompatibility attribute
        addAttribute(doc, "isbackcompatible",
                String.valueOf(codeGenConfiguration.isBackwordCompatibilityMode()),
                rootElement);

        if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
            addAttribute(doc, "skeletonname",
                    makeJavaClassName(axisService.getBindingName()) +
                            SKELETON_CLASS_SUFFIX_BACK,
                    rootElement);
            if (isServerSideInterface) {
                addAttribute(doc, "skeletonInterfaceName", makeJavaClassName(
                        axisService.getEndpointName()) + SKELETON_INTERFACE_SUFFIX_BACK,
                        rootElement);
            } else {
                addAttribute(doc, "skeletonInterfaceName", makeJavaClassName(
                        axisService.getBindingName()) + SKELETON_CLASS_SUFFIX_BACK,
                        rootElement);
            }
        } else {
            if (this.codeGenConfiguration.getSkeltonClassName() != null){
                addAttribute(doc, "skeletonname", this.codeGenConfiguration.getSkeltonClassName(), rootElement);
            } else {
                addAttribute(doc, "skeletonname", localPart + SKELETON_CLASS_SUFFIX, rootElement);
            }
            if (isServerSideInterface) {
                if (this.codeGenConfiguration.getSkeltonInterfaceName() != null){
                    addAttribute(doc, "skeletonInterfaceName", this.codeGenConfiguration.getSkeltonInterfaceName(),
                        rootElement);
                } else {
                    addAttribute(doc, "skeletonInterfaceName", localPart + SKELETON_INTERFACE_SUFFIX,
                        rootElement);
                }
            } else {
                if (this.codeGenConfiguration.getSkeltonClassName() != null){
                    addAttribute(doc, "skeletonInterfaceName", this.codeGenConfiguration.getSkeltonClassName(),
                        rootElement);
                } else {
                    addAttribute(doc, "skeletonInterfaceName", localPart + SKELETON_CLASS_SUFFIX,
                        rootElement);
                }
            }
        }

        addAttribute(doc, "basereceiver", (String) mepToClassMap.get(mep), rootElement);

        fillSyncAttributes(doc, rootElement);

        // ###########################################################################################
        // this block of code specifically applies to the integration of databinding code into the
        // generated classes tightly (probably as inner classes)
        // ###########################################################################################
        // check for the special models in the mapper and if they are present process them
        if (mapper.isObjectMappingPresent()) {
            // add an attribute to the root element showing that the writing has been skipped
            addAttribute(doc, "skip-write", "yes", rootElement);
            // process the mapper objects
            processModelObjects(mapper.getAllMappedObjects(), rootElement, doc);
        }
        // #############################################################################################

        boolean isOpsFound = loadOperations(doc, rootElement, mep);
        //put the result in the property map
        infoHolder.put(mep, isOpsFound ? Boolean.TRUE : Boolean.FALSE);
        //create the databinder element with serverside as true
        rootElement.appendChild(createDOMElementforDatabinders(doc, true));

        //attach a list of faults
        rootElement.appendChild(getUniqueListofFaultsofMep(doc, mep));

        doc.appendChild(rootElement);

        //////////////////////////////////////////////////////////
//        System.out.println(DOM2Writer.nodeToString(rootElement));
        ////////////////////////////////////////////////////////////

        return doc;
    }

    /**
     * create a dom element for databinders. This is called by other
     *
     * @param doc
     */
    protected Element createDOMElementforDatabinders(Document doc, boolean isServerside) {

        // First Iterate through the operations and find the relevant fromOM and toOM methods to be generated
        ArrayList parameters = new ArrayList();

        AxisOperation axisOperation = null;
        AxisBindingOperation axisBindingOperation = null;
        for (Iterator bindingOperationsIter = this.axisBinding.getChildren();
             bindingOperationsIter.hasNext();) {
            axisBindingOperation = (AxisBindingOperation) bindingOperationsIter.next();
            axisOperation = axisBindingOperation.getAxisOperation();

            // Add the parameters to a map with their type as the key
            // this step is needed to remove repetitions

            // process the input parameters
            String MEP = axisOperation.getMessageExchangePattern();
            if (WSDLUtil.isInputPresentForMEP(MEP)) {
                Element[] inputParamElement = getInputParamElement(doc, axisOperation);
                for (int i = 0; i < inputParamElement.length; i++) {
                    //add an attribute to the parameter saying that this is an
                    //input
                    addAttribute(doc, "direction", "in", inputParamElement[i]);
                    //add the short type name
                    parameters.add(
                            inputParamElement[i]);

                }
            }
            // process output parameters
            if (WSDLUtil.isOutputPresentForMEP(MEP)) {
                Element outputParamElement = getOutputParamElement(doc, axisOperation);
                if (outputParamElement != null) {
                    //set the direction as out
                    addAttribute(doc, "direction", "out", outputParamElement);
                    parameters.add(outputParamElement);
                }
            }

            //process faults
            Element[] faultParamElements = getFaultParamElements(doc, axisOperation);
            for (int i = 0; i < faultParamElements.length; i++) {
                //set the direction as out - all faults are out messages ?
                addAttribute(doc, "direction", "out", faultParamElements[i]);
                parameters.add(faultParamElements[i]);
            }

            // process the header parameters
            Element newChild;
            List headerParameterQNameList = new ArrayList();
            addHeaderOperations(headerParameterQNameList, axisBindingOperation, true);
            List parameterElementList = getParameterElementList(doc, headerParameterQNameList,
                    WSDLConstants.SOAP_HEADER);

            for (int i = 0; i < parameterElementList.size(); i++) {
                newChild = (Element) parameterElementList.get(i);
                parameters.add(newChild);
            }

            headerParameterQNameList.clear();
            parameterElementList.clear();
            addHeaderOperations(headerParameterQNameList, axisBindingOperation, false);
            parameterElementList = getParameterElementList(doc, headerParameterQNameList,
                    WSDLConstants.SOAP_HEADER);

            for (int i = 0; i < parameterElementList.size(); i++) {
                newChild = (Element) parameterElementList.get(i);
                parameters.add(newChild);
            }
        }

        Element rootElement = doc.createElement("databinders");
        //add the db type attribute  - the name of the databinding type
        //this will be used to select the correct template
        addAttribute(doc, "dbtype", codeGenConfiguration.getDatabindingType(), rootElement);
        //add the wrapped flag state - this is used by JiBX, but may be useful
        //for other frameworks in the future
        String wrapflag = Boolean.toString(codeGenConfiguration.isParametersWrapped());
        addAttribute(doc, "wrapped", wrapflag, rootElement);

        //at this point we may need to capture the extra parameters passes to the
        //particular databinding framework
        //these parameters showup in the property map with String keys, and we
        //can just copy these items as attributes of the <extra> element.
        Element extraElement = addElement(doc, "extra", null, rootElement);
        Map propertiesMap = codeGenConfiguration.getProperties();
        for (Iterator it = propertiesMap.keySet().iterator(); it.hasNext();) {
            Object key = it.next();
            if (key instanceof String) {
                Object value = propertiesMap.get(key);
                //if the value is null set it to empty string
                if (value == null) value = "";
                //add key="value" attribute to element iff value a string
                if (value instanceof String) {
                    addAttribute(doc, (String) key, (String) value, extraElement);
                }
            }
        }

        //add the server side attribute. this helps the databinding template
        //to determine the methods to generate
        if (isServerside) {
            addAttribute(doc, "isserverside", "yes", rootElement);
        }
        // add the names of the elements that have base 64 content
        // if the base64 name list is missing then this whole step is skipped
        rootElement.appendChild(getBase64Elements(doc));

        //add the method names
        rootElement.appendChild(getOpNames(doc));

        for (Iterator iterator = parameters.iterator(); iterator.hasNext();) {
            rootElement.appendChild((Element) iterator.next());
        }

        // finish with any extra information from service and operations
        Parameter details = axisService.getParameter(Constants.DATABINDING_SERVICE_DETAILS);
        if (details != null) {
            Object value = details.getValue();
            if (value instanceof Element) {
                rootElement.appendChild(doc.importNode((Element) value, true));
            } else if (value instanceof List) {
                for (Iterator iter = ((List) value).iterator(); iter.hasNext();) {
                    rootElement.appendChild(doc.importNode((Element) iter.next(), true));
                }
            }
        }

        axisOperation = null;
        for (Iterator operationsIterator = axisService.getOperations();
             operationsIterator.hasNext();) {
             axisOperation = (AxisOperation) operationsIterator.next();
            details = axisOperation.getParameter(Constants.DATABINDING_OPERATION_DETAILS);
            if (details != null) {
                rootElement.appendChild(doc.importNode((Element) details.getValue(), true));
            }
        }

        ///////////////////////////////////////////////
//        System.out.println("databinding root element " + DOM2Writer.nodeToString(rootElement));
        ////////////////////////////////////////////////

        return rootElement;
    }

    /**
     * set the short type as it is in the data binding
     *
     * @param paramElement
     * @param xmlName
     */


    protected void addShortType(Element paramElement, String xmlName) {

        if (xmlName != null) {
            String javaName;
            if (JavaUtils.isJavaKeyword(xmlName)) {
                javaName = JavaUtils.makeNonJavaKeyword(xmlName);
            } else {
                javaName = JavaUtils.capitalizeFirstChar(JavaUtils
                        .xmlNameToJava(xmlName));
            }
            addAttribute(paramElement.getOwnerDocument(),
                    "shorttype",
                    javaName,
                    paramElement);
        } else {
            addAttribute(paramElement.getOwnerDocument(),
                    "shorttype",
                    "",
                    paramElement);
        }
    }

    /**
     * Gets an element representing the operation names
     *
     * @param doc
     * @return Returns Element.
     */
    protected Element getOpNames(Document doc) {
        Element root = doc.createElement("opnames");
        Element elt;


        for (Iterator operationsIterator = axisService.getOperations();
             operationsIterator.hasNext();) {
            AxisOperation axisOperation = (AxisOperation) operationsIterator.next();
            elt = doc.createElement("name");
            String localPart = axisOperation.getName().getLocalPart();
            elt.appendChild(doc.createTextNode(JavaUtils.xmlNameToJava(localPart)));

            //what needs to be put here as the opertation namespace is actually the
            //traget namespace of the service
            addAttribute(doc, "opnsuri", axisService.getTargetNamespace(), elt);
            root.appendChild(elt);
        }

        return root;
    }

    /**
     * Gets the base64 types. If not available this will be empty!!!
     *
     * @param doc
     * @return Returns Element.
     */
    protected Element getBase64Elements(Document doc) {
        Element root = doc.createElement("base64Elements");
        Element elt;
        QName qname;

        // this is a list of QNames
        List list = (List) codeGenConfiguration.getProperties().get(Constants.BASE_64_PROPERTY_KEY);

        if ((list != null) && !list.isEmpty()) {
            int count = list.size();

            for (int i = 0; i < count; i++) {
                qname = (QName) list.get(i);
                elt = doc.createElement("name");
                addAttribute(doc, "ns-url", qname.getNamespaceURI(), elt);
                addAttribute(doc, "localName", qname.getLocalPart(), elt);
                root.appendChild(elt);
            }
        }

        return root;
    }

    /**
     * @param objectMappings
     * @param root
     * @param doc
     */
    protected void processModelObjects(Map objectMappings, Element root, Document doc) {
        Iterator objectIterator = objectMappings.values().iterator();

        while (objectIterator.hasNext()) {
            Object o = objectIterator.next();

            if (o instanceof Document) {
                //we cannot have an empty document
                root.appendChild(doc.importNode(((Document) o).getDocumentElement(), true));
            } else {

                // oops we have no idea how to do this, if the model provided is not a DOM document
                // we are done. we might as well skip  it here
            }
        }
    }

    /**
     * we need to modify the mapper's class name list. The issue here is that in this case we do not
     * expect the fully qulified class names to be present in the class names list due to the simple
     * reason that they've not been written yet! Hence the mappers class name list needs to be
     * updated to suit the expected package to be written in this case we modify the package name to
     * have the class a inner class of the stub, interface or the message receiver depending on the
     * style
     */
    protected void updateMapperClassnames(String fullyQulifiedIncludingClassNamePrefix) {
        Map classNameMap = mapper.getAllMappedNames();
        Iterator keys = classNameMap.keySet().iterator();

        while (keys.hasNext()) {
            Object key = keys.next();
            String className = (String) classNameMap.get(key);

            String realClassName = className;
            if (className.endsWith("[]")){
               realClassName = realClassName.substring(0,realClassName.indexOf("[]"));
            }
            //this is a generated class name - update the name
            if (!TypeTesterUtil.hasPackage(realClassName) && !TypeTesterUtil.isPrimitive(realClassName)) {
                classNameMap.put(key, fullyQulifiedIncludingClassNamePrefix + "." + className);
                instantiatableMessageClassNames.put(key,
                        fullyQulifiedIncludingClassNamePrefix + "$" +
                                className);
            } else {
                //this is a fully qualified class name - just leave it as it is
                classNameMap.put(key, className);
                instantiatableMessageClassNames.put(key,
                        className);
            }
        }
    }

    /**
     * Write the service XML
     *
     * @throws Exception
     */
    protected void writeServiceXml() throws Exception {

        // Write the service xml in a folder with the
        Document serviceXMLModel = createDOMDocumentForServiceXML();
        debugLogDocument("Document for service XML:", serviceXMLModel);
        FileWriter serviceXmlWriter =
                new ServiceXMLWriter(
                        codeGenConfiguration.isFlattenFiles() ?
                                getOutputDirectory(codeGenConfiguration.getOutputLocation(), null) :
                                getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                        codeGenConfiguration.getResourceLocation()),
                        this.codeGenConfiguration.getOutputLanguage());
        serviceXmlWriter.setOverride(codeGenConfiguration.isOverride());
        writeFile(serviceXMLModel, serviceXmlWriter);
        codeGenConfiguration.addXmlFileName(serviceXmlWriter.getOutputFile().getAbsolutePath());//$NON-SEC-3

    }

    protected Document createDOMDocumentForServiceXML() {
        Document doc = getEmptyDocument();
        String className = null;
        String serviceName = null;

        Element rootElement = doc.createElement("interfaces");
        doc.appendChild(rootElement);

        for (Iterator iter = this.axisServices.iterator(); iter.hasNext();) {
            this.axisService = (AxisService) iter.next();
            this.axisBinding = axisService.getEndpoint(axisService.getEndpointName()).getBinding();
            serviceName = axisService.getName();
            if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
                className = makeJavaClassName(axisService.getBindingName());
            } else {
                className = makeJavaClassName(serviceName);
            }

            rootElement.appendChild(getServiceElement(serviceName, className, doc));
        }

        return doc;
    }

    /**
     * A resusable method to return the service element for creating the service xml
     *
     * @param serviceName
     * @param className
     * @param doc
     * @return DOM Element
     */
    protected Element getServiceElement(String serviceName, String className, Document doc) {

        if (allServiceInfoHolder.get(serviceName) != null){
            this.infoHolder = (Map) allServiceInfoHolder.get(serviceName);
        }
        Element rootElement = doc.createElement("interface");

        addAttribute(doc, "package", "", rootElement);
        addAttribute(doc, "classpackage", codeGenConfiguration.getPackageName(), rootElement);
        if (this.codeGenConfiguration.getSkeltonClassName() != null) {
            addAttribute(doc, "name", this.codeGenConfiguration.getSkeltonClassName(), rootElement);
        } else {
            if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
                addAttribute(doc, "name", className + SKELETON_CLASS_SUFFIX_BACK, rootElement);
            } else {
                addAttribute(doc, "name", className + SKELETON_CLASS_SUFFIX, rootElement);
            }
        }

        if (!codeGenConfiguration.isWriteTestCase()) {
            addAttribute(doc, "testOmit", "true", rootElement);
        }
        addAttribute(doc, "servicename", serviceName, rootElement);

        Iterator it = mepToClassMap.keySet().iterator();
        while (it.hasNext()) {
            Object key = it.next();

            if (Boolean.TRUE.equals(infoHolder.get(key))) {
                Element elt = addElement(doc, "messagereceiver",
                        makeJavaClassName(serviceName) + mepToSuffixMap.get(key),
                        rootElement);
                addAttribute(doc, "mepURI", key.toString(), elt);
            }

        }

        loadOperations(doc, rootElement, null);

        return rootElement;
    }

    protected void writeSkeleton() throws Exception {
        Document skeletonModel =
                createDOMDocumentForSkeleton(codeGenConfiguration.isServerSideInterface());
        debugLogDocument("Document for skeleton:", skeletonModel);
        FileWriter skeletonWriter = new SkeletonWriter(
                codeGenConfiguration.isFlattenFiles() ?
                        getOutputDirectory(codeGenConfiguration.getOutputLocation(), null) :
                        getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                codeGenConfiguration.getSourceLocation())
                , this.codeGenConfiguration.getOutputLanguage());
        skeletonWriter.setOverride(codeGenConfiguration.isOverride());
        writeFile(skeletonModel, skeletonWriter);
    }

    /**
     * Write the skeletonInterface
     *
     * @throws Exception
     */
    protected void writeSkeletonInterface() throws Exception {
        Document skeletonModel = createDOMDocumentForSkeletonInterface();
        debugLogDocument("Document for skeleton Interface:", skeletonModel);
        FileWriter skeletonInterfaceWriter = new SkeletonInterfaceWriter(
                codeGenConfiguration.isFlattenFiles() ?
                        getOutputDirectory(codeGenConfiguration.getOutputLocation(), null) :
                        getOutputDirectory(codeGenConfiguration.getOutputLocation(),
                                codeGenConfiguration.getSourceLocation())
                , this.codeGenConfiguration.getOutputLanguage());
        skeletonInterfaceWriter.setOverride(codeGenConfiguration.isOverride());
        writeFile(skeletonModel, skeletonInterfaceWriter);
    }

    /**
     * Creates the XMLModel for the skeleton
     *
     * @param isSkeletonInterface
     * @return DOM Document
     */
    protected Document createDOMDocumentForSkeleton(boolean isSkeletonInterface) {
        Document doc = getEmptyDocument();
        Element rootElement = doc.createElement("interface");

        String serviceName = makeJavaClassName(axisService.getName());
        addAttribute(doc, "package", codeGenConfiguration.getPackageName(), rootElement);
        if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
            addAttribute(doc, "name",
                    makeJavaClassName(axisService.getBindingName()) +
                            SKELETON_CLASS_SUFFIX_BACK,
                    rootElement);
        } else if (this.codeGenConfiguration.getSkeltonClassName() != null){
            addAttribute(doc, "name", this.codeGenConfiguration.getSkeltonClassName(), rootElement);
        } else {
            addAttribute(doc, "name", serviceName + SKELETON_CLASS_SUFFIX, rootElement);
        }
        addAttribute(doc, "callbackname", serviceName + CALL_BACK_HANDLER_SUFFIX,
                rootElement);
        //add backwordcompatibility attribute
        addAttribute(doc, "isbackcompatible",
                String.valueOf(codeGenConfiguration.isBackwordCompatibilityMode()),
                rootElement);
        if (isSkeletonInterface) {
            if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
                addAttribute(doc, "skeletonInterfaceName", makeJavaClassName(
                        axisService.getEndpointName()) + SKELETON_INTERFACE_SUFFIX_BACK,
                        rootElement);
            } else if (this.codeGenConfiguration.getSkeltonInterfaceName() != null){
                addAttribute(doc, "skeletonInterfaceName", this.codeGenConfiguration.getSkeltonInterfaceName(),
                        rootElement);
            } else {
                addAttribute(doc, "skeletonInterfaceName", serviceName + SKELETON_INTERFACE_SUFFIX,
                        rootElement);
            }

        }
        fillSyncAttributes(doc, rootElement);
        loadOperations(doc, rootElement, null);

        //attach a list of faults
        rootElement.appendChild(getUniqueListofFaults(doc));

        doc.appendChild(rootElement);

        //////////////////////////////////////////////////////////
//        System.out.println(DOM2Writer.nodeToString(rootElement));
        ////////////////////////////////////////////////////////////
        return doc;

    }

    /**
     * Creates the XML model for the skeleton interface
     *
     * @return DOM Document
     */
    protected Document createDOMDocumentForSkeletonInterface() {
        Document doc = getEmptyDocument();
        Element rootElement = doc.createElement("interface");

        String serviceName = makeJavaClassName(axisService.getName());
        addAttribute(doc, "package", codeGenConfiguration.getPackageName(), rootElement);
        if (this.codeGenConfiguration.isBackwordCompatibilityMode()) {
            addAttribute(doc, "name", makeJavaClassName(axisService.getEndpointName()) +
                    SKELETON_INTERFACE_SUFFIX_BACK, rootElement);
        } else if (this.codeGenConfiguration.getSkeltonInterfaceName() != null){
            addAttribute(doc, "name", this.codeGenConfiguration.getSkeltonInterfaceName() , rootElement);
        } else {
            addAttribute(doc, "name", serviceName + SKELETON_INTERFACE_SUFFIX, rootElement);
        }

        addAttribute(doc, "callbackname", serviceName + CALL_BACK_HANDLER_SUFFIX,
                rootElement);

        //add backwordcompatibility attribute
        addAttribute(doc, "isbackcompatible",
                String.valueOf(codeGenConfiguration.isBackwordCompatibilityMode()),
                rootElement);

        fillSyncAttributes(doc, rootElement);
        loadOperations(doc, rootElement, null);

        //attach a list of faults
        rootElement.appendChild(getUniqueListofFaults(doc));

        doc.appendChild(rootElement);
        //////////////////////////////////////////////////////////
//        System.out.println(DOM2Writer.nodeToString(rootElement));
        ////////////////////////////////////////////////////////////
        return doc;

    }

    /**
     * Loads the operations
     *
     * @param doc
     * @param rootElement
     * @param mep
     * @return boolean
     */
    protected boolean loadOperations(Document doc, Element rootElement, String mep) {
        Element methodElement;
        String serviceName = makeJavaClassName(axisService.getName());

        Iterator bindingOperations = this.axisBinding.getChildren();
        boolean opsFound = false;
        AxisBindingOperation axisBindingOperation = null;
        AxisOperation axisOperation = null;
        while (bindingOperations.hasNext()) {
            axisBindingOperation = (AxisBindingOperation) bindingOperations.next();
            axisOperation = axisBindingOperation.getAxisOperation();
            // populate info holder with mep information. This will used in determining which
            // message receiver to use, etc.,


            String messageExchangePattern = axisOperation.getMessageExchangePattern();
            if (infoHolder.get(messageExchangePattern) == null) {
                infoHolder.put(messageExchangePattern, Boolean.TRUE);
            }

            if (mep == null) {
                opsFound = true;
                methodElement = generateMethodElement(doc, serviceName, axisBindingOperation);
                rootElement.appendChild(methodElement);

            } else {
                //mep is present - we move ahead only if the given mep matches the mep of this operation

                if (mep.equals(axisOperation.getMessageExchangePattern())) {
                    //at this point we know it's true
                    opsFound = true;
                    methodElement = generateMethodElement(doc, serviceName, axisBindingOperation);
                    rootElement.appendChild(methodElement);
                    //////////////////////
                }
            }

        }

        return opsFound;
    }

    /**
     * Common code to generate a <method> element from an operation.
     *
     * @param doc
     * @param endpointName
     * @param bindingOperation
     * @return generated element
     * @throws DOMException
     */
    protected Element generateMethodElement(Document doc,
                                            String endpointName,
                                            AxisBindingOperation bindingOperation) throws DOMException {
        AxisOperation axisOperation = bindingOperation.getAxisOperation();
        Element methodElement;
        List soapHeaderInputParameterList = new ArrayList();
        List soapHeaderOutputParameterList = new ArrayList();
        methodElement = doc.createElement("method");
        String localPart = axisOperation.getName().getLocalPart();
        if (this.codeGenConfiguration.isLowerCaseMethodName()){
            addAttribute(doc, "name", JavaUtils.xmlNameToJavaIdentifier(localPart), methodElement);
        } else {
            addAttribute(doc, "name", localPart, methodElement);
        }
        addAttribute(doc, "originalName", localPart, methodElement);
        addAttribute(doc, "namespace", axisOperation.getName().getNamespaceURI(), methodElement);
        addAttribute(doc, "style", (String) getBindingPropertyFromOperation(
                WSDLConstants.WSDL_1_1_STYLE, axisOperation.getName()), methodElement);

        // add documentation for this operation
        String comment = "";
        if (axisOperation.getDocumentation() != null){
            comment = axisOperation.getDocumentation().trim();
        }
        addAttribute(doc, "comment", comment, methodElement);

        String messageExchangePattern = axisOperation.getMessageExchangePattern();

        //Jaxws Specific
        if("jax-ws".equals(codeGenConfiguration.getOutputLanguage())){
            boolean wrapped = false;
            if (WSDLUtil.isInputPresentForMEP(messageExchangePattern)) {
                AxisMessage msg = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
                if(msg.getParameter(Constants.UNWRAPPED_KEY) != null){
                    wrapped = true;
                }
            }
            addAttribute(doc, "parameterstyle", (wrapped)?"WRAPPPED":"BARE", methodElement);
        }


        addAttribute(doc, "dbsupportname",
                endpointName + localPart + DATABINDING_SUPPORTER_NAME_SUFFIX,
                methodElement);
        addAttribute(doc, "mep", Utils.getAxisSpecifMEPConstant(messageExchangePattern) + "",
                methodElement);
        addAttribute(doc, "mepURI", messageExchangePattern, methodElement);
        Parameter wsdl2StyleParameter = axisOperation.getParameter(WSDL2Constants.OPERATION_STYLE);
        if (wsdl2StyleParameter != null) {
            // provide WSDL2 styles to allow templates to take advantage of them, if desired
            addAttribute(doc, "wsdl2Styles", arrayToString((URI[])wsdl2StyleParameter.getValue()), methodElement);
        }

        // check for this operation to be handled directly by databinding code generation
        Parameter dbmethname = axisOperation.getParameter(Constants.DATABINDING_GENERATED_RECEIVER);
        if (dbmethname != null) {
            addAttribute(doc, "usedbmethod", (String) dbmethname.getValue(), methodElement);
        }
        Parameter dbgenimpl =
                axisOperation.getParameter(Constants.DATABINDING_GENERATED_IMPLEMENTATION);
        if (dbgenimpl != null && Boolean.TRUE.equals(dbgenimpl.getValue())) {
            addAttribute(doc, "usdbimpl", "true", methodElement);
        } else {
            addAttribute(doc, "usdbimpl", "false", methodElement);
        }

        addSOAPAction(doc, methodElement, bindingOperation.getName());
        addOutputAndFaultActions(doc, methodElement, axisOperation);
        addHeaderOperations(soapHeaderInputParameterList, bindingOperation, true);
//        addHeaderOperations(soapHeaderOutputParameterList, axisOperation, false);


        if (WSDLUtil.isInputPresentForMEP(messageExchangePattern)) {
            if("jax-ws".equals(codeGenConfiguration.getOutputLanguage())){
                useHolderClass_jaxws = false;
                AxisMessage inMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
                if (WSDLUtil.isOutputPresentForMEP(messageExchangePattern)) {
                    AxisMessage outMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
                    if(inMessage.getName().equals(outMessage.getName())){
                        // in/out message
                        useHolderClass_jaxws = true;
                        addAttribute(doc, "useholder", "true", methodElement);
                    }
                }
            }
            methodElement.appendChild(getInputElement(doc,
                    bindingOperation, soapHeaderInputParameterList));
        }
        if (WSDLUtil.isOutputPresentForMEP(messageExchangePattern)) {
            methodElement.appendChild(getOutputElement(doc,
                    bindingOperation,
                    soapHeaderOutputParameterList));
        }
        methodElement.appendChild(getFaultElement(doc,
                axisOperation));

        setTransferCoding(axisOperation, methodElement, doc);

        String property = (String) getBindingPropertyFromOperation(
                WSDL2Constants.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR,
                axisOperation.getName());
        if (property != null) {
            methodElement.appendChild(generateOptionParamComponent(doc,
                    "org.apache.axis2.description.WSDL2Constants.ATTR_WHTTP_QUERY_PARAMETER_SEPARATOR",
                    "\"" + property + "\""));
        }

        property = (String) getBindingPropertyFromOperation(
                WSDL2Constants.ATTR_WHTTP_LOCATION,
                axisOperation.getName());
        if (property != null) {
            methodElement.appendChild(generateOptionParamComponent(doc,
                    "org.apache.axis2.description.WSDL2Constants.ATTR_WHTTP_LOCATION",
                    "\"" + property + "\""));
        }

        String mep = (String) getBindingPropertyFromOperation(WSDL2Constants.ATTR_WSOAP_MEP,
                axisOperation.getName());

        String bindingType = null;
        if (axisBinding != null) {
            bindingType = axisBinding.getType();
        }

        if (WSDL2Constants.URI_WSOAP_MEP.equalsIgnoreCase(mep)) {
            methodElement.appendChild(generateOptionParamComponent(doc,
                    "org.apache.axis2.Constants.Configuration.ENABLE_REST",
                    "true"));
            methodElement.appendChild(generateOptionParamComponent(doc,
                    "org.apache.axis2.Constants.Configuration.HTTP_METHOD",
                    "\"" +
                            org.apache.axis2.Constants.Configuration
                                    .HTTP_METHOD_GET +
                            "\""));
            methodElement.appendChild(generateOptionParamComponent(doc,
                    "org.apache.axis2.Constants.Configuration.CONTENT_TYPE",
                    "\"" +
                            org.apache.axis2.transport.http.HTTPConstants
                                    .MEDIA_TYPE_X_WWW_FORM +
                            "\""));
            methodElement.appendChild(generateOptionParamComponent(doc,
                    "org.apache.axis2.Constants.Configuration.MESSAGE_TYPE",
                    "\"" +
                            org.apache.axis2.transport.http.HTTPConstants
                                    .MEDIA_TYPE_X_WWW_FORM +
                            "\""));
            methodElement.appendChild(generateOptionParamComponent(doc,
                    "org.apache.axis2.Constants.Configuration.SOAP_RESPONSE_MEP",
                    "true"));
        } else if (bindingType != null && bindingType.equals(WSDL2Constants.URI_WSDL2_HTTP)) {

            methodElement.appendChild(generateOptionParamComponent(doc,
                    "org.apache.axis2.Constants.Configuration.ENABLE_REST",
                    "true"));

            property = (String) getBindingPropertyFromOperation(WSDL2Constants.ATTR_WHTTP_METHOD,
                    axisOperation.getName());
            if (property != null) {
                methodElement.appendChild(generateOptionParamComponent(doc,
                        "org.apache.axis2.Constants.Configuration.HTTP_METHOD",
                        "\"" + property + "\""));
            } else if (!WSDL2Constants.URI_WSOAP_MEP.equalsIgnoreCase(mep)) {
                // If there is no WHTTP_METHOD defined then we better compute the default value which is get if the operation
                // is wsdlx:safe or post otherwise
                Parameter safe = axisOperation.getParameter(WSDL2Constants.ATTR_WSDLX_SAFE);
                if (safe != null) {
                    if (((Boolean) safe.getValue()).booleanValue()) {
                        methodElement.appendChild(generateOptionParamComponent(doc,
                                "org.apache.axis2.Constants.Configuration.HTTP_METHOD",
                                "\"" +
                                        org.apache.axis2.Constants.Configuration
                                                .HTTP_METHOD_GET +
                                        "\""));
                    } else {
                        methodElement.appendChild(generateOptionParamComponent(doc,
                                "org.apache.axis2.Constants.Configuration.HTTP_METHOD",
                                "\"" +
                                        org.apache.axis2.Constants.Configuration
                                                .HTTP_METHOD_POST +
                                        "\""));
                    }
                }
            }

            Boolean value = (Boolean) getBindingPropertyFromOperation(
                    WSDL2Constants.ATTR_WHTTP_IGNORE_UNCITED,
                    axisOperation.getName());
            if (value != null) {
                methodElement.appendChild(generateOptionParamComponent(doc,
                        "org.apache.axis2.description.WSDL2Constants.ATTR_WHTTP_IGNORE_UNCITED",
                        "\"" + value.booleanValue() +
                                "\""));
            }

            property = (String) getBindingPropertyFromOperation(WSDL2Constants.ATTR_WHTTP_CODE,
                    axisOperation.getName());
            if (property != null) {
                methodElement.appendChild(generateOptionParamComponent(doc,
                        "org.apache.axis2.description.WSDL2Constants.ATTR_WHTTP_CODE",
                        "\"" + property + "\""));
            }

            property = (String) getBindingPropertyFromOperation(
                    WSDL2Constants.ATTR_WHTTP_INPUT_SERIALIZATION,
                    axisOperation.getName());
            if (property != null) {
                methodElement.appendChild(generateOptionParamComponent(doc,
                        "org.apache.axis2.Constants.Configuration.CONTENT_TYPE",
                        "\"" + property + "\""));
                methodElement.appendChild(generateOptionParamComponent(doc,
                        "org.apache.axis2.Constants.Configuration.MESSAGE_TYPE",
                        "\"" + property + "\""));
            }

        }
        return methodElement;
    }

    /**
     * Returns a comma-separated list of the string representations of the array elements.
     * @param array the array to be processed
     * @return the empty string "" if array is null or empty, the array element if size is 1,
     * or a comma-separated list when size > 1.
     */
    private String arrayToString(Object[] array) {
        if (array == null || array.length == 0) {
            return "";
        }
        int size = array.length;
        if (size == 1) {
            return String.valueOf(array[0]);
        }
        StringBuffer result = new StringBuffer(String.valueOf(array[0]));
        for (int i=1; i<size; i++) {
            result.append(",");
            result.append(String.valueOf(array[i]));
        }
        return result.toString();
    }

    /**
     * Set the transfer coding property of the input message
     *
     * @param axisOperation
     * @param methodElement
     * @param doc
     */
    private void setTransferCoding(AxisOperation axisOperation, Element methodElement,
                                   Document doc) {
        // Add a optionParam element which holds the value of transferCoding
        String transferCoding =
                (String) getBindingPropertyFromMessage(WSDL2Constants.ATTR_WHTTP_CONTENT_ENCODING,
                        axisOperation.getName(),
                        WSDLConstants.WSDL_MESSAGE_DIRECTION_IN);
        if (!"".equals(transferCoding)) {
            if ("gzip".equals(transferCoding) || "compress".equals(transferCoding)) {
                methodElement.appendChild(generateOptionParamComponent(doc,
                        "org.apache.axis2.transport.http.HTTPConstants.MC_GZIP_REQUEST",
                        "true"));
            }
        }
    }

    /**
     * Set thttp header properties needed for the stub
     *
     * @param axisOperation
     * @param methodElement
     * @param doc
     */
    private void setHttpHeaderOptions(AxisOperation axisOperation, Element methodElement,
                                      Document doc) {
        // Add a optionParam elements here

    }

    // ==================================================================
    //                   Util Methods
    // ==================================================================

    protected Document getEmptyDocument() {
        try {
            DocumentBuilder documentBuilder =
                    DocumentBuilderFactory.newInstance().newDocumentBuilder();
            return documentBuilder.newDocument();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @param word
     * @return Returns character removed string.
     */
    protected String makeJavaClassName(String word) {
        if (JavaUtils.isJavaKeyword(word)) {
            return JavaUtils.makeNonJavaKeyword(word);
        } else {
            return JavaUtils.capitalizeFirstChar(JavaUtils.xmlNameToJava(word));
        }
    }

    /**
     * Utility method to add an attribute to a given element.
     *
     * @param document
     * @param AttribName
     * @param attribValue
     * @param element
     */
    protected void addAttribute(Document document, String AttribName, String attribValue,
                                Element element) {
        XSLTUtils.addAttribute(document, AttribName, attribValue, element);
    }

    /**
     * @param doc
     * @param rootElement
     */
    protected void fillSyncAttributes(Document doc, Element rootElement) {
        addAttribute(doc, "isAsync", this.codeGenConfiguration.isAsyncOn()
                ? "1"
                : "0", rootElement);
        addAttribute(doc, "isSync", this.codeGenConfiguration.isSyncOn()
                ? "1"
                : "0", rootElement);
    }

    /**
     * debugging method - write the output to the debugger
     *
     * @param description
     * @param doc
     */
    protected void debugLogDocument(String description, Document doc) {
        if (log.isDebugEnabled()) {
            try {
                DOMSource source = new DOMSource(doc);
                StringWriter swrite = new StringWriter();
                swrite.write(description);
                swrite.write("\n");
                Transformer transformer =
                        TransformerFactory.newInstance().newTransformer();
                transformer.setOutputProperty("omit-xml-declaration", "yes");
                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                transformer.transform(source, new StreamResult(swrite));

                log.debug(swrite.toString());

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Gets the output directory for source files.
     *
     * @param outputDir
     * @return Returns File.
     */
    protected File getOutputDirectory(File outputDir, String dir2) {
        if (dir2 != null && !"".equals(dir2)) {
            outputDir = new File(outputDir, dir2);
        }

        if (!outputDir.exists()) {//$NON-SEC-3
            outputDir.mkdirs();//$NON-SEC-2
        }


        return outputDir;
    }

    /**
     * A resusable method for the implementation of interface and implementation writing.
     *
     * @param model
     * @param writer
     * @throws java.io.IOException
     * @throws Exception
     */
    protected void writeFile(Document model, FileWriter writer) throws IOException, Exception {
        writer.loadTemplate();

        String packageName = model.getDocumentElement().getAttribute("package");
        String className = model.getDocumentElement().getAttribute("name");

        writer.createOutFile(packageName, className);

        // use the global resolver
        writer.parse(model, resolver);
    }

    /**
     * Adds the soap action
     *
     * @param doc
     * @param rootElement
     * @param qName
     */
    protected void addSOAPAction(Document doc, Element rootElement, QName qName) {
        addAttribute(doc, "soapaction",
                (String) getBindingPropertyFromOperation(WSDL2Constants.ATTR_WSOAP_ACTION,
                        qName),
                rootElement);
    }

    /**
     * Adds the output and fault actions
     *
     * @param doc
     * @param methodElement
     * @param operation
     */
    private void addOutputAndFaultActions(Document doc, Element methodElement,
                                          AxisOperation operation) {
        String outputAction = operation.getOutputAction();
        if (outputAction != null) {
            Element outputActionElt =
                    doc.createElement(org.apache.axis2.Constants.OUTPUT_ACTION_MAPPING);
            outputActionElt.setAttribute(AddressingConstants.WSA_ACTION, outputAction);
            methodElement.appendChild(outputActionElt);
        }

        String[] faultActionNames = operation.getFaultActionNames();
        if (faultActionNames != null) {
            for (int i = 0; i < faultActionNames.length; i++) {
                Element faultActionElt =
                        doc.createElement(org.apache.axis2.Constants.FAULT_ACTION_MAPPING);
                faultActionElt.setAttribute(org.apache.axis2.Constants.FAULT_ACTION_NAME,
                        faultActionNames[i]);
                faultActionElt.setAttribute(AddressingConstants.WSA_ACTION,
                        operation.getFaultAction(faultActionNames[i]));
                methodElement.appendChild(faultActionElt);
            }
        }
    }

    /**
     * populate the header parameters
     *
     * @param soapHeaderParameterQNameList
     * @param bindingOperation
     * @param input
     */
    protected void addHeaderOperations(List soapHeaderParameterQNameList,
                                       AxisBindingOperation bindingOperation,
                                       boolean input) {

        AxisOperation axisOperation = bindingOperation.getAxisOperation();
        ArrayList headerparamList = new ArrayList();
        String MEP = axisOperation.getMessageExchangePattern();
        if (input) {
            if (WSDLUtil.isInputPresentForMEP(MEP)) {

                headerparamList = (ArrayList) getBindingPropertyFromMessage(
                        WSDL2Constants.ATTR_WSOAP_HEADER, bindingOperation.getName(),
                        WSDLConstants.MESSAGE_LABEL_IN_VALUE);

            }
        } else {
            if (WSDLUtil.isOutputPresentForMEP(MEP)) {
                headerparamList = (ArrayList) getBindingPropertyFromMessage(
                        WSDL2Constants.ATTR_WSOAP_HEADER, bindingOperation.getName(),
                        WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
            }
        }
        if (headerparamList != null) {
            for (Iterator iterator = headerparamList.iterator(); iterator.hasNext();) {
                SOAPHeaderMessage header = (SOAPHeaderMessage) iterator.next();
                soapHeaderParameterQNameList.add(header);
            }
        }

    }

    /**
     * populate the header parameters to faults
     *
     * @param soapHeaderParameterQNameList
     * @param axisOperation
     */
    protected void addHeaderOperationsToFault(List soapHeaderParameterQNameList,
                                              AxisOperation axisOperation) {
        ArrayList headerparamList = new ArrayList();
        ArrayList faultMessages = axisOperation.getFaultMessages();
        Iterator iter = faultMessages.iterator();
        while (iter.hasNext()) {
            AxisMessage axisFaultMessage = (AxisMessage) iter.next();
            headerparamList.addAll((ArrayList) getBindingPropertyFromMessageFault(
                    WSDL2Constants.ATTR_WSOAP_HEADER, axisOperation.getName(),
                    axisFaultMessage.getName()));
        }

        if (headerparamList != null) {
            for (Iterator iterator = headerparamList.iterator(); iterator.hasNext();) {
                SOAPHeaderMessage header = (SOAPHeaderMessage) iterator.next();
                soapHeaderParameterQNameList.add(header.getElement());
            }
        }
    }


    /**
     * Get the input element
     *
     * @param doc
     * @param bindingOperation
     * @param headerParameterQNameList
     * @return DOM element
     */
    protected Element getInputElement(Document doc,
                                      AxisBindingOperation bindingOperation,
                                      List headerParameterQNameList) {
        AxisOperation operation = bindingOperation.getAxisOperation();
        Element inputElt = doc.createElement("input");
        String mep = operation.getMessageExchangePattern();

        if (WSDLUtil.isInputPresentForMEP(mep)) {

            Element[] param = getInputParamElement(doc, operation);
            for (int i = 0; i < param.length; i++) {
                inputElt.appendChild(param[i]);
            }

            List parameterElementList = getParameterElementList(doc, headerParameterQNameList,
                    WSDLConstants.SOAP_HEADER);
            parameterElementList.addAll(getParameterElementListForHttpHeader(doc,
                    (ArrayList) getBindingPropertyFromMessage(
                            WSDL2Constants.ATTR_WHTTP_HEADER,
                            operation.getName(),
                            WSDLConstants.WSDL_MESSAGE_DIRECTION_IN),
                    WSDLConstants.HTTP_HEADER));
            parameterElementList.addAll(getParameterElementListForSOAPModules(doc,
                    (ArrayList) getBindingPropertyFromMessage(
                            WSDL2Constants.ATTR_WSOAP_MODULE,
                            operation.getName(),
                            WSDLConstants.WSDL_MESSAGE_DIRECTION_IN)));

            for (int i = 0; i < parameterElementList.size(); i++) {
                inputElt.appendChild((Element) parameterElementList.get(i));
            }

            /*
            * Setting the effective policy of input message
            */
            Policy policy = getBindingPolicyFromMessage(bindingOperation,
                    WSDLConstants.MESSAGE_LABEL_IN_VALUE);

            if (policy != null) {
                try {
                    addAttribute(doc, "policy",
                            PolicyUtil.getSafeString(PolicyUtil.policyComponentToString(policy)),
                            inputElt);
                } catch (Exception ex) {
                    throw new RuntimeException("can't serialize the policy ..");
                }
            }

        }
        return inputElt;
    }

    /**
     * Get the fault element - No header faults are supported
     *
     * @param doc
     * @param operation
     */
    protected Element getFaultElement(Document doc, AxisOperation operation) {
        Element faultElt = doc.createElement("fault");
        Element[] param = getFaultParamElements(doc, operation);

        for (int i = 0; i < param.length; i++) {
            faultElt.appendChild(param[i]);
        }

        return faultElt;
    }

    /**
     * Finds the output element.
     *
     * @param doc
     * @param bindingOperation
     * @param headerParameterQNameList
     */
    protected Element getOutputElement(Document doc,
                                       AxisBindingOperation bindingOperation,
                                       List headerParameterQNameList) {
        AxisOperation operation = bindingOperation.getAxisOperation();
        Element outputElt = doc.createElement("output");
        String mep = operation.getMessageExchangePattern();


        if (WSDLUtil.isOutputPresentForMEP(mep)) {

            Element param = getOutputParamElement(doc, operation);

            if (param != null) {
                outputElt.appendChild(param);
            }

            List outputElementList = getParameterElementList(doc, headerParameterQNameList,
                    WSDLConstants.SOAP_HEADER);
            outputElementList.addAll(getParameterElementListForHttpHeader(doc,
                    (ArrayList) getBindingPropertyFromMessage(
                            WSDL2Constants.ATTR_WHTTP_HEADER,
                            operation.getName(),
                            WSDLConstants.WSDL_MESSAGE_DIRECTION_OUT),
                    WSDLConstants.HTTP_HEADER));

            for (int i = 0; i < outputElementList.size(); i++) {
                outputElt.appendChild((Element) outputElementList.get(i));
            }

            /*
            * Setting the effective policy for the output message.
            */
            Policy policy = getBindingPolicyFromMessage(bindingOperation,
                    WSDLConstants.MESSAGE_LABEL_OUT_VALUE);

            if (policy != null) {
                try {
                    addAttribute(doc, "policy",
                            PolicyUtil.getSafeString(PolicyUtil.policyComponentToString(policy)),
                            outputElt);
                } catch (Exception ex) {
                    throw new RuntimeException("can't serialize the policy ..");
                }
            }
        }
        return outputElt;
    }

    /**
     * @param doc
     * @param operation
     * @return Returns the parameter element.
     */
    protected Element[] getFaultParamElements(Document doc, AxisOperation operation) {
        ArrayList params = new ArrayList();
        ArrayList faultMessages = operation.getFaultMessages();

        if (faultMessages != null && !faultMessages.isEmpty()) {
            Element paramElement;
            AxisMessage msg;
            for (int i = 0; i < faultMessages.size(); i++) {
                paramElement = doc.createElement("param");
                msg = (AxisMessage) faultMessages.get(i);

                if (msg.getElementQName() == null) {
                    throw new RuntimeException("Element QName is null for " + msg.getName() + "!");
                }

                //as for the name of a fault, we generate an exception
                String faultComment = "";
                if (msg.getDocumentation() != null){
                    faultComment = msg.getDocumentation().trim();
                }
                addAttribute(doc, "comment", faultComment, paramElement);
                addAttribute(doc, "name",
                        (String) fullyQualifiedFaultClassNameMap.get(msg.getName()),
                        paramElement);
                addAttribute(doc, "shortName",
                        (String) faultClassNameMap.get(msg.getName()),
                        paramElement);

                // attach the namespace and the localName
                addAttribute(doc, "namespace",
                        msg.getElementQName().getNamespaceURI(),
                        paramElement);
                addAttribute(doc, "localname",
                        msg.getElementQName().getLocalPart(),
                        paramElement);

                if (msg.getElementQName() != null) {
                    Element qNameElement = doc.createElement("qname");
                    addAttribute(doc, "nsuri", msg.getElementQName().getNamespaceURI(), qNameElement);
                    addAttribute(doc, "localname", msg.getElementQName().getLocalPart(), qNameElement);
                    paramElement.appendChild(qNameElement);
                }
                //the type represents the type that will be wrapped by this
                //name
                String typeMapping =
                        this.mapper.getTypeMappingName(msg.getElementQName());
                addAttribute(doc, "type", (typeMapping == null)
                        ? ""
                        : typeMapping, paramElement);

                //add the short name
                addShortType(paramElement, (msg.getElementQName() == null) ? null :
                        msg.getElementQName().getLocalPart());

                String attribValue = (String) instantiatableMessageClassNames.
                        get(msg.getElementQName());
                addAttribute(doc, "instantiatableType",
                        attribValue == null ? "" : attribValue,
                        paramElement);

                // add an extra attribute to say whether the type mapping is
                // the default
                if (mapper.getDefaultMappingName().equals(typeMapping)) {
                    addAttribute(doc, "default", "yes", paramElement);
                }
                addAttribute(doc, "value", getParamInitializer(typeMapping),
                        paramElement);

                Iterator iter = msg.getExtensibilityAttributes().iterator();
                while (iter.hasNext()) {
                    // process extensibility attributes
                }
                params.add(paramElement);
            }

            return (Element[]) params.toArray(new Element[params.size()]);
        } else {
            return new Element[]{};//return empty array
        }


    }


    /**
     * @param doc
     * @param operation
     * @return Returns the parameter element.
     */
    protected Element[] getInputParamElement(Document doc, AxisOperation operation) {

        AxisMessage inputMessage = operation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
        List paramElementList = new ArrayList();
        if (inputMessage != null) {

            // This is the  wrapped component - add the type mapping
            Element mainParameter = generateParamComponent(doc,
                    this.mapper.getParameterName(
                            inputMessage.getElementQName()),
                    this.mapper.getTypeMappingName(
                            inputMessage.getElementQName()),
                    operation.getName(),
                    inputMessage.getElementQName(),
                    inputMessage.getPartName(),
                    false,false
            );

            paramElementList.add(mainParameter);

            //if the unwrapping or backWordCompatibility flag is on then we have to
            //put the element complex type if it exits
            if (this.codeGenConfiguration.isBackwordCompatibilityMode() ||
                    !this.codeGenConfiguration.isParametersWrapped()) {
                if (inputMessage.getParameter(Constants.COMPLEX_TYPE) != null) {
                    Parameter parameter = inputMessage.getParameter(Constants.COMPLEX_TYPE);
                    addAttribute(doc, "complextype", (String) parameter.getValue(), mainParameter);
                }
            }

            //added the unwapparameters attribute this is use full to unwrap if paramerters are
            //zero
            if (!this.codeGenConfiguration.isParametersWrapped()){
                addAttribute(doc, "unwrappParameters", "true", mainParameter);
            }

            // this message has been unwrapped - find the correct references of the
            // the message by looking at the unwrapped details object and attach the
            // needed parameters inside main parameter element
            if (inputMessage.getParameter(Constants.UNWRAPPED_KEY) != null) {

                //we have this unwrapped earlier. get the info holder
                //and then look at the parameters
                Parameter detailsParameter =
                        inputMessage.getParameter(Constants.UNWRAPPED_DETAILS);
                MessagePartInformationHolder infoHolder =
                        (MessagePartInformationHolder) detailsParameter.getValue();
                List partsList = infoHolder.getPartsList();
                wrapped_jaxws = true;
                //populate the parts list - this list is needed to generate multiple
                //parameters in the signatures
                for (int i = 0; i < partsList.size(); i++) {
                    QName qName = (QName) partsList.get(i);
                    mainParameter.appendChild(generateParamComponent(doc,
                            this.mapper.getParameterName(
                                    qName),
                            this.mapper.getTypeMappingName(
                                    qName),
                            operation.getName(),
                            qName,
                            qName.getLocalPart(),
                            (this.mapper
                                    .getTypeMappingStatus(
                                            qName) !=
                                    null),
                            Constants.ARRAY_TYPE.equals(
                                    this.mapper.getTypeMappingStatus(
                                            qName)))
                    );
                }


            }


        }

        return (Element[]) paramElementList.toArray(
                new Element[paramElementList.size()]);
    }

    /**
     * A convenient method for the generating the parameter element
     *
     * @param doc
     * @param paramName
     * @param paramType
     * @return DOM Element
     */
    protected Element generateParamComponent(Document doc,
                                             String paramName,
                                             String paramType,
                                             QName operationName,
                                             QName paramQName) {
        return generateParamComponent(doc, paramName, paramType, operationName, paramQName, null,
                false, false);
    }

    /**
     * A convenient method for the generating the parameter element
     *
     * @param doc
     * @param paramName
     * @param paramType
     * @return DOM Element
     */
    protected Element generateParamComponent(Document doc,
                                             String paramName,
                                             String paramType,
                                             QName paramQName) {
        return generateParamComponent(doc, paramName, paramType, null, paramQName, null, false,
                false);
    }

    /**
     * A convenient method for the generating optionParam components
     *
     * @param doc
     * @param name
     * @param value
     * @return Element
     */
    protected Element generateOptionParamComponent(Document doc, String name, String value) {

        Element optionParamElement = doc.createElement("optionParam");
        addAttribute(doc, "name", name, optionParamElement);
        addAttribute(doc, "value", value, optionParamElement);
        return optionParamElement;
    }

    /**
     * A convenient method for the generating the parameter element
     *
     * @param doc
     * @param paramName
     * @param paramType
     * @param opName
     * @param paramName
     */
    protected Element generateParamComponent(Document doc,
                                             String paramName,
                                             String paramType,
                                             QName opName,
                                             QName paramQName,
                                             String partName,
                                             boolean isPrimitive,
                                             boolean isArray) {
        Element paramElement = doc.createElement("param");
        addAttribute(doc, "name",
                paramName, paramElement);

        if (codeGenConfiguration.getOutputLanguage().equals("jax-ws") && useHolderClass_jaxws) {
            Class primitive = JavaUtils.getWrapperClass(paramType);
            if(primitive != null){
                paramType = primitive.getName();
            }
        }

        addAttribute(doc, "type",
                (paramType == null) ? "" : paramType,
                paramElement);

        //adds the short type
        addShortType(paramElement, (paramQName == null) ? null : paramQName.getLocalPart());

        // add an extra attribute to say whether the type mapping is the default
        if (mapper.getDefaultMappingName().equals(paramType)) {
            addAttribute(doc, "default", "yes", paramElement);
        }
        addAttribute(doc, "value", getParamInitializer(paramType), paramElement);
        // add this as a body parameter
        addAttribute(doc, "location", "body", paramElement);

        //if the opName and partName are present , add them
        if (opName != null) {
            String localPart = opName.getLocalPart();
            addAttribute(doc, "opname", JavaUtils.xmlNameToJava(localPart), paramElement);
        }

        if (paramQName != null) {
            Element qNameElement = doc.createElement("qname");
            addAttribute(doc, "nsuri", paramQName.getNamespaceURI(), qNameElement);
            addAttribute(doc, "localname", paramQName.getLocalPart(), qNameElement);
            paramElement.appendChild(qNameElement);
        }

        if (partName != null) {
            String javaName = null;
            if (JavaUtils.isJavaKeyword(partName)) {
                javaName = JavaUtils.makeNonJavaKeyword(partName);
            } else {
                if (codeGenConfiguration.getOutputLanguage().equals("jax-ws")) {
                    javaName = JavaUtils.xmlNameToJavaIdentifier(JavaUtils.xmlNameToJava(partName));
                } else {
                    javaName = JavaUtils.capitalizeFirstChar(JavaUtils.xmlNameToJava(partName));
                }
            }
            addAttribute(doc, "partname", javaName, paramElement);
        }

        if (isPrimitive) {
            addAttribute(doc, "primitive", "yes", paramElement);
        }

        if (isArray) {
            addAttribute(doc, "array", "yes", paramElement);
        }

        return paramElement;
    }

    /**
     * @param doc
     * @param operation
     * @return Returns Element.
     */
    protected Element   getOutputParamElement(Document doc, AxisOperation operation) {
        Element paramElement = doc.createElement("param");
        AxisMessage outputMessage = operation.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
        String typeMappingStr;
        String parameterName;

        if (outputMessage != null) {
            parameterName = this.mapper.getParameterName(outputMessage.getElementQName());
            String typeMapping = this.mapper.getTypeMappingName(outputMessage.getElementQName());
            typeMappingStr = (typeMapping == null)
                    ? ""
                    : typeMapping;
        } else {
            parameterName = "";
            typeMappingStr = "";
        }

        addAttribute(doc, "name", parameterName, paramElement);
        addAttribute(doc, "type", typeMappingStr, paramElement);

        //adds the short type
        addShortType(paramElement,
                (outputMessage.getElementQName() == null) ? null :
                        outputMessage.getElementQName().getLocalPart());

        // add an extra attribute to say whether the type mapping is the default
        if (mapper.getDefaultMappingName().equals(typeMappingStr)) {
            addAttribute(doc, "default", "yes", paramElement);
        }

        // add this as a body parameter
        addAttribute(doc, "location", "body", paramElement);
        String localPart = operation.getName().getLocalPart();
        addAttribute(doc, "opname", JavaUtils.xmlNameToJava(localPart), paramElement);

        //if the unwrapping or backWordCompatibility flag is on then we have to
        //put the element complex type if it exits
        if (this.codeGenConfiguration.isBackwordCompatibilityMode() ||
                !this.codeGenConfiguration.isParametersWrapped()) {
            if (outputMessage.getParameter(Constants.COMPLEX_TYPE) != null) {
                Parameter parameter = outputMessage.getParameter(Constants.COMPLEX_TYPE);
                addAttribute(doc, "complextype", (String) parameter.getValue(), paramElement);
            }
        }
        String partName = outputMessage.getPartName();
        if (partName != null && codeGenConfiguration.getOutputLanguage().equals("jax-ws")) {
            String javaName = null;
            if (JavaUtils.isJavaKeyword(partName)) {
                javaName = JavaUtils.makeNonJavaKeyword(partName);
            } else {
                javaName = JavaUtils.xmlNameToJavaIdentifier(JavaUtils.xmlNameToJava(partName));
            }
            addAttribute(doc, "partname", javaName, paramElement);
        }

        // this message has been unwrapped - find the correct references of the
        // the message by looking at the unwrapped details object and attach the
        // needed parameters inside main parameter element
        if (outputMessage.getParameter(Constants.UNWRAPPED_KEY) != null) {

            //we have this unwrapped earlier. get the info holder
            //and then look at the parameters
            Parameter detailsParameter =
                    outputMessage.getParameter(Constants.UNWRAPPED_DETAILS);
            MessagePartInformationHolder infoHolder =
                    (MessagePartInformationHolder) detailsParameter.getValue();
            List partsList = infoHolder.getPartsList();

            //populate the parts list - this list is needed to generate multiple
            //parameters in the signatures
            // in out put params we only intersted if there is only one parameter
            // otherwise we can not unwrap it.
            // this logic handles at the template level
             QName qName = null;
            for (Iterator iter = partsList.iterator(); iter.hasNext();) {
                qName = (QName) iter.next();
                paramElement.appendChild(generateParamComponent(doc,
                        this.mapper.getParameterName(qName),
                        this.mapper.getTypeMappingName(
                                qName),
                        operation.getName(),
                        qName,
                        qName.getLocalPart(),
                        (this.mapper.getTypeMappingStatus(
                                qName) != null),
                        Constants.ARRAY_TYPE.equals(
                                this.mapper.getTypeMappingStatus(
                                        qName)))
                );
            }

        }

        QName paramQName = outputMessage.getElementQName();
        if (paramQName != null) {
            Element qNameElement = doc.createElement("qname");
            addAttribute(doc, "nsuri", paramQName.getNamespaceURI(), qNameElement);
            addAttribute(doc, "localname", paramQName.getLocalPart(), qNameElement);
            paramElement.appendChild(qNameElement);
        }

        return paramElement;
    }

    /**
     * @param paramType
     */
    protected String getParamInitializer(String paramType) {

        // Look up paramType in the table
        String out = (String) constructorMap.get(paramType);

        if (out == null) {
            out = "null";
        }

        return out;
    }

    /**
     * @param doc
     * @param parameters
     * @param location
     */
    protected List getParameterElementList(Document doc, List parameters, String location) {
        List parameterElementList = new ArrayList();

        if ((parameters != null) && !parameters.isEmpty()) {
            int count = parameters.size();

            for (int i = 0; i < count; i++) {
                Element param = doc.createElement("param");
                SOAPHeaderMessage header = (SOAPHeaderMessage) parameters.get(i);
                QName name = header.getElement();

                addAttribute(doc, "name", this.mapper.getParameterName(name), param);

                String typeMapping = this.mapper.getTypeMappingName(name);
                String typeMappingStr = (typeMapping == null)
                        ? ""
                        : typeMapping;

                addAttribute(doc, "type", typeMappingStr, param);
                addAttribute(doc, "location", location, param);
                if (header.isMustUnderstand()) {
                    addAttribute(doc, "mustUnderstand", "true", param);
                }

                if (name != null) {
                    Element qNameElement = doc.createElement("qname");
                    addAttribute(doc, "nsuri", name.getNamespaceURI(), qNameElement);
                    addAttribute(doc, "localname", name.getLocalPart(), qNameElement);
                    param.appendChild(qNameElement);
                }
                parameterElementList.add(param);
            }
        }
        return parameterElementList;
    }


    protected List getParameterElementListForHttpHeader(Document doc, List parameters,
                                                        String location) {


        List parameterElementList = new ArrayList();

        if ((parameters != null) && !parameters.isEmpty()) {
            int count = parameters.size();

            for (int i = 0; i < count; i++) {
                Element param = doc.createElement("param");
                HTTPHeaderMessage httpHeaderMessage = (HTTPHeaderMessage) parameters.get(i);
                QName qName = httpHeaderMessage.getqName();
                String name = httpHeaderMessage.getName();

                // use name as the name attribute of the parameter
                addAttribute(doc, "name", JavaUtils.xmlNameToJavaIdentifier(name), param);
                // header name is to set the header value
                addAttribute(doc, "headername", name, param);

                String typeMapping = this.mapper.getTypeMappingName(qName);
                String typeMappingStr = (typeMapping == null)
                        ? ""
                        : typeMapping;

                addAttribute(doc, "type", typeMappingStr, param);
                addAttribute(doc, "location", location, param);
                parameterElementList.add(param);
            }
        }

        return parameterElementList;
    }

    protected List getParameterElementListForSOAPModules(Document doc, List parameters) {

        List parameterElementList = new ArrayList();

        if ((parameters != null) && !parameters.isEmpty()) {
            int count = parameters.size();

            for (int i = 0; i < count; i++) {
                Element param = doc.createElement("param");
                SOAPModuleMessage soapModuleMessage = (SOAPModuleMessage) parameters.get(i);

                // header name is to set the header value
                addAttribute(doc, "uri", soapModuleMessage.getUri(), param);

                addAttribute(doc, "location", "wsoap_module", param);
                parameterElementList.add(param);
            }
        }

        return parameterElementList;
    }

    /**
     * Utility method to add an attribute to a given element.
     *
     * @param document
     * @param eltName
     * @param eltValue
     * @param element
     */
    protected Element addElement(Document document, String eltName, String eltValue,
                                 Element element) {
        Element elt = XSLTUtils.addChildElement(document, eltName, element);
        if (eltValue != null) {
            elt.appendChild(document.createTextNode(eltValue));
        }
        return elt;
    }


}
