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

import org.apache.axis2.AxisFault;
import org.apache.axis2.description.AxisMessage;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.wsdl.SOAPHeaderMessage;
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.extension.JiBXExtension;
import org.apache.axis2.wsdl.databinding.JavaTypeMapper;
import org.apache.axis2.wsdl.util.Constants;
import org.apache.axis2.wsdl.util.MessagePartInformationHolder;
import org.apache.ws.commons.schema.XmlSchemaComplexType;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaObjectCollection;
import org.apache.ws.commons.schema.XmlSchemaParticle;
import org.apache.ws.commons.schema.XmlSchemaSequence;
import org.apache.ws.commons.schema.XmlSchemaSimpleType;
import org.apache.ws.commons.schema.XmlSchemaSimpleTypeContent;
import org.apache.ws.commons.schema.XmlSchemaSimpleTypeRestriction;
import org.apache.ws.commons.schema.XmlSchemaType;
import org.jibx.binding.model.BindingElement;
import org.jibx.binding.model.ElementBase;
import org.jibx.binding.model.FormatElement;
import org.jibx.binding.model.IncludeElement;
import org.jibx.binding.model.MappingElementBase;
import org.jibx.binding.model.ModelVisitor;
import org.jibx.binding.model.NamespaceElement;
import org.jibx.binding.model.ValidationContext;
import org.jibx.binding.model.ValidationProblem;
import org.jibx.runtime.JiBXException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Framework-linked code used by JiBX data binding support. This is accessed via reflection from the
 * JiBX code generation extension when JiBX data binding is selected. JiBX uses a different approach
 * to unwrapping method parameters from that implemented by ADB, and since the ADB technique is
 * assumed by all code generation templates this has to create the same data structures. These data
 * structures are undocumented, and can only be determined by going through the {@link
 * org.apache.axis2.wsdl.codegen.extension.SchemaUnwrapperExtension} and {@link
 * org.apache.axis2.wsdl.codegen.emitter.AxisServiceBasedMultiLanguageEmitter} code.
 */
public class CodeGenerationUtility {
    private static final String SCHEMA_NAMESPACE = "http://www.w3.org/2001/XMLSchema";

    private final CodeGenConfiguration codeGenConfig;

    private static HashSet s_primitiveSet = new HashSet();

    static {
        s_primitiveSet.add("boolean");
        s_primitiveSet.add("byte");
        s_primitiveSet.add("char");
        s_primitiveSet.add("double");
        s_primitiveSet.add("float");
        s_primitiveSet.add("int");
        s_primitiveSet.add("long");
        s_primitiveSet.add("short");
        s_primitiveSet.add("void");
    }

    private static HashMap s_wrapperMap = new HashMap();

    static {
        s_wrapperMap.put("boolean", "Boolean");
        s_wrapperMap.put("byte", "Byte");
        s_wrapperMap.put("char", "Character");
        s_wrapperMap.put("double", "Double");
        s_wrapperMap.put("float", "Float");
        s_wrapperMap.put("int", "Integer");
        s_wrapperMap.put("long", "Long");
        s_wrapperMap.put("short", "Short");
    }

    /** Reserved words for Java (keywords and literals). */
    private static final HashSet s_reservedWords = new HashSet();

    static {

        // keywords
        s_reservedWords.add("abstract");
        s_reservedWords.add("assert");
        s_reservedWords.add("boolean");
        s_reservedWords.add("break");
        s_reservedWords.add("byte");
        s_reservedWords.add("case");
        s_reservedWords.add("catch");
        s_reservedWords.add("char");
        s_reservedWords.add("class");
        s_reservedWords.add("const");
        s_reservedWords.add("continue");

        s_reservedWords.add("default");
        s_reservedWords.add("do");
        s_reservedWords.add("double");
        s_reservedWords.add("else");
        s_reservedWords.add("enum");
        s_reservedWords.add("extends");
        s_reservedWords.add("final");
        s_reservedWords.add("finally");
        s_reservedWords.add("float");
        s_reservedWords.add("for");
        s_reservedWords.add("goto");

        s_reservedWords.add("if");
        s_reservedWords.add("implements");
        s_reservedWords.add("import");
        s_reservedWords.add("instanceof");
        s_reservedWords.add("int");
        s_reservedWords.add("interface");
        s_reservedWords.add("long");
        s_reservedWords.add("native");
        s_reservedWords.add("new");
        s_reservedWords.add("package");

        s_reservedWords.add("private");
        s_reservedWords.add("protected");
        s_reservedWords.add("public");
        s_reservedWords.add("return");
        s_reservedWords.add("short");
        s_reservedWords.add("static");
        s_reservedWords.add("strictfp");
        s_reservedWords.add("super");
        s_reservedWords.add("switch");
        s_reservedWords.add("synchronized");

        s_reservedWords.add("this");
        s_reservedWords.add("throw");
        s_reservedWords.add("throws");
        s_reservedWords.add("transient");
        s_reservedWords.add("try");
        s_reservedWords.add("void");
        s_reservedWords.add("volatile");
        s_reservedWords.add("while");

        // literals
        s_reservedWords.add("true");
        s_reservedWords.add("false");
        s_reservedWords.add("null");

        // variable names used by template unwrapped code generation
        // TODO change templates to use $xxx names, block generation from WSDL
        s_reservedWords.add("true");
        s_reservedWords.add("uctx");
        s_reservedWords.add("child");
        s_reservedWords.add("wrapper");
    }

    /**
     * Constructor.
     *
     * @param config code generation configuration
     */
    public CodeGenerationUtility(CodeGenConfiguration config) {
        codeGenConfig = config;
    }

    /**
     * Configure the code generation based on the supplied parameters and WSDL. This first gets type
     * mappings from binding definition, then goes through the operations checking the input and
     * output messages. If unwrapping is disabled the message element must be handled directly by a
     * mapping. If unwrapping is enabled, this checks that the message element is of the proper form
     * (a sequence of other elements, which all have maxOccurs="1"). It then generates an unwrapping
     * description and adds it to the code generation configuration, where it'll be picked up and
     * included in the XML passed to code generation. This also constructs a type mapping, since
     * that's required by the base Axis2 code generation. In the case of unwrapped elements, the
     * type mapping includes a synthesized qname for each unwrapped parameter, and the detailed
     * information is set on the message information. Sound confusing? Welcome to Axis2 code
     * generation.
     *
     * @param path binding path (<code>null</code> if none)
     */
    public void engage(String path) {

        // make sure the binding definition file is present, if passed
        File file = null;
        if (path != null) {
            file = new File(path);
            if (!file.exists()) {
                throw new RuntimeException("jibx binding definition file " + path + " not found");
            }
        }
        try {

            // set flag for unwrapping
            boolean unwrap = !codeGenConfig.isParametersWrapped();

            // initialize the binding information
            BindingElement binding = null;
            if (file == null) {

                // unwrapped can be used without a binding, but wrapped requires one
                if (!unwrap) {
                    throw new RuntimeException(
                            "JiBX wrapped support requires a binding definition to be provided using the -E" +
                                    JiBXExtension.BINDING_PATH_OPTION + " {file-path} parameter");
                }

            } else {

                // Read the JiBX binding definition into memory. The binding definition
                // is only prevalidated so as not to require the user to have all
                // the referenced classes in the classpath, though this does make for
                // added work in finding the namespaces.
                ValidationContext vctx = BindingElement.newValidationContext();
                binding = BindingElement.readBinding(new FileInputStream(file), path, vctx);
                binding.setBaseUrl(file.toURL());
                vctx.setBindingRoot(binding);
                IncludePrevalidationVisitor ipv = new IncludePrevalidationVisitor(vctx);
                vctx.tourTree(binding, ipv);
                if (vctx.getErrorCount() != 0 || vctx.getFatalCount() != 0) {
                    ArrayList probs = vctx.getProblems();
                    System.err.println("Errors in generated binding:");
                    for (int j = 0; j < probs.size(); j++) {
                        ValidationProblem prob = (ValidationProblem)probs.get(j);
                        System.err.print(prob.getSeverity() >=
                                ValidationProblem.ERROR_LEVEL ? "Error: " : "Warning: ");
                        System.err.println(prob.getDescription());
                    }
                    throw new RuntimeException("invalid jibx binding definition file " + path);
                }
            }

            // create table with all built-in format definitions
            Map simpleTypeMap = new HashMap();
            buildFormat("byte", "byte",
                        "org.jibx.runtime.Utility.serializeByte",
                        "org.jibx.runtime.Utility.parseByte", "0", simpleTypeMap);
            buildFormat("unsignedShort", "char",
                        "org.jibx.runtime.Utility.serializeChar",
                        "org.jibx.runtime.Utility.parseChar", "0", simpleTypeMap);
            buildFormat("double", "double",
                        "org.jibx.runtime.Utility.serializeDouble",
                        "org.jibx.runtime.Utility.parseDouble", "0.0", simpleTypeMap);
            buildFormat("float", "float",
                        "org.jibx.runtime.Utility.serializeFloat",
                        "org.jibx.runtime.Utility.parseFloat", "0.0", simpleTypeMap);
            buildFormat("int", "int",
                        "org.jibx.runtime.Utility.serializeInt",
                        "org.jibx.runtime.Utility.parseInt", "0", simpleTypeMap);
            buildFormat("long", "long",
                        "org.jibx.runtime.Utility.serializeLong",
                        "org.jibx.runtime.Utility.parseLong", "0", simpleTypeMap);
            buildFormat("short", "short",
                        "org.jibx.runtime.Utility.serializeShort",
                        "org.jibx.runtime.Utility.parseShort", "0", simpleTypeMap);
            buildFormat("boolean", "boolean",
                        "org.jibx.runtime.Utility.serializeBoolean",
                        "org.jibx.runtime.Utility.parseBoolean", "false",
                        simpleTypeMap);
            buildFormat("dateTime", "java.util.Date",
                        "org.jibx.runtime.Utility.serializeDateTime",
                        "org.jibx.runtime.Utility.deserializeDateTime", null,
                        simpleTypeMap);
            buildFormat("date", "java.sql.Date",
                        "org.jibx.runtime.Utility.serializeSqlDate",
                        "org.jibx.runtime.Utility.deserializeSqlDate", null,
                        simpleTypeMap);
            buildFormat("time", "java.sql.Time",
                        "org.jibx.runtime.Utility.serializeSqlTime",
                        "org.jibx.runtime.Utility.deserializeSqlTime", null,
                        simpleTypeMap);
            buildFormat("base64Binary", "byte[]",
                        "org.jibx.runtime.Utility.serializeBase64",
                        "org.jibx.runtime.Utility.deserializeBase64", null,
                        simpleTypeMap);
            buildFormat("string", "java.lang.String", null, null, null,
                        simpleTypeMap);

            // collect all the top-level mapping and format definitions
            Map elementMap = new HashMap();
            Map complexTypeMap = new HashMap();
            Map bindingMap = new HashMap();
            if (binding != null) {
                collectTopLevelComponents(binding, "", elementMap,
                                          complexTypeMap, simpleTypeMap, bindingMap);
            }

            // make sure classes will be generated for abstract mappings
            if (unwrap && complexTypeMap.size() > 0 && (binding == null || !binding.isForceClasses())) {
                throw new RuntimeException(
                        "unwrapped binding must use force-classes='true' option in " + path);
            }

            // force off inappropriate option (set by error in options handling)
            codeGenConfig.setPackClasses(false);

            // configure handling for all operations of service
            codeGenConfig.setTypeMapper(new NamedParameterTypeMapper());
            Iterator operations = codeGenConfig.getAxisService().getOperations();
            Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            int opindex = 0;
            Map typeMappedClassMap = new HashMap();
            String mappedclass = null;
            Set objins = new HashSet();
            Set objouts = new HashSet();
            Set objfaults = new HashSet();
            Map nsMap = new HashMap();
            ArrayList wrappers = new ArrayList();
            while (operations.hasNext()) {

                // get the basic operation information
                AxisOperation op = (AxisOperation)operations.next();
                String mep = op.getMessageExchangePattern();
                AxisMessage inmsg = null;
                AxisMessage outmsg = null;
                if (WSDLUtil.isInputPresentForMEP(mep)) {
                    inmsg = op.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
                    if (inmsg == null) {
                        throw new RuntimeException(
                                "Expected input message not found for operation " + op.getName());
                    }
                    ArrayList headers = inmsg.getSoapHeaders();
                    for (int i = 0; i < headers.size(); i++) {
                        SOAPHeaderMessage header = (SOAPHeaderMessage)headers.get(i);
                        String cname = mapMessage(header, elementMap);
                        objins.add(cname);
                        if (mappedclass == null && isLookupClass(cname)) {
                            mappedclass = cname;
                        }
                    }
                }
                if (WSDLUtil.isOutputPresentForMEP(mep)) {
                    outmsg = op.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
                    if (outmsg == null) {
                        throw new RuntimeException(
                                "Expected output message not found for operation " + op.getName());
                    }
                    ArrayList headers = outmsg.getSoapHeaders();
                    for (int i = 0; i < headers.size(); i++) {
                        SOAPHeaderMessage header = (SOAPHeaderMessage)headers.get(i);
                        String cname = mapMessage(header, elementMap);
                        objouts.add(cname);
                        if (mappedclass == null && isLookupClass(cname)) {
                            mappedclass = cname;
                        }
                    }
                }
                if (unwrap) {

                    // use unwrapping for both input and output
                    String receivername = "jibxReceiver" + opindex++;
                    Element dbmethod = doc.createElement("dbmethod");
                    dbmethod.setAttribute("receiver-name", receivername);
                    dbmethod.setAttribute("method-name", op.getName().getLocalPart());
                    Set nameset = new HashSet(s_reservedWords);
                    if (inmsg != null) {
                        Element wrapper = unwrapMessage(inmsg, false, simpleTypeMap, elementMap,
                                                        complexTypeMap, typeMappedClassMap,
                                                        bindingMap, nameset, nsMap, doc);
                        dbmethod.appendChild(wrapper);
                        wrappers.add(wrapper);
                    }
                    if (outmsg != null) {
                        Element wrapper = unwrapMessage(outmsg, true, simpleTypeMap, elementMap,
                                                        complexTypeMap, typeMappedClassMap,
                                                        bindingMap, nameset, nsMap, doc);
                        dbmethod.appendChild(wrapper);
                        wrappers.add(wrapper);
                    }

                    // save unwrapping information for use in code generation
                    op.addParameter(
                            new Parameter(Constants.DATABINDING_GENERATED_RECEIVER, receivername));
                    op.addParameter(new Parameter(Constants.DATABINDING_GENERATED_IMPLEMENTATION,
                                                  Boolean.TRUE));
                    op.addParameter(
                            new Parameter(Constants.DATABINDING_OPERATION_DETAILS, dbmethod));

                } else {

                    // concrete mappings, just save the mapped class name(s)
                    if (inmsg != null) {
                        String cname = mapMessage(inmsg, elementMap);
                        objins.add(cname);
                        if (mappedclass == null && isLookupClass(cname)) {
                            mappedclass = cname;
                        }
                    }
                    if (outmsg != null) {
                        String cname = mapMessage(outmsg, elementMap);
                        objouts.add(cname);
                        if (mappedclass == null && isLookupClass(cname)) {
                            mappedclass = cname;
                        }
                    }

                }

                // always handle faults as wrapped
                for (Iterator iter = op.getFaultMessages().iterator(); iter.hasNext();) {
                    String cname = mapMessage((AxisMessage)iter.next(), elementMap);
                    objfaults.add(cname);
                    if (mappedclass == null && isLookupClass(cname)) {
                        mappedclass = cname;
                    }
                }
            }

            // check for default namespace usage within bindings or wrappers
            //  (meaning we can't declare a conflicting default namespace)
            Collection prefixes = nsMap.values();
            boolean dfltns = prefixes.contains("");
            boolean wrapdflt = false;
            if (!dfltns) {
                for (int i = 0; i < wrappers.size(); i++) {
                    Element wrapper = (Element)wrappers.get(i);
                    if ("true".equals(wrapper.getAttribute("uses-default"))) {
                        wrapdflt = true;
                        break;
                    }
                }
            }

            // find a prefix that we can use where needed for extra namespace
            String xtrapref = "";
            if (dfltns || wrapdflt) {
                xtrapref = "_";
                int index = 0;
                while (prefixes.contains(xtrapref)) {
                    xtrapref = "_" + index++;
                }
            }

            // for each wrapper (input and output), determine what additional
            //  namespaces need to be declared, what prefix is to be used for
            //  the wrapper element, and what prefix to be used for each child
            //  element
            for (int i = 0; i < wrappers.size(); i++) {
                Element wrapper = (Element)wrappers.get(i);
                boolean addns = false;
                String ns = wrapper.getAttribute("ns");
                String prefix = "";
                if ("true".equals(wrapper.getAttribute("need-namespaces"))) {

                    // check extra definition needed for wrapper namespace
                    if (!"".equals(ns)) {
                        if (dfltns || wrapdflt) {

                            // need a namespace, can't be default, get or set it
                            prefix = (String)nsMap.get(ns);
                            if (prefix == null) {
                                prefix = xtrapref;
                                addns = true;
                            }

                        } else {

                            // just make the wrapper namespace the default
                            prefix = "";
                            addns = true;

                        }
                    }
                    wrapper.setAttribute("prefix", prefix);

                    // set prefixes for child elements of wrapper
                    Node node = wrapper.getFirstChild();
                    while (node != null) {
                        if (node.getNodeType() == Node.ELEMENT_NODE) {
                            Element element = (Element)node;
                            String lname = element.getNodeName();
                            if ("parameter-element".equals(lname) || "return-element".equals(lname))
                            {
                                String childns = element.getAttribute("ns");
                                if ("".equals(childns)) {
                                    element.setAttribute("prefix", "");
                                } else if (ns.equals(childns)) {
                                    element.setAttribute("prefix", prefix);
                                } else {
                                    String childprefix = (String)nsMap.get(childns);
                                    if (childprefix == null) {
                                        throw new RuntimeException("Unable to set namespace " +
                                                childns + " for child element");
                                    }
                                    element.setAttribute("prefix", childprefix);
                                }
                            }
                        }
                        node = node.getNextSibling();
                    }

                } else {

                    // check extra definition needed for wrapper namespace
                    if (!"".equals(ns)) {

                        // just make the wrapper namespace the default
                        prefix = "";
                        addns = true;

                    }
                    wrapper.setAttribute("prefix", prefix);

                    // set prefixes for child elements of wrapper
                    Node node = wrapper.getFirstChild();
                    while (node != null) {
                        if (node.getNodeType() == Node.ELEMENT_NODE) {
                            Element element = (Element)node;
                            String lname = element.getNodeName();
                            if ("parameter-element".equals(lname) || "return-element".equals(lname))
                            {
                                String childns = element.getAttribute("ns");
                                if ("".equals(childns)) {
                                    element.setAttribute("prefix", "");
                                } else if (ns.equals(childns)) {
                                    element.setAttribute("prefix", prefix);
                                } else {
                                    throw new RuntimeException("Unable to set namespace " +
                                            childns + " for child element");
                                }
                            }
                        }
                        node = node.getNextSibling();
                    }

                }
                if (addns) {
                    Element addedns = doc.createElement("extra-namespace");
                    addedns.setAttribute("ns", ns);
                    addedns.setAttribute("prefix", prefix);
                    wrapper.appendChild(addedns);
                }
            }

            // add type usage information for binding initialization
            List details = new ArrayList();
            Element bindinit = doc.createElement("initialize-binding");
            if (!typeMappedClassMap.isEmpty()) {
                for (Iterator iter = typeMappedClassMap.keySet().iterator(); iter.hasNext();) {
                    QName tname = (QName)iter.next();
                    String clsindex = ((Integer)typeMappedClassMap.get(tname)).toString();
                    Element detail = doc.createElement("abstract-type");
                    detail.setAttribute("ns", tname.getNamespaceURI());
                    detail.setAttribute("name", tname.getLocalPart());
                    detail.setAttribute("type-index", clsindex);
                    bindinit.appendChild(detail);
                    if (mappedclass == null) {
                        MappingElementBase mapping = (MappingElementBase)complexTypeMap.get(tname);
                        mappedclass = mapping.getClassName();
                    }
                }
            }

            // set binding lookup parameters
            if (binding != null && binding.getName() != null && binding.getTargetPackage() != null) {
                bindinit.setAttribute("binding-name", binding.getName());
                bindinit.setAttribute("binding-package", binding.getTargetPackage());
            } else {
                if (mappedclass == null) {
                    mappedclass = "";
                }
                bindinit.setAttribute("bound-class", mappedclass);
            }

            // include binding namespaces in initialization data
            for (Iterator iter = nsMap.keySet().iterator(); iter.hasNext();) {
                String ns = (String)iter.next();
                String prefix = (String)nsMap.get(ns);
                Element detail = doc.createElement("binding-namespace");
                detail.setAttribute("ns", ns);
                detail.setAttribute("prefix", prefix);
                bindinit.appendChild(detail);
            }
            details.add(bindinit);

            // add details for all objects used as inputs/outputs/faults
            for (Iterator iter = objins.iterator(); iter.hasNext();) {
                String classname = (String)iter.next();
                Element detail = doc.createElement("object-input");
                detail.setAttribute("type", classname);
                details.add(detail);
            }
            for (Iterator iter = objouts.iterator(); iter.hasNext();) {
                String classname = (String)iter.next();
                Element detail = doc.createElement("object-output");
                detail.setAttribute("type", classname);
                details.add(detail);
            }
            for (Iterator iter = objfaults.iterator(); iter.hasNext();) {
                String classname = (String)iter.next();
                Element detail = doc.createElement("object-fault");
                detail.setAttribute("type", classname);
                details.add(detail);
            }
            codeGenConfig.getAxisService()
                    .addParameter(new Parameter(Constants.DATABINDING_SERVICE_DETAILS, details));

        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (JiBXException e) {
            throw new RuntimeException(e);
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        } catch (AxisFault e) {
            throw new RuntimeException(e);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Check if a class is potentially usable for looking up binding information.
     *
     * @param type fully-qualified type name
     * @return <code>true</code> if potentially usable, <code>false</code> if not
     */
    private static boolean isLookupClass(String type) {
        return !type.startsWith("java.") && !type.startsWith("javax.") &&
                !type.startsWith("org.w3c.");
    }

    /**
     * Add format definition for type with built-in JiBX handling to map.
     *
     * @param stype schema type name
     * @param jtype java type name
     * @param sname serializer method name
     * @param dname deserializer method name
     * @param dflt  default value
     * @param map   schema type qname to format definition map
     */
    private static void buildFormat(String stype, String jtype, String sname,
                                    String dname, String dflt, Map map) {
        FormatElement format = new FormatElement();
        format.setTypeName(jtype);
        format.setSerializerName(sname);
        format.setDeserializerName(dname);
        format.setDefaultText(dflt);
        map.put(new QName(SCHEMA_NAMESPACE, stype), format);
    }

    /**
     * Handles unwrapping a message. This generates and returns the detailed description of how the
     * message is to be unwrapped. It also creates the data structures expected by the code
     * generation in order to be somewhat compatible with ADB unwrapping.
     *
     * @param msg                message to be unwrapped
     * @param isout              output message flag (wrapper inherits inner type, for XSLTs)
     * @param simpleTypeMap      binding formats
     * @param elementMap         map from element names to concrete mapping components of binding
     * @param complexTypeMap     binding mappings
     * @param typeMappedClassMap map from type qname to index
     * @param bindingMap         map from mapping components to containing binding definition
     * @param nameset            parameter variable names used in method
     * @param nsmap              mapr from URI to prefix for namespaces to be defined on wrapper
     *                           element
     * @param doc                document used for DOM components
     * @return detailed description element for code generation
     */
    private Element unwrapMessage(AxisMessage msg, boolean isout,
                                  Map simpleTypeMap, Map elementMap, Map complexTypeMap, Map typeMappedClassMap,
                                  Map bindingMap, Set nameset, Map nsmap, Document doc) {

        // find the schema definition for this message element
        QName qname = msg.getElementQName();
        if (qname == null) {
            throw new RuntimeException("No element reference in message " + msg.getName());
        }
        XmlSchemaElement wrapdef = codeGenConfig.getAxisService().getSchemaElement(qname);
        if (wrapdef == null) {
            throw new RuntimeException("Cannot unwrap - no definition found for element " + qname);
        }
        XmlSchemaType type = wrapdef.getSchemaType();

        // create document to hold data binding details for element
        Element wrapdetail = doc.createElement(isout ? "out-wrapper" : "in-wrapper");
        wrapdetail.setAttribute("ns", qname.getNamespaceURI());
        wrapdetail.setAttribute("name", qname.getLocalPart());

        // dig down to the complexType particle
        List partNameList = new ArrayList();
        String wrappertype = "";
        boolean nons = qname.getNamespaceURI().length() == 0;
        boolean dfltns = false;
        boolean complex = false;
        if (type instanceof XmlSchemaComplexType) {
            XmlSchemaComplexType ctype = (XmlSchemaComplexType)type;
            if (ctype.getAttributes().getCount() != 0) {
                throw new RuntimeException("Cannot unwrap element " +
                        qname + ": attributes not allowed on type to be unwrapped");
            }
            XmlSchemaParticle particle = ctype.getParticle();
            if (particle != null) {

                // if there's a particle present, it must be a sequence
                if (!(particle instanceof XmlSchemaSequence)) {
                    throw new RuntimeException("Cannot unwrap element " +
                            qname + ": type to be unwrapped must be a sequence");
                }
                if (particle.getMinOccurs() != 1 || particle.getMaxOccurs() != 1) {
                    throw new RuntimeException("Cannot unwrap element " +
                            qname +
                            ": contained sequence must have minOccurs='1' and maxOccurs='1'");
                }
                XmlSchemaSequence sequence = (XmlSchemaSequence)particle;

                // add child param element matching each child of wrapper element
                QName opName = msg.getAxisOperation().getName();
                XmlSchemaObjectCollection items = sequence.getItems();
                boolean first = true;
                for (Iterator iter = items.getIterator(); iter.hasNext();) {

                    // check that child item obeys the unwrapping rules
                    XmlSchemaParticle item = (XmlSchemaParticle)iter.next();
                    if (!(item instanceof XmlSchemaElement)) {
                        throw new RuntimeException("Cannot unwrap element " +
                                qname + ": only element items allowed in sequence");
                    }
                    XmlSchemaElement element = (XmlSchemaElement)item;
                    QName refname = element.getRefName();
                    QName typename = element.getSchemaTypeName();
                    if (refname == null && typename == null) {
                        throw new RuntimeException("Cannot unwrap element " +
                                qname +
                                ": all elements in contained sequence must be element references or reference a named type");
                    }
                    if (first) {
                        first = false;
                    } else if (isout) {
                        throw new RuntimeException("Cannot unwrap element " +
                                qname +
                                ": only one child element allowed in sequence for wrapped output");
                    }

                    // add element to output with details of this element handling
                    Element param =
                            doc.createElement(isout ? "return-element" : "parameter-element");
                    QName itemname = (refname == null) ? element.getQName() : refname;
                    nons = nons || itemname.getNamespaceURI().length() == 0;
                    param.setAttribute("ns", itemname.getNamespaceURI());
                    param.setAttribute("name", itemname.getLocalPart());
                    String javaname = toJavaName(itemname.getLocalPart(), nameset);
                    param.setAttribute("java-name", javaname);
                    param.setAttribute("nillable", Boolean.toString(element.isNillable()));
                    boolean optional = element.getMinOccurs() == 0;
                    param.setAttribute("optional", Boolean.toString(optional));
                    boolean isarray = element.getMaxOccurs() > 1;
                    param.setAttribute("array", Boolean.toString(isarray));
                    String javatype;
                    String createtype = null;
                    if (element.getSchemaType() instanceof XmlSchemaSimpleType) {

                        // simple type translates to format element in binding
                        FormatElement format = (FormatElement)simpleTypeMap.get(typename);
                        if (format == null) {
                            
                            // check for restriction with simple base, and treat as base if so
                            XmlSchemaSimpleType stype = (XmlSchemaSimpleType)element.getSchemaType();
                            XmlSchemaSimpleTypeContent content = stype.getContent();
                            if (content instanceof XmlSchemaSimpleTypeRestriction) {
                                QName tname = ((XmlSchemaSimpleTypeRestriction)content).getBaseTypeName();
                                if (SCHEMA_NAMESPACE.equals(tname.getNamespaceURI())) {
                                    format = (FormatElement)simpleTypeMap.get(tname);
                                    if (format != null) {
                                        typename = tname;
                                    }
                                }
                            }
                        }
                        if (format == null) {
                            throw new RuntimeException("Cannot unwrap element " +
                                qname + ": no format definition found for type " +
                                typename + " (used by element " + itemname + ')');
                        }
                        javatype = format.getTypeName();
                        param.setAttribute("form", "simple");
                        param.setAttribute("serializer", format.getSerializerName());
                        param.setAttribute("deserializer", format.getDeserializerName());

                        // convert primitive types to wrapper types for nillable
                        if ((optional || element.isNillable()) &&
                                s_wrapperMap.containsKey(javatype)) {
                            param.setAttribute("wrapped-primitive", "true");
                            param.setAttribute("value-method", javatype + "Value");
                            javatype = (String)s_wrapperMap.get(javatype);
                        } else {
                            param.setAttribute("wrapped-primitive", "false");
                            String dflt = element.getDefaultValue();
                            if (dflt == null) {
                                dflt = format.getDefaultText();
                                if (javatype.equals("float")) {
                                    dflt = dflt + 'F';
                                }
                            }
                            if (dflt != null) {
                                param.setAttribute("default", dflt);
                            }
                        }

                    } else {
                        
                        // conversion must be defined by mapping
                        MappingElementBase mapping;
                        if (refname == null) {

                            // complex type reference translates to abstract mapping in binding
                            mapping = (MappingElementBase)complexTypeMap.get(typename);
                            if (mapping == null) {
                                throw new RuntimeException("Cannot unwrap element " +
                                        qname + ": no abstract mapping definition found for type " +
                                        typename + " (used by element " + itemname + ')');
                            }
                            Integer tindex = (Integer)typeMappedClassMap.get(typename);
                            if (tindex == null) {
                                tindex = new Integer(typeMappedClassMap.size());
                                typeMappedClassMap.put(typename, tindex);
                            }
                            param.setAttribute("type-index", tindex.toString());
                            
                        } else {
                            
                            // element reference translates to concrete mapping
                            mapping = (MappingElementBase)elementMap.get(refname);
                            if (mapping == null) {
                                throw new RuntimeException("Cannot unwrap element " +
                                        qname + ": no concrete mapping definition found for element " +
                                        refname + " (used by element " + itemname + ')');
                            }
                            param.setAttribute("type-index", "");
                            
                        }

                        // configure based on the mapping information
                        param.setAttribute("form", "complex");
                        complex = true;
                        javatype = mapping.getClassName();
                        createtype = mapping.getCreateType();
                        if (createtype == null && mapping.isAbstract() &&
                            mapping.getExtensionTypes().isEmpty()) {
                            
                            // abstract mapping with no extensions requires instance
                            //  this assumes the mapped type can be created, but no easy way to check
                            createtype = javatype;
                        }

                        // merge contained namespace definitions into set for operation
                        Iterator citer = mapping.topChildIterator();
                        while (citer.hasNext()) {
                            ElementBase child = (ElementBase)citer.next();
                            if (child.type() == ElementBase.NAMESPACE_ELEMENT) {
                                dfltns = mapNamespace((NamespaceElement)child, dfltns, nsmap);
                            } else {
                                break;
                            }
                        }

                        // also merge namespace definitions from binding
                        BindingElement binding = (BindingElement)bindingMap.get(mapping);
                        citer = binding.topChildIterator();
                        while (citer.hasNext()) {
                            ElementBase child = (ElementBase)citer.next();
                            if (child.type() == ElementBase.NAMESPACE_ELEMENT) {
                                dfltns = mapNamespace((NamespaceElement)child, dfltns, nsmap);
                            } else if (child.type() != ElementBase.INCLUDE_ELEMENT) {
                                break;
                            }
                        }
                    }
                    param.setAttribute("java-type", javatype);
                    if (createtype != null) {
                        param.setAttribute("create-type", createtype);
                    }

                    boolean isobj = !s_primitiveSet.contains(javatype);
                    String fulltype = javatype;
                    if (isarray) {
                        fulltype += "[]";
                        isobj = false;
                    }
                    param.setAttribute("object", Boolean.toString(isobj));
                    if (isout) {
                        wrappertype = fulltype;
                    } else {
                        wrappertype = "java.lang.Object";
                    }
                    wrapdetail.appendChild(param);

                    // this magic code comes from org.apache.axis2.wsdl.codegen.extension.SchemaUnwrapperExtension
                    //  it's used here to fit into the ADB-based code generation model
                    QName partqname = WSDLUtil.getPartQName(opName.getLocalPart(),
                                                            WSDLConstants.INPUT_PART_QNAME_SUFFIX,
                                                            javaname);
                    partNameList.add(partqname);

                    // add type mapping so we look like ADB
                    codeGenConfig.getTypeMapper().addTypeMappingName(partqname, fulltype);
                }

                // check namespace prefix usage
                if (nons && dfltns) {
                    throw new RuntimeException("Cannot unwrap element " + qname +
                            ": no-namespace element(s) conflict with default namespace use in binding");
                }
                wrapdetail.setAttribute("uses-default", Boolean.toString(nons));

                // set flag for namespace declarations needed on wrapper
                wrapdetail.setAttribute("need-namespaces", Boolean.toString(complex));

            }

        } else if (type != null) {
            throw new RuntimeException("Cannot unwrap element " + qname +
                    ": not a complexType definition");
        }
        if (wrapdetail.getFirstChild() == null) {
            wrapdetail.setAttribute("empty", "true");
            wrapdetail.setAttribute("need-namespaces", "false");
            wrappertype = "";
        } else {
            wrapdetail.setAttribute("empty", "false");
        }

        // this magic code comes from org.apache.axis2.wsdl.codegen.extension.SchemaUnwrapperExtension
        //  it's used here to fit into the ADB-based code generation model
        MessagePartInformationHolder infoHolder = new MessagePartInformationHolder();
        infoHolder.setOperationName(msg.getAxisOperation().getName());
        infoHolder.setPartsList(partNameList);
        try {
            msg.addParameter(new Parameter(Constants.UNWRAPPED_DETAILS, infoHolder));
        } catch (AxisFault e) {
            throw new RuntimeException(e);
        }

        // set indication for unwrapped message
        try {
            msg.addParameter(new Parameter(Constants.UNWRAPPED_KEY, Boolean.TRUE));
        } catch (AxisFault e) {
            throw new RuntimeException(e);
        }

        // add fake mapping for wrapper name (necessary for current XSLTs)
        codeGenConfig.getTypeMapper().addTypeMappingName(qname, wrappertype);

        // return the unwrapping details
        return wrapdetail;
    }

    /**
     * Add mapping from namespace URI to prefix. In the case where multiple prefixes are used with a
     * single URI, this will preserve the last non-empty prefix for that URI.
     *
     * @param ns     namespace definition
     * @param dfltns flag for default namespace used in binding
     * @param nsmap  map from namespace URIs to prefixes
     * @return flag for default namespace used in binding
     */
    private boolean mapNamespace(NamespaceElement ns, boolean dfltns, Map nsmap) {
        String prefix = ns.getPrefix();
        if (prefix == null) {
            prefix = "";
        }
        String prior = (String)nsmap.get(ns.getUri());
        if (prior != null) {
            if (prefix.length() == 0) {
                return dfltns;
            } else if (prior.length() == 0) {
                dfltns = false;
            }
        }
        nsmap.put(ns.getUri(), prefix);
        return dfltns || prefix.length() == 0;
    }

    private static String toJavaName(String name, Set nameset) {
        StringBuffer buff = new StringBuffer(name.length());
        for (int i = 0; i < name.length(); i++) {
            char chr = name.charAt(i);
            if ((i == 0 && Character.isJavaIdentifierStart(chr)) ||
                    (i > 0 && Character.isJavaIdentifierPart(chr))) {
                buff.append(chr);
            } else if (chr == ':' || chr == '.') {
                buff.append('$');
            } else {
                buff.append('_');
            }
        }
        int count = 0;
        String jname = buff.toString();
        while (!nameset.add(jname)) {
            jname = buff.toString() + count++;
        }
        return jname;
    }

    private String mapMessage(AxisMessage msg, Map complexTypeMap) {
        QName qname = msg.getElementQName();
        if (qname == null) {
            throw new RuntimeException("No element reference in message " + msg.getName());
        }
        return mapQName(qname, complexTypeMap);
    }

    private String mapMessage(SOAPHeaderMessage msg, Map complexTypeMap) {
        QName qname = msg.getElement();
        if (qname == null) {
            throw new RuntimeException("No element reference in header");
        }
        return mapQName(qname, complexTypeMap);
    }

    private String mapQName(QName qname, Map complexTypeMap) throws RuntimeException {
        Object obj = complexTypeMap.get(qname);
        if (obj == null) {
            throw new RuntimeException("No mapping defined for element " + qname);
        }
        MappingElementBase mapping = (MappingElementBase)obj;
        String cname = mapping.getClassName();
        codeGenConfig.getTypeMapper().addTypeMappingName(qname, cname);
        return cname;
    }

    /**
     * Collect mapping from qnames to classes for top level mappings in JiBX binding.
     *
     * @param binding
     * @param dns            default namespace to be used unless overridden (empty string if none)
     * @param elementMap     map from element names to concrete mapping components of binding
     * @param complexTypeMap map from type names to abstract mapping components of binding
     * @param simpleTypeMap  map from type names to format definition components of binding
     * @param bindingMap     map from mapping components to containing binding definition
     */
    private static void collectTopLevelComponents(BindingElement binding,
                                                  String dns, Map elementMap, Map complexTypeMap,
                                                  Map simpleTypeMap,
                                                  Map bindingMap) {

        // check default namespace set at top level of binding
        String defaultns = findDefaultNS(binding.topChildIterator(), dns);

        // add all top level mapping and format definitions to maps
        for (Iterator iter = binding.topChildIterator(); iter.hasNext();) {
            ElementBase child = (ElementBase)iter.next();
            if (child.type() == ElementBase.INCLUDE_ELEMENT) {

                // recurse to process included binding definitions
                IncludeElement include = (IncludeElement)child;
                collectTopLevelComponents(include.getBinding(), defaultns,
                                          elementMap, complexTypeMap, simpleTypeMap, bindingMap);

            } else if (child.type() == ElementBase.FORMAT_ELEMENT) {

                // register named formats as simple type conversions
                FormatElement format = (FormatElement)child;
                registerElement(format.getQName(), format, simpleTypeMap);
                bindingMap.put(format, binding);

            } else if (child.type() == ElementBase.MAPPING_ELEMENT) {
                
                // record only abstract mappings with type names, and mappings with names
                MappingElementBase mapping = (MappingElementBase)child;
                bindingMap.put(mapping, binding);
                if (mapping.isAbstract() && mapping.getTypeQName() != null) {

                    // register named abstract mappings as complex type conversions
                    registerElement(mapping.getTypeQName(), mapping,
                                    complexTypeMap);

                } else if (mapping.getName() != null) {

                    // register concrete mappings as element conversions
                    String uri = mapping.getUri();
                    if (uri == null) {
                        uri = findDefaultNS(mapping.topChildIterator(),
                                            defaultns);
                    }
                    elementMap.put(new QName(uri, mapping.getName()), mapping);
                }
            }
        }
    }

    /**
     * Register binding element by qualified name. This converts the qualified name format used by
     * the JiBX binding model to that used by Axis2.
     *
     * @param qname   qualified name in JiBX format (<code>null</code> if none)
     * @param element corresponding element of binding definition
     * @param map     qualified name to element map
     */
    private static void registerElement(org.jibx.runtime.QName qname,
                                        ElementBase element, Map map) {
        if (qname != null) {
            map.put(new QName(qname.getUri(), qname.getName()), element);
        }
    }

    /**
     * Find the default namespace within a list of JiBX binding model elements possibly including
     * namespace definitions. Once a non-namespace definition element is seen in the list, this just
     * returns (since the namespace definitions always come first in JiBX's binding format).
     *
     * @param iter iterator for elements in list
     * @param dns  default namespace if not overridden
     * @return default namespace
     */
    private static String findDefaultNS(Iterator iter, String dns) {
        while (iter.hasNext()) {
            ElementBase child = (ElementBase)iter.next();
            if (child.type() == ElementBase.NAMESPACE_ELEMENT) {
                NamespaceElement namespace = (NamespaceElement)child;
                String defaultName = namespace.getDefaultName();
                if ("elements".equals(defaultName) || "all".equals(defaultName)) {
                    return namespace.getUri();
                }
            } else {
                break;
            }
        }
        return dns;
    }

    /**
     * Inner class for handling prevalidation of include elements only. Unlike the normal JiBX
     * binding definition prevalidation step, this visitor ignores everything except include
     * elements.
     */
    private class IncludePrevalidationVisitor extends ModelVisitor {
        private final ValidationContext m_context;

        private IncludePrevalidationVisitor(ValidationContext vctx) {
            m_context = vctx;
        }

        /* (non-Javadoc)
        * @see org.jibx.binding.model.ModelVisitor#visit(org.jibx.binding.model.ElementBase)
        */
        public boolean visit(IncludeElement node) {
            try {
                // force creation of defintions context for containing binding
                m_context.getFormatDefinitions();
                node.prevalidate(m_context);
            } catch (Throwable t) {
                m_context.addFatal("Error during validation: " +
                        t.getMessage());
                t.printStackTrace();
                return false;
            }
            return true;
        }
    }

    private static class NamedParameterTypeMapper extends JavaTypeMapper {
        /**
         * Return the real parameter name, not a dummy.
         *
         * @param qname
         * @return local part of name
         */
        public String getParameterName(QName qname) {
            return qname.getLocalPart();
        }
    }
}