/*
 * 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:
//     Oracle - initial API and implementation from Oracle TopLink
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
package org.eclipse.persistence.oxm;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.xml.namespace.QName;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.descriptors.InstantiationPolicy;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.TreeObjectBuilder;
import org.eclipse.persistence.internal.oxm.Unmarshaller;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.XPathQName;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.record.UnmarshalRecord;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.AggregateMapping;
import org.eclipse.persistence.mappings.AttributeAccessor;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.oxm.mappings.XMLChoiceCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLChoiceObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeDirectCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.eclipse.persistence.oxm.mappings.XMLMapping;
import org.eclipse.persistence.oxm.record.XMLRecord;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
import org.eclipse.persistence.queries.AttributeGroup;
import org.eclipse.persistence.queries.DoesExistQuery;

/**
 * Use an XML project for nontransactional, nonpersistent (in-memory) conversions between Java objects and XML documents.
 *
 * An XMLDescriptor is a set of mappings that describe how an objects's data is to be represented in an
 * XML document. XML descriptors describe Java objects that you map to simple and complex types defined
 * by an XML schema document (XSD). Using XML descriptors in an EclipseLink XML project, you can configure XML mappings.
 *
 * @see org.eclipse.persistence.oxm.mappings
 */
public class XMLDescriptor extends ClassDescriptor implements Descriptor<AttributeAccessor, DatabaseMapping, DatabaseField, InheritancePolicy, InstantiationPolicy, NamespaceResolver, ObjectBuilder, DatabaseTable, UnmarshalRecord, XMLUnmarshaller>{

    /*
     * Character used to separate individual xPath elements.
     * TODO: Use some global value reference.
     */
    private static final char XPATH_FRAGMENT_SEPARATOR = '/';

    private static final Vector EMPTY_VECTOR = NonSynchronizedVector.newInstance(1);

    private NamespaceResolver namespaceResolver;
    private XMLSchemaReference schemaReference;
    private boolean shouldPreserveDocument = false;
    private XMLField defaultRootElementField;
    private boolean sequencedObject = false;
    private boolean isWrapper = false;
    private boolean resultAlwaysXMLRoot = false;
    private boolean lazilyInitialized = false;
    private AttributeAccessor locationAccessor = null;
    private boolean hasReferenceMappings = false;


    /**
     * PUBLIC:
     * Return a new XMLDescriptor.
     */
    public XMLDescriptor() {
        this.tables = NonSynchronizedVector.newInstance(3);
        this.mappings = NonSynchronizedVector.newInstance();
        this.primaryKeyFields = null;
        this.fields = NonSynchronizedVector.newInstance();
        this.allFields = NonSynchronizedVector.newInstance();
        this.constraintDependencies = EMPTY_VECTOR;
        this.multipleTableForeignKeys = Collections.EMPTY_MAP;
        this.queryKeys = Collections.EMPTY_MAP;
        this.initializationStage = UNINITIALIZED;
        this.interfaceInitializationStage = UNINITIALIZED;
        this.descriptorType = NORMAL;
        this.shouldOrderMappings = true;
        this.shouldBeReadOnly = false;
        this.shouldAlwaysConformResultsInUnitOfWork = false;
        this.shouldAcquireCascadedLocks = false;
        this.hasSimplePrimaryKey = false;
        this.idValidation = null;
        this.derivesIdMappings = Collections.EMPTY_MAP;
        this.additionalWritableMapKeyFields = Collections.EMPTY_LIST;

        // Policies
        this.objectBuilder = new TreeObjectBuilder(this);

        this.shouldOrderMappings = false;
        descriptorIsAggregate();
    }

    /**
     * PUBLIC:
     * Return the default root element name for the ClassDescriptor
     * This value is stored in place of a table name
     * This value is mandatory for all root objects
     * @return the default root element specified on this ClassDescriptor
     */
    @Override
    public String getDefaultRootElement() {
        if (getTables().isEmpty()) {
            return null;
        }
        return getTables().firstElement().getName();
    }

    /**
     * PUBLIC:
     * Return if unmapped information from the XML document should be maintained for this
     * descriptor
     * By default unmapped data is not preserved.
     * @return if this descriptor should preserve unmapped data
     */
    @Override
    public boolean shouldPreserveDocument() {
        return this.shouldPreserveDocument;
    }

    /**
     * PUBLIC:
     * Specifies that object built from this descriptor should retain any unmapped
     * information from their original XML Document when being written back out.
     * By default unmapped data is not preserved.
     *
     * @param shouldPreserveDocument if this descriptor should preserve unmapped data
     */
    public void setShouldPreserveDocument(boolean shouldPreserveDocument) {
        this.shouldPreserveDocument = shouldPreserveDocument;
    }

    /**
    * PUBLIC:
    * Add a root element name for the Descriptor
    * This value is stored in place of a table name
    * @param rootElementName a root element to specify on this Descriptor
    */
    @Override
    public void addRootElement(String rootElementName) {
        if (rootElementName != null) {
            if (!getTableNames().contains(rootElementName)) {
                addTableName(rootElementName);
            }
        }
    }

    /**
    * PUBLIC:
    * Return the default root element name for the ClassDescriptor
    * This value is stored in place of a table name
    * This value is mandatory for all root objects
    * @param newDefaultRootElement the default root element to specify on this ClassDescriptor
    */
    @Override
    public void setDefaultRootElement(String newDefaultRootElement) {
        if(setDefaultRootElementField(newDefaultRootElement)) {
            int index = getTableNames().indexOf(newDefaultRootElement);
            if (index == 0) {
                return;
            }
            DatabaseTable databaseTable = new DatabaseTable();
            databaseTable.setUseDelimiters(false);
            databaseTable.setName(newDefaultRootElement);
            if (index >= 0) {
                getTables().remove(index);
                getTables().add(0, databaseTable);
            } else {
                getTables().add(0, databaseTable);
            }
        }
    }

    /**
    * PUBLIC:
    * Return the NamespaceResolver associated with this descriptor
    * @return the NamespaceResolver associated with this descriptor
    * @see org.eclipse.persistence.oxm.NamespaceResolver
    */
    @Override
    public NamespaceResolver getNamespaceResolver() {
        return namespaceResolver;
    }

    @Override
    public NamespaceResolver getNonNullNamespaceResolver() {
        if (namespaceResolver == null) {
            namespaceResolver = new NamespaceResolver();
        }
        return namespaceResolver;
    }

    /**
     * PUBLIC:
     * The inheritance policy is used to define how a descriptor takes part in inheritance.
     * All inheritance properties for both child and parent classes is configured in inheritance policy.
     * Caution must be used in using this method as it lazy initializes an inheritance policy.
     * Calling this on a descriptor that does not use inheritance will cause problems, #hasInheritance() must always first be called.
     * @return the InheritancePolicy associated with this descriptor
     */
    @Override
    public InheritancePolicy getInheritancePolicy() {
        if (inheritancePolicy == null) {
            // Lazy initialize to conserve space in non-inherited classes.
            setInheritancePolicy(new org.eclipse.persistence.internal.oxm.QNameInheritancePolicy(this));
        }
        return inheritancePolicy;
    }

    /**
    * PUBLIC:
    * Set the NamespaceResolver to associate with this descriptor
    * @param newNamespaceResolver the NamespaceResolver to associate with this descriptor
    * @see org.eclipse.persistence.oxm.NamespaceResolver
    */
    @Override
    public void setNamespaceResolver(NamespaceResolver newNamespaceResolver) {
        namespaceResolver = newNamespaceResolver;
    }

    /**
    * PUBLIC:
    * Return the SchemaReference associated with this descriptor
    * @return the SchemaReference associated with this descriptor
    * @see org.eclipse.persistence.oxm.schema
    */
    @Override
    public XMLSchemaReference getSchemaReference() {
        return schemaReference;
    }

    /**
     * PUBLIC:
     * Set the SchemaReference to associate with this descriptor
     * @param newSchemaReference the SchemaReference to associate with this descriptor
     * @see org.eclipse.persistence.oxm.schema
     */
    @Override
    public void setSchemaReference(XMLSchemaReference newSchemaReference) {
        schemaReference = newSchemaReference;
    }

    /**
     * PUBLIC:
     * Return if the descriptor maps to XML.
     */
    @Override
    public boolean isXMLDescriptor() {
        return true;
    }

    /**
     * If true, the descriptor may be lazily initialized.  This is useful if the
     * descriptor may not get used.
     */
    @Override
    public boolean isLazilyInitialized() {
        return lazilyInitialized;
    }

    /**
     * Specify in the descriptor may be lazily initialized.  The default is
     * false.
     */
    public void setLazilyInitialized(boolean shouldLazyInitiailize) {
        this.lazilyInitialized = shouldLazyInitiailize;
    }

    @Override
    public Vector<String> getPrimaryKeyFieldNames() {
        if(null == primaryKeyFields) {
            return new Vector<>(0);
        }
        return super.getPrimaryKeyFieldNames();
    }

    @Override
    protected void validateMappingType(DatabaseMapping mapping) {
        if (!(mapping.isXMLMapping())) {
            throw DescriptorException.invalidMappingType(mapping);
        }
    }

    /**
     * INTERNAL:
     * Avoid SDK initialization.

    public void setQueryManager(DescriptorQueryManager queryManager) {
        this.queryManager = queryManager;
        if (queryManager != null) {
            queryManager.setDescriptor(this);
        }
    }*/
    /**
    * INTERNAL:
    * Build(if necessary) and return the nested XMLRecord from the specified field value.
    * The field value should be an XMLRecord or and XMLElement
    */
    @Override
    public AbstractRecord buildNestedRowFromFieldValue(Object fieldValue) {
        if (fieldValue instanceof XMLRecord) {
            return (XMLRecord) fieldValue;
        }

        // BUG#2667762 - If the tag was empty this could be a string of whitespace.
        if (!(fieldValue instanceof Vector)) {
            return getObjectBuilder().createRecord(null);
        }

        Vector nestedRows = (Vector) fieldValue;
        if (nestedRows.isEmpty()) {
            return getObjectBuilder().createRecord(null);
        } else {
            // BUG#2667762 - If the tag was empty this could be a string of whitespace.
            if (!(nestedRows.firstElement() instanceof AbstractRecord)) {
                return getObjectBuilder().createRecord(null);
            }
            return (XMLRecord) nestedRows.firstElement();
        }
    }

    /**
    * INTERNAL:
    * Build(if necessary) and return a Vector of the nested XMLRecords from the specified field value.
    * The field value should be a Vector, an XMLRecord, or an XMLElement
    */
    @Override
    public Vector buildNestedRowsFromFieldValue(Object fieldValue, AbstractSession session) {
        // BUG#2667762 - If the tag was empty this could be a string of whitespace.
        if (!(fieldValue instanceof Vector)) {
            return new Vector(0);
        }
        return (Vector) fieldValue;
    }

    /**
     * Return a new direct/basic mapping for this type of descriptor.
     */
    @Override
    public AbstractDirectMapping newDirectMapping() {
        return new XMLDirectMapping();
    }

    /**
     * Return a new aggregate/embedded mapping for this type of descriptor.
     */
    @Override
    public AggregateMapping newAggregateMapping() {
        return new XMLCompositeObjectMapping();
    }

    /**
     * Return a new aggregate collection/element collection mapping for this type of descriptor.
     */
    @Override
    public DatabaseMapping newAggregateCollectionMapping() {
        return new XMLCompositeCollectionMapping();
    }

    /**
     * Return a new direct collection/element collection mapping for this type of descriptor.
     */
    @Override
    public DatabaseMapping newDirectCollectionMapping() {
        return new XMLCompositeDirectCollectionMapping();
    }

    /**
    * PUBLIC:
    * Add a direct mapping to the receiver. The new mapping specifies that
    * an instance variable of the class of objects which the receiver describes maps in
    * the default manner for its type to the indicated database field.
    *
    * @param attributeName  the name of an instance variable of the
    * class which the receiver describes.
    * @param xpathString the xpath of the xml element or attribute which corresponds
    * with the designated instance variable.
    * @return The newly created DatabaseMapping is returned.
    */
    @Override
    public DatabaseMapping addDirectMapping(String attributeName, String xpathString) {
        XMLDirectMapping mapping = new XMLDirectMapping();

        mapping.setAttributeName(attributeName);
        mapping.setXPath(xpathString);

        return addMapping(mapping);
    }

    /**
    * PUBLIC:
    * Add a direct to node mapping to the receiver. The new mapping specifies that
    * a variable accessed by the get and set methods of the class of objects which
    * the receiver describes maps in  the default manner for its type to the indicated
    * database field.
    */
    @Override
    public DatabaseMapping addDirectMapping(String attributeName, String getMethodName, String setMethodName, String xpathString) {
        XMLDirectMapping mapping = new XMLDirectMapping();

        mapping.setAttributeName(attributeName);
        mapping.setSetMethodName(setMethodName);
        mapping.setGetMethodName(getMethodName);
        mapping.setXPath(xpathString);

        return addMapping(mapping);
    }

    @Override
    public void addPrimaryKeyFieldName(String fieldName) {
        addPrimaryKeyField(new XMLField(fieldName));
    }

    @Override
    public void addPrimaryKeyField(DatabaseField field) {
        if (!(field instanceof XMLField)) {
            String fieldName = field.getName();
            field = new XMLField(fieldName);
        }
        if(null == primaryKeyFields) {
            primaryKeyFields = new ArrayList<>(1);
        }
        super.addPrimaryKeyField(field);
    }

    @Override
    public void setPrimaryKeyFields(List<DatabaseField> thePrimaryKeyFields) {
        if(null == thePrimaryKeyFields) {
            return;
        }
        List<DatabaseField> xmlFields = new ArrayList(thePrimaryKeyFields.size());
        Iterator<DatabaseField> it = thePrimaryKeyFields.iterator();

        while (it.hasNext()) {
            DatabaseField field = it.next();
            if (!(field instanceof XMLField)) {
                String fieldName = field.getName();
                field = new XMLField(fieldName);
            }
            xmlFields.add(field);
        }

        super.setPrimaryKeyFields(xmlFields);
    }

    /**
     * INTERNAL:
     * Extract the direct values from the specified field value.
     * Return them in a vector.
     * The field value could be a vector or could be a text value if only a single value.
     */
    @Override
    public Vector buildDirectValuesFromFieldValue(Object fieldValue) throws DatabaseException {
        if (!(fieldValue instanceof Vector)) {
            Vector fieldValues = new Vector(1);
            fieldValues.add(fieldValue);
            return fieldValues;
        }
        return (Vector) fieldValue;
    }

    /**
     * INTERNAL:
     * Build the appropriate field value for the specified
     * set of direct values.
     * The database better be expecting a Vector.
     */
    @Override
    public Object buildFieldValueFromDirectValues(Vector directValues, String elementDataTypeName, AbstractSession session) throws DatabaseException {
        return directValues;
    }

    /**
     * INTERNAL:
     * Build and return the appropriate field value for the specified
     * set of nested rows.
     */
    @Override
    public Object buildFieldValueFromNestedRows(Vector nestedRows, String structureName, AbstractSession session) throws DatabaseException {
        return nestedRows;
    }

    /**
     * INTERNAL:
     * A DatabaseField is built from the given field name.
     */
    @Override
    public DatabaseField buildField(String fieldName) {
        XMLField xmlField = new XMLField(fieldName);
        xmlField.setNamespaceResolver(this.getNamespaceResolver());
        //xmlField.initialize();
        return xmlField;
    }

    /**
     * INTERNAL:
     * This is used only in initialization.
     */
    @Override
    public DatabaseField buildField(DatabaseField field) {
        try {
            XMLField xmlField = (XMLField) field;
            xmlField.setNamespaceResolver(this.getNamespaceResolver());
            xmlField.initialize();
        } catch (ClassCastException e) {
            // Assumes field is always an XMLField
        }
        return super.buildField(field);
    }

    /**
     * INTERNAL:
     * This is needed by regular aggregate descriptors (because they require review);
     * but not by XML aggregate descriptors.
     */
    @Override
    public void initializeAggregateInheritancePolicy(AbstractSession session) {
        // do nothing, since the parent descriptor was already modified during pre-initialize
    }

    @Override
    public void setTableNames(Vector tableNames) {
        if (null != tableNames && tableNames.size() > 0) {
            setDefaultRootElementField((String) tableNames.get(0));
        }
        super.setTableNames(tableNames);
    }

    /**
     * INTERNAL:
     * Sets the tables
     */
    @Override
    public void setTables(Vector<DatabaseTable> theTables) {
         super.setTables(theTables);
    }

    /**
     * INTERNAL:
     * Allow the descriptor to initialize any dependencies on this session.
     */
    @Override
    public void preInitialize(AbstractSession session) throws DescriptorException {
        // Avoid repetitive initialization (this does not solve loops)
        if (isInitialized(PREINITIALIZED)) {
            return;
        }
        setInitializationStage(PREINITIALIZED);

        // Allow mapping pre init, must be done before validate.
        for (Enumeration mappingsEnum = getMappings().elements(); mappingsEnum.hasMoreElements();) {
            try {
                DatabaseMapping mapping = (DatabaseMapping) mappingsEnum.nextElement();
                mapping.preInitialize(session);
            } catch (DescriptorException exception) {
                session.getIntegrityChecker().handleError(exception);
            }
        }

        getCachePolicy().useNoIdentityMap();
        getQueryManager().getDoesExistQuery().setExistencePolicy(DoesExistQuery.CheckDatabase);

        validateBeforeInitialization(session);

        preInitializeInheritancePolicy(session);

        verifyTableQualifiers(session.getDatasourcePlatform());
        initializeProperties(session);

        if (hasInterfacePolicy()) {
            preInterfaceInitialization(session);
        }
        getCachePolicy().assignDefaultValues(session);
    }


    @Override
    protected void preInitializeInheritancePolicy(AbstractSession session) throws DescriptorException {
        super.preInitializeInheritancePolicy(session);
        // Make sure that parent is already preinitialized
        if (hasInheritance()) {
            if(isChildDescriptor()) {
                XMLDescriptor parentDescriptor = (XMLDescriptor) getInheritancePolicy().getParentDescriptor();
                NamespaceResolver parentNamespaceResolver = parentDescriptor.getNamespaceResolver();
                if(null != parentNamespaceResolver && parentNamespaceResolver != namespaceResolver) {
                    if(null == namespaceResolver) {
                        namespaceResolver = getNonNullNamespaceResolver();
                    }
                    if(parentNamespaceResolver.hasPrefixesToNamespaces()) {
                        for(Entry<String, String> entry : parentNamespaceResolver.getPrefixesToNamespaces().entrySet()) {
                            String namespaceURI = namespaceResolver.resolveNamespacePrefix(entry.getKey());
                            if(null == namespaceURI) {
                                namespaceResolver.put(entry.getKey(), entry.getValue());
                            } else if(!namespaceURI.equals(entry.getValue())) {
                                throw XMLMarshalException.subclassAttemptedToOverrideNamespaceDeclaration(entry.getKey(), getJavaClassName(), namespaceURI, parentDescriptor.getJavaClassName(), entry.getValue());
                            }
                        }
                    }
                }
            }
            // The default table will be set in this call once the duplicate
            // tables have been removed.
            getInheritancePolicy().preInitialize(session);
        } else {
            // This must be done now, after validate, before init anything else.
            setInternalDefaultTable();
        }
    }

    /**
     * INTERNAL:
     * Post initializations after mappings are initialized.
     */
    @Override
    public void postInitialize(AbstractSession session) throws DescriptorException {
        // Avoid repetitive initialization (this does not solve loops)
        if (isInitialized(POST_INITIALIZED) || isInvalid()) {
            return;
        }

        setInitializationStage(POST_INITIALIZED);

        // Make sure that child is post initialized,
        // this initialize bottom up, unlike the two other phases that to top down.
        if (hasInheritance()) {
            for (ClassDescriptor child : getInheritancePolicy().getChildDescriptors()) {
                child.postInitialize(session);
            }
        }

        // Allow mapping to perform post initialization.
        for (DatabaseMapping mapping : getMappings()) {
            // This causes post init to be called multiple times in inheritance.
            mapping.postInitialize(session);
        }

        if (hasInheritance()) {
            getInheritancePolicy().postInitialize(session);
        }

        //PERF: Ensure that the identical primary key fields are used to avoid equals.
        if(null != primaryKeyFields) {
            for (int index = (primaryKeyFields.size() - 1); index >= 0; index--) {
                DatabaseField primaryKeyField = getPrimaryKeyFields().get(index);
                int fieldIndex = getFields().indexOf(primaryKeyField);

                // Aggregate/agg-collections may not have a mapping for pk field.
                if (fieldIndex != -1) {
                    primaryKeyField = getFields().get(fieldIndex);
                    getPrimaryKeyFields().set(index, primaryKeyField);
                }
            }
        }

        // Index and classify fields and primary key.
        // This is in post because it needs field classification defined in initializeMapping
        // this can come through a 1:1 so requires all descriptors to be initialized (mappings).
        // May 02, 2000 - Jon D.
        for (int index = 0; index < getFields().size(); index++) {
            DatabaseField field = getFields().elementAt(index);
            if (field.getType() == null) {
                DatabaseMapping mapping = getObjectBuilder().getMappingForField(field);
                if (mapping != null) {
                    field.setType(mapping.getFieldClassification(field));
                }
            }
            field.setIndex(index);
        }

        validateAfterInitialization(session);
    }

    /**
     * INTERNAL:
     * Initialize the mappings as a separate step.
     * This is done as a separate step to ensure that inheritance has been first resolved.
     */
    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
        if (this.hasInheritance()) {
            ((org.eclipse.persistence.internal.oxm.QNameInheritancePolicy) this.getInheritancePolicy()).setNamespaceResolver(this.getNamespaceResolver());
        }

        if(null != this.defaultRootElementField) {
            defaultRootElementField.setNamespaceResolver(this.namespaceResolver);
            defaultRootElementField.initialize();
        }
        if(schemaReference != null && schemaReference.getSchemaContext() != null && (schemaReference.getType() == XMLSchemaReference.COMPLEX_TYPE || schemaReference.getType() == XMLSchemaReference.SIMPLE_TYPE) && getDefaultRootElementType() == null){

            if(hasInheritance() && isChildDescriptor()){
                XMLField parentField = ((XMLDescriptor)getInheritancePolicy().getParentDescriptor()).getDefaultRootElementField();
                //if this descriptor has a root element field different than it's parent set the leaf element type of the default root field
                if(parentField == null || (parentField !=null && defaultRootElementField !=null && !defaultRootElementField.getXPathFragment().equals(parentField.getXPathFragment()))){
                    setDefaultRootElementType(schemaReference.getSchemaContextAsQName(getNamespaceResolver()));
                }
            }else{
                setDefaultRootElementType(schemaReference.getSchemaContextAsQName(getNamespaceResolver()));
            }

        }

        if(null != primaryKeyFields) {
            for(int x = 0, primaryKeyFieldsSize = this.primaryKeyFields.size(); x<primaryKeyFieldsSize; x++) {
                XMLField pkField = (XMLField) this.primaryKeyFields.get(x);
                pkField.setNamespaceResolver(this.namespaceResolver);
                pkField.initialize();
            }
        }

        // These cached settings on the project must be set even if descriptor is initialized.
        // If defined as read-only, add to it's project's default read-only classes collection.
        if (shouldBeReadOnly() && (!session.getDefaultReadOnlyClasses().contains(getJavaClass()))) {
            session.getDefaultReadOnlyClasses().add(getJavaClass());
        }

        // Avoid repetitive initialization (this does not solve loops)
        if (isInitialized(INITIALIZED) || isInvalid()) {
            return;
        }

        setInitializationStage(INITIALIZED);

        // make sure that parent mappings are initialized?
        if (isChildDescriptor()) {
            ClassDescriptor parentDescriptor = getInheritancePolicy().getParentDescriptor();
            parentDescriptor.initialize(session);
            if(parentDescriptor.hasEventManager()) {
                getEventManager();
            }
        }

        for (Enumeration mappingsEnum = getMappings().elements(); mappingsEnum.hasMoreElements();) {
            DatabaseMapping mapping = (DatabaseMapping) mappingsEnum.nextElement();
            validateMappingType(mapping);
            mapping.initialize(session);
            if(mapping.isObjectReferenceMapping()) {
                this.hasReferenceMappings = true;
            }
            if(mapping instanceof XMLChoiceObjectMapping) {
                XMLChoiceObjectMapping choiceMapping = ((XMLChoiceObjectMapping)mapping);
                for(XMLMapping next : choiceMapping.getChoiceElementMappings().values()) {
                    if(((DatabaseMapping)next).isObjectReferenceMapping()) {
                        this.hasReferenceMappings = true;
                    }
                }
            }
            if(mapping instanceof XMLChoiceCollectionMapping) {
                XMLChoiceCollectionMapping choiceMapping = ((XMLChoiceCollectionMapping)mapping);
                for(XMLMapping next : choiceMapping.getChoiceElementMappings().values()) {
                    if(((DatabaseMapping)next).isObjectReferenceMapping()) {
                        this.hasReferenceMappings = true;
                    }
                }
            }
            // Add all the fields in the mapping to myself.
            Helper.addAllUniqueToVector(getFields(), mapping.getFields());
        }

        // If this has inheritance then it needs to be initialized before all fields is set.
        if (hasInheritance()) {
            getInheritancePolicy().initialize(session);
        }

        // Initialize the allFields to its fields, this can be done now because the fields have been computed.
        setAllFields((Vector) getFields().clone());

        getObjectBuilder().initialize(session);
        if (hasInterfacePolicy()) {
            interfaceInitialization(session);
        }
        if (hasReturningPolicy()) {
            getReturningPolicy().initialize(session);
        }
        if (eventManager != null) {
            eventManager.initialize(session);
        }
        if (copyPolicy != null) {
            copyPolicy.initialize(session);
        }
        getInstantiationPolicy().initialize(session);
        if (getSchemaReference() != null) {
            getSchemaReference().initialize(session);
        }
        // If a Location Accessor is set on a superclass, inherit it
        if (getInheritancePolicyOrNull() != null && getInheritancePolicy().getParentDescriptor() != null) {
            XMLDescriptor d = (XMLDescriptor) getInheritancePolicy().getParentDescriptor();
            locationAccessor = d.getLocationAccessor();
        }
        if (locationAccessor != null) {
            locationAccessor.initializeAttributes(getJavaClass());
        }
    }

    /**
     * INTERNAL:
     * XML descriptors are initialized normally, since they do
     * not need to be cloned by XML aggregate mappings.
     */
    @Override
    public boolean requiresInitialization(AbstractSession session) {
        return (!isDescriptorForInterface());
    }

    /**
     * Aggregates use a dummy table as default.
     */
    @Override
    protected DatabaseTable extractDefaultTable() {
        return new DatabaseTable();
    }

    /**
     * INTERNAL:
     * Determines the appropriate object to return from the unmarshal
     * call.  The method will either return the object created in the
     * xmlReader.parse() call or an instance of Root.  An Root
     * instance will be returned if the DOMRecord element being
     * unmarshalled does not equal the descriptor's default root
     * element.
     *
     * @return object
     */
    @Override
    public Object wrapObjectInXMLRoot(UnmarshalRecord unmarshalRecord, boolean forceWrap) {
        String elementLocalName = unmarshalRecord.getLocalName();
        String elementNamespaceUri = unmarshalRecord.getRootElementNamespaceUri();
        if (forceWrap || shouldWrapObject(unmarshalRecord.getCurrentObject(), elementNamespaceUri, elementLocalName, null, unmarshalRecord.isNamespaceAware())) {
            Root xmlRoot = new XMLRoot();
            xmlRoot.setLocalName(elementLocalName);
            xmlRoot.setNamespaceURI(elementNamespaceUri);
            xmlRoot.setObject(unmarshalRecord.getCurrentObject());
            xmlRoot.setEncoding(unmarshalRecord.getEncoding());
            xmlRoot.setVersion(unmarshalRecord.getVersion());
            xmlRoot.setSchemaLocation(unmarshalRecord.getSchemaLocation());
            xmlRoot.setNoNamespaceSchemaLocation(unmarshalRecord.getNoNamespaceSchemaLocation());
            xmlRoot.setNil(unmarshalRecord.isNil());
            setDeclaredTypeOnXMLRoot(xmlRoot, elementNamespaceUri, elementLocalName, unmarshalRecord.isNamespaceAware(), unmarshalRecord.getUnmarshaller());

            return xmlRoot;
        }
        return unmarshalRecord.getCurrentObject();
    }

    /**
      * INTERNAL:
      * Determines the appropriate object to return from the unmarshal
      * call.  The method will either return the object created in the
      * xmlReader.parse() call or an instance of Root.  An Root
      * instance will be returned if the DOMRecord element being
      * unmarshalled does not equal the descriptor's default root
      * element.
      *
      * @return object
      */
    @Override
    public Object wrapObjectInXMLRoot(Object object, String elementNamespaceUri, String elementLocalName, String elementPrefix, boolean forceWrap, boolean isNamespaceAware, XMLUnmarshaller xmlUnmarshaller) {

        if (forceWrap || shouldWrapObject(object, elementNamespaceUri, elementLocalName, elementPrefix, isNamespaceAware)) {
            // if the DOMRecord element != descriptor's default
            // root element, create an Root, populate and return it
            Root xmlRoot = new XMLRoot();
            xmlRoot.setLocalName(elementLocalName);
            xmlRoot.setNamespaceURI(elementNamespaceUri);
            xmlRoot.setObject(object);

            setDeclaredTypeOnXMLRoot(xmlRoot, elementNamespaceUri, elementLocalName, isNamespaceAware, xmlUnmarshaller);

            return xmlRoot;
        }
        return object;
    }

    /**
     * INTERNAL:
     */
    @Override
    public Object wrapObjectInXMLRoot(Object object, String elementNamespaceUri, String elementLocalName, String elementPrefix, String encoding, String version, boolean forceWrap, boolean isNamespaceAware, XMLUnmarshaller unmarshaller) {
        if (forceWrap || shouldWrapObject(object, elementNamespaceUri, elementLocalName, elementPrefix, isNamespaceAware)) {
            // if the DOMRecord element != descriptor's default
            // root element, create an XMLRoot, populate and return it
            Root xmlRoot = new XMLRoot();
            xmlRoot.setLocalName(elementLocalName);
            xmlRoot.setNamespaceURI(elementNamespaceUri);
            xmlRoot.setObject(object);
            xmlRoot.setEncoding(encoding);
            xmlRoot.setVersion(version);
            setDeclaredTypeOnXMLRoot(xmlRoot, elementNamespaceUri, elementLocalName, isNamespaceAware, unmarshaller);

            return xmlRoot;
        }
        return object;

    }

    private void setDeclaredTypeOnXMLRoot(Root xmlRoot, String elementNamespaceUri, String elementLocalName, boolean isNamespaceAware, Unmarshaller unmarshaller){
        XPathQName xpathQName = new XPathQName(elementNamespaceUri, elementLocalName, isNamespaceAware);
        Descriptor desc = unmarshaller.getContext().getDescriptor(xpathQName);
        if(desc != null){
            xmlRoot.setDeclaredType(desc.getJavaClass());
        }
    }

    /**
     * INTERNAL:
     */
    public boolean shouldWrapObject(Object object, String elementNamespaceUri, String elementLocalName, String elementPrefix, boolean isNamespaceAware) {
        if(resultAlwaysXMLRoot){
            return true;
        }
        XMLField defaultRootField = getDefaultRootElementField();

        // if the descriptor's default root element is null, we want to
        // create/return an XMLRoot - otherwise, we need to compare the
        // default root element vs. the root element in the instance doc.
        if (defaultRootField != null) {
            // resolve namespace prefix if one exists
            String defaultRootName = defaultRootField.getXPathFragment().getLocalName();
            String defaultRootNamespaceUri = defaultRootField.getXPathFragment().getNamespaceURI();
            // if the DOMRecord element == descriptor's default
            // root element, return the object as per usual

            if(isNamespaceAware){
                if ((((defaultRootNamespaceUri == null) && (elementNamespaceUri == null)) || ((defaultRootNamespaceUri == null) && (elementNamespaceUri.length() == 0)) || ((elementNamespaceUri == null) && (defaultRootNamespaceUri.length() == 0)) || (((defaultRootNamespaceUri != null) && (elementNamespaceUri != null)) && (defaultRootNamespaceUri
                        .equals(elementNamespaceUri))))
                        && (defaultRootName.equals(elementLocalName))) {
                    return false;
                }
            }else{
                if (defaultRootName.equals(elementLocalName)) {
                    return false;
                }
            }
        }
        return true;
    }

    @Override
    public XMLField getDefaultRootElementField() {
        return defaultRootElementField;
    }

    /**
     * @return true if a new default root element field was created, else false.
     */
    private boolean setDefaultRootElementField(String newDefaultRootElement) {
        if (null == newDefaultRootElement || 0 == newDefaultRootElement.length()) {
            setDefaultRootElementField((XMLField) null);
            return false;
        }
        if(getDefaultRootElementField() != null && newDefaultRootElement.equals(getDefaultRootElementField().getName())){
            return false;
        }
        // create the root element xml field based on default root element name
        setDefaultRootElementField(new XMLField(newDefaultRootElement));
        return true;
    }

    public void setDefaultRootElementField(XMLField xmlField) {
        defaultRootElementField = xmlField;
    }

    @Override
    public QName getDefaultRootElementType() {
        if (defaultRootElementField != null) {
            return defaultRootElementField.getLeafElementType();
        }
        return null;
    }

    /**
     * The default root element type string will be stored until
     * initialization - a QName will be created and stored on the
     * default root element field during initialize.
     *
     */
    public void setDefaultRootElementType(QName type) {
        if (defaultRootElementField != null) {
            defaultRootElementField.setLeafElementType(type);
        }
    }

    /**
     * INTERNAL:
     * <p>Indicates if the Object mapped by this descriptor is a sequenced data object
     * and should be marshalled accordingly.
     */
    @Override
    public boolean isSequencedObject() {
        return sequencedObject;
    }

    public void setSequencedObject(boolean isSequenced) {
        this.sequencedObject = isSequenced;
    }

    @Override
    public boolean isWrapper() {
        return isWrapper;
    }

    public void setIsWrapper(boolean value) {
        this.isWrapper = value;
    }

    @Override
    public boolean isResultAlwaysXMLRoot() {
        return resultAlwaysXMLRoot;
    }

    @Override
    public void setResultAlwaysXMLRoot(boolean resultAlwaysXMLRoot) {
        this.resultAlwaysXMLRoot = resultAlwaysXMLRoot;
    }

    /**
     * INTERNAL:
     * Returns true if any of the mappings on this descriptor are key-based reference
     * mappings.
     */
    public boolean hasReferenceMappings() {
        return this.hasReferenceMappings;
    }

    @Override
    public DatabaseField getTypedField(DatabaseField field) {
        XMLField foundField = (XMLField) super.getTypedField(field);
        if(null != foundField) {
            return foundField;
        }
        StringTokenizer stringTokenizer = new StringTokenizer(field.getName(), String.valueOf(XPATH_FRAGMENT_SEPARATOR));
        DatabaseField typedField = getTypedField(stringTokenizer);
        if(null == typedField) {
            DatabaseMapping selfMapping = objectBuilder.getMappingForField(new XMLField("."));
            if(null != selfMapping) {
                return selfMapping.getReferenceDescriptor().getTypedField(field);
            }
        }
        return typedField;
    }

    protected DatabaseField getTypedField(StringTokenizer stringTokenizer) {
        StringBuilder xPath = new StringBuilder();
        XMLField xmlField = new XMLField();
        xmlField.setNamespaceResolver(namespaceResolver);
        while(stringTokenizer.hasMoreElements()) {
            String nextToken = stringTokenizer.nextToken();
            xmlField.setXPath(xPath.toString() + nextToken);
            xmlField.initialize();
            DatabaseMapping mapping = objectBuilder.getMappingForField(xmlField);
            if(null == mapping) {
                XPathFragment xPathFragment = new XPathFragment(nextToken);
                if(xPathFragment.getIndexValue() > 0) {
                    xmlField.setXPath(xPath.toString() + nextToken.substring(0, nextToken.indexOf('[')));
                    xmlField.initialize();
                    mapping = objectBuilder.getMappingForField(xmlField);
                    if(null != mapping) {
                        if(mapping.isCollectionMapping()) {
                            if(mapping.getContainerPolicy().isListPolicy()) {
                                if(stringTokenizer.hasMoreElements()) {
                                    return ((XMLDescriptor) mapping.getReferenceDescriptor()).getTypedField(stringTokenizer);
                                } else {
                                    return mapping.getField();
                                }
                            }
                        }
                    }
                }
            } else {
                if(stringTokenizer.hasMoreElements()) {
                    return ((XMLDescriptor) mapping.getReferenceDescriptor()).getTypedField(stringTokenizer);
                } else {
                    return mapping.getField();
                }
            }
            xPath = xPath.append(nextToken).append(XPATH_FRAGMENT_SEPARATOR);
        }
        return null;
    }

    /**
     * INTERNAL:
     * Returns this Descriptor's location accessor, if one is defined.
     */
    @Override
    public AttributeAccessor getLocationAccessor() {
        return locationAccessor;
    }

    /**
     * INTERNAL:
     * Set this Descriptor's location accessor.
     */
    @Override
    public void setLocationAccessor(AttributeAccessor value) {
        this.locationAccessor = value;
    }


    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this Descriptor to actual class-based
     * settings. This method is used when converting a project that has been built
     * with class names to a project with classes.
     */
    @Override
    public void convertClassNamesToClasses(ClassLoader classLoader){
        super.convertClassNamesToClasses(classLoader);
        if(this.attributeGroups != null) {
            for(AttributeGroup next:attributeGroups.values()) {
                next.convertClassNamesToClasses(classLoader);
            }
        }
    }
}
