/*
 * Copyright (c) 1998, 2019 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.
     *
     * @param desc
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     */
    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.
     *
     * @param uri
     * @param nr
     * @param schemaForNamespace
     * @param properties
     * @return
     * @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.
     *
     * @param desc
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     * @param simple
     * @return
     */
    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.
     *
     * @param desc
     * @param workingSchema
     * @return
     */
    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.
     *
     * @param name
     * @return
     */
    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.
     *
     * @param anonymous
     * @param desc
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     * @return
     */
    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.
     *
     * @param desc
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     * @return
     */
    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.
     *
     * @param mapping
     * @param workingSchema
     * @return
     */
    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.
     *
     * @param xmlField
     * @param attrClass
     * @param workingSchema
     * @return
     */
    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.
     *
     * @param javaClassName
     * @param descriptors
     * @return
     */
    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.
     *
     * @param javaClass
     * @param descriptors
     * @return
     */
    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.
     *
     * @param seq
     * @param isCollection
     * @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.
     *
     * @param mapping
     * @param seq
     * @param ct
     * @param workingSchema
     */
    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.
     *
     * @param mapping
     * @param seq
     * @param ct
     * @param workingSchema
     */
    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.
     *
     * @param mapping
     * @param seq
     * @param ct
     * @param workingSchema
     */
    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.
     *
     * @param mapping
     * @param seq
     * @param ct
     * @param workingSchema
     */
    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.
     *
     * @param mapping
     * @param seq
     * @param ct
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     * @param collection
     */
    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.
     *
     * @param mapping
     * @param seq
     * @param ct
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     */
    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);
    }

    /**
     *
     * @param mapping
     * @param seq
     * @param ct
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     */
    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.
     *
     * @param fieldToClassMap
     * @param choiceFieldToClassList
     * @param seq
     * @param ct
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     * @param isCollection
     */
    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
     *
     * @param mapping
     * @param seq
     * @param ct
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     * @param isCollection
     */
    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.
     *
     * @param mapping
     * @param seq
     * @param ct
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     */
    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.
     *
     * @param frag
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param element
     * @param schemaTypeString
     * @return
     */
    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.
     *
     * @param frag
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param element
     * @param ctype
     * @param refDesc
     */
    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.
     *
     * @param frag
     * @return
     */
    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.
     *
     * @param frag
     * @param seq
     * @return
     */
    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.
     *
     * @param mapping
     * @param schemaType
     * @return
     */
    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.
     *
     * @param frag
     * @param schemaType
     * @return
     */
    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.
     *
     * @param frag
     * @param schemaType
     * @param minOccurs
     * @param maxOccurs
     * @return
     */
    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.
     *
     * @param name
     * @param minOccurs
     * @param maxOccurs
     * @return
     */
    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.
     *
     * @param ns1
     * @param ns2
     * @return
     */
    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.
     *
     * @param schemaType
     * @param workingSchema
     * @return
     */
    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.
     *
     * @param nr
     * @param workingSchema
     */
    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.
     *
     * @param uri
     * @param nr
     * @param schemaCount
     * @param properties
     * @return
     */
    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.
     *
     * @param schema
     * @param schemaName
     * @return
     */
    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.
     *
     * @param desc
     * @param qualifiedTableName
     * @return
     */
    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;
    }

    /**
     *
     * @param element
     * @param refDesc
     * @param schemaForNamespace
     * @param workingSchema
     * @param properties
     * @param descriptors
     * @param field
     * @param isCollection
     * @return
     */
    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.
     *
     * @param elementName
     * @param seq
     * @return
     */
    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
     *
     * @param desc
     * @return
     */
    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.
     *
     * @param desc
     * @return
     */
    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.
     *
     * @param schemaTypeString
     * @param frag
     * @param mapping
     * @param seq
     * @param ct
     * @param workingSchema
     * @param converter
     */
    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.
     *
     * @param frag
     * @param mapping
     * @return
     */
    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;
    }

}
