/*
 * 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
package org.eclipse.persistence.internal.oxm;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

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.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.core.sessions.CoreAbstractSession;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.record.AbstractMarshalRecord;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DatabaseMapping.WriteType;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.documentpreservation.DocumentPreservationPolicy;
import org.eclipse.persistence.oxm.record.DOMRecord;
import org.eclipse.persistence.oxm.record.XMLRecord;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * INTERNAL:
 * <p><b>Purpose</b>: Object-to-XML specific ObjectBuilder.</p>
 * @author Rick Barkhouse - rick.barkhouse@oracle.com
 * @since TopLink 10<i>i</i>, 03/31/2003 16:29:40
 */
public class XMLObjectBuilder extends ObjectBuilder {
    private Boolean isXMLDescriptor;
    private boolean xsiTypeIndicatorField;

    /**
     * Create an XML object builder for the descriptor.
     */
    public XMLObjectBuilder(ClassDescriptor descriptor) {
        super(descriptor);
    }

    /**
     * Build the nested row into the parent dom.
     */
    public AbstractRecord buildRow(Object object, AbstractSession session, DatabaseField xmlField, XMLRecord parentRecord) {
        if (isXmlDescriptor() && ((Descriptor)getDescriptor()).shouldPreserveDocument()) {
            Object pk = extractPrimaryKeyFromObject(object, session);
            if ((pk == null) || (pk instanceof CacheId) && (((CacheId)pk).getPrimaryKey().length == 0)) {
                pk = new CacheId(new Object[]{ new WeakObjectWrapper(object) });
            }
            CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(pk, getDescriptor().getJavaClass(), getDescriptor(), false);
            if ((cacheKey != null) && (cacheKey.getRecord() != null)) {
                XMLRecord nestedRecord = (XMLRecord)cacheKey.getRecord();
                nestedRecord.setMarshaller(parentRecord.getMarshaller());
                nestedRecord.setLeafElementType(parentRecord.getLeafElementType());
                parentRecord.setLeafElementType((XPathQName)null);
                return buildIntoNestedRow(nestedRecord, object, session);
            }
        }
        Element newNode = XPathEngine.getInstance().createUnownedElement(parentRecord.getDOM(), (Field)xmlField);
        XMLRecord nestedRecord = new DOMRecord(newNode);
        nestedRecord.setNamespaceResolver(parentRecord.getNamespaceResolver());
        nestedRecord.setMarshaller(parentRecord.getMarshaller());
        nestedRecord.setLeafElementType(parentRecord.getLeafElementType());
        parentRecord.setLeafElementType((XPathQName)null);
        return buildIntoNestedRow(nestedRecord, object, session);

    }

    /**
     * Create a new row/record for the object builder.
     * This allows subclasses to define different record types.
     */
    @Override
    public AbstractRecord createRecord(AbstractSession session) {
        return (AbstractRecord) createRecord(getDescriptor().getTableName(), session);
    }

    /**
     * Create a new row/record for the object builder.
     * This allows subclasses to define different record types.
     */
    @Override
    public AbstractRecord createRecord(int size, AbstractSession session) {
        return (AbstractRecord) createRecord(getDescriptor().getTableName(), session);
    }

    /**
     * Create a new row/record for the object builder with the given name. This
     * allows subclasses to define different record types.
     */
    public AbstractMarshalRecord createRecord(String rootName, AbstractSession session) {
        NamespaceResolver namespaceResolver = getNamespaceResolver();
        XMLRecord xmlRec = new DOMRecord(rootName, namespaceResolver);
        xmlRec.setSession(session);
        return xmlRec;
    }

    /**
     * Create a new row/record for the object builder with the given name and
     * namespace resolver instead of the namespace resolver from the descriptor.
     * This allows subclasses to define different record types.
     */
    public AbstractRecord createRecord(String rootName, String rootUri, AbstractSession session) {
        XMLRecord xmlRec = new DOMRecord(rootName, rootUri);
        xmlRec.setSession(session);
        return xmlRec;
    }

    /**
     * Create a new row/record for the object builder with the given name. This
     * allows subclasses to define different record types.
     */
    public AbstractMarshalRecord createRecord(String rootName, Node parent, AbstractSession session) {
        NamespaceResolver namespaceResolver = getNamespaceResolver();
        XMLRecord xmlRec = new DOMRecord(rootName, namespaceResolver, parent);
        xmlRec.setSession(session);
        return xmlRec;
    }

    public AbstractRecord createRecordFor(Object attributeValue, Field xmlField, XMLRecord parentRecord, Mapping mapping) {
        DocumentPreservationPolicy policy = parentRecord.getDocPresPolicy();
        Element newNode = null;
        if(policy != null) {
            newNode = (Element)policy.getNodeForObject(attributeValue);
        }
        if(newNode == null) {
           newNode = XPathEngine.getInstance().createUnownedElement(parentRecord.getDOM(), xmlField);
           if(policy !=null ){
               if(xmlField.isSelfField()) {
                   policy.addObjectToCache(attributeValue, newNode, mapping);
               } else {
                   policy.addObjectToCache(attributeValue, newNode);
               }
           }
        }

        DOMRecord nestedRecord = new DOMRecord(newNode);
        nestedRecord.setMarshaller(parentRecord.getMarshaller());
        nestedRecord.setLeafElementType(parentRecord.getLeafElementType());
        parentRecord.setLeafElementType((XPathQName)null);
        nestedRecord.setDocPresPolicy(policy);
        nestedRecord.setXOPPackage(parentRecord.isXOPPackage());
        nestedRecord.setReferenceResolver(((DOMRecord) parentRecord).getReferenceResolver());
        return nestedRecord;
    }

    public AbstractRecord createRecordFor(Object object, DocumentPreservationPolicy docPresPolicy) {
        Element cachedNode = null;
        XMLRecord record = null;
        if(docPresPolicy != null) {
            cachedNode = (Element)docPresPolicy.getNodeForObject(object);
        }
        if(cachedNode == null) {
            record = new DOMRecord(getDescriptor().getTableName(), getNamespaceResolver());
            docPresPolicy.addObjectToCache(object, record.getDOM());
        } else {
            record = new DOMRecord(cachedNode);
        }
        record.setDocPresPolicy(docPresPolicy);
        return record;
    }

    public AbstractRecord createRecordFor(Object object, DocumentPreservationPolicy docPresPolicy, String rootName, String rootUri) {
        Element cachedNode = null;
        XMLRecord record = null;
        if(docPresPolicy != null) {
            cachedNode = (Element)docPresPolicy.getNodeForObject(object);
        }
        if(cachedNode == null) {
            record = new DOMRecord(rootName, rootUri);
            docPresPolicy.addObjectToCache(object, record.getDOM());
        } else {
            record = new DOMRecord(cachedNode);
        }
        record.setDocPresPolicy(docPresPolicy);
        return record;
    }

    /**
     * Create a new row/record for the object builder. This allows subclasses to
     * define different record types.  This will typically be called when a
     * record will be used for temporarily holding on to primary key fields.
     */
    @Override
    protected AbstractRecord createRecordForPKExtraction(int size, AbstractSession session) {
        NamespaceResolver namespaceResolver = getNamespaceResolver();
        XMLRecord xmlRec = new DOMRecord(getDescriptor().getTableName(), namespaceResolver);
        xmlRec.setSession(session);
        return xmlRec;
    }

    /**
     * INTERNAL: Override the parent's buildObject to allow for the caching of
     * aggregate objects in OX. By caching aggregates along with XML Nodes that
     * they were created from, we are able to preserve the structure and
     * unmapped content of the document that was used to create these objects.
     */
    @Override
    public Object buildObject(ObjectBuildingQuery query, AbstractRecord databaseRow, JoinedAttributeManager joinManager) throws DatabaseException, QueryException {
        XMLRecord row = (XMLRecord) databaseRow;
        row.setSession(query.getSession());

        XMLUnmarshaller unmarshaller = row.getUnmarshaller();
        Object parent = row.getOwningObject();

        if (!(isXmlDescriptor() || getDescriptor().isDescriptorTypeAggregate())) {
            return super.buildObject(query, databaseRow, joinManager);
        }
        query.getSession().startOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
        ClassDescriptor concreteDescriptor = getDescriptor();
        Object domainObject = null;

        // only need to check in the root case since the nested case is handled
        // in the mapping
        if (concreteDescriptor.hasInheritance() && (parent == null)) {
            // look for an xsi:type attribute in the xml document
            InheritancePolicy inheritancePolicy = concreteDescriptor.getInheritancePolicy();
            Class classValue = inheritancePolicy.classFromRow(databaseRow, query.getSession());
            if ((classValue == null) && isXmlDescriptor()) {
                // no xsi:type attribute - look for type indicator on the
                // default root element
                QName leafElementType = ((Descriptor) concreteDescriptor).getDefaultRootElementType();

                // if we have a user-set type, try to get the class from the
                // inheritance policy
                if (leafElementType != null) {
                    XPathQName xpathQName = new XPathQName(leafElementType, row.isNamespaceAware());
                    Object indicator = inheritancePolicy.getClassIndicatorMapping().get(xpathQName);
                    if (indicator != null) {
                        classValue = (Class) indicator;
                    }
                }
            }

            // if we found the class, use it - otherwise, use the descriptor
            // class, if non-abstract
            if (classValue != null) {
                concreteDescriptor = query.getSession().getDescriptor(classValue);
                if ((concreteDescriptor == null) && query.hasPartialAttributeExpressions()) {
                    concreteDescriptor = getDescriptor();
                }
                if (concreteDescriptor == null) {
                    throw QueryException.noDescriptorForClassFromInheritancePolicy(query, classValue);
                }
            } else {
                // make sure the class is non-abstract
                if (Modifier.isAbstract(concreteDescriptor.getJavaClass().getModifiers())) {
                    // throw an exception
                    throw DescriptorException.missingClassIndicatorField(databaseRow, inheritancePolicy.getDescriptor());
                }
            }
        }
        domainObject = concreteDescriptor.getObjectBuilder().buildNewInstance();
        row.setCurrentObject(domainObject);
        if ((unmarshaller != null) && (unmarshaller.getUnmarshalListener() != null)) {
            unmarshaller.getUnmarshalListener().beforeUnmarshal(domainObject, parent);
        }
        concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, null, databaseRow, query, joinManager, null, false, query.getSession());
        if (isXmlDescriptor() && ((Descriptor) concreteDescriptor).getPrimaryKeyFieldNames().size() > 0) {
            Object pk = extractPrimaryKeyFromRow(databaseRow, query.getSession());
            if ((pk != null) && (((CacheId) pk).getPrimaryKey().length > 0)) {
                DOMRecord domRecord = (DOMRecord) databaseRow;
                domRecord.getReferenceResolver().putValue(concreteDescriptor.getJavaClass(), pk, domainObject);
            }
        }
        DocumentPreservationPolicy docPresPolicy = row.getDocPresPolicy();
        if (docPresPolicy != null) {
            // EIS XML Cases won't have a doc pres policy set
            row.getDocPresPolicy().addObjectToCache(domainObject, row.getDOM());
        }
        query.getSession().endOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
        if ((unmarshaller != null) && (unmarshaller.getUnmarshalListener() != null)) {
            unmarshaller.getUnmarshalListener().afterUnmarshal(domainObject, parent);
        }
        return domainObject;
    }

    public AbstractRecord buildRow(AbstractRecord databaseRow, Object object, AbstractSession session) {
        return buildRow(databaseRow, object, session, false);
    }

    public AbstractRecord buildRow(AbstractRecord databaseRow, Object object, AbstractSession session, boolean wasXMLRoot) {
        XMLRecord row = (XMLRecord)databaseRow;
        row.setSession(session);

        XMLMarshaller marshaller = row.getMarshaller();
        if ((marshaller != null) && (marshaller.getMarshalListener() != null)) {
            marshaller.getMarshalListener().beforeMarshal(object);
        }
        addNamespaceDeclarations((row).getDocument());
        writeOutMappings(row, object, session);


        // If this descriptor has multiple tables then we need to append the
        // primary keys for
        // the non default tables.
        if (!getDescriptor().isAggregateDescriptor()) {
            addPrimaryKeyForNonDefaultTable(row);
        }



        if ((marshaller != null) && (marshaller.getMarshalListener() != null)) {
            marshaller.getMarshalListener().afterMarshal(object);
        }
        return row;
    }

    public void writeOutMappings(XMLRecord row, Object object, AbstractSession session) {
        List<DatabaseMapping> mappings = getDescriptor().getMappings();
        for (int index = 0; index < mappings.size(); index++) {
            DatabaseMapping mapping = mappings.get(index);
            mapping.writeFromObjectIntoRow(object, row, session, WriteType.UNDEFINED);
        }
    }
    public void addNamespaceDeclarations(Document document) {
        NamespaceResolver namespaceResolver = getNamespaceResolver();

        if (namespaceResolver == null) {
            return;
        }

        Element docElement = document.getDocumentElement();
        if(namespaceResolver.getDefaultNamespaceURI() != null) {
            docElement.setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE, namespaceResolver.getDefaultNamespaceURI());
        }

        Enumeration prefixes = namespaceResolver.getPrefixes();
        String prefix;
        String namespace;
        while (prefixes.hasMoreElements()) {
            prefix = (String)prefixes.nextElement();
            namespace = namespaceResolver.resolveNamespacePrefix(prefix);
            docElement.setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE + Constants.COLON + prefix, namespace);
        }
    }

    /**
     * Override method in superclass in order to set the session on the record.
     * Each mapping is recursed to assign values from the Record to the attributes in the domain object.
     */
    @Override
    public void buildAttributesIntoObject(Object domainObject, CacheKey cacheKey, AbstractRecord databaseRow, ObjectBuildingQuery query, JoinedAttributeManager joinManager, FetchGroup executionFetchGroup, boolean forRefresh, AbstractSession targetSession) throws DatabaseException {
        ((XMLRecord)databaseRow).setSession(query.getSession().getExecutionSession(query));
        super.buildAttributesIntoObject(domainObject, cacheKey, databaseRow, query, joinManager, executionFetchGroup, forRefresh, targetSession);
    }

    /**
     * Override method in superclass in order to set the session on the record.
     * Return the row with primary keys and their values from the given expression.
     */
    @Override
    public AbstractRecord extractPrimaryKeyRowFromExpression(Expression expression, AbstractRecord translationRow, AbstractSession session) {
        AbstractRecord primaryKeyRow = createRecord(getPrimaryKeyMappings().size(), session);
        expression.getBuilder().setSession(session.getRootSession(null));
        // Get all the field & values from expression
        boolean isValid = expression.extractPrimaryKeyValues(true, getDescriptor(), primaryKeyRow, translationRow);
        if (!isValid) {
            return null;
        }

        // Check that the sizes match up
        if (primaryKeyRow.size() != getDescriptor().getPrimaryKeyFields().size()) {
            return null;
        }

        return primaryKeyRow;
    }

    /**
     * Override method in superclass in order to set the session on the record.
     * Return the row with primary keys and their values from the given expression.
     */
    @Override
    public Object extractPrimaryKeyFromExpression(boolean requiresExactMatch, Expression expression, AbstractRecord translationRow, AbstractSession session) {
        AbstractRecord primaryKeyRow = createRecord(getPrimaryKeyMappings().size(), session);
        expression.getBuilder().setSession(session.getRootSession(null));
        // Get all the field & values from expression.
        boolean isValid = expression.extractPrimaryKeyValues(requiresExactMatch, getDescriptor(), primaryKeyRow, translationRow);
        if (requiresExactMatch && (!isValid)) {
            return null;
        }

        // Check that the sizes match.
        if (primaryKeyRow.size() != getDescriptor().getPrimaryKeyFields().size()) {
            return null;
        }

        return extractPrimaryKeyFromRow(primaryKeyRow, session);
    }

    @Override
    public Object extractPrimaryKeyFromObject(Object domainObject, AbstractSession session) {
        if (getDescriptor().hasInheritance() && (domainObject.getClass() != getDescriptor().getJavaClass()) && (!domainObject.getClass().getSuperclass().equals(getDescriptor().getJavaClass()))) {
            return session.getDescriptor(domainObject.getClass()).getObjectBuilder().extractPrimaryKeyFromObject(domainObject, session);
        }
        List<DatabaseField> descriptorPrimaryKeyFields = getDescriptor().getPrimaryKeyFields();
        if (null == descriptorPrimaryKeyFields || descriptorPrimaryKeyFields.size() == 0) {
            return null;
        }
        return super.extractPrimaryKeyFromObject(domainObject, session);
    }

    public AbstractRecord buildIntoNestedRow(AbstractRecord row, Object object, AbstractSession session) {
        return buildIntoNestedRow(row, null, object, session, null, null, false);
    }

    public AbstractRecord buildIntoNestedRow(AbstractRecord row, Object object, AbstractSession session, Descriptor refDesc, Field xmlField) {
        return buildIntoNestedRow(row, null, object, session, refDesc, xmlField, false);
    }
   public AbstractRecord buildIntoNestedRow(AbstractRecord row, Object originalObject, Object object, AbstractSession session, Descriptor refDesc, Field xmlField, boolean wasXMLRoot) {
        // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
        XMLRecord record = (XMLRecord)row;
        record.setSession(session);

        XMLMarshaller marshaller = record.getMarshaller();

        if ((marshaller != null) && (marshaller.getMarshalListener() != null)) {
            marshaller.getMarshalListener().beforeMarshal(object);
        }
        List extraNamespaces = null;
        if (isXmlDescriptor()) {
            Descriptor xmlDescriptor = (Descriptor)getDescriptor();
            extraNamespaces = addExtraNamespacesToNamespaceResolver(xmlDescriptor, record, session, false, false);
            writeExtraNamespaces(extraNamespaces, record);
            record.addXsiTypeAndClassIndicatorIfRequired(xmlDescriptor, refDesc, xmlField, originalObject, object, wasXMLRoot, false);
        }

        writeOutMappings(record, object, session);
        // If this descriptor is involved in inheritance add the class type.
        if (isXmlDescriptor()) {
            record.removeExtraNamespacesFromNamespaceResolver(extraNamespaces, session);
        }

        // If this descriptor has multiple tables then we need to append the
        // primary keys for
        // the non default tables.
        if (!getDescriptor().isAggregateDescriptor()) {
            addPrimaryKeyForNonDefaultTable(row);
        }
        if ((marshaller != null) && (marshaller.getMarshalListener() != null)) {
            marshaller.getMarshalListener().afterMarshal(object);
        }
        return row;
    }

    public NamespaceResolver getNamespaceResolver() {
        NamespaceResolver namespaceResolver = null;
        if (isXmlDescriptor()) {
            namespaceResolver = ((XMLDescriptor)getDescriptor()).getNamespaceResolver();
        } else if (getDescriptor() instanceof org.eclipse.persistence.eis.EISDescriptor) {
            namespaceResolver = ((org.eclipse.persistence.eis.EISDescriptor)getDescriptor()).getNamespaceResolver();
        }
        return namespaceResolver;
    }
    /**
     * Indicates if the object builder's descriptor is an XMLDescriptor.
     * The value is lazily initialized.
     *
     */
    protected boolean isXmlDescriptor() {
        if (isXMLDescriptor == null) {
            isXMLDescriptor = getDescriptor() instanceof Descriptor;
        }
        return isXMLDescriptor;
    }

    /**
     * Set the descriptor.  This method is overridden so the
     * isXMLDescriptor Boolean can be reset.
     */
    @Override
    public void setDescriptor(ClassDescriptor aDescriptor) {
        super.setDescriptor(aDescriptor);
        isXMLDescriptor = null;
    }

    protected List<Namespace> addExtraNamespacesToNamespaceResolver(Descriptor desc, AbstractMarshalRecord marshalRecord, CoreAbstractSession session, boolean allowOverride, boolean ignoreEqualResolvers) {
        return marshalRecord.addExtraNamespacesToNamespaceResolver(desc, session, allowOverride, ignoreEqualResolvers);
    }

    public void writeExtraNamespaces(List extraNamespaces, XMLRecord xmlRecord) {
        if(extraNamespaces == null){
          return;
        }

        if(xmlRecord.getDOM().getNodeType() != Node.ELEMENT_NODE) {
            return;
        }

        for (int i = 0; i < extraNamespaces.size(); i++) {
            Namespace next = (Namespace)extraNamespaces.get(i);
            ((Element)xmlRecord.getDOM()).setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE + Constants.COLON + next.getPrefix(), next.getNamespaceURI());
        }
    }

    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
        mappingsByField.clear();
        if(null != readOnlyMappingsByField) {
            readOnlyMappingsByField.clear();
        }
        if(null != mappingsByAttribute) {
            mappingsByAttribute.clear();
        }
        cloningMappings.clear();
        if(null != eagerMappings) {
            eagerMappings.clear();
        }
        if(null != relationshipMappings) {
            relationshipMappings.clear();
        }

        for (Enumeration mappings = this.descriptor.getMappings().elements();
                 mappings.hasMoreElements();) {
            DatabaseMapping mapping = (DatabaseMapping)mappings.nextElement();

            // Add attribute to mapping association
            if (!mapping.isWriteOnly()) {
                if(mappingsByAttribute != null) {
                    getMappingsByAttribute().put(mapping.getAttributeName(), mapping);
                }
            }
            // Cache mappings that require cloning.
            if (mapping.isCloningRequired()) {
                getCloningMappings().add(mapping);
            }
            // Cache eager mappings.
            if (mapping.isForeignReferenceMapping() && ((ForeignReferenceMapping)mapping).usesIndirection() && (!mapping.isLazy())) {
                getEagerMappings().add(mapping);
            }
            // Cache relationship mappings.
            if (!mapping.isDirectToFieldMapping()) {
                if(null != relationshipMappings) {
                    relationshipMappings.add(mapping);
                }
            }

            // Add field to mapping association
            for (DatabaseField field : mapping.getFields()) {

                if (mapping.isReadOnly()) {
                    if(null != readOnlyMappingsByField) {
                        List readOnlyMappings = getReadOnlyMappingsByField().get(field);

                        if (readOnlyMappings == null) {
                            readOnlyMappings = new ArrayList();
                            getReadOnlyMappingsByField().put(field, readOnlyMappings);
                        }

                        readOnlyMappings.add(mapping);
                    }
                } else {
                    if (mapping.isAggregateObjectMapping()) {
                        // For Embeddable class, we need to test read-only
                        // status of individual fields in the embeddable.
                        ObjectBuilder aggregateObjectBuilder = mapping.getReferenceDescriptor().getObjectBuilder();

                        // Look in the non-read-only fields mapping
                        DatabaseMapping aggregatedFieldMapping = aggregateObjectBuilder.getMappingForField(field);

                        if (aggregatedFieldMapping == null) { // mapping must be read-only
                            List readOnlyMappings = getReadOnlyMappingsByField().get(field);

                            if (readOnlyMappings == null) {
                                readOnlyMappings = new ArrayList();
                                getReadOnlyMappingsByField().put(field, readOnlyMappings);
                            }

                            readOnlyMappings.add(mapping);
                        } else {
                            getMappingsByField().put(field, mapping);
                        }
                    } else { // Not an embeddable mapping
                        if (!getMappingsByField().containsKey(field)) {
                            getMappingsByField().put(field, mapping);
                        }
                    }
                }
            }
        }
        this.isSimple = null == relationshipMappings || relationshipMappings.isEmpty();

        initializePrimaryKey(session);
        initializeJoinedAttributes();

        if (this.descriptor.usesSequenceNumbers()) {
            DatabaseMapping sequenceMapping = getMappingForField(this.descriptor.getSequenceNumberField());
            if ((sequenceMapping != null) && sequenceMapping.isDirectToFieldMapping()) {
                setSequenceMapping((AbstractDirectMapping)sequenceMapping);
            }
        }



        if (descriptor.hasInheritance() ) {
            Field indicatorField = (Field) descriptor.getInheritancePolicy().getClassIndicatorField();
            if(indicatorField != null){
               if (indicatorField.getLastXPathFragment().getNamespaceURI() != null && indicatorField.getLastXPathFragment().getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI)
                        && indicatorField.getLastXPathFragment().getLocalName().equals(Constants.SCHEMA_TYPE_ATTRIBUTE)){
                     xsiTypeIndicatorField = true;
               }

            }
        }
    }

    @Override
    public boolean isXMLObjectBuilder() {
        return true;
    }

    public boolean isXsiTypeIndicatorField() {
        return xsiTypeIndicatorField;
    }

}
