/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
// dmccann - Mar 2/2009 - 2.0 - Initial implementation
package org.eclipse.persistence.internal.oxm.schema;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Vector;

import javax.xml.namespace.QName;

import org.eclipse.persistence.core.descriptors.CoreInheritancePolicy;
import org.eclipse.persistence.core.mappings.CoreMapping;
import org.eclipse.persistence.core.mappings.converters.CoreConverter;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.ConversionManager;
import org.eclipse.persistence.internal.oxm.Namespace;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.XMLChoiceFieldToClassAssociation;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.AnyAttributeMapping;
import org.eclipse.persistence.internal.oxm.mappings.AnyCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.AnyObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.BinaryDataCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.BinaryDataMapping;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.CollectionReferenceMapping;
import org.eclipse.persistence.internal.oxm.mappings.CompositeCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.CompositeObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.DirectCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.DirectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.internal.oxm.schema.model.Any;
import org.eclipse.persistence.internal.oxm.schema.model.AnyAttribute;
import org.eclipse.persistence.internal.oxm.schema.model.Attribute;
import org.eclipse.persistence.internal.oxm.schema.model.Choice;
import org.eclipse.persistence.internal.oxm.schema.model.ComplexContent;
import org.eclipse.persistence.internal.oxm.schema.model.ComplexType;
import org.eclipse.persistence.internal.oxm.schema.model.Element;
import org.eclipse.persistence.internal.oxm.schema.model.Extension;
import org.eclipse.persistence.internal.oxm.schema.model.Import;
import org.eclipse.persistence.internal.oxm.schema.model.Occurs;
import org.eclipse.persistence.internal.oxm.schema.model.Restriction;
import org.eclipse.persistence.internal.oxm.schema.model.Schema;
import org.eclipse.persistence.internal.oxm.schema.model.Sequence;
import org.eclipse.persistence.internal.oxm.schema.model.SimpleContent;
import org.eclipse.persistence.internal.oxm.schema.model.SimpleType;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.EnumTypeConverter;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
import org.eclipse.persistence.sessions.Project;

/**
 * INTERNAL:
 *  <p><b>Purpose:</b>Generate one or more EclipseLink Schema model objects based
 *  on a given list of XMLDescriptors.
 *  <p><b>Responsibilities:</b><ul>
 *  <li>Return a Map of generated EclipseLink Schema objects based on a given list of XMLDescriptors</li>
 *  </ul>
 *  <p> This class will create and populate one or more EclipseLink schema model Schema objects for a
 *  given list of EclipseLink XMLDescriptors.
 *
 *  @see Schema
 *  @see XMLDescriptor
 */
public class SchemaModelGenerator {
    protected static final String SCHEMA_FILE_NAME = "schema";
    protected static final String SCHEMA_FILE_EXT = ".xsd";
    protected static final String TEXT = "text()";
    protected static final String ID = "ID";
    protected static final String IDREF = "IDREF";
    protected static String SWAREF_LOCATION;

    private ConversionManager conversionManager;

    /**
     * The default constructor.
     */
    public SchemaModelGenerator(ConversionManager conversionManager) {
        this(conversionManager, false);
    }

    /**
     * This constructor should be used with a value of 'true' when the schemaLocation
     * attribute of the import for swaRef should be swaref.xsd.  This is useful when
     * the user has a local copy of the swaRef schema and wants to use it when access
     * to external URLs is not available.  The default value is:
     * "http://ws-i.org/profiles/basic/1.1/swaref.xsd".
     */
    public SchemaModelGenerator(ConversionManager conversionManager, boolean customSwaRefSchema) {
        this.conversionManager = conversionManager;
        if (customSwaRefSchema) {
            SWAREF_LOCATION = Constants.SWA_REF.toLowerCase() + SCHEMA_FILE_EXT;
        } else {
            SWAREF_LOCATION = Constants.SWAREF_XSD;
        }
    }

    /**
     * Generates a Map of EclipseLink schema model Schema objects for a given list of XMLDescriptors.
     * The descriptors are assumed to have been initialized.  One Schema  object will be generated
     * per namespace.
     *
     * @param descriptorsToProcess list of XMLDescriptors which will be used to generate Schema objects
     * @param properties holds a namespace to Properties map containing schema settings, such as elementFormDefault
     * @param additionalGlobalElements a map of QName-Type entries identifying additional global elements to be added
     * @return a map of namespaces to EclipseLink schema model Schema objects
     * @throws DescriptorException if the reference descriptor for a composite mapping is not in the list of descriptors
     * @see Schema
     */
    public Map<String, Schema> generateSchemas(List<Descriptor> descriptorsToProcess, SchemaModelGeneratorProperties properties, Map<QName, Type> additionalGlobalElements) throws DescriptorException {
        Map<String, Schema> schemaForNamespace = generateSchemas(descriptorsToProcess, properties);
        // process any additional global elements
        if (additionalGlobalElements != null) {
            for(Entry<QName, Type> entry : additionalGlobalElements.entrySet()) {
                QName qname = entry.getKey();
                Type type = entry.getValue();
                if (type instanceof Class) {
                    Class tClass = (Class) type;
                    String nsKey = qname.getNamespaceURI();
                    Schema schema = schemaForNamespace.get(nsKey);

                    QName typeAsQName = conversionManager.schemaType(tClass);
                    if (typeAsQName == null) {
                        // not a built in type - need to get the type via schema reference
                        Descriptor desc = getDescriptorByClass(tClass, descriptorsToProcess);
                        if (desc == null) {
                            // at this point we can't determine the element type, so don't add anything
                            continue;
                        }
                        // if the schema is null generate a new one and create an import
                        if (schema == null) {
                            schema = buildNewSchema(nsKey, new org.eclipse.persistence.oxm.NamespaceResolver(), schemaForNamespace.size(), properties);
                            schemaForNamespace.put(nsKey, schema);
                            typeAsQName = desc.getSchemaReference().getSchemaContextAsQName();

                            Schema schemaForUri = schemaForNamespace.get(typeAsQName.getNamespaceURI());

                            if (!importExists(schema, schemaForUri.getTargetNamespace())) {
                                Import newImport = new Import();
                                newImport.setNamespace(schemaForUri.getTargetNamespace());
                                newImport.setSchemaLocation(schemaForUri.getName());
                                schema.getImports().add(newImport);
                            }
                        } else {
                            typeAsQName = desc.getSchemaReference().getSchemaContextAsQName(schema.getNamespaceResolver());
                        }
                    }
                    if (schema == null) {
                        schema = buildNewSchema(nsKey, new org.eclipse.persistence.oxm.NamespaceResolver(), schemaForNamespace.size(), properties);
                        schemaForNamespace.put(nsKey, schema);
                    }
                    Element element = new Element();
                    element.setName(qname.getLocalPart());
                    element.setType(getSchemaTypeString(typeAsQName, schema));
                    schema.addTopLevelElement(element);
                }
            }
        }
        return schemaForNamespace;
    }

    /**
     * Generates a Map of EclipseLink schema model Schema objects for a given list of XMLDescriptors.
     * The descriptors are assumed to have been initialized.  One Schema  object will be generated
     * per namespace.
     *
     * @param descriptorsToProcess list of XMLDescriptors which will be used to generate Schema objects
     * @param properties holds a namespace to Properties map containing schema settings, such as elementFormDefault
     * @return a map of namespaces to EclipseLink schema model Schema objects
     * @throws DescriptorException if the reference descriptor for a composite mapping is not in the list of descriptors
     * @see Schema
     */
    public Map<String, Schema> generateSchemas(List<Descriptor> descriptorsToProcess, SchemaModelGeneratorProperties properties) throws DescriptorException {
        HashMap<String, Schema> schemaForNamespace = new HashMap<>();
        Schema workingSchema = null;
        if (properties == null) {
            properties = new SchemaModelGeneratorProperties();
        }
        // set up schemas for the descriptors
        for (Descriptor desc : descriptorsToProcess) {
            String namespace;
            XMLSchemaReference schemaRef = desc.getSchemaReference();
            if (schemaRef != null) {
                namespace = schemaRef.getSchemaContextAsQName(desc.getNamespaceResolver()).getNamespaceURI();
                workingSchema = getSchema(namespace, desc.getNamespaceResolver(), schemaForNamespace, properties);
                addNamespacesToWorkingSchema(desc.getNamespaceResolver(), workingSchema);
            } else {
                // at this point there is no schema reference set, but if a descriptor has a
                // default root element set we will need to generate a global element for it
                for (DatabaseTable table : (Vector<DatabaseTable>)desc.getTables()) {
                    namespace = getDefaultRootElementAsQName(desc, table.getName()).getNamespaceURI();
                    workingSchema = getSchema(namespace, desc.getNamespaceResolver(), schemaForNamespace, properties);
                    addNamespacesToWorkingSchema(desc.getNamespaceResolver(), workingSchema);
                }
            }
        }
        // process the descriptors
        for (Descriptor xdesc : descriptorsToProcess) {
            processDescriptor(xdesc, schemaForNamespace, workingSchema, properties, descriptorsToProcess);
        }
        // return the generated schema(s)
        return schemaForNamespace;
    }

    /**
     * Generates a Map of EclipseLink schema model Schema objects for a given list of XMLDescriptors.
     * The descriptors are assumed to have been initialized.  One Schema  object will be generated
     * per namespace.
     *
     * @param descriptorsToProcess list of XMLDescriptors which will be used to generate Schema objects
     * @param properties holds a namespace to Properties map containing schema settings, such as elementFormDefault
     * @param additionalGlobalElements a map of QName-Type entries identifying additional global elements to be added
     * @return a map of namespaces to EclipseLink schema model Schema objects
     * @throws DescriptorException if the reference descriptor for a composite mapping is not in the list of descriptors
     * @see Schema
     */
    public Map<String, Schema> generateSchemas(List<Descriptor> descriptorsToProcess, SchemaModelGeneratorProperties properties, SchemaModelOutputResolver outputResolver, Map<QName, Type> additionalGlobalElements) throws DescriptorException {
        Map<String, Schema> schemas = generateSchemas(descriptorsToProcess, properties, additionalGlobalElements);
        // write out the generates schema(s) via the given output resolver
        Project proj = new SchemaModelProject();
        XMLContext context = new XMLContext(proj);
        XMLMarshaller marshaller = context.createMarshaller();
        Descriptor schemaDescriptor = (Descriptor)proj.getDescriptor(Schema.class);
        int schemaCount = 0;
        for (Entry<String, Schema> entry : schemas.entrySet()) {
            Schema schema = entry.getValue();
            try {
                NamespaceResolver schemaNamespaces = schema.getNamespaceResolver();
                schemaNamespaces.put(Constants.SCHEMA_PREFIX, "http://www.w3.org/2001/XMLSchema");
                schemaDescriptor.setNamespaceResolver(schemaNamespaces);
                javax.xml.transform.Result target = outputResolver.createOutput(schema.getTargetNamespace(), schema.getName());
                marshaller.marshal(schema, target);
                schemaCount++;
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return schemas;
    }

    /**
     * Generates a Map of EclipseLink schema model Schema objects for a given list of XMLDescriptors.
     * The descriptors are assumed to have been initialized.  One Schema  object will be generated
     * per namespace.
     *
     * @param descriptorsToProcess list of XMLDescriptors which will be used to generate Schema objects
     * @param properties holds a namespace to Properties map containing schema settings, such as elementFormDefault
     * @return a map of namespaces to EclipseLink schema model Schema objects
     * @throws DescriptorException if the reference descriptor for a composite mapping is not in the list of descriptors
     * @see Schema
     */
    public Map<String, Schema> generateSchemas(List<Descriptor> descriptorsToProcess, SchemaModelGeneratorProperties properties, SchemaModelOutputResolver outputResolver) throws DescriptorException {
        return generateSchemas(descriptorsToProcess, properties, outputResolver, null);
    }

    /**
     * Process a given descriptor.  Global complex types will be generated for based on
     * schema context, and global elements based on default root element.
     *
     */
    protected void processDescriptor(Descriptor desc, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors) {
        // determine if a simple type (or complex type with simple content) or complex type is required
        boolean simple = isSimple(desc);

        XMLSchemaReference schemaRef = desc.getSchemaReference();
        if (schemaRef != null) {
            if (schemaRef.getType() == org.eclipse.persistence.platform.xml.XMLSchemaReference.COMPLEX_TYPE) {
                workingSchema.addTopLevelComplexTypes(buildComplexType(false, desc, schemaForNamespace, workingSchema, properties, descriptors));
            } else if (schemaRef.getType() == org.eclipse.persistence.platform.xml.XMLSchemaReference.SIMPLE_TYPE) {
                workingSchema.addTopLevelSimpleTypes(buildSimpleType(desc, workingSchema, true));
            } else if (schemaRef.getType() == org.eclipse.persistence.platform.xml.XMLSchemaReference.ELEMENT) {
                workingSchema.addTopLevelElement(buildElement(desc, schemaForNamespace, workingSchema, properties, descriptors, simple));
            }

            for (DatabaseTable table :  (Vector<DatabaseTable>)desc.getTables()) {
                String localName = getDefaultRootElementAsQName(desc, table.getName()).getLocalPart();
                // don't overwrite existing top level elements
                if (workingSchema.getTopLevelElements().get(localName) != null) {
                    continue;
                }
                Element topLevelElement = new Element();
                topLevelElement.setName(localName);

                QName qname = schemaRef.getSchemaContextAsQName(workingSchema.getNamespaceResolver());
                String elementType = qname.getLocalPart();
                String elementTypeUri = qname.getNamespaceURI();
                String elementTypePrefix = workingSchema.getNamespaceResolver().resolveNamespaceURI(elementTypeUri);
                if (elementTypePrefix != null) {
                    elementType = elementTypePrefix + Constants.COLON + elementType;
                }

                topLevelElement.setType(elementType);
                workingSchema.addTopLevelElement(topLevelElement);
            }
        } else {
            // here we have a descriptor that does not have a schema reference set, but since
            // there is a default root element set we need to generate a global element
            for (DatabaseTable table :  (Vector<DatabaseTable>)desc.getTables()) {
                String localName = getDefaultRootElementAsQName(desc, table.getName()).getLocalPart();
                // a global element may have been created while generating an element ref
                if (workingSchema.getTopLevelElements().get(localName) == null) {
                    Element topLevelElement = new Element();
                    topLevelElement.setName(localName);
                    if (simple) {
                        if (isComplexTypeWithSimpleContentRequired(desc)) {
                            topLevelElement.setComplexType(buildComplexTypeWithSimpleContent(desc, schemaForNamespace, workingSchema, properties, descriptors));
                        } else {
                            topLevelElement.setSimpleType(buildSimpleType(desc, workingSchema, false));
                        }
                    } else {
                        topLevelElement.setComplexType(buildComplexType(true, desc, schemaForNamespace, workingSchema, properties, descriptors));
                    }
                    workingSchema.addTopLevelElement(topLevelElement);
                }
            }
        }
    }

    /**
     * Return the Schema for a given namespace.  If one doesn't exist, a new one will
     * be created and returned.
     *
     * @see Schema
     */
    protected Schema getSchema(String uri, NamespaceResolver nr, HashMap<String, Schema> schemaForNamespace, SchemaModelGeneratorProperties properties) {
        Schema schema = schemaForNamespace.get(uri);
        if (schema == null) {
            schema = buildNewSchema(uri, nr, schemaForNamespace.size(), properties);
            schemaForNamespace.put(uri, schema);
        }
        return schema;
    }

    /**
     * Create and return an Element for a given XMLDescriptor.
     *
     */
    protected Element buildElement(Descriptor desc,  HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors, boolean simple) {
        Element element = new Element();
        element.setName(desc.getSchemaReference().getSchemaContextAsQName(workingSchema.getNamespaceResolver()).getLocalPart());
        if (simple) {
            if (isComplexTypeWithSimpleContentRequired(desc)) {
                element.setComplexType(buildComplexTypeWithSimpleContent(desc, schemaForNamespace, workingSchema, properties, descriptors));
            } else {
                element.setSimpleType(buildSimpleType(desc, workingSchema, false));
            }
        } else {
            element.setComplexType(buildComplexType(true, desc, schemaForNamespace, workingSchema, properties, descriptors));
        }

        return element;
    }

    /**
     * Create and return a SimpleType for a given XMLDescriptor.
     *
     */
    protected SimpleType buildSimpleType(Descriptor desc, Schema workingSchema, boolean global) {
        SimpleType st;
        if (global) {
            st = buildNewSimpleType(desc.getSchemaReference().getSchemaContextAsQName(workingSchema.getNamespaceResolver()).getLocalPart());
        } else {
            st = new SimpleType();
        }

        CoreMapping mapping = (CoreMapping)desc.getMappings().get(0);
        QName qname = conversionManager.schemaType(mapping.getAttributeClassification());
        String baseType = qname.getLocalPart();

        if (qname.getNamespaceURI() != null) {
            String prefix = workingSchema.getNamespaceResolver().resolveNamespaceURI(qname.getNamespaceURI());
            if (prefix == null) {
                prefix = workingSchema.getNamespaceResolver().generatePrefix();
                workingSchema.getNamespaceResolver().put(prefix, qname.getNamespaceURI());
            }
            baseType = prefix + Constants.COLON + baseType;
        }

        Restriction restriction = new Restriction();
        restriction.setBaseType(baseType);
        st.setRestriction(restriction);
        return st;
    }

    /**
     * Create and return a SimpleType with name set to the given name.
     *
     */
    protected SimpleType buildNewSimpleType(String name) {
        SimpleType st = new SimpleType();
        st.setName(name);
        return st;
    }

    /**
     * Create and return a ComplexType for a given XMLDescriptor.  Assumes that the descriptor has a schema context
     * set.
     *
     */
    protected ComplexType buildComplexType(boolean anonymous, Descriptor desc,  HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors) {
        ComplexType ct = new ComplexType();
        if (!anonymous) {
            ct.setName(desc.getSchemaReference().getSchemaContextAsQName(workingSchema.getNamespaceResolver()).getLocalPart());
        }

        CoreInheritancePolicy inheritancePolicy = desc.getInheritancePolicyOrNull();
        Extension extension = null;
        if (inheritancePolicy != null && inheritancePolicy.getParentClass() != null) {
            extension = new Extension();
            extension.setBaseType(desc.getSchemaReference().getSchemaContextAsQName(workingSchema.getNamespaceResolver()).getLocalPart());
            ComplexContent complexContent = new ComplexContent();
            complexContent.setExtension(extension);
            ct.setComplexContent(complexContent);
        }
        Sequence seq = new Sequence();
        for (CoreMapping mapping : (Vector<CoreMapping>)desc.getMappings()) {
            processMapping(mapping, seq, ct, schemaForNamespace, workingSchema, properties, descriptors);
        }
        if (extension != null) {
            extension.setSequence(seq);
        } else {
            ct.setSequence(seq);
        }
        return ct;
    }

    /**
     * Create and return a ComplexType containing simple content for a given XMLDescriptor.  Assumes
     * that the descriptor has a schema context set.
     *
     */
    private ComplexType buildComplexTypeWithSimpleContent(Descriptor desc,  HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors) {
        ComplexType ct = new ComplexType();
        SimpleContent sc = new SimpleContent();
        Extension extension = new Extension();
        sc.setExtension(extension);
        ct.setSimpleContent(sc);
        for (CoreMapping mapping : (Vector<CoreMapping>)desc.getMappings()) {
            Field xFld = (Field) mapping.getField();
            if (xFld.getXPath().equals(TEXT)) {
                extension.setBaseType(getSchemaTypeForDirectMapping((DirectMapping) mapping, workingSchema));
            } else if (xFld.getXPathFragment().isAttribute()) {
                String schemaTypeString = getSchemaTypeForDirectMapping((DirectMapping) mapping, workingSchema);
                Attribute attr = buildAttribute((DirectMapping) mapping, schemaTypeString);
                extension.getOrderedAttributes().add(attr);
            }
        }
        return ct;
    }

    /**
     * Return the schema type for a given mapping's xmlfield.  If the field does not have a schema type
     * set, the attribute classification will be used if non-null.  Otherwise, ClassConstants.STRING
     * will be returned.
     *
     */
    protected String getSchemaTypeForDirectMapping(DirectMapping mapping, Schema workingSchema) {
        return getSchemaTypeForElement((Field) mapping.getField(), mapping.getAttributeClassification(), workingSchema);
    }

    /**
     * Return the schema type for a given xmlfield.  If the field does not have a schema type set,
     * the attribute classification will be used if non-null.  Otherwise, ClassConstants.STRING
     * will be returned.
     *
     */
    protected String getSchemaTypeForElement(Field xmlField, Class attrClass, Schema workingSchema) {
        String schemaTypeString = null;
        QName schemaType = xmlField.getSchemaType();
        if (schemaType != null) {
            schemaTypeString = getSchemaTypeString(schemaType, workingSchema);
        } else {
            if (attrClass != null && !attrClass.equals(CoreClassConstants.STRING)) {
                QName qName = conversionManager.schemaType(attrClass);
                if (qName != null) {
                    schemaTypeString = getSchemaTypeString(qName, workingSchema);
                }
            } else {
                // default to string
                schemaTypeString = getSchemaTypeString(Constants.STRING_QNAME, workingSchema);
            }
        }
        return schemaTypeString;
    }

    /**
     * Return the descriptor from the list whose java class name matches
     * javaClassName.  If none exists null will be returned.
     *
     */
    protected Descriptor getDescriptorByName(String javaClassName, List<Descriptor> descriptors) {
        for (Descriptor xDesc : descriptors) {
            if (xDesc.getJavaClassName().equals(javaClassName)) {
                return xDesc;
            }
        }
        return null;
    }

    /**
     * Return the descriptor from the list whose java class matches
     * javaClass.  If none exists null will be returned.
     *
     */
    protected Descriptor getDescriptorByClass(Class javaClass, List<Descriptor> descriptors) {
        for (Descriptor xDesc : descriptors) {
            if (xDesc.getJavaClass() != null && xDesc.getJavaClass() == javaClass) {
                return xDesc;
            }
        }
        return null;
    }

    /**
     * Adds an Any to a given sequence.  If isCollection is true, maxOccurs will
     * be set to unbounded.
     *
     * @see Any
     * @see Occurs#UNBOUNDED
     */
    protected void processAnyMapping(Sequence seq, boolean isCollection) {
        Any any = new Any();
        any.setProcessContents(Any.LAX);
        any.setMinOccurs(Occurs.ZERO);
        if (isCollection) {
            any.setMaxOccurs(Occurs.UNBOUNDED);
        }
        seq.addAny(any);
    }

    /**
     * Process a given XMLBinaryDataMapping.
     *
     */
    protected void processXMLBinaryDataMapping(BinaryDataMapping mapping, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties) {
        Field xmlField = (Field) mapping.getField();
        XPathFragment frag = xmlField.getXPathFragment();

        String schemaTypeString;
        if (mapping.isSwaRef()) {
            schemaTypeString = getSchemaTypeString(Constants.SWA_REF_QNAME, workingSchema);
            Import newImport = new Import();
            newImport.setNamespace(Constants.REF_URL);
            newImport.setSchemaLocation(SWAREF_LOCATION);
            workingSchema.getImports().add(newImport);
        } else {
            schemaTypeString = getSchemaTypeString(Constants.BASE_64_BINARY_QNAME, workingSchema);
        }

        seq = buildSchemaComponentsForXPath(frag, seq, schemaForNamespace, workingSchema, properties);
        frag = getTargetXPathFragment(frag);

        Element elem = elementExistsInSequence(frag.getLocalName(), frag.getShortName(), seq);
        if (elem == null) {
            if (frag.getNamespaceURI() != null) {
                elem = handleFragNamespace(frag, schemaForNamespace, workingSchema, properties, null, schemaTypeString);
            } else {
                elem = buildElement(frag, schemaTypeString, Occurs.ZERO, null);
            }
            if (mapping.getNullPolicy().isNullRepresentedByXsiNil()) {
                elem.setNillable(true);
            }
            if (xmlField.isRequired()) {
                elem.setMinOccurs("1");
            }
            if (mapping.getMimeType() != null) {
                elem.getAttributesMap().put(Constants.EXPECTED_CONTENT_TYPES_QNAME, mapping.getMimeType());
            }
            seq.addElement(elem);
        }
    }

    /**
     * Process a given XMLBinaryDataCollectionMapping.
     *
     */
    protected void processXMLBinaryDataCollectionMapping(BinaryDataCollectionMapping mapping, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties) {
        Field xmlField = (Field) mapping.getField();
        XPathFragment frag = xmlField.getXPathFragment();

        String schemaTypeString;
        if (mapping.isSwaRef()) {
            schemaTypeString = getSchemaTypeString(Constants.SWA_REF_QNAME, workingSchema);
        } else {
            schemaTypeString = getSchemaTypeString(Constants.BASE_64_BINARY_QNAME, workingSchema);
        }

        seq = buildSchemaComponentsForXPath(frag, seq, schemaForNamespace, workingSchema, properties);
        frag = getTargetXPathFragment(frag);

        Element elem = elementExistsInSequence(frag.getLocalName(), frag.getShortName(), seq);
        if (elem == null) {
            if (frag.getNamespaceURI() != null) {
                elem = handleFragNamespace(frag, schemaForNamespace, workingSchema, properties, null, schemaTypeString);
                elem.setMaxOccurs(Occurs.UNBOUNDED);
            } else {
                elem = buildElement(frag, schemaTypeString, Occurs.ZERO, Occurs.UNBOUNDED);
            }
            if (mapping.getNullPolicy().isNullRepresentedByXsiNil()) {
                elem.setNillable(true);
            }
            if (xmlField.isRequired()) {
                elem.setMinOccurs("1");
            }
            if (mapping.getMimeType() != null) {
                elem.getAttributesMap().put(Constants.EXPECTED_CONTENT_TYPES_QNAME, mapping.getMimeType());
            }
            seq.addElement(elem);
        }
    }

    /**
     * Process a given XMLDirectMapping.
     *
     */
    protected void processXMLDirectMapping(DirectMapping mapping, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties) {
        Field xmlField = (Field) mapping.getField();

        XPathFragment frag = xmlField.getXPathFragment();
        if (frag.isSelfFragment()) {
            // do nothing;
            return;
        }

        // Handle ID
        boolean isPk = isFragPrimaryKey(frag, mapping);
        String schemaTypeString = null;
        if (isPk) {
            schemaTypeString = Constants.SCHEMA_PREFIX + Constants.COLON + ID;
        } else {
            schemaTypeString = getSchemaTypeForDirectMapping(mapping, workingSchema);
        }

        // Handle enumerations
        Class attributeClassification = mapping.getAttributeClassification();
        if (attributeClassification != null && Enum.class.isAssignableFrom(attributeClassification)) {
            CoreConverter converter = mapping.getConverter();
            if (converter != null && converter instanceof EnumTypeConverter) {
                processEnumeration(schemaTypeString, frag, mapping, seq, ct, workingSchema, converter);
                return;
            }
        }

        if (frag.isAttribute()) {
            Attribute attr = buildAttribute(mapping, schemaTypeString);
            if (xmlField.isRequired()) {
                attr.setUse(Attribute.REQUIRED);
            }
            ct.getOrderedAttributes().add(attr);
        } else {
            seq = buildSchemaComponentsForXPath(frag, seq, schemaForNamespace, workingSchema, properties);
            frag = getTargetXPathFragment(frag);

            Element elem = elementExistsInSequence(frag.getLocalName(), frag.getShortName(), seq);
            if (elem == null) {
                if (frag.getNamespaceURI() != null) {
                    elem = handleFragNamespace(frag, schemaForNamespace, workingSchema, properties, null, schemaTypeString);
                } else {
                    elem = buildElement(frag, schemaTypeString, Occurs.ZERO, null);
                }
                if (mapping.getNullPolicy().isNullRepresentedByXsiNil()) {
                    elem.setNillable(true);
                }
                if (xmlField.isRequired()) {
                    elem.setMinOccurs("1");
                }
                seq.addElement(elem);
            }
        }
    }

    /**
     * Process a given XMLCompositeDirectCollectionMapping.
     *
     */
    protected void processXMLCompositeDirectCollectionMapping(DirectCollectionMapping mapping, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties) {
        Field xmlField = ((Field) (mapping).getField());

        XPathFragment frag = xmlField.getXPathFragment();
        seq = buildSchemaComponentsForXPath(frag, seq, schemaForNamespace, workingSchema, properties);
        frag = getTargetXPathFragment(frag);

        String schemaTypeString = getSchemaTypeForElement(xmlField, mapping.getAttributeElementClass(), workingSchema);
        Element element = null;
        if (xmlField.usesSingleNode()) {
            SimpleType st = new SimpleType();
            org.eclipse.persistence.internal.oxm.schema.model.List list = new org.eclipse.persistence.internal.oxm.schema.model.List();

            if (schemaTypeString == null) {
                schemaTypeString = getSchemaTypeString(Constants.ANY_SIMPLE_TYPE_QNAME, workingSchema);
            }
            list.setItemType(schemaTypeString);
            st.setList(list);

            element = buildElement(xmlField.getXPathFragment(), null, Occurs.ZERO, null);
            element.setSimpleType(st);
        } else {
            if (frag.getNamespaceURI() != null) {
                element = handleFragNamespace(frag, schemaForNamespace, workingSchema, properties, element, schemaTypeString);
                element.setMaxOccurs(Occurs.UNBOUNDED);
            } else {
                element = buildElement(frag, schemaTypeString, Occurs.ZERO, Occurs.UNBOUNDED);
            }
        }

        if (mapping.getNullPolicy().isNullRepresentedByXsiNil()) {
            element.setNillable(true);
        }

        if (xmlField.isRequired()) {
            element.setMinOccurs("1");
        }

        seq.addElement(element);
    }

    /**
     * Process a given XML composite mapping - either an XMLCompositeObjectMapping, or an
     * XMLCompositeCollectionMapping.  For XMLCompositeDirectCollectionMappings the
     * processXMLCompositeDirectCollectionMapping method should be used.
     *
     */
    protected void processXMLCompositeMapping(CompositeObjectMapping mapping, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors, boolean collection) {
        Field xmlField = (Field) mapping.getField();

        String refClassName = mapping.getReferenceClassName();
        Descriptor refDesc = getDescriptorByName(refClassName, descriptors);
        if (refDesc == null) {
            throw DescriptorException.descriptorIsMissing(refClassName, (DatabaseMapping)mapping);
        }

        XPathFragment frag = xmlField.getXPathFragment();
        seq = buildSchemaComponentsForXPath(frag, seq, schemaForNamespace, workingSchema, properties);
        frag = getTargetXPathFragment(frag);

        Element element = buildElement(frag, null, Occurs.ZERO, (collection ? Occurs.UNBOUNDED : null));
        ComplexType ctype = null;

        // if the reference descriptor's schema context is null we need to generate an anonymous complex type
        if (refDesc.getSchemaReference() == null) {
            ctype = buildComplexType(true, refDesc, schemaForNamespace, workingSchema, properties, descriptors);
        } else {
            element.setType(getSchemaTypeString(refDesc.getSchemaReference().getSchemaContextAsQName(workingSchema.getNamespaceResolver()), workingSchema));
        }

        if (frag.getNamespaceURI() != null) {
            // may need to add a global element
            element = handleFragNamespace(frag, schemaForNamespace, workingSchema, properties, element, ctype, refDesc);
        } else if (ctype != null) {
            // set an anonymous complex type
            element.setComplexType(ctype);
        }

        boolean isNillable = false;
        if (!collection) {
            isNillable = mapping.getNullPolicy().isNullRepresentedByXsiNil();
        } else {
            isNillable = mapping.getNullPolicy().isNullRepresentedByXsiNil();
        }
        element.setNillable(isNillable);

        if (xmlField.isRequired()) {
            element.setMinOccurs("1");
        }

        seq.addElement(element);
    }

    /**
     * Process a given XMLChoiceCollectionMapping.
     *
     */
    protected void processXMLChoiceCollectionMapping(ChoiceCollectionMapping mapping, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors) {
        Map<Field, Class> fieldToClassMap = mapping.getFieldToClassMappings();
        List<XMLChoiceFieldToClassAssociation> choiceFieldToClassList = mapping.getChoiceFieldToClassAssociations();
        processChoiceMapping(fieldToClassMap, choiceFieldToClassList, seq, ct, schemaForNamespace, workingSchema, properties, descriptors, true);
    }

    /**
     *
     */
    protected void processXMLChoiceObjectMapping(ChoiceObjectMapping mapping, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors) {
        Map<Field, Class> fieldToClassMap =mapping.getFieldToClassMappings();
        List<XMLChoiceFieldToClassAssociation> choiceFieldToClassList = mapping.getChoiceFieldToClassAssociations();
        processChoiceMapping(fieldToClassMap, choiceFieldToClassList, seq, ct, schemaForNamespace, workingSchema, properties, descriptors, false);
    }

    /**
     * Process a given XMLChoiceMapping.
     *
     */
    protected void processChoiceMapping(Map<Field, Class> fieldToClassMap, List<XMLChoiceFieldToClassAssociation> choiceFieldToClassList, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors, boolean isCollection) {
        Choice theChoice = new Choice();
        if (isCollection) {
            theChoice.setMaxOccurs(Occurs.UNBOUNDED);
        }
        for (XMLChoiceFieldToClassAssociation next : choiceFieldToClassList) {
            Field field = next.getXmlField();
            Element element = buildElement(field.getXPathFragment().getShortName(), Occurs.ZERO, null);

            QName schemaTypeQName = field.getSchemaType();
            if (schemaTypeQName != null) {
                element.setType(getSchemaTypeString(schemaTypeQName, workingSchema));
            } else {
                element = processReferenceDescriptor(element, getDescriptorByClass(fieldToClassMap.get(field), descriptors), schemaForNamespace, workingSchema, properties, descriptors, field, false);
            }
            theChoice.addElement(element);
        }
        seq.addChoice(theChoice);
    }

    /**
     * Process a given XMLObjectReferenceMapping.  In the case of an XMLCollectionReferenceMapping,
     * i.e. the isCollection flag is set to true, maxOccurs will be set to 'unbounded' on any
     * source elements
     *
     */
    protected void processXMLObjectReferenceMapping(ObjectReferenceMapping mapping, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors, boolean isCollection) {
        String tgtClassName = mapping.getReferenceClassName();
        Descriptor tgtDesc = getDescriptorByName(tgtClassName, descriptors);
        if (tgtDesc == null) {
            throw DescriptorException.descriptorIsMissing(tgtClassName, (DatabaseMapping)mapping);
        }

        // get the target mapping(s) to determine the appropriate type(s)
        String schemaTypeString = null;
        Map<Field, Field> associations = mapping.getSourceToTargetKeyFieldAssociations();
        for (Entry<Field, Field> entry : associations.entrySet()) {
            Field tgtField = entry.getValue();
            Vector mappings = tgtDesc.getMappings();
            // Until IDREF support is added, we want the source type to be that of the target
            //schemaTypeString = Constants.SCHEMA_PREFIX + COLON + IDREF;
            for (Enumeration mappingsNum = mappings.elements(); mappingsNum.hasMoreElements();) {
                Mapping nextMapping = (Mapping)mappingsNum.nextElement();
                if (nextMapping.getField() != null && nextMapping.getField() instanceof Field) {
                    Field xFld = (Field) nextMapping.getField();
                    if (xFld == tgtField) {
                        schemaTypeString = getSchemaTypeForElement(tgtField, nextMapping.getAttributeClassification(), workingSchema);
                    }
                }
            }
            if (schemaTypeString == null) {
                schemaTypeString = getSchemaTypeString(Constants.STRING_QNAME, workingSchema);
            }

            XPathFragment frag = entry.getKey().getXPathFragment();
            if (frag.isAttribute()) {
                Attribute attr = buildAttribute(frag, schemaTypeString);
                ct.getOrderedAttributes().add(attr);
            } else {
                Element elem = buildElement(frag, schemaTypeString, Occurs.ZERO, null);
                if (isCollection) {
                    elem.setMaxOccurs(Occurs.UNBOUNDED);
                }
                seq.addElement(elem);
            }
        }
    }

    /**
     * Process a given mapping.
     *
     */
    protected void processMapping(CoreMapping mapping, Sequence seq, ComplexType ct, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors) {
        if (mapping instanceof BinaryDataMapping) {
            processXMLBinaryDataMapping((BinaryDataMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties);
        } else if (mapping instanceof BinaryDataCollectionMapping) {
            processXMLBinaryDataCollectionMapping((BinaryDataCollectionMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties);
        } else if (mapping instanceof DirectMapping) {
            processXMLDirectMapping((DirectMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties);
        } else if (mapping instanceof DirectCollectionMapping) {
            processXMLCompositeDirectCollectionMapping((DirectCollectionMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties);
        } else if (mapping instanceof CompositeCollectionMapping) {
            processXMLCompositeMapping((CompositeCollectionMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties, descriptors, true);
        } else if (mapping instanceof CompositeObjectMapping) {
            processXMLCompositeMapping((CompositeObjectMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties, descriptors, false);
        } else if (mapping instanceof AnyAttributeMapping) {
            AnyAttribute anyAttribute = new AnyAttribute();
            anyAttribute.setProcessContents(AnyAttribute.LAX);
            ct.setAnyAttribute(anyAttribute);
        } else if (mapping instanceof AnyObjectMapping) {
            processAnyMapping(seq, false);
        } else if (mapping instanceof AnyCollectionMapping) {
            processAnyMapping(seq, true);
        } else if (mapping instanceof ChoiceObjectMapping) {
            processXMLChoiceObjectMapping((ChoiceObjectMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties, descriptors);
        } else if (mapping instanceof ChoiceCollectionMapping) {
            processXMLChoiceCollectionMapping((ChoiceCollectionMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties, descriptors);
        } else if (mapping instanceof CollectionReferenceMapping) {
            processXMLObjectReferenceMapping((CollectionReferenceMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties, descriptors, true);
        } else if (mapping instanceof ObjectReferenceMapping) {
            processXMLObjectReferenceMapping((ObjectReferenceMapping) mapping, seq, ct, schemaForNamespace, workingSchema, properties, descriptors, false);
        }
    }

    /**
     * This method will generate a global element if required (based in URI and elementFormDefault) and
     * set a reference to it on a given element accordingly.  This method will typically be used for
     * direct mappings.
     *
     */
    protected Element handleFragNamespace(XPathFragment frag, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, Element element, String schemaTypeString) {
        String fragUri = frag.getNamespaceURI();
        // may need to add a global element
        Schema s = getSchema(fragUri, null, schemaForNamespace, properties);
        String targetNS = workingSchema.getTargetNamespace();
        if ((s.isElementFormDefault() && !fragUri.equals(targetNS)) || (!s.isElementFormDefault() && fragUri.length() > 0)) {
            if (s.getTopLevelElements().get(frag.getLocalName()) == null) {
                Element globalElement = new Element();
                globalElement.setName(frag.getLocalName());
                globalElement.setType(schemaTypeString);
                s.addTopLevelElement(globalElement);
            }
            element = new Element();
            element.setRef(frag.getShortName());
        } else {
            element = buildElement(frag, schemaTypeString, Occurs.ZERO, null);
        }
        return element;
    }

    /**
     * This method will generate a global element if required (based in URI and elementFormDefault) and
     * set a reference to it on a given element accordingly, or set an anonymous complex type on a given
     * element.  This method will typically be used by composite mappings.
     *
     */
    protected Element handleFragNamespace(XPathFragment frag, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, Element element, ComplexType ctype, Descriptor refDesc) {
        String fragUri = frag.getNamespaceURI();
        // may need to add a global element
        Element globalElement = null;
        Schema s = getSchema(fragUri, null, schemaForNamespace, properties);
        String targetNS = workingSchema.getTargetNamespace();
        if ((s.isElementFormDefault() && !fragUri.equals(targetNS)) || (!s.isElementFormDefault() && fragUri.length() > 0)) {
            globalElement = (Element) s.getTopLevelElements().get(frag.getLocalName());
            if (globalElement == null) {
                globalElement = new Element();
                globalElement.setName(frag.getLocalName());
                if (ctype != null) {
                    globalElement.setComplexType(ctype);
                } else {
                    globalElement.setType(getSchemaTypeString(refDesc.getSchemaReference().getSchemaContextAsQName(workingSchema.getNamespaceResolver()), workingSchema));
                }
                s.addTopLevelElement(globalElement);
            }
            element = new Element();
            element.setMaxOccurs(Occurs.UNBOUNDED);
            element.setRef(frag.getShortName());
        }

        if (globalElement == null && ctype != null) {
            element.setComplexType(ctype);
        }
        return element;
    }

    /**
     * Return the last fragment before text() in the XPath that a given XPathFragment
     * is part of.
     *
     */
    protected XPathFragment getTargetXPathFragment(XPathFragment frag) {
        if (frag.isAttribute() || frag.isSelfFragment()) {
            return frag;
        }
        while (frag.getNextFragment() != null && !frag.getNextFragment().nameIsText()) {
            frag = frag.getNextFragment();
            if (frag.getNextFragment() == null || frag.getNextFragment().nameIsText()) {
                break;
            }
        }
        return frag;
    }

    /**
     * This method will build element/complexType/sequence components for a given XPath,
     * and return the sequence that the target element of the mapping should be added
     * to. For example, if the XPath was "contact-info/address/street/text()", street
     * would be the target.  This method defers processing of the target path element
     * to the calling method, allowing for differences in handling, such as direct
     * mappings versus composite mappings, etc.
     *
     */
    protected Sequence buildSchemaComponentsForXPath(XPathFragment frag, Sequence seq, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties) {
        // the mapping will handle processing of the target fragment; return the sequence it will be added to
        if (frag.getNextFragment() == null || frag.getNextFragment().nameIsText()) {
            return seq;
        }

        Sequence currentSequence = seq;

        // if the current element exists, use it; otherwise create a new one
        Element currentElement = elementExistsInSequence(frag.getLocalName(), frag.getShortName(), currentSequence);
        boolean currentElementExists = (currentElement != null);
        if (currentElement == null) {
            currentElement = new Element();
            // don't set the element name yet, as it may end up being a ref
            ComplexType cType = new ComplexType();
            Sequence sequence = new Sequence();
            cType.setSequence(sequence);
            currentElement.setComplexType(cType);
        }

        Element globalElement = null;
        String fragUri = frag.getNamespaceURI();
        if (fragUri != null) {
            Schema s = getSchema(fragUri, null, schemaForNamespace, properties);
            String targetNS = workingSchema.getTargetNamespace();
            if ((s.isElementFormDefault() && !fragUri.equals(targetNS)) || (!s.isElementFormDefault() && fragUri.length() > 0)) {
                // must generate a global element are create a reference to it
                // if the global element exists, use it; otherwise create a new one
                globalElement = (Element) s.getTopLevelElements().get(frag.getLocalName());
                if (globalElement == null) {
                    globalElement = new Element();
                    globalElement.setName(frag.getLocalName());
                    ComplexType gCType = new ComplexType();
                    Sequence gSequence = new Sequence();
                    gCType.setSequence(gSequence);
                    globalElement.setComplexType(gCType);
                    s.addTopLevelElement(globalElement);
                }
                // if the current element doesn't exist set a ref and add it to the sequence
                if (!currentElementExists) {
                    // ref won't have a complex type
                    currentElement.setComplexType(null);
                    currentElement.setRef(frag.getShortName());
                    currentSequence.addElement(currentElement);
                    currentElementExists = true;
                }
                // make the global element current
                currentElement = globalElement;
            }
        }
        // if we didn't process a global element, and the current element isn't already in the sequence, add it
        if (!currentElementExists && globalElement == null) {
            currentElement.setName(frag.getLocalName());
            currentSequence.addElement(currentElement);
        }
        // set the correct sequence to use/return
        currentSequence = currentElement.getComplexType().getSequence();

        // don't process the last element in the path - let the calling mapping process it
        frag = frag.getNextFragment();
        if (frag.getNextFragment() != null && !frag.getNextFragment().nameIsText()) {
            Element childElt = buildElement(frag, null, Occurs.ZERO, null);
            currentSequence.addElement(childElt);
        }
        // call back into this method to process the next path element
        return buildSchemaComponentsForXPath(frag, currentSequence, schemaForNamespace, workingSchema, properties);
    }

    /**
     * Build and return an Attribute for a given XMLDirectMapping.
     *
     */
    protected Attribute buildAttribute(DirectMapping mapping, String schemaType) {
        XPathFragment frag = ((Field) mapping.getField()).getXPathFragment();
        Attribute attr = new Attribute();
        attr.setName(frag.getShortName());
        attr.setType(schemaType);
        return attr;
    }

    /**
     * Build and return an Attribute for a given XPathFragment.
     *
     */
    protected Attribute buildAttribute(XPathFragment frag, String schemaType) {
        Attribute attr = new Attribute();
        attr.setName(frag.getShortName());
        attr.setType(schemaType);
        return attr;
    }

    /**
     * Build and return an Element for a given XPathFragment.
     *
     */
    protected Element buildElement(XPathFragment frag, String schemaType, String minOccurs, String maxOccurs) {
        Element element = new Element();
        element.setName(frag.getLocalName());
        element.setMinOccurs(minOccurs);
        element.setMaxOccurs(frag.containsIndex() ? Occurs.UNBOUNDED : maxOccurs);
        if (schemaType != null) {
            element.setType(schemaType);
        }
        return element;
    }

    /**
     * Build and return an Element based on a given name, minOccurs and
     * maxOccurs.
     *
     */
    protected Element buildElement(String name, String minOccurs, String maxOccurs) {
        Element element = new Element();
        element.setName(name);
        element.setMinOccurs(minOccurs);
        element.setMaxOccurs(maxOccurs);
        return element;
    }

    /**
     * Indicates if two namespaces are equal.  The result is TRUE if the two URI strings are
     * equal according to the equals() method, if one is null and the other is "", or
     * both are null.
     *
     */
    public boolean areNamespacesEqual(String ns1, String ns2) {
        if (ns1 == null) {
            return (ns2 == null || ns2.equals(Constants.EMPTY_STRING));
        }
        return ((ns1.equals(ns2)) || (ns1.equals(Constants.EMPTY_STRING) && ns2 == null));
    }

    /**
     * Return the schema type as a string for a given QName and Schema.  The schema's
     * namespace resolver will be used to determine the prefix (if any) to use.
     *
     */
    protected String getSchemaTypeString(QName schemaType, Schema workingSchema) {
        String schemaTypeString = schemaType.getLocalPart();
        String uri = schemaType.getNamespaceURI();
        String prefix = workingSchema.getNamespaceResolver().resolveNamespaceURI(uri);
        if (prefix == null && !areNamespacesEqual(uri, workingSchema.getDefaultNamespace())) {
            if (uri.equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
                prefix = workingSchema.getNamespaceResolver().generatePrefix(Constants.SCHEMA_PREFIX);
            } else if (uri.equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)) {
                prefix = workingSchema.getNamespaceResolver().generatePrefix(Constants.SCHEMA_INSTANCE_PREFIX);
            } else if (uri.equals(Constants.REF_URL)) {
                prefix = workingSchema.getNamespaceResolver().generatePrefix(Constants.REF_PREFIX);
            } else {
                prefix = workingSchema.getNamespaceResolver().generatePrefix();
            }
            workingSchema.getNamespaceResolver().put(prefix, uri);
        }
        if (prefix != null) {
            schemaTypeString = prefix + Constants.COLON + schemaTypeString;
        }
        return schemaTypeString;
    }

    /**
     * Adds each namespace in the given resolver to the schema.
     *
     */
    protected void addNamespacesToWorkingSchema(NamespaceResolver nr, Schema workingSchema) {
        if (nr != null) {
            Vector<Namespace> descNamespaces = nr.getNamespaces();
            for (Namespace nextNamespace : descNamespaces) {
                workingSchema.getNamespaceResolver().put(nextNamespace.getPrefix(), nextNamespace.getNamespaceURI());
            }
        }
    }

    /**
     * Create and return a new schema for the given namespace.  ElementFormDefault and
     * AttributeFormDefault can be set via SchemaModelGeneratorProperties object.  The
     * namespace resolver's default namespace will be set if non-null.
     *
     */
    protected Schema buildNewSchema(String uri, NamespaceResolver nr, int schemaCount, SchemaModelGeneratorProperties properties) {
        Schema schema = new Schema();
        schema.setName(SCHEMA_FILE_NAME + schemaCount + SCHEMA_FILE_EXT);

        String defaultNamespace = null;
        if (nr != null) {
            defaultNamespace = nr.getDefaultNamespaceURI();
            if (defaultNamespace != null) {
                schema.setDefaultNamespace(defaultNamespace);
                schema.getNamespaceResolver().setDefaultNamespaceURI(defaultNamespace);
            }
        }

        if (!uri.equals(Constants.EMPTY_STRING)) {
            schema.setTargetNamespace(uri);
            String prefix = null;
            if (nr != null) {
                prefix = nr.resolveNamespaceURI(uri);
            }

            if (prefix == null && !uri.equals(defaultNamespace)) {
                prefix = schema.getNamespaceResolver().generatePrefix();
                schema.getNamespaceResolver().put(prefix, uri);
            }
        }

        if (properties != null) {
            // set elementFormDefault and attributeFormDefault to qualified if necessary
            Properties props = properties.getProperties(uri);
            if (props != null) {
                if (props.containsKey(SchemaModelGeneratorProperties.ELEMENT_FORM_QUALIFIED_KEY)) {
                    schema.setElementFormDefault((Boolean) props.get(SchemaModelGeneratorProperties.ELEMENT_FORM_QUALIFIED_KEY));
                }
                if (props.containsKey(SchemaModelGeneratorProperties.ATTRIBUTE_FORM_QUALIFIED_KEY)) {
                    schema.setAttributeFormDefault((Boolean) props.get(SchemaModelGeneratorProperties.ATTRIBUTE_FORM_QUALIFIED_KEY));
                }
            }
        }
        return schema;
    }

    /**
     * Determines if a given schema contains an import for a given schema name.
     *
     */
    protected boolean importExists(Schema schema, String schemaName) {
        java.util.List<Import> imports = schema.getImports();
        for (Import nextImport : imports) {
            if (nextImport.getSchemaLocation() != null && nextImport.getSchemaLocation().equals(schemaName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Return a QName representation of a qualified table name (aka default root element).  The
     * given descriptor's namespace resolver will be used to determine the correct prefix - if
     * any - to be used.
     *
     */
    protected QName getDefaultRootElementAsQName(Descriptor desc, String qualifiedTableName) {
        QName qName = null;
        int idx = qualifiedTableName.indexOf(Constants.COLON);
        String localName = qualifiedTableName.substring(idx + 1);
        NamespaceResolver nsResolver = desc.getNamespaceResolver();
        if (nsResolver == null) {
            qName = new QName(localName);
        } else if (idx > -1) {
            String prefix = qualifiedTableName.substring(0, idx);
            String uri = nsResolver.resolveNamespacePrefix(prefix);
            qName = new QName(uri, localName);
        } else {
            if (nsResolver.getDefaultNamespaceURI() != null) {
                qName = new QName(nsResolver.getDefaultNamespaceURI(), localName);
            } else {
                qName = new QName(localName);
            }
        }
        return qName;
    }

    /**
     *
     */
    protected Element processReferenceDescriptor(Element element, Descriptor refDesc, HashMap<String, Schema> schemaForNamespace, Schema workingSchema, SchemaModelGeneratorProperties properties, List<Descriptor> descriptors, Field field, boolean isCollection) {
        ComplexType ctype = null;

        if (refDesc.getSchemaReference() == null) {
            ctype = buildComplexType(true, refDesc, schemaForNamespace, workingSchema, properties, descriptors);
        } else {
            element.setType(getSchemaTypeString(refDesc.getSchemaReference().getSchemaContextAsQName(workingSchema.getNamespaceResolver()), workingSchema));
        }

        XPathFragment frag = field.getXPathFragment();
        String fragUri = frag.getNamespaceURI();
        if (fragUri != null) {
            // may need to add a global element
            Schema s = getSchema(fragUri, null, schemaForNamespace, properties);
            String targetNS = workingSchema.getTargetNamespace();
            if ((s.isElementFormDefault() && !fragUri.equals(targetNS)) || (!s.isElementFormDefault() && fragUri.length() > 0)) {
                if (s.getTopLevelElements().get(frag.getShortName()) == null) {
                    Element globalElement = new Element();
                    globalElement.setName(frag.getLocalName());
                    if (ctype != null) {
                        globalElement.setComplexType(ctype);
                    } else {
                        globalElement.setType(getSchemaTypeString(refDesc.getSchemaReference().getSchemaContextAsQName(workingSchema.getNamespaceResolver()), workingSchema));
                    }
                    s.getTopLevelElements().put(frag.getShortName(), globalElement);
                }
                element = new Element();
                element.setMinOccurs(Occurs.ZERO);
                if (isCollection) {
                    element.setMaxOccurs(Occurs.UNBOUNDED);
                }
                element.setRef(frag.getShortName());
            } else {
                element.setComplexType(ctype);
            }
        } else if (ctype != null) {
            element.setComplexType(ctype);
        }
        return element;
    }

    /**
     * Convenience method for determining if an element already exists in a given
     * sequence.  If an element exists whose name is equal to 'elementName' true
     * is returned.  False otherwise.
     *
     */
    protected Element elementExistsInSequence(String elementName, String refString, Sequence seq) {
        if (seq.isEmpty()) {
            return null;
        }
        List existingElements = seq.getOrderedElements();
        if (existingElements != null) {
            Iterator elementIt = existingElements.iterator();
            while (elementIt.hasNext()) {
                Element element;
                // could be other components in the list, like Any, but we only care about Element
                try {
                    element = (Element) elementIt.next();
                } catch (ClassCastException cce) {
                    continue;
                }
                if ((element.getRef() != null && element.getRef().equals(refString)) || (element.getName() != null && element.getName().equals(elementName))) {
                    return element;
                }
            }
        }
        return null;
    }

    /**
     * Determines if a given descriptor contains a direct mapping to "text()" indicating a
     * simple mapping.  In this case, a simple type or complex type with simple content
     * will be generated
     *
     */
    protected boolean isSimple(Descriptor desc) {
        boolean isSimple = false;
        for (CoreMapping mapping : (Vector<CoreMapping>)desc.getMappings()) {
            if (mapping.isDirectToFieldMapping()) {
                Field xFld = (Field) mapping.getField();
                if (xFld.getXPath().equals(TEXT)) {
                    isSimple = true;
                    break;
                }
            } else {
                break;
            }
        }
        return isSimple;
    }

    /**
     * Indicates if a complex type with simple content is to be generated. This is true when
     * the given descriptor has more than one mapping.  It is assumed that isSimple(desc)
     * will return true for the given descriptor, and that the descriptor will contain at most
     * one direct with a 'text()' xpath, and any additional mappings are attribute mappings.
     *
     */
    protected boolean isComplexTypeWithSimpleContentRequired(Descriptor desc) {
        return desc.getMappings().size() > 1 ? true : false;
    }

    /**
     * Process information contained within an EnumTypeConverter.  This will generate a simple
     * type containing enumeration info.
     *
     */
    protected void processEnumeration(String schemaTypeString, XPathFragment frag, DirectMapping mapping, Sequence seq, ComplexType ct, Schema workingSchema, CoreConverter converter) {
        Element elem = null;
        Attribute attr = null;
        if (frag.isAttribute()) {
            attr = buildAttribute(mapping, schemaTypeString);
        } else {
            elem = buildElement(frag, schemaTypeString, Occurs.ZERO, null);
        }

        Collection<String> fieldValues = ((EnumTypeConverter) converter).getAttributeToFieldValues().values();
        ArrayList facets = new ArrayList();
        for (String field : fieldValues) {
            facets.add(field);
        }

        Restriction restriction = new Restriction();
        restriction.setEnumerationFacets(facets);
        SimpleType st = new SimpleType();
        st.setRestriction(restriction);

        if (frag.isAttribute()) {
            attr.setSimpleType(st);
            ct.getOrderedAttributes().add(attr);
        } else {
            elem.setSimpleType(st);
            seq.addElement(elem);
        }
    }

    /**
     * Indicates if a given fragment is a primary key.
     *
     */
    protected boolean isFragPrimaryKey(XPathFragment frag, DirectMapping mapping) {
        /* Uncomment the following when ID support is needed
        Vector<String> pkFieldNames = mapping.getDescriptor().getPrimaryKeyFieldNames();
        if (pkFieldNames != null) {
            if (frag.isAttribute()) {
                return pkFieldNames.contains(XMLConstants.ATTRIBUTE + frag.getLocalName());
            }
            return pkFieldNames.contains(frag.getLocalName() + '/' + TEXT);
        }
        */
        return false;
    }

}
