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

import org.apache.axis2.namespace.Constants;
import org.apache.axis2.schema.i18n.SchemaCompilerMessages;
import org.apache.axis2.schema.util.PrimitiveTypeFinder;
import org.apache.axis2.schema.util.PrimitiveTypeWrapper;
import org.apache.axis2.schema.util.SchemaPropertyLoader;
import org.apache.axis2.schema.writer.BeanWriter;
import org.apache.axis2.util.SchemaUtil;
import org.apache.axis2.util.URLProcessor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.*;
import org.apache.ws.commons.schema.utils.XmlSchemaObjectBase;
import org.xml.sax.InputSource;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Schema compiler for ADB. Based on WS-Commons schema object model.
 */
public class SchemaCompiler {

    public static final int COMPONENT_TYPE = 1;
    public static final int COMPONENT_ELEMENT = 2;
    public static final int COMPONENT_ATTRIBUTE = 3;
    public static final int COMPONENT_ATTRIBUTE_GROUP = 4;
    public static final int COMPONENT_GROUP = 5;


    private static final Log log = LogFactory.getLog(SchemaCompiler.class);

    private CompilerOptions options;
    private HashMap<QName, String> processedTypemap;
    // have to keep a seperate group type map since same
    // name can be used to group and complextype
    private HashMap<QName, String> processedGroupTypeMap;

    //the list of processedElements for the outer elements
    private HashMap<QName, String> processedElementMap;

    //need to use IdentityHashMap to store processedAnonymousComplexTypes
    //because the key used with the map, XmlSchemaElement, is not immutable
    private IdentityHashMap<XmlSchemaElement, BeanWriterMetaInfoHolder> processedAnonymousComplexTypesMap;

    //we need this map to keep the referenced elements. these elements need to be kept seperate
    //to avoid conflicts
    private HashMap<QName, String> processedElementRefMap;
    private HashMap<QName, String> simpleTypesMap;
    private HashMap<QName, QName> changedTypeMap;

    private HashSet<XmlSchemaSimpleType> changedSimpleTypeSet;
    private HashSet<XmlSchemaComplexType> changedComplexTypeSet;
    private HashSet<XmlSchemaElement> changedElementSet;

    // this map is necessary to retain the metainformation of types. The reason why these
    // meta info 'bags' would be useful later is to cater for the extensions and restrictions
    // of types
    private HashMap<QName, BeanWriterMetaInfoHolder> processedTypeMetaInfoMap;

    //
    private ArrayList<QName> processedElementList;

    //a list of nillable elements - used to generate code
    //for nillable elements
    private List<QName> nillableElementList;
    // writee reference
    private BeanWriter writer = null;
    private Map<QName, String> baseSchemaTypeMap = null;

    //a map for keeping the already loaded schemas
    //the key is the targetnamespace and the value is the schema object
    private Map<String, XmlSchema> loadedSchemaMap = new HashMap<String, XmlSchema>();

    // A map keeping the available schemas
    //the key is the targetnamespace and the value is the schema object
    //this map will be populated when multiple schemas
    //are fed to the schema compiler!
    private Map<String, XmlSchema> availableSchemaMap = new HashMap<String, XmlSchema>();

    private Map<String, String> loadedSourceURI = new HashMap<String, String>();

    // a list of externally identified QNames to be processed. This becomes
    // useful when  only a list of external elements need to be processed

    public static final String ANY_ELEMENT_FIELD_NAME = "extraElement";
    public static final String EXTRA_ATTRIBUTE_FIELD_NAME = "extraAttributes";

    public static final String USE_OPTIONAL = "optional";
    public static final String USE_REQUIRED = "required";
    public static final String USE_NONE = "none";

    /**
     * @return the processes element map
     *         includes the Qname of the element as the key and a
     *         String representing the fully qualified class name
     */
    public HashMap<QName, String> getProcessedElementMap() {
        return processedElementMap;
    }


    /**
     * @return a map of Qname vs models. A model can be anything,
     *         ranging from a DOM document to a stream. This is taken from the
     *         writer and the schema compiler has no control over it
     */
    public Map getProcessedModelMap() {
        return writer.getModelMap();
    }

    /**
     * Constructor - Accepts a options bean
     *
     * @param options
     */
    public SchemaCompiler(CompilerOptions options) throws SchemaCompilationException {

        if (options == null) {
            //create an empty options object
            this.options = new CompilerOptions();
        } else {
            this.options = options;
        }

        Map<String, String> nsp2PackageMap = this.options.getNs2PackageMap();

        if (nsp2PackageMap == null) {
            nsp2PackageMap = new HashMap();
            this.options.setNs2PackageMap(nsp2PackageMap);
        }

        if (!nsp2PackageMap.containsKey("")) {
            nsp2PackageMap.put("", "axis2.apache.org");
        }

        //instantiate the maps
        processedTypemap = new HashMap<QName, String>();
        processedGroupTypeMap = new HashMap<QName, String>();

        processedElementMap = new HashMap<QName, String>();
        simpleTypesMap = new HashMap<QName, String>();
        processedElementList = new ArrayList<QName>();
        processedAnonymousComplexTypesMap = new IdentityHashMap<XmlSchemaElement, BeanWriterMetaInfoHolder>();
        changedTypeMap = new HashMap<QName, QName>();
        processedTypeMetaInfoMap = new HashMap<QName, BeanWriterMetaInfoHolder>();
        processedElementRefMap = new HashMap<QName, String>();
        nillableElementList = new ArrayList<QName>();

        changedComplexTypeSet = new HashSet<XmlSchemaComplexType>();
        changedSimpleTypeSet = new HashSet<XmlSchemaSimpleType>();
        changedElementSet = new HashSet<XmlSchemaElement>();

        //load the writer and initiliaze the base types
        writer = SchemaPropertyLoader.getBeanWriterInstance();
        writer.init(this.options);

        //load the base types
        baseSchemaTypeMap = SchemaPropertyLoader.getTypeMapperInstance().getTypeMap();
    }

    /**
     * Compile a list of schemas
     * This actually calls the compile (XmlSchema s) method repeatedly
     *
     * @param schemalist
     * @throws SchemaCompilationException
     * @see #compile(org.apache.ws.commons.schema.XmlSchema)
     */
    public void compile(List<XmlSchema> schemalist) throws SchemaCompilationException {
        try {

            if (schemalist.isEmpty()) {
                return;
            }

            //clear the loaded and available maps
            loadedSchemaMap.clear();
            availableSchemaMap.clear();

            // first round - populate the avaialble map
            for (XmlSchema schema : schemalist) {
                availableSchemaMap.put(
                        schema.getTargetNamespace(),
                        schema);
            }

            //set a mapper package if not avaialable
            if (writer.getExtensionMapperPackageName() == null) {
                String nsp = null;
                //get the first schema from the list and take that namespace as the
                //mapper namespace
                for (XmlSchema schema : schemalist) {
                    nsp = schema.getTargetNamespace();
                    if ((nsp != null) && !nsp.equals("")) {
                        break;
                    }
                    XmlSchema[] schemas = SchemaUtil.getAllSchemas(schema);
                    for (int j = 0; schemas != null && j < schemas.length; j++) {
                        nsp = schemas[j].getTargetNamespace();
                        if (nsp != null) {
                            break;
                        }
                    }
                }
                if (nsp == null) {
                    nsp = URLProcessor.DEFAULT_PACKAGE;
                }

                // if this name space exists in the ns2p list then we use it.
                if ((options.getNs2PackageMap() != null)
                    && (options.getNs2PackageMap().containsKey(nsp))) {
                    writer.registerExtensionMapperPackageName(options.getNs2PackageMap().get(nsp));
                } else {
                    writer.registerExtensionMapperPackageName(nsp == null ? null :
                                                              URLProcessor.makePackageName(nsp));
                }
            }
            // second round - call the schema compiler one by one
            for (XmlSchema schema : schemalist) {
                compile(schema, true);
            }

            //finish up
            finalizeSchemaCompilation();

        } catch (SchemaCompilationException e) {
            throw e;
        } catch (Exception e) {
            throw new SchemaCompilationException(e);
        }
    }

    /**
     * Compile (rather codegen) a single schema element
     *
     * @param schema
     * @throws SchemaCompilationException
     */
    public void compile(XmlSchema schema) throws SchemaCompilationException {
        compile(schema, false);
    }

    /**
     * Compile (rather codegen) a single schema element
     *
     * @param schema
     * @param isPartofGroup
     * @throws SchemaCompilationException
     */
    private void compile(XmlSchema schema, boolean isPartofGroup)
            throws SchemaCompilationException {

        // some documents explicitly imports the schema of built in types. We don't actually need to compile
        // the built-in types. So check the target namespace here and ignore it.
        if (Constants.URI_2001_SCHEMA_XSD.equals(schema.getTargetNamespace())) {
            return;
        }

        //register the package from this namespace as the mapper classes package
        if (!isPartofGroup) {
            //set a mapper package if not avaialable
            if (writer.getExtensionMapperPackageName() == null) {
                String ns = schema.getTargetNamespace();
                if (ns == null) {
                    ns = URLProcessor.DEFAULT_PACKAGE;
                }
                // if this name space exists in the ns2p list then we use it.
                if ((options.getNs2PackageMap() != null)
                    && (options.getNs2PackageMap().containsKey(ns))) {
                    writer.registerExtensionMapperPackageName(options.getNs2PackageMap().get(ns));
                } else {
                    writer.registerExtensionMapperPackageName(URLProcessor.makePackageName(ns));
                }
            }
        }

        //First look for the schemas that are imported and process them
        //Note that these are processed recursively!

        //add the schema to the loaded schema list
        if (!loadedSchemaMap.containsKey(schema.getTargetNamespace())) {
            loadedSchemaMap.put(schema.getTargetNamespace(), schema);
            // when the target name space is not given schema.getTargetNamesapce returns null.
            // but when importing import namesapce location is given as "".
            // this causese a problem in finding reference elements. see AXIS2-3029
            // kept the null entry as well to safe gaurd any thing which acess using null
            if (schema.getTargetNamespace() == null) {
                loadedSchemaMap.put("", schema);
            }
        }

        // If we have/are loading a schema with a specific targetnamespace from a certain URI,
        // then just return back to the caller to avoid recursion.
        if (schema.getSourceURI() != null) {
            String key = schema.getTargetNamespace() + ":" + schema.getSourceURI();
            if (loadedSourceURI.containsKey(key)) {
                return;
            }
            loadedSourceURI.put(key, key);
        }

        for (XmlSchemaObject object : schema.getExternals()) {

            if (object instanceof XmlSchemaImport) {
                XmlSchemaImport schemaImport = (XmlSchemaImport) object;
                XmlSchema schema1 = schemaImport.getSchema();
                if (schema1 != null) {
                    compile(schema1, isPartofGroup);
                } else if (schemaImport.getNamespace().equals(Constants.NS_URI_XML)) {
                    // AXIS2-3229: some Web services (e.g. MS Exchange) assume that
                    // http://www.w3.org/XML/1998/namespace is a known namespace and that
                    // no schemaLocation is required when importing it. Load a local copy of
                    // the schema in that case.
                    schema1 = new XmlSchemaCollection().read(new InputSource(
                            SchemaCompiler.class.getResource("namespace.xsd").toExternalForm()));
                    schemaImport.setSchema(schema1);
                    compile(schema1, isPartofGroup);
                } else if (!schemaImport.getNamespace().equals(Constants.URI_2001_SCHEMA_XSD)) {
                    // Give the user a hint why the schema compilation fails...
                    log.warn("No schemaLocation for import of " + schemaImport.getNamespace() +
                             "; compilation may fail");
                }
            }
            if (object instanceof XmlSchemaInclude) {
                XmlSchema schema1 = ((XmlSchemaInclude) object).getSchema();
                if (schema1 != null) {
                    if (schema1.getTargetNamespace() == null) {
                        // the target namespace of an included shchema should be same
                        // as the parent schema however if the schema uses the chemalon pattern
                        // target namespace can be null. so set it here.
                        // http://www.xfront.com/ZeroOneOrManyNamespaces.html#mixed
                        schema1.setTargetNamespace(schema.getTargetNamespace());
                    }
                    compile(schema1, isPartofGroup);
                }

            }

        }

        //select all the elements. We generate the code for types
        //only if the elements refer them!!! regardless of the fact that
        //we have a list of elementnames, we'll need to process all the elements
        for (XmlSchemaElement element : schema.getElements().values()) {
            //this is the set of outer elements so we need to generate classes
            //The outermost elements do not contain occurence counts (!) so we do not need
            //to check for arraytypes
            processElement(element, schema);
        }

        // re-iterate through the elements and write them one by one
        // if the mode is unpack this process will not really write the
        // classes but will accumilate the models for a final single shot
        // write
        for (XmlSchemaElement element : schema.getElements().values()) {
            //this is the set of outer elements so we need to generate classes
            writeElement(element);
        }

        if (options.isGenerateAll()) {
            for (XmlSchemaType schemaType : schema.getSchemaTypes().values()) {
                if (this.isAlreadyProcessed(schemaType.getQName())) {
                    continue;
                }
                if (schemaType instanceof XmlSchemaComplexType) {
                    //write classes for complex types
                    XmlSchemaComplexType complexType = (XmlSchemaComplexType) schemaType;
                    if (complexType.getName() != null) {
                        processNamedComplexSchemaType(complexType, schema);
                    }
                } else if (schemaType instanceof XmlSchemaSimpleType) {
                    //process simple type
                    processSimpleSchemaType((XmlSchemaSimpleType) schemaType,
                                            null,
                                            schema, null);
                }
            }
        }

        if (!isPartofGroup) {
            //complete the compilation
            finalizeSchemaCompilation();
        }
    }

    /**
     * Completes the schema compilation process by writing the
     * mappers and the classes in a batch if needed
     *
     * @throws SchemaCompilationException
     */
    private void finalizeSchemaCompilation() throws SchemaCompilationException {
        //write the extension mapping class
        writer.writeExtensionMapper(
                processedTypeMetaInfoMap.values().toArray(
                        new BeanWriterMetaInfoHolder[processedTypeMetaInfoMap.size()]));


        if (options.isWrapClasses()) {
            writer.writeBatch();
        }

        // resets the changed types
        for (XmlSchemaComplexType xmlSchemaComplexType : changedComplexTypeSet) {
            xmlSchemaComplexType.setName(null);
        }

        for (XmlSchemaSimpleType xmlSchemaSimpleType : changedSimpleTypeSet) {
            xmlSchemaSimpleType.setName(null);
        }

        for (XmlSchemaElement xmlSchemaElement : changedElementSet) {
            xmlSchemaElement.setSchemaTypeName(null);
        }

    }

    /**
     * @return the property map of the schemacompiler.
     *         In this case it would be the property map loaded from
     *         the configuration file
     */
    public Properties getCompilerProperties() {
        return SchemaPropertyLoader.getPropertyMap();
    }


    /**
     * Writes the element
     *
     * @param xsElt
     * @throws SchemaCompilationException
     */
    private void writeElement(XmlSchemaElement xsElt) throws SchemaCompilationException {

        if (this.processedElementMap.containsKey(xsElt.getQName())) {
            return;
        }

        XmlSchemaType schemaType = xsElt.getSchemaType();

        BeanWriterMetaInfoHolder metainf = new BeanWriterMetaInfoHolder();
        if (schemaType != null && schemaType.getName() != null) {
            //this is a named type
            QName qName = schemaType.getQName();
            //find the class name
            String className = findClassName(qName, isArray(xsElt));

            // element declared at the top level and have simple types may
            // use primitive type if we do not add this check
            if (options.isUseWrapperClasses() && PrimitiveTypeFinder.isPrimitive(className)) {
                className = PrimitiveTypeWrapper.getWrapper(className);
            }

            //this means the schema type actually returns a different QName
            if (changedTypeMap.containsKey(qName)) {
                metainf.registerMapping(xsElt.getQName(),
                                        changedTypeMap.get(qName),
                                        className);
            } else {
                metainf.registerMapping(xsElt.getQName(),
                                        qName,
                                        className);
            }

            // register the default value if present
            if (xsElt.getDefaultValue() != null) {
                metainf.registerDefaultValue(xsElt.getQName(), xsElt.getDefaultValue());
            }

            // register the fixed value if present
            if (xsElt.getFixedValue() != null) {
                metainf.registerDefaultValue(xsElt.getQName(), xsElt.getFixedValue());
                metainf.registerFixedQName(xsElt.getQName());
            }

            if (isBinary(xsElt)) {
                metainf.addtStatus(xsElt.getQName(),
                                   SchemaConstants.BINARY_TYPE);
            }

        } else if (xsElt.getRef().getTargetQName() != null) {
            // Since top level elements would not have references
            // and we only write toplevel elements, this should
            // not be a problem , atleast should not occur in a legal schema
        } else if (xsElt.getSchemaTypeName() != null) {
            QName qName = xsElt.getSchemaTypeName();
            String className = findClassName(qName, isArray(xsElt));
            metainf.registerMapping(xsElt.getQName(),
                                    qName,
                                    className);


        } else if (schemaType != null) {  //the named type should have been handled already

            //we are going to special case the anonymous complex type. Our algorithm for dealing
            //with it is to generate a single object that has the complex content inside. Really the
            //intent of the user when he declares the complexType anonymously is to use it privately
            //First copy the schema types content into the metainf holder
            metainf = this.processedAnonymousComplexTypesMap.get(xsElt);
            metainf.setAnonymous(true);
        } else {
            //this means we did not find any schema type associated with the particular element.
            log.warn(SchemaCompilerMessages.getMessage("schema.elementWithNoType", xsElt.getQName().toString()));
            metainf.registerMapping(xsElt.getQName(),
                                    null,
                                    writer.getDefaultClassName(),
                                    SchemaConstants.ANY_TYPE);
        }

        if (nillableElementList.contains(xsElt.getQName())) {
            metainf.registerNillableQName(xsElt.getQName());
        }


        String writtenClassName = writer.write(xsElt, processedTypemap, processedGroupTypeMap, metainf);
        //register the class name
        xsElt.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY, writtenClassName);
        processedElementMap.put(xsElt.getQName(), writtenClassName);
    }

    /**
     * For inner elements
     *
     * @param xsElt
     * @param innerElementMap
     * @param parentSchema
     * @throws SchemaCompilationException
     */
    private void processElement(XmlSchemaElement xsElt, Map<QName, String> innerElementMap,
                                List<QName> localNillableList, XmlSchema parentSchema)
            throws SchemaCompilationException {
        processElement(xsElt, false, innerElementMap, localNillableList, parentSchema);
    }

    /**
     * For outer elements
     *
     * @param xsElt
     * @param parentSchema
     * @throws SchemaCompilationException
     */
    private void processElement(XmlSchemaElement xsElt, XmlSchema parentSchema)
            throws SchemaCompilationException {
        processElement(xsElt, true, null, null, parentSchema);
    }

    /**
     * Process and Element
     *
     * @param xsElt
     * @param isOuter We need to know this since the treatment of outer elements is different that
     *                inner elements
     * @throws SchemaCompilationException
     */
    private void processElement(XmlSchemaElement xsElt, boolean isOuter,
                                Map<QName, String> innerElementMap, List<QName> localNillableList,
                                XmlSchema parentSchema) throws SchemaCompilationException {

        //if the element is null, which usually happens when the qname is not
        //proper, throw an exceptions
        if (xsElt == null) {
            throw new SchemaCompilationException(
                    SchemaCompilerMessages.getMessage("schema.elementNull"));
        }


        //The processing element logic seems to be quite simple. Look at the relevant schema type
        //for each and every element and process that accordingly.
        //this means that any unused type definitions would not be generated!
        if (isOuter && processedElementList.contains(xsElt.getQName())) {
            return;
        }

        XmlSchemaType schemaType = xsElt.getSchemaType();
        if (schemaType != null) {
            processSchema(xsElt, schemaType, parentSchema, false);
            //at this time it is not wise to directly write the class for the element
            //so we push the complete element to an arraylist and let the process
            //pass through. We'll be iterating through the elements writing them
            //later

            if (!isOuter) {
                if (schemaType.getName() != null) {
                    // this element already has a name. Which means we can directly
                    // register it
                    String className = findClassName(schemaType.getQName(),
                                                     isArray(xsElt));

                    innerElementMap.put(xsElt.getWireName(), className);

                    // always store the class name in the element meta Info itself
                    // this details only needed by the unwrappig to set the complex type
                    if (options.isUseWrapperClasses() && PrimitiveTypeFinder.isPrimitive(className)) {
                        className = PrimitiveTypeWrapper.getWrapper(className);
                    }
                    schemaType.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                           className);
                    xsElt.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                      className);

                    if (baseSchemaTypeMap.containsValue(className)) {
                        schemaType.addMetaInfo(
                                SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_PRIMITVE_KEY,
                                Boolean.TRUE);
                    }
                    //since this is a inner element we should add it to the inner element map
                } else {
                    //this is an anon type. This should have been already processed and registered at
                    //the anon map. we've to write it just like we treat a referenced type(giving due
                    //care that this is meant to be an attribute in some class)

                    QName generatedTypeName = generateTypeQName(xsElt.getWireName(), parentSchema);

                    if (schemaType instanceof XmlSchemaComplexType) {
                        //set a name
                        schemaType.setName(generatedTypeName.getLocalPart());
                        changedComplexTypeSet.add((XmlSchemaComplexType) schemaType);
                        // Must do this up front to support recursive types
                        String fullyQualifiedClassName = writer.
                                makeFullyQualifiedClassName(schemaType.getQName());
                        processedTypemap.put(schemaType.getQName(), fullyQualifiedClassName);

                        BeanWriterMetaInfoHolder metaInfHolder =
                                processedAnonymousComplexTypesMap.get(xsElt);
                        metaInfHolder.setOwnQname(schemaType.getQName());
                        metaInfHolder.setOwnClassName(fullyQualifiedClassName);

                        writeComplexType((XmlSchemaComplexType) schemaType,
                                         metaInfHolder);
                        //remove the reference from the anon list since we named the type
                        processedAnonymousComplexTypesMap.remove(xsElt);
                        String className = findClassName(schemaType.getQName(), isArray(xsElt));
                        innerElementMap.put(
                                xsElt.getWireName(),
                                className);

                        //store in the schema map to retrive in the unwrapping
                        xsElt.addMetaInfo(
                                SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                className);
                    } else if (schemaType instanceof XmlSchemaSimpleType) {
                        //set a name
                        schemaType.setName(generatedTypeName.getLocalPart());
                        changedSimpleTypeSet.add((XmlSchemaSimpleType) schemaType);
                        // Must do this up front to support recursive types
                        String fullyQualifiedClassName = writer.
                                makeFullyQualifiedClassName(schemaType.getQName());
                        processedTypemap.put(schemaType.getQName(), fullyQualifiedClassName);

                        BeanWriterMetaInfoHolder metaInfHolder =
                                processedAnonymousComplexTypesMap.get(xsElt);
                        metaInfHolder.setOwnQname(schemaType.getQName());
                        metaInfHolder.setOwnClassName(fullyQualifiedClassName);

                        writeSimpleType((XmlSchemaSimpleType) schemaType,
                                        metaInfHolder);
                        //remove the reference from the anon list since we named the type
                        processedAnonymousComplexTypesMap.remove(xsElt);
                        String className = findClassName(schemaType.getQName(), isArray(xsElt));
                        innerElementMap.put(
                                xsElt.getWireName(),
                                className);

                        //store in the schema map
                        xsElt.addMetaInfo(
                                SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                className);
                    }
                }
            } else {
                // set the binary status of this element
                this.processedElementList.add(xsElt.getQName());
            }
            //referenced name
        } else if (xsElt.getRef().getTargetQName() != null) {

            if (xsElt.getRef().getTargetQName().equals(SchemaConstants.XSD_SCHEMA)) {
                innerElementMap.put(xsElt.getQName(), writer.getDefaultClassName());
                return;
            }
            //process the referenced type. It could be thought that the referenced element replaces this
            //element
            XmlSchema resolvedSchema = getParentSchema(parentSchema,
                                                       xsElt.getRef().getTargetQName(),
                                                       COMPONENT_ELEMENT);
            if (resolvedSchema == null) {
                throw new SchemaCompilationException("can not find the element " +
                                                     xsElt.getRef().getTargetQName()
                                                     + " from the parent schema " +
                                                     parentSchema.getTargetNamespace());
            }
            XmlSchemaElement referencedElement = resolvedSchema.
                    getElementByName(xsElt.getRef().getTargetQName());
            if (referencedElement == null) {
                throw new SchemaCompilationException(
                        SchemaCompilerMessages.
                                getMessage("schema.referencedElementNotFound",
                                           xsElt.getRef().getTargetQName().toString()));
            }

            // here what we want is to set the schema type name for the element
            if ((referencedElement.getSchemaType() != null)
                && (referencedElement.getSchemaType().getQName() != null)) {

                // i.e this element refers to an complex type name
                if (!this.processedElementRefMap.containsKey(referencedElement.getQName())) {
                    if (this.baseSchemaTypeMap.containsKey(referencedElement.getSchemaTypeName())) {
                        this.processedElementRefMap.put(referencedElement.getQName(),
                                                        this.baseSchemaTypeMap.
                                                                get(referencedElement.
                                                                        getSchemaTypeName()));
                    } else {
                        XmlSchema resolvedTypeSchema = getParentSchema(resolvedSchema,
                                                                       referencedElement.
                                                                               getSchemaTypeName(),
                                                                       COMPONENT_TYPE);
                        XmlSchemaType xmlSchemaType = resolvedTypeSchema.getTypeByName(
                                referencedElement.getSchemaTypeName().getLocalPart());
                        processSchema(referencedElement, xmlSchemaType, resolvedTypeSchema, true);
                        this.processedElementRefMap.put(referencedElement.getQName(),
                                                        this.processedTypemap.
                                                                get(referencedElement.
                                                                        getSchemaTypeName()));
                    }
                }
                String javaClassName;
                if (this.baseSchemaTypeMap.containsKey(referencedElement.getSchemaTypeName())) {
                    // here we have to do nothing since we do not generate a name
                } else {
                    javaClassName = this.processedTypemap.get(referencedElement.getSchemaTypeName());
                    referencedElement.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.
                                                          CLASSNAME_KEY,
                                                  javaClassName);
                    xsElt.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                      javaClassName);
                }
            } else if (referencedElement.getSchemaType() != null) {
                if (!this.processedElementRefMap.containsKey(referencedElement.getQName())) {

                    processSchema(referencedElement, referencedElement.getSchemaType(),
                                  resolvedSchema, true);
                    // if this is an anonomous complex type we have to set this
                    this.processedElementRefMap.put(referencedElement.getQName(),
                                                    this.processedTypemap.get(referencedElement.
                                                            getSchemaTypeName()));

                }

                String javaClassName = this.processedTypemap.
                        get(referencedElement.getSchemaTypeName());
                referencedElement.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                              javaClassName);
                xsElt.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                  javaClassName);
            } else if (referencedElement.getSchemaTypeName() != null) {
                QName schemaTypeName = referencedElement.getSchemaTypeName();
                XmlSchema newResolvedSchema = getParentSchema(resolvedSchema, schemaTypeName,
                                                              COMPONENT_TYPE);
                XmlSchemaType xmlSchemaType = newResolvedSchema.getTypeByName(schemaTypeName);
                if (xmlSchemaType != null) {
                    if (!this.processedElementRefMap.containsKey(referencedElement.getQName())) {
                        // we know this is a named complex type
                        processSchema(referencedElement, xmlSchemaType, newResolvedSchema, false);
                        // if this is an anonomous complex type we have to set this
                        this.processedElementRefMap.put(referencedElement.getQName(),
                                                        this.processedTypemap.get(schemaTypeName));

                    }

                    String javaClassName = this.processedTypemap.get(referencedElement.
                            getSchemaTypeName());
                    referencedElement.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.
                                                          CLASSNAME_KEY,
                                                  javaClassName);
                    xsElt.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                      javaClassName);
                } else {
                    throw new SchemaCompilationException(" Can not find the schema type with name " +
                                                         schemaTypeName);
                }

            }

            // schema type name is present but not the schema type object
        } else if (xsElt.getSchemaTypeName() != null) {
            //There can be instances where the SchemaType is null but the schemaTypeName is not!
            //this specifically happens with xsd:anyType.
            QName schemaTypeName = xsElt.getSchemaTypeName();

            XmlSchema resolvedSchema = getParentSchema(parentSchema, schemaTypeName, COMPONENT_TYPE);
            XmlSchemaType typeByName = null;
            if (resolvedSchema != null) {
                typeByName = resolvedSchema.getTypeByName(schemaTypeName);
            }

            if (typeByName != null) {
                //this type is found in the schema so we can process it
                processSchema(xsElt, typeByName, resolvedSchema, false);
                if (!isOuter) {
                    String className = findClassName(schemaTypeName, isArray(xsElt));
                    //since this is a inner element we should add it to the inner element map
                    innerElementMap.put(xsElt.getWireName(), className);
                    // set the class name to be used in unwrapping
                    xsElt.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                      className);
                } else {
                    this.processedElementList.add(xsElt.getQName());
                }
            } else {
                //this type is not found at all. we'll just register it with whatever the class name we can comeup with
                if (!isOuter) {
                    String className = findClassName(schemaTypeName, isArray(xsElt));
                    innerElementMap.put(xsElt.getWireName(), className);
                    // set the class name to be used in unwrapping
                    xsElt.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                      className);
                } else {
                    this.processedElementList.add(xsElt.getQName());
                }
            }
        }

        //add this elements QName to the nillable group if it has the  nillable attribute
        if (xsElt.isNillable()) {
            if (isOuter) {
                this.nillableElementList.add(xsElt.getQName());
            } else {
                localNillableList.add(xsElt.getWireName());
            }
        }

    }

    /**
     * Generate a unique type Qname using an element name
     *
     * @param referenceEltQName
     * @param parentSchema
     */
    private QName generateTypeQName(QName referenceEltQName, XmlSchema parentSchema) {
        QName generatedTypeName = new QName(referenceEltQName.getNamespaceURI(),
                                            referenceEltQName.getLocalPart() +
                                            getNextTypeSuffix(referenceEltQName.getLocalPart()));
        while (parentSchema.getTypeByName(generatedTypeName) != null) {
            generatedTypeName = new QName(referenceEltQName.getNamespaceURI(),
                                          referenceEltQName.getLocalPart() +
                                          getNextTypeSuffix(referenceEltQName.getLocalPart()));
        }
        return generatedTypeName;
    }

    /**
     * Finds whether a given class is already made
     *
     * @param qName
     */
    private boolean isAlreadyProcessed(QName qName) {
        return processedTypemap.containsKey(qName) ||
               simpleTypesMap.containsKey(qName) ||
               baseSchemaTypeMap.containsKey(qName) ||
               processedGroupTypeMap.containsKey(qName);
    }


    /**
     * A method to pick the ref class name
     *
     * @param name
     * @param isArray
     */
    private String findRefClassName(QName name, boolean isArray) {
        String className = null;
        if (processedElementRefMap.get(name) != null) {
            className = processedElementRefMap.get(name);

            if (isArray) {
                //append the square braces that say this is an array
                //hope this works for all cases!!!!!!!
                //todo this however is a thing that needs to be
                //todo fixed to get complete language support
                className = className + "[]";
            }
        }
        return className;

    }

    /**
     * Finds a class name from the given Qname
     *
     * @param qName
     * @param isArray
     * @return FQCN
     */
    private String findClassName(QName qName, boolean isArray) throws SchemaCompilationException {

        //find the class name
        String className;
        if (processedTypemap.containsKey(qName)) {
            className = processedTypemap.get(qName);
        } else if (simpleTypesMap.containsKey(qName)) {
            className = simpleTypesMap.get(qName);
        } else if (baseSchemaTypeMap.containsKey(qName)) {
            className = baseSchemaTypeMap.get(qName);
        } else {
            if (isSOAP_ENC(qName.getNamespaceURI())) {
                throw new SchemaCompilationException(SchemaCompilerMessages.
                        getMessage("schema.soapencoding.error", qName.toString()));

            }
            // We seem to have failed in finding a class name for the
            //contained schema type. We better set the default then
            //however it's better if the default can be set through the
            //property file
            className = writer.getDefaultClassName();
            log.warn(SchemaCompilerMessages
                             .getMessage("schema.typeMissing", qName.toString()));
        }

        if (isArray) {
            //append the square braces that say this is an array
            //hope this works for all cases!!!!!!!
            //todo this however is a thing that needs to be
            //todo fixed to get complete language support
            className = className + "[]";
        }
        return className;
    }

    /**
     * Returns true if SOAP_ENC Namespace.
     *
     * @param s a string representing the URI to check
     * @return true if <code>s</code> matches a SOAP ENCODING namespace URI,
     *         false otherwise
     */
    public static boolean isSOAP_ENC(String s) {
        if (s.equals(Constants.URI_SOAP11_ENC)) {
            return true;
        }
        return s.equals(Constants.URI_SOAP12_ENC);
    }

    /**
     * Process a schema element which has been refered to by an element
     *
     * @param schemaType
     * @throws SchemaCompilationException
     */
    private void processSchema(XmlSchemaElement xsElt,
                               XmlSchemaType schemaType,
                               XmlSchema parentSchema,
                               boolean isWriteAnonComplexType) throws SchemaCompilationException {
        if (schemaType instanceof XmlSchemaComplexType) {
            //write classes for complex types
            XmlSchemaComplexType complexType = (XmlSchemaComplexType) schemaType;
            // complex type name may not be null if we have set it
            if (complexType.getName() != null && !this.changedComplexTypeSet.contains(schemaType)) {
                // here complex type may be in another shcema so we have to find the
                // correct parent schema.
                XmlSchema resolvedSchema = getParentSchema(parentSchema, complexType.getQName(),
                                                           COMPONENT_TYPE);
                if (resolvedSchema == null) {
                    throw new SchemaCompilationException("can not find the parent schema for the " +
                                                         "complex type " + complexType.getQName() +
                                                         " from the parent schema " +
                                                         parentSchema.getTargetNamespace());
                } else {
                    processNamedComplexSchemaType(complexType, resolvedSchema);
                }
            } else {
                processAnonymousComplexSchemaType(xsElt, complexType, parentSchema,
                                                  isWriteAnonComplexType);
            }
        } else if (schemaType instanceof XmlSchemaSimpleType) {
            //process simple type
            processSimpleSchemaType((XmlSchemaSimpleType) schemaType,
                                    xsElt,
                                    parentSchema, null);
        }
    }


    /**
     * @param complexType
     * @throws SchemaCompilationException
     */
    private void processAnonymousComplexSchemaType(XmlSchemaElement elt,
                                                   XmlSchemaComplexType complexType,
                                                   XmlSchema parentSchema,
                                                   boolean isWriteAnonComplexType)
            throws SchemaCompilationException {

        //here we have a problem when processing the circulare element
        // references if we differ this processing
        // generate a name to the complex type and register it here
        QName generatedTypeName = null;
        String javaClassName = null;
        if (isWriteAnonComplexType) {

            generatedTypeName = generateTypeQName(elt.getQName(), parentSchema);

            if (elt.getSchemaTypeName() == null) {
                elt.setSchemaTypeName(generatedTypeName);
                this.changedElementSet.add(elt);
            }

            //set a name
            complexType.setName(generatedTypeName.getLocalPart());
            this.changedComplexTypeSet.add(complexType);

            javaClassName = writer.makeFullyQualifiedClassName(generatedTypeName);
            processedTypemap.put(generatedTypeName, javaClassName);
            this.processedElementRefMap.put(elt.getQName(), javaClassName);
            complexType.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                    javaClassName);
        }


        BeanWriterMetaInfoHolder metaInfHolder = processComplexType(elt.getQName(), complexType,
                                                                    parentSchema);

        // here the only difference is that we generate the class
        // irrespective of where we need it or not
        if (isWriteAnonComplexType) {
            metaInfHolder.setOwnClassName(javaClassName);
            metaInfHolder.setOwnQname(generatedTypeName);
            writeComplexType(complexType, metaInfHolder);
        }

        //since this is a special case (an unnamed complex type) we'll put the already processed
        //metainf holder in a special map to be used later
        this.processedAnonymousComplexTypesMap.put(elt, metaInfHolder);

    }

    /**
     * handle the complex types which are named
     *
     * @param complexType
     */
    private void processNamedComplexSchemaType(XmlSchemaComplexType complexType,
                                               XmlSchema parentSchema)
            throws SchemaCompilationException {

        if (processedTypemap.containsKey(complexType.getQName())
            || baseSchemaTypeMap.containsKey(complexType.getQName())) {
            return;
        }

        // Must do this up front to support recursive types
        String fullyQualifiedClassName = writer.makeFullyQualifiedClassName(complexType.getQName());
        processedTypemap.put(complexType.getQName(), fullyQualifiedClassName);

        //register that in the schema metainfo bag
        complexType.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                                fullyQualifiedClassName);

        BeanWriterMetaInfoHolder metaInfHolder = processComplexType(complexType.getQName(),
                                                                    complexType, parentSchema);
        //add this information to the metainfo holder
        metaInfHolder.setOwnQname(complexType.getQName());
        metaInfHolder.setOwnClassName(fullyQualifiedClassName);
        //write the class. This type mapping would have been populated right now
        //Note - We always write classes for named complex types
        writeComplexType(complexType, metaInfHolder);


    }

    /**
     * Writes a complex type
     *
     * @param complexType
     * @param metaInfHolder
     * @throws SchemaCompilationException
     */
    private String writeComplexType(XmlSchemaComplexType complexType,
                                    BeanWriterMetaInfoHolder metaInfHolder)
            throws SchemaCompilationException {
        String javaClassName = writer.write(complexType.getQName(),
                                            processedTypemap, processedGroupTypeMap, metaInfHolder,
                                            complexType.isAbstract());
        processedTypeMetaInfoMap.put(complexType.getQName(), metaInfHolder);
        return javaClassName;
    }


    /**
     * Writes complex Sequence,Choice, all elements
     *
     * @param qname         complex type qname
     * @param metaInfHolder
     * @return written java class name
     * @throws SchemaCompilationException
     */


    private String writeComplexParticle(QName qname, BeanWriterMetaInfoHolder metaInfHolder)
            throws SchemaCompilationException {
        String javaClassName = writer.write(qname, processedTypemap, processedGroupTypeMap,
                                            metaInfHolder, false);
        processedTypeMetaInfoMap.put(qname, metaInfHolder);
        return javaClassName;
    }

    /**
     * Writes a complex type
     *
     * @param simpleType
     * @param metaInfHolder
     * @throws SchemaCompilationException
     */
    private void writeSimpleType(XmlSchemaSimpleType simpleType,
                                 BeanWriterMetaInfoHolder metaInfHolder)
            throws SchemaCompilationException {
        writer.write(simpleType, processedTypemap, processedGroupTypeMap, metaInfHolder);
        processedTypeMetaInfoMap.put(simpleType.getQName(), metaInfHolder);
    }

    private BeanWriterMetaInfoHolder processComplexType(
            QName parentElementQName,
            XmlSchemaComplexType complexType,
            XmlSchema parentSchema) throws SchemaCompilationException {
        XmlSchemaParticle particle = complexType.getParticle();
        BeanWriterMetaInfoHolder metaInfHolder = new BeanWriterMetaInfoHolder();
        if (particle != null) {
            //Process the particle
            processParticle(parentElementQName, particle, metaInfHolder, parentSchema);
        }

        if (complexType.isMixed()) {
            throw new SchemaCompilationException("XSD complexType with mix content not " +
                                                 "supported in ADB");
        }

        //process attributes - first look for the explicit attributes
        processAttributes(complexType.getAttributes(), metaInfHolder, parentSchema);

        //process any attribute
        //somehow the xml schema parser does not seem to pickup the any attribute!!
        XmlSchemaAnyAttribute anyAtt = complexType.getAnyAttribute();
        if (anyAtt != null) {
            processAnyAttribute(metaInfHolder, anyAtt);
        }


        //process content ,either  complex or simple
        if (complexType.getContentModel() != null) {
            processContentModel(complexType.getContentModel(),
                                metaInfHolder,
                                parentSchema);
        }
        return metaInfHolder;
    }

    private void processAttributes(List<XmlSchemaAttributeOrGroupRef> attributes,
                                   BeanWriterMetaInfoHolder metaInfHolder,
                                   XmlSchema parentSchema) throws SchemaCompilationException {

        for (XmlSchemaObject object : attributes) {
            if (object instanceof XmlSchemaAttribute) {
                processAttribute((XmlSchemaAttribute) object, metaInfHolder, parentSchema);
            } else if (object instanceof XmlSchemaAttributeGroupRef) {
                processAttributeGroupReference((XmlSchemaAttributeGroupRef) object, metaInfHolder,
                                               parentSchema);
            }
        }
    }

    private void processGroupAttributes(List<XmlSchemaAttributeGroupMember> attributes,
                                        BeanWriterMetaInfoHolder metaInfHolder,
                                        XmlSchema resolvedSchema)
            throws SchemaCompilationException {
        for (XmlSchemaAttributeGroupMember member : attributes) {
            if (member instanceof XmlSchemaAttribute) {
                processAttribute((XmlSchemaAttribute) member, metaInfHolder, resolvedSchema);
            } else if (member instanceof XmlSchemaAttributeGroupRef) {
                processAttributeGroupReference((XmlSchemaAttributeGroupRef) member, metaInfHolder,
                                               resolvedSchema);
            }
        }
    }


    private void processAttributeGroupReference(XmlSchemaAttributeGroupRef attributeGroupRef,
                                                BeanWriterMetaInfoHolder metaInfHolder,
                                                XmlSchema parentSchema)
            throws SchemaCompilationException {

        QName attributeGroupRefName = attributeGroupRef.getRef().getTargetQName();
        if (attributeGroupRefName != null) {
            XmlSchema resolvedSchema = getParentSchema(parentSchema, attributeGroupRefName,
                                                       COMPONENT_ATTRIBUTE_GROUP);
            if (resolvedSchema == null) {
                throw new SchemaCompilationException("can not find the attribute group reference name " +
                                                     attributeGroupRefName + " from the parent schema " +
                                                     parentSchema.getTargetNamespace());
            } else {
                XmlSchemaAttributeGroup xmlSchemaAttributeGroup =
                        resolvedSchema.getAttributeGroups().get(attributeGroupRefName);
                if (xmlSchemaAttributeGroup != null) {
                    processGroupAttributes(xmlSchemaAttributeGroup.getAttributes(), metaInfHolder,
                                           resolvedSchema);
                } else {
                    throw new SchemaCompilationException("Can not find an attribute group for group reference "
                                                         + attributeGroupRefName.getLocalPart());
                }
            }

        } else {
            throw new SchemaCompilationException("No group refernce has given");
        }
    }

    /**
     * Process the content models. A content model is either simple type or a complex type
     * and included inside a complex content
     */
    private void processContentModel(XmlSchemaContentModel content,
                                     BeanWriterMetaInfoHolder metaInfHolder,
                                     XmlSchema parentSchema)
            throws SchemaCompilationException {
        if (content instanceof XmlSchemaComplexContent) {
            processComplexContent((XmlSchemaComplexContent) content, metaInfHolder, parentSchema);
        } else if (content instanceof XmlSchemaSimpleContent) {
            processSimpleContent((XmlSchemaSimpleContent) content, metaInfHolder, parentSchema);
        }
    }

    /**
     * Prcess the complex content
     */
    private void processComplexContent(XmlSchemaComplexContent complexContent,
                                       BeanWriterMetaInfoHolder metaInfHolder,
                                       XmlSchema parentSchema)
            throws SchemaCompilationException {
        XmlSchemaContent content = complexContent.getContent();

        if (content instanceof XmlSchemaComplexContentExtension) {

            // to handle extension we need to attach the extended items to the base type
            // and create a new type
            XmlSchemaComplexContentExtension extension = (XmlSchemaComplexContentExtension) content;

            //process the base type if it has not been processed yet
            if (!isAlreadyProcessed(extension.getBaseTypeName())) {
                //pick the relevant basetype from the schema and process it
                XmlSchema resolvedSchema = getParentSchema(parentSchema, extension.getBaseTypeName(),
                                                           COMPONENT_TYPE);
                if (resolvedSchema == null) {
                    throw new SchemaCompilationException("can not find the compley type " +
                                                         extension.getBaseTypeName()
                                                         + " from the parent type " +
                                                         parentSchema.getTargetNamespace());
                } else {
                    XmlSchemaType type = resolvedSchema.getTypeByName(extension.getBaseTypeName());
                    if (type instanceof XmlSchemaComplexType) {
                        XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
                        if (complexType.getName() != null) {
                            processNamedComplexSchemaType(complexType, resolvedSchema);
                        } else {
                            //this is not possible. The extension should always
                            //have a name
                            throw new SchemaCompilationException("Unnamed complex type used in extension");//Internationlize this
                        }
                    } else if (type instanceof XmlSchemaSimpleType) {
                        //process simple type
                        processSimpleSchemaType((XmlSchemaSimpleType) type, null, resolvedSchema, null);
                    }
                }

            }

            // before actually processing this node, we need to recurse through the base types and add their
            // children (sometimes even preserving the order) to the metainfo holder of this type
            // the reason is that for extensions, the prefered way is to have the sequences of the base class
            //* before * the sequence of the child element.
            copyMetaInfoHierarchy(metaInfHolder, extension.getBaseTypeName(), parentSchema);

            //process the particle of this node
            if (extension.getParticle() != null) {
                processParticle(extension.getBaseTypeName(), extension.getParticle(), metaInfHolder,
                                parentSchema);
            }

            // process attributes
            //process attributes - first look for the explicit attributes
            processAttributes(extension.getAttributes(), metaInfHolder, parentSchema);

            //process any attribute
            //somehow the xml schema parser does not seem to pickup the any attribute!!
            XmlSchemaAnyAttribute anyAtt = extension.getAnyAttribute();
            if (anyAtt != null) {
                processAnyAttribute(metaInfHolder, anyAtt);
            }
            String className = findClassName(extension.getBaseTypeName(), false);

            if (!writer.getDefaultClassName().equals(className)) {
                //the particle has been processed, However since this is an extension we need to
                //add the basetype as an extension to the complex type class.
                // The basetype has been processed already
                metaInfHolder.setExtension(true);
                metaInfHolder.setExtensionClassName(className);
                //Note  - this is no array! so the array boolean is false
            }
        } else if (content instanceof XmlSchemaComplexContentRestriction) {
            XmlSchemaComplexContentRestriction restriction =
                    (XmlSchemaComplexContentRestriction) content;

            //process the base type if it has not been processed yet
            if (!isAlreadyProcessed(restriction.getBaseTypeName())) {
                //pick the relevant basetype from the schema and process it
                XmlSchema resolvedSchema = getParentSchema(parentSchema,
                                                           restriction.getBaseTypeName(),
                                                           COMPONENT_TYPE);
                if (resolvedSchema == null) {
                    throw new SchemaCompilationException("can not find the complex type " +
                                                         restriction.getBaseTypeName()
                                                         + " from the parent type " +
                                                         parentSchema.getTargetNamespace());
                } else {
                    XmlSchemaType type = resolvedSchema.getTypeByName(restriction.getBaseTypeName());
                    if (type instanceof XmlSchemaComplexType) {
                        XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
                        if (complexType.getName() != null) {
                            processNamedComplexSchemaType(complexType, resolvedSchema);
                        } else {
                            //this is not possible. The restriction should always
                            //have a name
                            throw new SchemaCompilationException("Unnamed complex type used in restriction");//Internationlize this
                        }
                    } else if (type instanceof XmlSchemaSimpleType) {
                        throw new SchemaCompilationException("Not a valid restriction, " +
                                                             "complex content restriction base type cannot be a simple type.");
                    }
                }
            }

            copyMetaInfoHierarchy(metaInfHolder, restriction.getBaseTypeName(), parentSchema);

            //process the particle of this node
            processParticle(restriction.getBaseTypeName(), restriction.getParticle(), metaInfHolder,
                            parentSchema);

            //process attributes - first look for the explicit attributes
            processAttributes(restriction.getAttributes(), metaInfHolder, parentSchema);

            //process any attribute
            //somehow the xml schema parser does not seem to pickup the any attribute!!
            XmlSchemaAnyAttribute anyAtt = restriction.getAnyAttribute();
            if (anyAtt != null) {
                processAnyAttribute(metaInfHolder, anyAtt);
            }
            String className = findClassName(restriction.getBaseTypeName(), false);

            if (!writer.getDefaultClassName().equals(className)) {
                metaInfHolder.setRestriction(true);
                metaInfHolder.setRestrictionClassName(findClassName(restriction.getBaseTypeName(),
                                                                    false));
                //Note  - this is no array! so the array boolean is false
            }
        }
    }

    /**
     * Recursive method to populate the metainfo holders with info from the base types
     *
     * @param metaInfHolder
     * @param baseTypeName
     * @param parentSchema
     */
    private void copyMetaInfoHierarchy(BeanWriterMetaInfoHolder metaInfHolder,
                                       QName baseTypeName,
                                       XmlSchema parentSchema)
            throws SchemaCompilationException {

        XmlSchema resolvedSchema = getParentSchema(parentSchema, baseTypeName, COMPONENT_TYPE);
        if (resolvedSchema == null) {
            throw new SchemaCompilationException("can not find type " + baseTypeName
                                                 + " from the parent schema " +
                                                 parentSchema.getTargetNamespace());
        } else {
            XmlSchemaType type = resolvedSchema.getTypeByName(baseTypeName);
            BeanWriterMetaInfoHolder baseMetaInfoHolder =
                    processedTypeMetaInfoMap.get(baseTypeName);


            if (baseMetaInfoHolder != null) {

                // see whether this type is also extended from some other type first
                // if so proceed to set their parents as well.
                if (type instanceof XmlSchemaComplexType) {
                    XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
                    if (complexType.getContentModel() != null) {
                        XmlSchemaContentModel content = complexType.getContentModel();
                        if (content instanceof XmlSchemaComplexContent) {
                            XmlSchemaComplexContent complexContent =
                                    (XmlSchemaComplexContent) content;
                            if (complexContent.getContent() instanceof
                                    XmlSchemaComplexContentExtension) {
                                XmlSchemaComplexContentExtension extension =
                                        (XmlSchemaComplexContentExtension) complexContent.getContent();
                                //recursively call the copyMetaInfoHierarchy method
                                copyMetaInfoHierarchy(baseMetaInfoHolder,
                                                      extension.getBaseTypeName(),
                                                      resolvedSchema);

                            } else if (complexContent.getContent() instanceof
                                    XmlSchemaComplexContentRestriction) {

                                XmlSchemaComplexContentRestriction restriction =
                                        (XmlSchemaComplexContentRestriction) complexContent.getContent();
                                //recursively call the copyMetaInfoHierarchy method
                                copyMetaInfoHierarchy(baseMetaInfoHolder,
                                                      restriction.getBaseTypeName(),
                                                      resolvedSchema);

                            } else {
                                throw new SchemaCompilationException(
                                        SchemaCompilerMessages.
                                                getMessage("schema.unknowncontenterror"));
                            }

                        } else if (content instanceof XmlSchemaSimpleContent) {

                            XmlSchemaSimpleContent simpleContent = (XmlSchemaSimpleContent) content;
                            if (simpleContent.getContent() instanceof
                                    XmlSchemaSimpleContentExtension) {
                                XmlSchemaSimpleContentExtension extension =
                                        (XmlSchemaSimpleContentExtension) simpleContent
                                        .getContent();
                                // recursively call the copyMetaInfoHierarchy
                                // method
                                copyMetaInfoHierarchy(baseMetaInfoHolder,
                                                      extension.getBaseTypeName(), resolvedSchema);

                            } else if (simpleContent.getContent() instanceof
                                    XmlSchemaSimpleContentRestriction) {

                                XmlSchemaSimpleContentRestriction restriction =
                                        (XmlSchemaSimpleContentRestriction) simpleContent
                                        .getContent();
                                // recursively call the copyMetaInfoHierarchy
                                // method
                                copyMetaInfoHierarchy(baseMetaInfoHolder,
                                                      restriction.getBaseTypeName(), resolvedSchema);

                            }

                        } else {
                            throw new SchemaCompilationException(
                                    SchemaCompilerMessages.getMessage("schema.unknowncontenterror"));
                        }
                    }
                    //Do the actual parent setting
                    metaInfHolder.setAsParent(baseMetaInfoHolder);

                } else if (type instanceof XmlSchemaSimpleType) {

                    // we have to copy the uion data if the parent simple type restriction
                    // is an union
                    // this union attribute is copied from the child to parent to genrate the parent
                    // code as union
                    if (baseMetaInfoHolder.isUnion()) {
                        metaInfHolder.setUnion(true);
                        for (Map.Entry<QName, String> entry : baseMetaInfoHolder.getMemberTypes().entrySet()) {
                            metaInfHolder.addMemberType(entry.getKey(), entry.getValue());
                        }
                    }

                    // we have to copy the list type data to parent if it is a list
                    if (baseMetaInfoHolder.isList()) {
                        metaInfHolder.setList(true);
                        metaInfHolder.setItemTypeQName(baseMetaInfoHolder.getItemTypeQName());
                        metaInfHolder.setItemTypeClassName(baseMetaInfoHolder.getItemTypeClassName());
                    }
                    metaInfHolder.setAsParent(baseMetaInfoHolder);
                }

            }
        }
    }

    /**
     * @param simpleContent
     * @param metaInfHolder
     * @throws SchemaCompilationException
     */
    private void processSimpleContent(XmlSchemaSimpleContent simpleContent,
                                      BeanWriterMetaInfoHolder metaInfHolder,
                                      XmlSchema parentSchema)
            throws SchemaCompilationException {
        XmlSchemaContent content;
        content = simpleContent.getContent();
        if (content instanceof XmlSchemaSimpleContentExtension) {
            XmlSchemaSimpleContentExtension extension = (XmlSchemaSimpleContentExtension) content;

            //process the base type if it has not been processed yet
            if (!isAlreadyProcessed(extension.getBaseTypeName())) {
                //pick the relevant basetype from the schema and process it
                XmlSchema resolvedSchema = getParentSchema(parentSchema, extension.getBaseTypeName(),
                                                           COMPONENT_TYPE);
                if (resolvedSchema == null) {
                    throw new SchemaCompilationException("can not find type " +
                                                         extension.getBaseTypeName()
                                                         + " from the parent schema " +
                                                         parentSchema.getTargetNamespace());
                } else {
                    XmlSchemaType type = resolvedSchema.getTypeByName(extension.getBaseTypeName());
                    if (type instanceof XmlSchemaComplexType) {
                        XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
                        if (complexType.getName() != null) {
                            processNamedComplexSchemaType(complexType, resolvedSchema);
                        } else {
                            //this is not possible. The extension should always
                            //have a name
                            throw new SchemaCompilationException("Unnamed complex type used in extension");//Internationlize this
                        }
                    } else if (type instanceof XmlSchemaSimpleType) {
                        //process simple type
                        processSimpleSchemaType((XmlSchemaSimpleType) type, null, resolvedSchema, null);
                    }
                }

            }

            //process extension base type
            processSimpleExtensionBaseType(extension.getBaseTypeName(), metaInfHolder, parentSchema);

            //process attributes
            for (XmlSchemaAttributeOrGroupRef attr : extension.getAttributes()) {
                if (attr instanceof XmlSchemaAttribute) {
                    processAttribute((XmlSchemaAttribute) attr, metaInfHolder, parentSchema);

                }
            }

            //process any attribute
            XmlSchemaAnyAttribute anyAtt = extension.getAnyAttribute();
            if (anyAtt != null) {
                processAnyAttribute(metaInfHolder, anyAtt);
            }

        } else if (content instanceof XmlSchemaSimpleContentRestriction) {
            XmlSchemaSimpleContentRestriction restriction = (XmlSchemaSimpleContentRestriction) content;

            //process the base type if it has not been processed yet
            if (!isAlreadyProcessed(restriction.getBaseTypeName())) {
                //pick the relevant basetype from the schema and process it
                XmlSchema resolvedSchema = getParentSchema(parentSchema,
                                                           restriction.getBaseTypeName(),
                                                           COMPONENT_TYPE);
                if (resolvedSchema == null) {
                    throw new SchemaCompilationException("can not find type " +
                                                         restriction.getBaseTypeName()
                                                         + " from the parent schema " +
                                                         parentSchema.getTargetNamespace());
                } else {
                    XmlSchemaType type = resolvedSchema.getTypeByName(restriction.getBaseTypeName());

                    if (type instanceof XmlSchemaComplexType) {
                        XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
                        if (complexType.getName() != null) {
                            processNamedComplexSchemaType(complexType, resolvedSchema);
                        } else {
                            //this is not possible. The extension should always
                            //have a name
                            throw new SchemaCompilationException("Unnamed complex type used in restriction");//Internationlize this
                        }
                    } else if (type instanceof XmlSchemaSimpleType) {
                        //process simple type
                        processSimpleSchemaType((XmlSchemaSimpleType) type, null, resolvedSchema, null);
                    }
                }

            }
            //process restriction base type
            processSimpleRestrictionBaseType(restriction.getBaseTypeName(),
                                             restriction.getBaseTypeName(),
                                             metaInfHolder,
                                             parentSchema);
            metaInfHolder.setSimple(true);

            if (!SchemaConstants.XSD_BOOLEAN.equals(restriction.getBaseTypeName())) {
                processFacets(restriction.getFacets(), restriction.getBaseTypeName(), metaInfHolder,
                              parentSchema);
            }
        }
    }

    /**
     * Process Simple Extension Base Type.
     *
     * @param extBaseType
     * @param metaInfHolder
     */
    public void processSimpleExtensionBaseType(QName extBaseType,
                                               BeanWriterMetaInfoHolder metaInfHolder,
                                               XmlSchema parentSchema)
            throws SchemaCompilationException {

        //find the class name
        String className = findClassName(extBaseType, false);

        // if the base type is an primitive then we do not have to extend them
        // and it is considered as a property
        // on the otherhand if the base type is an generated class then we have to
        // extend from it

        if (baseSchemaTypeMap.containsKey(extBaseType)) {
            //this means the schema type actually returns a different QName
            if (changedTypeMap.containsKey(extBaseType)) {
                metaInfHolder.registerMapping(extBaseType,
                                              changedTypeMap.get(extBaseType),
                                              className, SchemaConstants.ELEMENT_TYPE);
            } else {
                metaInfHolder.registerMapping(extBaseType,
                                              extBaseType,
                                              className, SchemaConstants.ELEMENT_TYPE);
            }
            metaInfHolder.setSimple(true);
            // we have already process when it comes to this place
        } else if (processedTypemap.containsKey(extBaseType)) {
            //set the extension base class name
            XmlSchema resolvedSchema = getParentSchema(parentSchema, extBaseType, COMPONENT_TYPE);
            if (resolvedSchema == null) {
                throw new SchemaCompilationException("can not find the type " + extBaseType
                                                     + " from the parent schema " +
                                                     parentSchema.getTargetNamespace());
            } else {
                XmlSchemaType type = resolvedSchema.getTypeByName(extBaseType);
                if (type instanceof XmlSchemaSimpleType) {
                    metaInfHolder.setSimple(true);
                    metaInfHolder.setExtension(true);
                    metaInfHolder.setExtensionClassName(className);

                    copyMetaInfoHierarchy(metaInfHolder, extBaseType, resolvedSchema);
                } else if (type instanceof XmlSchemaComplexType) {
                    XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
                    // do not set as a simple type since we want to
                    // print the element names
                    metaInfHolder.setExtension(true);
                    metaInfHolder.setExtensionClassName(className);
                    copyMetaInfoHierarchy(metaInfHolder, extBaseType, resolvedSchema);
                    XmlSchemaContentModel typeContent = complexType.getContentModel();
                    if (typeContent != null && typeContent instanceof XmlSchemaSimpleContent) {
                        metaInfHolder.setSimple(true);
                    }
                }
            }

        } else {
            metaInfHolder.setSimple(true);
        }

        //get the binary state and add that to the status map
        if (isBinary(extBaseType)) {
            metaInfHolder.addtStatus(extBaseType,
                                     SchemaConstants.BINARY_TYPE);
        }
    }

    /**
     * Process Simple Restriction Base Type.
     *
     * @param resBaseType
     * @param metaInfHolder
     */
    public void processSimpleRestrictionBaseType(QName qName,
                                                 QName resBaseType,
                                                 BeanWriterMetaInfoHolder metaInfHolder,
                                                 XmlSchema parentSchema)
            throws SchemaCompilationException {

        //find the class name
        String className = findClassName(resBaseType, false);

        //this means the schema type actually returns a different QName
        if (baseSchemaTypeMap.containsKey(resBaseType)) {
            if (changedTypeMap.containsKey(resBaseType)) {
                metaInfHolder.registerMapping(qName,
                                              changedTypeMap.get(resBaseType),
                                              className, SchemaConstants.ELEMENT_TYPE);
            } else {
                metaInfHolder.registerMapping(qName,
                                              resBaseType,
                                              className, SchemaConstants.ELEMENT_TYPE);
            }
        } else if (processedTypemap.containsKey(resBaseType)) {
            //this is not a standared type
            // so the parent class must extend it
            metaInfHolder.setSimple(true);
            metaInfHolder.setRestriction(true);
            metaInfHolder.setRestrictionClassName(className);
            copyMetaInfoHierarchy(metaInfHolder, resBaseType, parentSchema);
        }

        metaInfHolder.setRestrictionBaseType(resBaseType);


    }

    /**
     * Process Facets.
     *
     * @param metaInfHolder
     * @param facets
     */
    private void processFacets(List<XmlSchemaFacet> facets, QName restrictionName,
                               BeanWriterMetaInfoHolder metaInfHolder,
                               XmlSchema parentSchema) {

        for (XmlSchemaFacet facet : facets) {
            if (facet instanceof XmlSchemaPatternFacet) {
                XmlSchemaPatternFacet pattern = (XmlSchemaPatternFacet) facet;
                // some patterns contain \ so we have to replace them
                String patternString = pattern.getValue().toString();
                // replace backword slashes
                patternString = patternString.replaceAll("\\\\", "\\\\\\\\");
                patternString = patternString.replaceAll("\"", "\\\\\"");
                if ((metaInfHolder.getPatternFacet() != null) &&
                    (metaInfHolder.getPatternFacet().trim().length() > 0)) {
                    // i.e there is a pattern faceset
                    patternString = metaInfHolder.getPatternFacet().trim() + "|" + patternString;
                }
                metaInfHolder.setPatternFacet(patternString);
            } else if (facet instanceof XmlSchemaEnumerationFacet) {
                XmlSchemaEnumerationFacet enumeration = (XmlSchemaEnumerationFacet) facet;
                if (restrictionName.equals(SchemaConstants.XSD_QNAME)) {
                    // we have to process the qname here and shoud find the local part and namespace uri
                    String value = enumeration.getValue().toString();
                    String prefix = value.substring(0, value.indexOf(":"));
                    String localPart = value.substring(value.indexOf(":") + 1);

                    String namespaceUri = parentSchema.getNamespaceContext().getNamespaceURI(prefix);
                    // set the string to suite for the convertQname method
                    String qNameString = value + "\", \"" + namespaceUri;
                    metaInfHolder.addEnumFacet(qNameString);
                } else {
                    metaInfHolder.addEnumFacet(enumeration.getValue().toString());
                }

            } else if (facet instanceof XmlSchemaLengthFacet) {
                XmlSchemaLengthFacet length = (XmlSchemaLengthFacet) facet;
                metaInfHolder.setLengthFacet(Integer.parseInt(length.getValue().toString()));
            } else if (facet instanceof XmlSchemaTotalDigitsFacet) {
                XmlSchemaTotalDigitsFacet totalDigits = (XmlSchemaTotalDigitsFacet) facet;
                metaInfHolder.setTotalDigitsFacet(totalDigits.getValue().toString());
            } else if (facet instanceof XmlSchemaMaxExclusiveFacet) {
                XmlSchemaMaxExclusiveFacet maxEx = (XmlSchemaMaxExclusiveFacet) facet;
                metaInfHolder.setMaxExclusiveFacet(maxEx.getValue().toString());
            } else if (facet instanceof XmlSchemaMinExclusiveFacet) {
                XmlSchemaMinExclusiveFacet minEx = (XmlSchemaMinExclusiveFacet) facet;
                metaInfHolder.setMinExclusiveFacet(minEx.getValue().toString());
            } else if (facet instanceof XmlSchemaMaxInclusiveFacet) {
                XmlSchemaMaxInclusiveFacet maxIn = (XmlSchemaMaxInclusiveFacet) facet;
                metaInfHolder.setMaxInclusiveFacet(maxIn.getValue().toString());
            } else if (facet instanceof XmlSchemaMinInclusiveFacet) {
                XmlSchemaMinInclusiveFacet minIn = (XmlSchemaMinInclusiveFacet) facet;
                metaInfHolder.setMinInclusiveFacet(minIn.getValue().toString());
            } else if (facet instanceof XmlSchemaMaxLengthFacet) {
                XmlSchemaMaxLengthFacet maxLen = (XmlSchemaMaxLengthFacet) facet;
                metaInfHolder.setMaxLengthFacet(Integer.parseInt(maxLen.getValue().toString()));
            } else if (facet instanceof XmlSchemaMinLengthFacet) {
                XmlSchemaMinLengthFacet minLen = (XmlSchemaMinLengthFacet) facet;
                metaInfHolder.setMinLengthFacet(Integer.parseInt(minLen.getValue().toString()));
            }
        }
    }

    /**
     * Handle any attribute
     *
     * @param metainf
     */
    private void processAnyAttribute(BeanWriterMetaInfoHolder metainf,
                                     XmlSchemaAnyAttribute anyAtt) {

        //The best thing we can do here is to add a set of OMAttributes
        //since attributes do not have the notion of minoccurs/maxoccurs the
        //safest option here is to have an OMAttribute array
        QName qName = new QName(EXTRA_ATTRIBUTE_FIELD_NAME);
        metainf.registerMapping(qName,
                                null,
                                writer.getDefaultAttribArrayClassName(),//always generate an array of
                                //OMAttributes
                                SchemaConstants.ANY_TYPE);
        metainf.addtStatus(qName, SchemaConstants.ATTRIBUTE_TYPE);
        metainf.addtStatus(qName, SchemaConstants.ARRAY_TYPE);

    }


    /**
     * Process the attribute
     *
     * @param att
     * @param metainf
     */
    public void processAttribute(XmlSchemaAttribute att, BeanWriterMetaInfoHolder metainf,
                                 XmlSchema parentSchema)
            throws SchemaCompilationException {

        QName schemaTypeName = att.getSchemaTypeName();
        if (schemaTypeName != null) {
            if (att.getWireName() != null) {
                if (baseSchemaTypeMap.containsKey(schemaTypeName)) {

                    metainf.registerMapping(att.getWireName(), schemaTypeName,
                                            baseSchemaTypeMap.get(schemaTypeName).toString(),
                                            SchemaConstants.ATTRIBUTE_TYPE);

                    // add optional attribute status if set
                    String use = att.getUse().toString();
                    if (USE_NONE.equals(use) || USE_OPTIONAL.equals(use)) {
                        metainf.addtStatus(att.getWireName(), SchemaConstants.OPTIONAL_TYPE);
                    }

                    String className = findClassName(schemaTypeName, false);

                    att.addMetaInfo(
                            SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                            className);
                    // set the default value
                    if (att.getDefaultValue() != null) {
                        metainf.registerDefaultValue(att.getWireName(), att.getDefaultValue());
                    }
                    if (att.getFixedValue() != null) {
                        metainf.registerDefaultValue(att.getWireName(), att.getFixedValue());
                        metainf.registerFixedQName(att.getWireName());
                    }
                    // after
                } else {
                    XmlSchema resolvedSchema = getParentSchema(parentSchema, schemaTypeName,
                                                               COMPONENT_TYPE);
                    if (resolvedSchema == null) {
                        throw new SchemaCompilationException("can not find the type " +
                                                             schemaTypeName +
                                                             " from the parent schema " +
                                                             parentSchema.getTargetNamespace());
                    } else {
                        XmlSchemaType type = resolvedSchema.getTypeByName(schemaTypeName);
                        if (type instanceof XmlSchemaSimpleType) {
                            XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType) type;

                            if (simpleType != null) {
                                if (!isAlreadyProcessed(schemaTypeName)) {
                                    //process simple type
                                    processSimpleSchemaType(simpleType, null, resolvedSchema, null);
                                }
                                metainf.registerMapping(att.getWireName(),
                                                        schemaTypeName,
                                                        processedTypemap.get(schemaTypeName).toString(),
                                                        SchemaConstants.ATTRIBUTE_TYPE);
                                // add optional attribute status if set
                                String use = att.getUse().toString();
                                if (USE_NONE.equals(use) || USE_OPTIONAL.equals(use)) {
                                    metainf.addtStatus(att.getWireName(), SchemaConstants.OPTIONAL_TYPE);
                                }
                            }

                        }
                    }
                }
            } else {
                // this attribute has a type but does not have a name, seems to be invalid
            }

        } else if (att.getRef().getTargetQName() != null) {

            XmlSchema resolvedSchema = getParentSchema(parentSchema, att.getRef().getTargetQName(),
                                                       COMPONENT_ATTRIBUTE);
            if (resolvedSchema == null) {
                throw new SchemaCompilationException("can not find the attribute " +
                                                     att.getRef().getTargetQName() +
                                                     " from the parent schema " +
                                                     parentSchema.getTargetNamespace());
            } else {
                XmlSchemaAttribute xmlSchemaAttribute =
                        resolvedSchema.getAttributes().get(att.getRef().getTargetQName());
                if (xmlSchemaAttribute != null) {
                    // call recursively to process the schema
                    processAttribute(xmlSchemaAttribute, metainf, resolvedSchema);
                } else {
                    throw new SchemaCompilationException("Attribute QName reference refer to an invalid attribute " +
                                                         att.getRef().getTargetQName());
                }
            }

        } else {
            // this attribute refers to a custom type, probably one of the extended simple types.
            // with the inline schema definition
            QName attributeQName = att.getWireName();
            if (attributeQName != null) {
                XmlSchemaSimpleType attributeSimpleType = att.getSchemaType();
                XmlSchema resolvedSchema = parentSchema;
                if (attributeSimpleType == null) {
                    // try to get the schema for using qname
                    QName attributeSchemaQname = att.getSchemaTypeName();
                    if (attributeSchemaQname != null) {
                        resolvedSchema = getParentSchema(parentSchema, attributeSchemaQname,
                                                         COMPONENT_TYPE);
                        if (resolvedSchema == null) {
                            throw new SchemaCompilationException("can not find the type " +
                                                                 attributeSchemaQname
                                                                 + " from the parent schema " +
                                                                 parentSchema.getTargetNamespace());
                        } else {
                            attributeSimpleType = (XmlSchemaSimpleType)
                                    resolvedSchema.getTypeByName(attributeSchemaQname);
                        }
                    }
                }

                if (attributeSimpleType != null) {
                    QName schemaTypeQName = att.getSchemaTypeName();
                    if (schemaTypeQName == null) {
                        // set the parent schema target name space since attribute Qname uri is ""
                        if (attributeSimpleType.getQName() != null) {
                            schemaTypeQName = attributeSimpleType.getQName();
                        } else {
                            schemaTypeQName = new QName(parentSchema.getTargetNamespace(),
                                                        attributeQName.getLocalPart() +
                                                        getNextTypeSuffix(attributeQName.getLocalPart()));

                        }
                    }
                    if (!isAlreadyProcessed(schemaTypeQName)) {
                        // we have to process only if it has not processed
                        processSimpleSchemaType(attributeSimpleType, null, resolvedSchema,
                                                schemaTypeQName);
                    }
                    metainf.registerMapping(att.getWireName(),
                                            schemaTypeQName,
                                            processedTypemap.get(schemaTypeQName).toString(),
                                            SchemaConstants.ATTRIBUTE_TYPE);
                    // add optional attribute status if set
                    String use = att.getUse().toString();
                    if (USE_NONE.equals(use) || USE_OPTIONAL.equals(use)) {
                        metainf.addtStatus(att.getWireName(), SchemaConstants.OPTIONAL_TYPE);
                    }
                } else {
                    // TODO: handle the case when no attribute type specifed
                    log.warn("No attribute type has defined to the Attribute " + attributeQName);
                }

            } else {
                throw new SchemaCompilationException("Attribute QName reference refer to an invalid attribute " +
                                                     attributeQName);
            }

        }
    }

    /**
     * Process a particle- A particle may be a sequence,all or a choice
     *
     * @param parentElementQName - this can either be parent element QName or parent Complex type qname
     * @param particle           - particle being processed
     * @param metainfHolder      -
     * @param parentSchema
     * @throws SchemaCompilationException
     */
    private void processParticle(QName parentElementQName,
                                 XmlSchemaParticle particle,
                                 BeanWriterMetaInfoHolder metainfHolder
            , XmlSchema parentSchema) throws SchemaCompilationException {

        if (particle instanceof XmlSchemaSequence) {
            XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) particle;

            List<XmlSchemaSequenceMember> items = xmlSchemaSequence.getItems();

            if ((xmlSchemaSequence.getMaxOccurs() > 1) && (parentElementQName != null)) {
                // we have to process many sequence types
                BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
                process(parentElementQName, items, beanWriterMetaInfoHolder, true, parentSchema);
                beanWriterMetaInfoHolder.setParticleClass(true);
                QName sequenceQName = new QName(parentElementQName.getNamespaceURI(),
                                                parentElementQName.getLocalPart() + "Sequence");
                String javaClassName = writeComplexParticle(sequenceQName, beanWriterMetaInfoHolder);
                processedTypemap.put(sequenceQName, javaClassName);

                // add this as an array to the original class
                metainfHolder.registerMapping(sequenceQName,
                                              sequenceQName,
                                              findClassName(sequenceQName, true),
                                              SchemaConstants.ARRAY_TYPE);
                metainfHolder.setOrdered(true);
                metainfHolder.registerQNameIndex(sequenceQName, metainfHolder.getOrderStartPoint() + 1);
                metainfHolder.setHasParticleType(true);
                metainfHolder.addtStatus(sequenceQName, SchemaConstants.PARTICLE_TYPE_ELEMENT);
                metainfHolder.addMaxOccurs(sequenceQName, xmlSchemaSequence.getMaxOccurs());
                metainfHolder.addMinOccurs(sequenceQName, xmlSchemaSequence.getMinOccurs());


            } else {
                if (options.isBackwordCompatibilityMode()) {
                    process(parentElementQName, items, metainfHolder, false, parentSchema);
                } else {
                    process(parentElementQName, items, metainfHolder, true, parentSchema);
                }
            }

        } else if (particle instanceof XmlSchemaAll) {
            List<XmlSchemaAllMember> items = ((XmlSchemaAll) particle).getItems();
            processSchemaAllItems(parentElementQName, items, metainfHolder, false, parentSchema);
        } else if (particle instanceof XmlSchemaChoice) {
            XmlSchemaChoice xmlSchemaChoice = (XmlSchemaChoice) particle;
            List<XmlSchemaChoiceMember> items = ((XmlSchemaChoice) particle).getItems();

            if ((xmlSchemaChoice.getMaxOccurs() > 1)) {
                // we have to process many sequence types
                BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
                beanWriterMetaInfoHolder.setChoice(true);
                processChoiceItems(parentElementQName, items, beanWriterMetaInfoHolder, false,
                                   parentSchema);
                beanWriterMetaInfoHolder.setParticleClass(true);
                QName choiceQName = new QName(parentElementQName.getNamespaceURI(),
                                              parentElementQName.getLocalPart() + "Choice");
                String javaClassName = writeComplexParticle(choiceQName, beanWriterMetaInfoHolder);
                processedTypemap.put(choiceQName, javaClassName);

                // add this as an array to the original class
                metainfHolder.registerMapping(choiceQName,
                                              choiceQName,
                                              findClassName(choiceQName, true),
                                              SchemaConstants.ARRAY_TYPE);
                metainfHolder.setOrdered(true);
                metainfHolder.setHasParticleType(true);
                metainfHolder.registerQNameIndex(choiceQName, metainfHolder.getOrderStartPoint() + 1);
                metainfHolder.addtStatus(choiceQName, SchemaConstants.PARTICLE_TYPE_ELEMENT);
                metainfHolder.addMaxOccurs(choiceQName, xmlSchemaChoice.getMaxOccurs());
                metainfHolder.addMinOccurs(choiceQName, xmlSchemaChoice.getMinOccurs());

            } else {
                metainfHolder.setChoice(true);
                processChoiceItems(parentElementQName, items, metainfHolder, false, parentSchema);
            }


        } else if (particle instanceof XmlSchemaGroupRef) {

            XmlSchemaGroupRef xmlSchemaGroupRef = (XmlSchemaGroupRef) particle;
            QName groupQName = xmlSchemaGroupRef.getRefName();
            if (groupQName != null) {
                if (!processedGroupTypeMap.containsKey(groupQName)) {
                    // processe the schema here
                    XmlSchema resolvedParentSchema = getParentSchema(parentSchema, groupQName,
                                                                     COMPONENT_GROUP);
                    if (resolvedParentSchema == null) {
                        throw new SchemaCompilationException("can not find the group " + groupQName
                                                             + " from the parent schema " +
                                                             parentSchema.getTargetNamespace());
                    } else {
                        XmlSchemaGroup xmlSchemaGroup =
                                resolvedParentSchema.getGroups().get(groupQName);
                        processGroup(xmlSchemaGroup, groupQName, resolvedParentSchema);
                    }
                }
            } else {
                throw new SchemaCompilationException("Referenced name is null");
            }
            boolean isArray = xmlSchemaGroupRef.getMaxOccurs() > 1;

            // add this as an array to the original class
            String groupClassName = processedGroupTypeMap.get(groupQName);
            if (isArray) {
                groupClassName = groupClassName + "[]";
            }
            metainfHolder.registerMapping(groupQName, groupQName, groupClassName);
            if (isArray) {
                metainfHolder.addtStatus(groupQName, SchemaConstants.ARRAY_TYPE);
            }
            metainfHolder.addtStatus(groupQName, SchemaConstants.PARTICLE_TYPE_ELEMENT);
            metainfHolder.addMaxOccurs(groupQName, xmlSchemaGroupRef.getMaxOccurs());
            metainfHolder.addMinOccurs(groupQName, xmlSchemaGroupRef.getMinOccurs());
            metainfHolder.setHasParticleType(true);
            metainfHolder.setOrdered(true);
            metainfHolder.registerQNameIndex(groupQName, metainfHolder.getOrderStartPoint() + 1);

        }
    }

    /**
     * @param parentElementQName - this could either be the complex type parentElementQName or element parentElementQName
     * @param items
     * @param metainfHolder
     * @param order
     * @param parentSchema
     * @throws SchemaCompilationException
     */
    private void process(QName parentElementQName,
                         List<XmlSchemaSequenceMember> items,
                         BeanWriterMetaInfoHolder metainfHolder,
                         boolean order,
                         XmlSchema parentSchema) throws SchemaCompilationException {

        Map<XmlSchemaObjectBase, Boolean> processedElementArrayStatusMap =
                new LinkedHashMap<XmlSchemaObjectBase, Boolean>();
        Map processedElementTypeMap = new LinkedHashMap(); // TODO: not sure what is the correct generic type here
        List<QName> localNillableList = new ArrayList<QName>();

        Map<XmlSchemaObjectBase, QName> particleQNameMap = new HashMap<XmlSchemaObjectBase, QName>();

        // this list is used to keep the details of the
        // elements within a choice withing sequence
        List<QName> innerChoiceElementList = new ArrayList<QName>();

        Map<XmlSchemaObjectBase, Integer> elementOrderMap = new HashMap<XmlSchemaObjectBase, Integer>();

        int sequenceCounter = 0;
        for (XmlSchemaSequenceMember member : items) {
            XmlSchemaObject item = (XmlSchemaObject) member;
            //recursively process the element
            processElements(parentElementQName, item, processedElementArrayStatusMap,
                            processedElementTypeMap, elementOrderMap, localNillableList,
                            particleQNameMap, order, sequenceCounter, parentSchema);
            sequenceCounter++;
        }

        addProcessedItemsToMetaInfoHolder(processedElementArrayStatusMap, processedElementTypeMap,
                                          innerChoiceElementList, elementOrderMap, localNillableList,
                                          particleQNameMap, metainfHolder, order, parentSchema);
    }

    private void processChoiceItems(QName parentElementQName,
                                    List<XmlSchemaChoiceMember> items,
                                    BeanWriterMetaInfoHolder metainfHolder,
                                    boolean order,
                                    XmlSchema parentSchema) throws SchemaCompilationException {

        Map<XmlSchemaObjectBase, Boolean> processedElementArrayStatusMap =
                new LinkedHashMap<XmlSchemaObjectBase, Boolean>();
        Map processedElementTypeMap = new LinkedHashMap(); // TODO: not sure what is the correct generic type here
        List<QName> localNillableList = new ArrayList<QName>();

        Map<XmlSchemaObjectBase, QName> particleQNameMap = new HashMap<XmlSchemaObjectBase, QName>();

        // this list is used to keep the details of the
        // elements within a choice withing sequence
        List<QName> innerChoiceElementList = new ArrayList<QName>();

        Map<XmlSchemaObjectBase, Integer> elementOrderMap = new HashMap<XmlSchemaObjectBase, Integer>();

        int sequenceCounter = 0;
        for (XmlSchemaChoiceMember item : items) {
            //recursively process the element
            processElements(parentElementQName, item, processedElementArrayStatusMap,
                            processedElementTypeMap, elementOrderMap, localNillableList,
                            particleQNameMap, order, sequenceCounter, parentSchema);
            sequenceCounter++;
        }
        addProcessedItemsToMetaInfoHolder(processedElementArrayStatusMap, processedElementTypeMap,
                                          innerChoiceElementList, elementOrderMap, localNillableList,
                                          particleQNameMap, metainfHolder, order, parentSchema);

    }


    private void processSchemaAllItems(QName parentElementQName,
                                       List<XmlSchemaAllMember> items,
                                       BeanWriterMetaInfoHolder metainfHolder,
                                       boolean order,
                                       XmlSchema parentSchema) throws SchemaCompilationException {

        Map<XmlSchemaObjectBase, Boolean> processedElementArrayStatusMap =
                new LinkedHashMap<XmlSchemaObjectBase, Boolean>();
        Map processedElementTypeMap = new LinkedHashMap(); // TODO: not sure what is the correct generic type here
        List<QName> localNillableList = new ArrayList<QName>();

        Map<XmlSchemaObjectBase, QName> particleQNameMap = new HashMap<XmlSchemaObjectBase, QName>();

        // this list is used to keep the details of the
        // elements within a choice withing sequence
        List<QName> innerChoiceElementList = new ArrayList<QName>();

        Map<XmlSchemaObjectBase, Integer> elementOrderMap = new HashMap<XmlSchemaObjectBase, Integer>();

        int sequenceCounter = 0;
        for (XmlSchemaAllMember item : items) {
            //recursively process the element
            processElements(parentElementQName, item, processedElementArrayStatusMap,
                            processedElementTypeMap, elementOrderMap, localNillableList,
                            particleQNameMap, order, sequenceCounter, parentSchema);
            sequenceCounter++;
        }
        addProcessedItemsToMetaInfoHolder(processedElementArrayStatusMap, processedElementTypeMap,
                                          innerChoiceElementList, elementOrderMap, localNillableList,
                                          particleQNameMap, metainfHolder, order, parentSchema);

    }


    private void addProcessedItemsToMetaInfoHolder(
            Map<XmlSchemaObjectBase, Boolean> processedElementArrayStatusMap,
            Map processedElementTypeMap,
            List<QName> innerChoiceElementList,
            Map<XmlSchemaObjectBase, Integer> elementOrderMap,
            List<QName> localNillableList,
            Map<XmlSchemaObjectBase, QName> particleQNameMap,
            BeanWriterMetaInfoHolder metainfHolder,
            boolean order,
            XmlSchema parentSchema) throws SchemaCompilationException {

        // loop through the processed items and add them to the matainf object
        int startingItemNumberOrder = metainfHolder.getOrderStartPoint();
        for (XmlSchemaObjectBase child : processedElementArrayStatusMap.keySet()) {

            // process the XmlSchemaElement
            if (child instanceof XmlSchemaElement) {
                XmlSchemaElement elt = (XmlSchemaElement) child;
                QName referencedQName = null;

                if (elt.getWireName() != null) {
                    referencedQName = elt.getWireName();
                    QName schemaTypeQName = elt.getSchemaType() != null ?
                                            elt.getSchemaType().getQName() : elt.getSchemaTypeName();
                    if (schemaTypeQName != null) {
                        String clazzName = (String) processedElementTypeMap.get(elt.getWireName());
                        metainfHolder.registerMapping(referencedQName,
                                                      schemaTypeQName,
                                                      clazzName,
                                                      processedElementArrayStatusMap.get(elt) ?
                                                      SchemaConstants.ARRAY_TYPE :
                                                      SchemaConstants.ELEMENT_TYPE);
                        if (innerChoiceElementList.contains(referencedQName)) {
                            metainfHolder.addtStatus(referencedQName,
                                                     SchemaConstants.INNER_CHOICE_ELEMENT);
                        }
                        // register the default value as well
                        if (elt.getDefaultValue() != null) {
                            metainfHolder.registerDefaultValue(referencedQName, elt.getDefaultValue());
                        }
                        // register the default value as well
                        if (elt.getFixedValue() != null) {
                            metainfHolder.registerDefaultValue(referencedQName, elt.getFixedValue());
                            metainfHolder.registerFixedQName(referencedQName);
                        }
                    }
                }

                if (elt.getRef().getTargetQName() != null) { //probably this is referenced
                    referencedQName = elt.getRef().getTargetQName();
                    boolean arrayStatus = processedElementArrayStatusMap.get(elt);
                    String clazzName = findRefClassName(referencedQName, arrayStatus);
                    if (clazzName == null) {
                        clazzName = findClassName(referencedQName, arrayStatus);
                    }
                    XmlSchema resolvedParentSchema = getParentSchema(parentSchema, referencedQName,
                                                                     COMPONENT_ELEMENT);
                    if (resolvedParentSchema == null) {
                        throw new SchemaCompilationException("Can not find the element " +
                                                             referencedQName +
                                                             " from the parent schema " +
                                                             parentSchema.getTargetNamespace());
                    } else {
                        XmlSchemaElement refElement = resolvedParentSchema.getElementByName(referencedQName);

                        // register the mapping if we found the referenced element
                        // else throw an exception
                        if (refElement != null) {
                            metainfHolder.registerMapping(referencedQName,
                                                          refElement.getSchemaTypeName()
                                    , clazzName,
                                                          arrayStatus ?
                                                          SchemaConstants.ARRAY_TYPE :
                                                          SchemaConstants.ELEMENT_TYPE);
                        } else {
                            if (referencedQName.equals(SchemaConstants.XSD_SCHEMA)) {
                                metainfHolder.registerMapping(referencedQName,
                                                              null,
                                                              writer.getDefaultClassName(),
                                                              SchemaConstants.ANY_TYPE);
                            } else {
                                throw new SchemaCompilationException(SchemaCompilerMessages.
                                        getMessage("schema.referencedElementNotFound",
                                                   referencedQName.toString()));
                            }
                        }
                    }
                }

                if (referencedQName == null) {
                    throw new SchemaCompilationException(SchemaCompilerMessages.
                            getMessage("schema.emptyName"));
                }

                //register the occurence counts
                metainfHolder.addMaxOccurs(referencedQName, elt.getMaxOccurs());
                // if the strict validation off then we consider all elements have minOccurs zero on it
                if (this.options.isOffStrictValidation()) {
                    metainfHolder.addMinOccurs(referencedQName, 0);
                } else {
                    metainfHolder.addMinOccurs(referencedQName, elt.getMinOccurs());
                }
                //we need the order to be preserved. So record the order also
                if (order) {
                    //record the order in the metainf holder
                    metainfHolder.registerQNameIndex(referencedQName,
                                                     startingItemNumberOrder +
                                                     elementOrderMap.get(elt));
                }

                //get the nillable state and register that on the metainf holder
                if (localNillableList.contains(elt.getWireName())) {
                    metainfHolder.registerNillableQName(elt.getWireName());
                }

                //get the binary state and add that to the status map
                if (isBinary(elt)) {
                    metainfHolder.addtStatus(elt.getWireName(),
                                             SchemaConstants.BINARY_TYPE);
                }
                // process the XMLSchemaAny
            } else if (child instanceof XmlSchemaAny) {
                XmlSchemaAny any = (XmlSchemaAny) child;

                //since there is only one element here it does not matter
                //for the constant. However the problem occurs if the users
                //uses the same name for an element decalration
                QName anyElementFieldName = new QName(ANY_ELEMENT_FIELD_NAME);

                //this can be an array or a single element
                boolean isArray = processedElementArrayStatusMap.get(any);
                metainfHolder.registerMapping(anyElementFieldName,
                                              null,
                                              isArray ? writer.getDefaultClassArrayName() : writer.
                                                      getDefaultClassName(),
                                              SchemaConstants.ANY_TYPE);
                //if it's an array register an extra status flag with the system
                if (isArray) {
                    metainfHolder.addtStatus(anyElementFieldName,
                                             SchemaConstants.ARRAY_TYPE);
                }
                metainfHolder.addMaxOccurs(anyElementFieldName, any.getMaxOccurs());
                metainfHolder.addMinOccurs(anyElementFieldName, any.getMinOccurs());

                if (order) {
                    //record the order in the metainf holder for the any
                    metainfHolder.registerQNameIndex(anyElementFieldName,
                                                     startingItemNumberOrder +
                                                     elementOrderMap.get(any));
                }
            } else if (child instanceof XmlSchemaSequence) {
                XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) child;
                QName sequenceQName = particleQNameMap.get(child);
                boolean isArray = xmlSchemaSequence.getMaxOccurs() > 1;

                // add this as an array to the original class
                metainfHolder.registerMapping(sequenceQName,
                                              sequenceQName,
                                              findClassName(sequenceQName, isArray));
                if (isArray) {
                    metainfHolder.addtStatus(sequenceQName, SchemaConstants.ARRAY_TYPE);
                }
                metainfHolder.addtStatus(sequenceQName, SchemaConstants.PARTICLE_TYPE_ELEMENT);
                metainfHolder.addMaxOccurs(sequenceQName, xmlSchemaSequence.getMaxOccurs());
                metainfHolder.addMinOccurs(sequenceQName, xmlSchemaSequence.getMinOccurs());
                metainfHolder.setHasParticleType(true);

                if (order) {
                    //record the order in the metainf holder for the any
                    metainfHolder.registerQNameIndex(sequenceQName,
                                                     startingItemNumberOrder +
                                                     elementOrderMap.get(child));
                }
            } else if (child instanceof XmlSchemaChoice) {
                XmlSchemaChoice xmlSchemaChoice = (XmlSchemaChoice) child;
                QName choiceQName = particleQNameMap.get(child);
                boolean isArray = xmlSchemaChoice.getMaxOccurs() > 1;

                // add this as an array to the original class
                metainfHolder.registerMapping(choiceQName,
                                              choiceQName,
                                              findClassName(choiceQName, isArray));
                if (isArray) {
                    metainfHolder.addtStatus(choiceQName, SchemaConstants.ARRAY_TYPE);
                }
                metainfHolder.addtStatus(choiceQName, SchemaConstants.PARTICLE_TYPE_ELEMENT);
                metainfHolder.addMaxOccurs(choiceQName, xmlSchemaChoice.getMaxOccurs());
                metainfHolder.addMinOccurs(choiceQName, xmlSchemaChoice.getMinOccurs());
                metainfHolder.setHasParticleType(true);

                if (order) {
                    //record the order in the metainf holder for the any
                    metainfHolder.registerQNameIndex(choiceQName,
                                                     startingItemNumberOrder +
                                                     elementOrderMap.get(child));
                }
            } else if (child instanceof XmlSchemaGroupRef) {
                XmlSchemaGroupRef xmlSchemaGroupRef = (XmlSchemaGroupRef) child;
                QName groupQName = particleQNameMap.get(child);
                boolean isArray = xmlSchemaGroupRef.getMaxOccurs() > 1;

                // add this as an array to the original class
                String groupClassName = processedGroupTypeMap.get(groupQName);
                if (isArray) {
                    groupClassName = groupClassName + "[]";
                }
                metainfHolder.registerMapping(groupQName,
                                              groupQName,
                                              groupClassName);
                if (isArray) {
                    metainfHolder.addtStatus(groupQName, SchemaConstants.ARRAY_TYPE);
                }
                metainfHolder.addtStatus(groupQName, SchemaConstants.PARTICLE_TYPE_ELEMENT);
                metainfHolder.addMaxOccurs(groupQName, xmlSchemaGroupRef.getMaxOccurs());
                metainfHolder.addMinOccurs(groupQName, xmlSchemaGroupRef.getMinOccurs());
                metainfHolder.setHasParticleType(true);

                if (order) {
                    //record the order in the metainf holder for the any
                    metainfHolder.registerQNameIndex(groupQName,
                                                     startingItemNumberOrder +
                                                     elementOrderMap.get(child));
                }
            }
        }

        //set the ordered flag in the metainf holder
        metainfHolder.setOrdered(order);

    }

    private void processElements(QName parentElementQName, XmlSchemaObjectBase item,
                                 Map<XmlSchemaObjectBase, Boolean> processedElementArrayStatusMap,
                                 Map processedElementTypeMap,
                                 Map<XmlSchemaObjectBase, Integer> elementOrderMap,
                                 List<QName> localNillableList,
                                 Map<XmlSchemaObjectBase, QName> particleQNameMap,
                                 boolean order, int sequenceCounter,
                                 XmlSchema parentSchema) throws SchemaCompilationException {

        if (item instanceof XmlSchemaElement) {
            //recursively process the element
            XmlSchemaElement xsElt = (XmlSchemaElement) item;

            boolean isArray = isArray(xsElt);
            processElement(xsElt, processedElementTypeMap, localNillableList, parentSchema); //we know for sure this is not an outer type
            processedElementArrayStatusMap.put(xsElt, isArray);
            if (order) {
                //we need to keep the order of the elements. So push the elements to another
                //hashmap with the order number
                elementOrderMap.put(xsElt, sequenceCounter);
            }

            //handle xsd:any ! We place an OMElement (or an array of OMElements) in the generated class
        } else if (item instanceof XmlSchemaAny) {
            XmlSchemaAny any = (XmlSchemaAny) item;
            processedElementTypeMap.put(new QName(ANY_ELEMENT_FIELD_NAME), any);
            //any can also be inside a sequence
            if (order) {
                elementOrderMap.put(any, new Integer(sequenceCounter));
            }
            //we do not register the array status for the any type
            processedElementArrayStatusMap.put(any, isArray(any));
        } else if (item instanceof XmlSchemaSequence) {
            // we have to process many sequence types

            XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) item;
            if (xmlSchemaSequence.getItems().size() > 0) {
                BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
                process(parentElementQName, xmlSchemaSequence.getItems(), beanWriterMetaInfoHolder,
                        true, parentSchema);
                beanWriterMetaInfoHolder.setParticleClass(true);
                String localName = parentElementQName.getLocalPart() + "Sequence";
                QName sequenceQName = new QName(parentElementQName.getNamespaceURI(),
                                                localName + getNextTypeSuffix(localName));
                String javaClassName = writeComplexParticle(sequenceQName, beanWriterMetaInfoHolder);
                processedTypemap.put(sequenceQName, javaClassName);

                //put the partical to array
                Boolean isArray = xmlSchemaSequence.getMaxOccurs() > 1 ? Boolean.TRUE : Boolean.FALSE;
                processedElementArrayStatusMap.put(item, isArray);
                particleQNameMap.put(item, sequenceQName);

                if (order) {
                    elementOrderMap.put(item, new Integer(sequenceCounter));
                }
            }

        } else if (item instanceof XmlSchemaChoice) {
            // we have to process many sequence types

            XmlSchemaChoice xmlSchemaChoice = (XmlSchemaChoice) item;
            if (xmlSchemaChoice.getItems().size() > 0) {
                BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
                beanWriterMetaInfoHolder.setChoice(true);
                processChoiceItems(parentElementQName, xmlSchemaChoice.getItems(),
                                   beanWriterMetaInfoHolder, false, parentSchema);
                beanWriterMetaInfoHolder.setParticleClass(true);
                String localName = parentElementQName.getLocalPart() + "Choice";
                QName choiceQName = new QName(parentElementQName.getNamespaceURI(),
                                              localName + getNextTypeSuffix(localName));
                String javaClassName = writeComplexParticle(choiceQName, beanWriterMetaInfoHolder);
                processedTypemap.put(choiceQName, javaClassName);

                //put the partical to array
                Boolean isArray = xmlSchemaChoice.getMaxOccurs() > 1 ? Boolean.TRUE : Boolean.FALSE;
                processedElementArrayStatusMap.put(item, isArray);
                particleQNameMap.put(item, choiceQName);

                if (order) {
                    elementOrderMap.put(item, new Integer(sequenceCounter));
                }
            }

        } else if (item instanceof XmlSchemaGroupRef) {

            XmlSchemaGroupRef xmlSchemaGroupRef = (XmlSchemaGroupRef) item;
            QName groupQName = xmlSchemaGroupRef.getRefName();
            if (groupQName != null) {
                if (!processedGroupTypeMap.containsKey(groupQName)) {
                    // processe the schema here
                    XmlSchema resolvedParentSchema = getParentSchema(parentSchema, groupQName,
                                                                     COMPONENT_GROUP);
                    if (resolvedParentSchema == null) {
                        throw new SchemaCompilationException("Can not find the group with the qname" +
                                                             groupQName + " from the parent schema " +
                                                             parentSchema.getTargetNamespace());
                    } else {
                        XmlSchemaGroup xmlSchemaGroup =
                                (XmlSchemaGroup) resolvedParentSchema.getGroups().get(groupQName);
                        if (xmlSchemaGroup != null) {
                            processGroup(xmlSchemaGroup, groupQName, resolvedParentSchema);
                        }
                    }
                }

                Boolean isArray = xmlSchemaGroupRef.getMaxOccurs() > 1 ? Boolean.TRUE : Boolean.FALSE;
                processedElementArrayStatusMap.put(item, isArray);
                particleQNameMap.put(item, groupQName);

                if (order) {
                    elementOrderMap.put(item, new Integer(sequenceCounter));
                }

            } else {
                throw new SchemaCompilationException("Referenced name is null");
            }
        } else {
            //there may be other types to be handled here. Add them
            //when we are ready
        }

    }


    /**
     * @param xmlSchemaGroup
     * @param schemaGroupQName- we have to pass this since xml schema does not provide
     *                          this properly
     * @param parentSchema
     * @throws SchemaCompilationException
     */

    private void processGroup(XmlSchemaGroup xmlSchemaGroup,
                              QName schemaGroupQName,
                              XmlSchema parentSchema) throws SchemaCompilationException {

        // find the group base item
        XmlSchemaGroupParticle xmlSchemaGroupParticle = xmlSchemaGroup.getParticle();
        if (xmlSchemaGroupParticle != null) {
            if (xmlSchemaGroupParticle instanceof XmlSchemaSequence) {
                XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) xmlSchemaGroupParticle;
                if (xmlSchemaSequence.getItems().size() > 0) {
                    BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
                    process(schemaGroupQName, xmlSchemaSequence.getItems(), beanWriterMetaInfoHolder,
                            true, parentSchema);
                    beanWriterMetaInfoHolder.setParticleClass(true);
                    String javaClassName = writeComplexParticle(schemaGroupQName,
                                                                beanWriterMetaInfoHolder);
                    processedGroupTypeMap.put(schemaGroupQName, javaClassName);
//                    processedTypemap.put(schemaGroupQName, javaClassName);
                }

            } else if (xmlSchemaGroupParticle instanceof XmlSchemaChoice) {
                XmlSchemaChoice xmlSchemaChoice = (XmlSchemaChoice) xmlSchemaGroupParticle;
                if (xmlSchemaChoice.getItems().size() > 0) {
                    BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
                    beanWriterMetaInfoHolder.setChoice(true);
                    processChoiceItems(schemaGroupQName, xmlSchemaChoice.getItems(),
                                       beanWriterMetaInfoHolder, false, parentSchema);
                    beanWriterMetaInfoHolder.setParticleClass(true);
                    String javaClassName = writeComplexParticle(schemaGroupQName,
                                                                beanWriterMetaInfoHolder);
                    processedGroupTypeMap.put(schemaGroupQName, javaClassName);
//                    processedTypemap.put(schemaGroupQName, javaClassName);
                }
            }
        }
    }

    /**
     * Checks whether a given element is a binary element
     *
     * @param elt
     */
    private boolean isBinary(XmlSchemaElement elt) {
        return elt.getSchemaType() != null &&
               SchemaConstants.XSD_BASE64.equals(elt.getSchemaType().getQName());
    }

    /**
     * Checks whether a given qname is a binary
     *
     * @param qName
     */
    private boolean isBinary(QName qName) {
        return qName != null &&
               SchemaConstants.XSD_BASE64.equals(qName);
    }

    /**
     * @param simpleType
     * @param xsElt
     * @param parentSchema
     * @param qname        - fake Qname to use if the xsElt is null.
     * @throws SchemaCompilationException
     */
    private void processSimpleSchemaType(XmlSchemaSimpleType simpleType,
                                         XmlSchemaElement xsElt,
                                         XmlSchema parentSchema,
                                         QName qname) throws SchemaCompilationException {

        String fullyQualifiedClassName = null;
        if (simpleType.getQName() != null) {
            if (processedTypemap.containsKey(simpleType.getQName())
                || baseSchemaTypeMap.containsKey(simpleType.getQName())) {
                return;
            }

            // Must do this up front to support recursive types
            fullyQualifiedClassName = writer.makeFullyQualifiedClassName(simpleType.getQName());
            // we put the qname to processed type map it is only named type
            // otherwise we have to any way process that element.
            processedTypemap.put(simpleType.getQName(), fullyQualifiedClassName);
        } else {

            QName fakeQname;
            if (xsElt != null) {
                fakeQname = new QName(xsElt.getQName().getNamespaceURI(),
                                      xsElt.getQName().getLocalPart() +
                                      getNextTypeSuffix(xsElt.getQName().getLocalPart()));
                // we have to set this otherwise the ours attribute would not set properly if refered to this simple
                // type from any other element
                xsElt.setSchemaTypeName(fakeQname);
                changedElementSet.add(xsElt);

            } else {
                fakeQname = qname;
            }
            if (processedTypemap.containsKey(fakeQname)
                || baseSchemaTypeMap.containsKey(fakeQname)) {
                return;
            }
            fullyQualifiedClassName = writer.makeFullyQualifiedClassName(fakeQname);
            simpleType.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.FAKE_QNAME, fakeQname);

            // should put this to the processedTypemap to generate the code correctly
            processedTypemap.put(fakeQname, fullyQualifiedClassName);
        }

        //register that in the schema metainfo bag
        simpleType.addMetaInfo(SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
                               fullyQualifiedClassName);

        BeanWriterMetaInfoHolder metaInfHolder = processSimpleType(simpleType, parentSchema);
        metaInfHolder.setSimple(true);

        if (simpleType.getQName() == null) {
            this.processedAnonymousComplexTypesMap.put(xsElt, metaInfHolder);
            QName fakeQname;
            if (xsElt != null) {
                fakeQname = new QName(xsElt.getQName().getNamespaceURI(),
                                      xsElt.getQName().getLocalPart());
            } else {
                fakeQname = qname;
                simpleType.setName(fakeQname.getLocalPart());
                changedSimpleTypeSet.add(simpleType);
                simpleType.setSourceURI(fakeQname.getNamespaceURI());
            }
            simpleTypesMap.put(fakeQname, fullyQualifiedClassName);
        }
        //add this information to the metainfo holder
        metaInfHolder.setOwnQname(simpleType.getQName());
        if (fullyQualifiedClassName != null) {
            metaInfHolder.setOwnClassName(fullyQualifiedClassName);
        }
        //write the class. This type mapping would have been populated right now
        //Note - We always write classes for named complex types
        writeSimpleType(simpleType, metaInfHolder);
    }

    private BeanWriterMetaInfoHolder processSimpleType(XmlSchemaSimpleType simpleType,
                                                       XmlSchema parentSchema)
            throws SchemaCompilationException {
        BeanWriterMetaInfoHolder metaInfHolder = new BeanWriterMetaInfoHolder();

        // handle the restriction
        XmlSchemaSimpleTypeContent content = simpleType.getContent();
        QName parentSimpleTypeQname = simpleType.getQName();
        if (parentSimpleTypeQname == null) {
            parentSimpleTypeQname = (QName) simpleType.getMetaInfoMap().
                    get(SchemaConstants.SchemaCompilerInfoHolder.FAKE_QNAME);
        }
        if (content != null) {
            if (content instanceof XmlSchemaSimpleTypeRestriction) {
                XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction) content;

                QName baseTypeName = restriction.getBaseTypeName();
                //check whether the base type is one of the base schema types

                if (baseSchemaTypeMap.containsKey(baseTypeName)) {
                    //process restriction base type

                    processSimpleRestrictionBaseType(parentSimpleTypeQname,
                                                     restriction.getBaseTypeName(), metaInfHolder,
                                                     parentSchema);
                    //process facets
                    if (!SchemaConstants.XSD_BOOLEAN.equals(baseTypeName)) {
                        processFacets(restriction.getFacets(), restriction.getBaseTypeName(),
                                      metaInfHolder, parentSchema);
                    }
                } else {
                    //recurse
                    // this must be a xmlschema bug
                    // it should return the schematype for restriction.getBaseType():
                    XmlSchema resolvedSchema = getParentSchema(parentSchema, baseTypeName,
                                                               COMPONENT_TYPE);
                    if (resolvedSchema == null) {
                        throw new SchemaCompilationException("can not find the type " + baseTypeName +
                                                             " from the parent schema " +
                                                             parentSchema.getTargetNamespace());
                    } else {
                        XmlSchemaType restrictionBaseType = resolvedSchema.getTypeByName(baseTypeName);
                        if (restrictionBaseType instanceof XmlSchemaSimpleType) {
                            if ((restrictionBaseType != null) && (!isAlreadyProcessed(baseTypeName))) {
                                processSimpleSchemaType((XmlSchemaSimpleType) restrictionBaseType,
                                                        null, resolvedSchema, null);
                            }
                            // process restriction
                            processSimpleRestrictionBaseType(parentSimpleTypeQname,
                                                             restriction.getBaseTypeName(),
                                                             metaInfHolder, resolvedSchema);
                        }
                    }

                }
            } else if (content instanceof XmlSchemaSimpleTypeUnion) {
                XmlSchemaSimpleTypeUnion simpleTypeUnion = (XmlSchemaSimpleTypeUnion) content;
                QName[] qnames = simpleTypeUnion.getMemberTypesQNames();
                if (qnames != null) {
                    QName qname;
                    for (int i = 0; i < qnames.length; i++) {
                        qname = qnames[i];
                        if (baseSchemaTypeMap.containsKey(qname)) {
                            metaInfHolder.addMemberType(qname, baseSchemaTypeMap.get(qname));
                        } else {
                            XmlSchema resolvedSchema = getParentSchema(parentSchema, qname,
                                                                       COMPONENT_TYPE);
                            if (resolvedSchema == null) {
                                throw new SchemaCompilationException("can not find the type " + qname +
                                                                     " from the parent schema " +
                                                                     parentSchema.getTargetNamespace());
                            } else {
                                XmlSchemaType type = resolvedSchema.getTypeByName(qname);
                                if (type instanceof XmlSchemaSimpleType) {
                                    XmlSchemaSimpleType memberSimpleType = (XmlSchemaSimpleType) type;
                                    if (!isAlreadyProcessed(qname)) {
                                        processSimpleSchemaType(memberSimpleType, null,
                                                                resolvedSchema, null);
                                    }
                                    metaInfHolder.addMemberType(qname, processedTypemap.get(qname));
                                } else {
                                    throw new SchemaCompilationException("Unions can not have complex types as a member type");
                                }
                            }
                        }
                    }
                } else {
                    QName childQname;
                    int i = 1;
                    for (XmlSchemaSimpleType xmlSchemaObject : simpleTypeUnion.getBaseTypes()) {
                        i++;
                        XmlSchemaSimpleType unionSimpleType = xmlSchemaObject;
                        childQname = unionSimpleType.getQName();
                        if (childQname == null) {
                            // we create a fake Qname for all these simple types since most propably they don't have one
                            childQname = new QName(parentSimpleTypeQname.getNamespaceURI(),
                                                   parentSimpleTypeQname.getLocalPart() +
                                                   getNextTypeSuffix(parentSimpleTypeQname.
                                                           getLocalPart()));
                        }
                        // this is an inner simple type of the union so it shold not have
                        // processed
                        processSimpleSchemaType(unionSimpleType, null, parentSchema, childQname);
                        metaInfHolder.addMemberType(childQname, processedTypemap.get(childQname));


                    }
                }

                metaInfHolder.setUnion(true);

            } else if (content instanceof XmlSchemaSimpleTypeList) {
                XmlSchemaSimpleTypeList simpleTypeList = (XmlSchemaSimpleTypeList) content;
                QName itemTypeQName = simpleTypeList.getItemTypeName();

                if (itemTypeQName != null) {
                    if (!isAlreadyProcessed(itemTypeQName)) {
                        XmlSchema resolvedSchema = getParentSchema(parentSchema, itemTypeQName,
                                                                   COMPONENT_TYPE);
                        if (resolvedSchema == null) {
                            throw new SchemaCompilationException("can not find the type " +
                                                                 itemTypeQName +
                                                                 " from the parent type " +
                                                                 parentSchema.getTargetNamespace());
                        } else {
                            XmlSchemaType simpleSchemaType = resolvedSchema.
                                    getTypeByName(itemTypeQName);
                            if (simpleSchemaType instanceof XmlSchemaSimpleType) {
                                processSimpleSchemaType((XmlSchemaSimpleType) simpleSchemaType,
                                                        null, resolvedSchema, null);
                            }
                        }
                    }
                } else {
                    XmlSchemaSimpleType listSimpleType = simpleTypeList.getItemType();
                    itemTypeQName = listSimpleType.getQName();
                    if (itemTypeQName == null) {
                        // we create a fake Qname for all these simple types since most propably they don't have one
                        itemTypeQName = new QName(parentSimpleTypeQname.getNamespaceURI(),
                                                  parentSimpleTypeQname.getLocalPart() + "_type0");
                    }
                    processSimpleSchemaType(listSimpleType, null, parentSchema, itemTypeQName);

                }

                String className = findClassName(itemTypeQName, false);
                metaInfHolder.setList(true);
                metaInfHolder.setItemTypeQName(itemTypeQName);
                metaInfHolder.setItemTypeClassName(className);

            }
        }
        return metaInfHolder;
    }


    /**
     * Find whether a given particle is an array. The logic for deciding
     * whether a given particle is an array is depending on their minOccurs
     * and maxOccurs counts. If Maxoccurs is greater than one (1) then the
     * content is an array.
     * Also no higher level element will have the maxOccurs greater than one
     *
     * @param particle
     * @throws SchemaCompilationException
     */
    private boolean isArray(XmlSchemaParticle particle) throws SchemaCompilationException {
        long minOccurs = particle.getMinOccurs();
        long maxOccurs = particle.getMaxOccurs();

        if (maxOccurs < minOccurs) {
            throw new SchemaCompilationException();
        } else {
            return (maxOccurs > 1);
        }

    }

    HashMap<String, Integer> mapTypeCount = new HashMap<String, Integer>();

    private String getNextTypeSuffix(String localName) {
        Integer typeCounter = mapTypeCount.get(localName);
        int count = 0;
        if (typeCounter != null) {
            if (typeCounter.intValue() == Integer.MAX_VALUE) {
                count = 0;
            } else {
                count = typeCounter.intValue();
            }
        }
        mapTypeCount.put(localName, count + 1);
        return ("_type" + count);
    }

    /**
     * returns the parent schema of the componet having QName compoentTypeQName.
     * withe the componet type.
     *
     * @param parentSchema   - parent schema of the given componet
     * @param componentQName - qname of the componet, of which we want to get the parent schema
     * @param componetType   - type of the componet. this can either be type,element,attribute or attribute group
     * @return parent schema.
     */

    private XmlSchema getParentSchema(XmlSchema parentSchema,
                                      QName componentQName,
                                      int componetType) throws SchemaCompilationException {
        // if the componet do not have a propernamesapce or
        // it is equals to the xsd schema namesapce
        // we do not have to do any thing.
        if ((componentQName == null) ||
            (componentQName.getNamespaceURI() == null) ||
            Constants.URI_2001_SCHEMA_XSD.equals(componentQName.getNamespaceURI())) {
            return parentSchema;
        }

        List<XmlSchema> visitedSchemas = new ArrayList<XmlSchema>();
        visitedSchemas.add(parentSchema);
        XmlSchema newParentSchema = getParentSchemaFromIncludes(parentSchema,
                                                                componentQName, componetType,
                                                                visitedSchemas);
        if (newParentSchema == null) {
            String targetNamespace = componentQName.getNamespaceURI();
            if (loadedSchemaMap.containsKey(targetNamespace)) {
                XmlSchema tempSchema = loadedSchemaMap.get(targetNamespace);
                if (isComponetExists(tempSchema, componentQName, componetType)) {
                    newParentSchema = tempSchema;
                }
            } else if (availableSchemaMap.containsKey(targetNamespace)) {
                XmlSchema tempSchema = availableSchemaMap.get(targetNamespace);
                if (isComponetExists(tempSchema, componentQName, componetType)) {
                    newParentSchema = tempSchema;
                }
            }
        }
        return newParentSchema;
    }

    private XmlSchema getParentSchemaFromIncludes(XmlSchema parentSchema,
                                                  QName componentQName,
                                                  int componetType,
                                                  List<XmlSchema> visitedSchemas)
            throws SchemaCompilationException {

        XmlSchema newParentSchema = null;
        if (isComponetExists(parentSchema, componentQName, componetType)) {
            newParentSchema = parentSchema;
        } else {
            // this componet must either be in a import or and include

            XmlSchema externalSchema = null;
            for (XmlSchemaExternal externalComponent : parentSchema.getExternals()) {
                externalSchema = externalComponent.getSchema();

                // if this is an inline import without a schema location
                // xmlschema does not load the schema.
                // so we try to figure out it either from the available schemas
                // or from the laded schemas.
                if ((externalSchema == null) && externalComponent instanceof XmlSchemaImport) {
                    XmlSchemaImport xmlSchemaImport = (XmlSchemaImport) externalComponent;
                    String importNamespce = xmlSchemaImport.getNamespace();
                    if ((importNamespce != null) && !importNamespce.
                            equals(Constants.URI_2001_SCHEMA_XSD)) {
                        if (loadedSchemaMap.containsKey(importNamespce)) {
                            externalSchema = loadedSchemaMap.get(importNamespce);
                        } else if (availableSchemaMap.containsKey(importNamespce)) {
                            XmlSchema tempSchema = availableSchemaMap.get(importNamespce);
                            compile(tempSchema);
                            externalSchema = tempSchema;
                        }
                    }
                }
                if (externalSchema != null) {
                    // find the componet in the new external schema.
                    if (!visitedSchemas.contains(externalSchema)) {
                        visitedSchemas.add(externalSchema);
                        newParentSchema = getParentSchemaFromIncludes(externalSchema,
                                                                      componentQName, componetType,
                                                                      visitedSchemas);
                    }
                }
                if (newParentSchema != null) {
                    // i.e we have found the schema
                    break;
                }
            }
        }
        return newParentSchema;
    }

    private boolean isComponetExists(XmlSchema schema,
                                     QName componentQName,
                                     int componetType) {
        //first we need to check whether we checking the correct schema.
        if ((schema.getTargetNamespace() != null)
            && (!schema.getTargetNamespace().equals(componentQName.getNamespaceURI()))) {
            return false;
        }

        boolean isExists = false;
        switch (componetType) {
            case COMPONENT_TYPE: {
                isExists = (schema.getTypeByName(componentQName.getLocalPart()) != null);
                break;
            }
            case COMPONENT_ELEMENT: {
                isExists = (schema.getElementByName(componentQName.getLocalPart()) != null);
                break;
            }
            case COMPONENT_ATTRIBUTE: {
                isExists = (schema.getAttributes().get(componentQName) != null);
                break;
            }
            case COMPONENT_ATTRIBUTE_GROUP: {
                isExists = (schema.getAttributeGroups().get(componentQName) != null);
                break;
            }
            case COMPONENT_GROUP: {
                isExists = (schema.getGroups().get(componentQName) != null);
                break;
            }
        }
        return isExists;
    }

    public Map<String, XmlSchema> getLoadedSchemaMap() {
        return this.loadedSchemaMap;
    }
}
