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

import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.Vector;

import javax.xml.namespace.QName;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.descriptors.DescriptorIterator;
import org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.oxm.NodeValue;
import org.eclipse.persistence.internal.oxm.XMLChoiceFieldToClassAssociation;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.mappings.XMLContainerMapping;
import org.eclipse.persistence.internal.queries.CollectionContainerPolicy;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.ChangeRecord;
import org.eclipse.persistence.internal.sessions.MergeManager;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.mappings.AttributeAccessor;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.mappings.foundation.AbstractCompositeCollectionMapping;
import org.eclipse.persistence.mappings.foundation.AbstractCompositeDirectCollectionMapping;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.XMLRoot;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.mappings.converters.XMLConverter;
import org.eclipse.persistence.oxm.mappings.nullpolicy.AbstractNullPolicy;
import org.eclipse.persistence.oxm.record.DOMRecord;
import org.eclipse.persistence.oxm.record.XMLEntry;
import org.eclipse.persistence.oxm.record.XMLRecord;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.remote.DistributedSession;

/**
 * PUBLIC:
 * <p><b>Purpose:</b>Provide a mapping that can map a single attribute to a number of
 * different elements in an XML Document. This will be used to map to Choices or Substitution
 * Groups in an XML Schema
 * <p><b>Responsibilities:</b><ul>
 * <li>Allow the user to specify XPath {@literal ->} Type mappings</li>
 * <li>Handle reading and writing of XML Documents containing a collection of choice or substitution
 * group elements</li>
 * </ul>
 * <p>The XMLChoiceCollectionMapping is the collection version of the XMLChoiceMapping. This mapping
 * allows the user to specify a number of different xpaths, and types associated with those xpaths.
 * When any of these elements are encountered in the XML Document, they are read in as the correct
 * type and added to the collection.
 * <p><b>Setting up XPath mappings:</b>Unlike other OXM Mappings, instead of setting a single xpath,
 * the addChoiceElement method is used to specify an xpath and the type associated with this xpath.
 * <br>
 * xmlChoiceCollectionMapping.addChoiceElement("mystring/text()", String.class);
 * <br>
 * xmlChoiceCollectionMapping.addChoiceElement("myaddress", Address.class);
 *
 */

public class XMLChoiceCollectionMapping extends DatabaseMapping implements ChoiceCollectionMapping<AbstractSession, AttributeAccessor, ContainerPolicy, Converter, ClassDescriptor, DatabaseField, XMLMarshaller, Session, XMLUnmarshaller, XMLField, XMLMapping, XMLRecord>, XMLMapping {
    private Map<XMLField, Class> fieldToClassMappings;
    private Map<Class, XMLField> classToFieldMappings;
    private Map<Class, List<XMLField>> classToSourceFieldsMappings;
    private Map<String, List<XMLField>> classNameToSourceFieldsMappings;
    private Map<XMLField, XMLMapping> choiceElementMappings;
    private Map<String, XMLMapping> choiceElementMappingsByClassName;
    private Map<Class, XMLMapping> choiceElementMappingsByClass;
    private Map<XMLField, String> fieldToClassNameMappings;
    private Map<String, XMLField> classNameToFieldMappings;
    private Map<XMLField, Converter> fieldsToConverters;
    private ContainerPolicy containerPolicy;
    private boolean isDefaultEmptyContainer = XMLContainerMapping.EMPTY_CONTAINER_DEFAULT;
    private boolean isMixedContent;
    private String mixedGroupingElement;
    private AbstractNullPolicy wrapperNullPolicy;

    private boolean isAny;
    private boolean isWriteOnly;
    private static final AttributeAccessor temporaryAccessor = new InstanceVariableAttributeAccessor();
    private boolean reuseContainer;
    private Converter converter;
    private XMLCompositeDirectCollectionMapping mixedContentMapping;
    private XMLAnyCollectionMapping anyMapping;

    private static final String DATA_HANDLER = "jakarta.activation.DataHandler";
    private static final String MIME_MULTIPART = "jakarta.mail.internet.MimeMultipart";
    private static final String IMAGE = "java.awt.Image";

    public XMLChoiceCollectionMapping() {
        fieldToClassMappings = new HashMap<>();
        fieldToClassNameMappings = new HashMap<>();
        classToFieldMappings = new HashMap<>();
        classNameToFieldMappings = new HashMap<>();
        choiceElementMappings = new LinkedHashMap<>();
        fieldsToConverters = new HashMap<>();
        choiceElementMappingsByClassName = new LinkedHashMap<>();
        choiceElementMappingsByClass = new LinkedHashMap<>();
        this.containerPolicy = ContainerPolicy.buildDefaultPolicy();
    }

    /**
     * Return the converter on the mapping.
     * A converter can be used to convert between the object's value and database value of the attribute.
     */
    @Override
    public Converter getConverter() {
        return converter;
    }

    /**
     * Set the converter on the mapping.
     * A converter can be used to convert between the object's value and database value of the attribute.
     */
    @Override
    public void setConverter(Converter converter) {
        this.converter = converter;
    }

    /**
     * INTERNAL:
     * Clone the attribute from the clone and assign it to the backup.
     */
    @Override
    public void buildBackupClone(Object clone, Object backup, UnitOfWorkImpl unitOfWork) {
        throw DescriptorException.invalidMappingOperation(this, "buildBackupClone");
    }

    /**
    * INTERNAL:
    * Clone the attribute from the original and assign it to the clone.
    */
    @Override
    public void buildClone(Object original, CacheKey cacheKey, Object clone, Integer refreshCascade, AbstractSession cloningSession) {
        throw DescriptorException.invalidMappingOperation(this, "buildClone");
    }

    @Override
    public void buildCloneFromRow(AbstractRecord databaseRow, JoinedAttributeManager joinManager, Object clone, CacheKey sharedCacheKey, ObjectBuildingQuery sourceQuery, UnitOfWorkImpl unitOfWork, AbstractSession executionSession) {
        throw DescriptorException.invalidMappingOperation(this, "buildCloneFromRow");
    }

    /**
     * INTERNAL:
     * Cascade perform delete through mappings that require the cascade
     */
    @Override
    public void cascadePerformRemoveIfRequired(Object object, UnitOfWorkImpl uow, Map visitedObjects) {
        //objects referenced by this mapping are not registered as they have
        // no identity, this is a no-op.
    }

    /**
     * INTERNAL:
     * Cascade registerNew for Create through mappings that require the cascade
     */
    @Override
    public void cascadeRegisterNewIfRequired(Object object, UnitOfWorkImpl uow, Map visitedObjects) {
        //Our current XML support does not make use of the UNitOfWork.
    }

    /**
     * INTERNAL:
     * This method was created in VisualAge.
     * @return prototype.changeset.ChangeRecord
     */
    @Override
    public ChangeRecord compareForChange(Object clone, Object backup, ObjectChangeSet owner, AbstractSession session) {
        throw DescriptorException.invalidMappingOperation(this, "compareForChange");
    }

    /**
    * INTERNAL:
    * Compare the attributes belonging to this mapping for the objects.
    */
    @Override
    public boolean compareObjects(Object firstObject, Object secondObject, AbstractSession session) {
        throw DescriptorException.invalidMappingOperation(this, "compareObjects");
    }

    /**
    * INTERNAL:
    * An object has been serialized from the server to the client.
    * Replace the transient attributes of the remote value holders
    * with client-side objects.
    */
    @Override
    public void fixObjectReferences(Object object, Map objectDescriptors, Map processedObjects, ObjectLevelReadQuery query, DistributedSession session) {
        throw DescriptorException.invalidMappingOperation(this, "fixObjectReferences");
    }

    /**
     * INTERNAL:
     * Iterate on the appropriate attribute value.
     */
    @Override
    public void iterate(DescriptorIterator iterator) {
        throw DescriptorException.invalidMappingOperation(this, "iterate");
    }

    /**
     * INTERNAL:
     * Merge changes from the source to the target object.
     */
    @Override
    public void mergeChangesIntoObject(Object target, ChangeRecord changeRecord, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        throw DescriptorException.invalidMappingOperation(this, "mergeChangesIntoObject");
    }

    /**
    * INTERNAL:
    * Merge changes from the source to the target object.
    */
    @Override
    public void mergeIntoObject(Object target, boolean isTargetUninitialized, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        throw DescriptorException.invalidMappingOperation(this, "mergeIntoObject");
    }

    @Override
    public Object valueFromRow(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, CacheKey cacheKey, AbstractSession executionSession, boolean isTargetProtected, Boolean[] wasCacheUsed) throws DatabaseException {
       List<XMLEntry> values = ((DOMRecord)row).getValuesIndicatingNoEntry(this.getFields());
       Object container = getContainerPolicy().containerInstance(values.size());
       for(XMLEntry next:values) {
           Field valueField = next.getXMLField();
           DatabaseMapping nextMapping = (DatabaseMapping)this.choiceElementMappings.get(valueField);
           if(nextMapping.isAbstractCompositeCollectionMapping()) {
               XMLCompositeCollectionMapping xmlMapping = (XMLCompositeCollectionMapping)nextMapping;
               Object value = xmlMapping.buildObjectFromNestedRow((AbstractRecord)next.getValue(), joinManager, sourceQuery, executionSession, isTargetProtected);
               value = convertDataValueToObjectValue(value, executionSession, ((XMLRecord) row).getUnmarshaller());
               getContainerPolicy().addInto(value, container, executionSession);
           } else if(nextMapping instanceof XMLCompositeDirectCollectionMapping){
               XMLCompositeDirectCollectionMapping xmlMapping = (XMLCompositeDirectCollectionMapping)nextMapping;
               Object value = next.getValue();
               value = convertDataValueToObjectValue(value, executionSession, ((XMLRecord) row).getUnmarshaller());
               getContainerPolicy().addInto(value, container, executionSession);
           }
       }
       ArrayList<XMLMapping> processedMappings = new ArrayList<>();
       for(XMLMapping mapping:choiceElementMappings.values()) {
           if(((DatabaseMapping)mapping).isObjectReferenceMapping() && ((DatabaseMapping)mapping).isCollectionMapping() && !(processedMappings.contains(mapping))) {
               ((XMLCollectionReferenceMapping)mapping).readFromRowIntoObject(row, joinManager, ((XMLRecord)row).getCurrentObject(), cacheKey, sourceQuery, executionSession, isTargetProtected, container);
               processedMappings.add(mapping);
           }
       }
       return container;
    }

    @Override
    public void writeFromObjectIntoRow(Object object, AbstractRecord row, AbstractSession session, WriteType writeType) throws DescriptorException {
        if(this.isReadOnly()) {
            return;
        }
        Object attributeValue = getAttributeValueFromObject(object);
        List<XMLEntry> nestedRows = new ArrayList<>();
        XMLRecord record = (XMLRecord)row;
        //First determine which Field is associated with each value:
        if(null != attributeValue) {
            ContainerPolicy cp = getContainerPolicy();
            Object iterator = cp.iteratorFor(attributeValue);
            if(null != iterator) {
                while(cp.hasNext(iterator)) {
                    Object value = cp.next(iterator, session);
                    value = convertObjectValueToDataValue(value, session, record.getMarshaller());
                    NodeValue associatedNodeValue = null;
                    XMLField associatedField = null;
                    Object fieldValue = value;
                    if(value instanceof XMLRoot) {
                        XMLRoot rootValue = (XMLRoot)value;
                        String localName = rootValue.getLocalName();
                        String namespaceUri = rootValue.getNamespaceURI();
                        fieldValue = rootValue.getObject();
                        associatedField = getFieldForName(localName, namespaceUri);
                        if(associatedField == null) {
                            associatedField = getClassToFieldMappings().get(fieldValue.getClass());
                        }
                    } else {
                        associatedField = getClassToFieldMappings().get(value.getClass());
                    }
                    if(associatedField == null) {
                        //this may be a reference mapping
                        List<XMLField> sourceFields = classToSourceFieldsMappings.get(value.getClass());
                        if(sourceFields != null && sourceFields.size() > 0) {
                            DatabaseMapping xmlMapping = (DatabaseMapping)this.choiceElementMappings.get(sourceFields.get(0));
                            for(XMLField next:sourceFields) {
                                fieldValue = ((XMLCollectionReferenceMapping)xmlMapping).buildFieldValue(value, next, session);
                                XMLEntry entry = new XMLEntry();
                                entry.setValue(fieldValue);
                                entry.setXMLField(next);
                                nestedRows.add(entry);
                            }
                        }
                    } else {
                        DatabaseMapping xmlMapping = (DatabaseMapping)this.choiceElementMappings.get(associatedField);
                        if(xmlMapping.isAbstractCompositeCollectionMapping()) {
                            fieldValue = ((XMLCompositeCollectionMapping)xmlMapping).buildCompositeRow(fieldValue, session, row, writeType);
                        }

                        XMLEntry entry = new XMLEntry();
                        entry.setValue(fieldValue);
                        entry.setXMLField(associatedField);
                        nestedRows.add(entry);
                    }
                }
            }
        }
        row.put(getFields(), nestedRows);
    }

    private XMLField getFieldForName(String localName, String namespaceUri) {
        Iterator fields = getFields().iterator();
        while(fields.hasNext()) {
            XMLField nextField = (XMLField)fields.next();
            XPathFragment fragment = nextField.getXPathFragment();
            while(fragment != null && (!fragment.nameIsText())) {
                if(fragment.getNextFragment() == null || fragment.getHasText()) {
                    if(fragment.getLocalName().equals(localName)) {
                        String fragUri = fragment.getNamespaceURI();
                        if((namespaceUri == null && fragUri == null) || (namespaceUri != null && fragUri != null && namespaceUri.equals(fragUri))) {
                            return nextField;
                        }
                    }
                }
                fragment = fragment.getNextFragment();
            }
        }
        return null;
    }
    @Override
    public void writeSingleValue(Object value, Object parent, XMLRecord row, AbstractSession session) {

    }

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

    @Override
    public Vector<DatabaseField> getFields() {
        if(fields == null || fields.size() == 0) {
            fields = this.collectFields();
        }
        return this.fields;
    }

    @Override
    protected Vector<DatabaseField> collectFields() {
        return new Vector<>(fieldToClassMappings.keySet());
    }

    public void addChoiceElement(String xpath, Class elementType) {
        XMLField field = new XMLField(xpath);
        addChoiceElement(field, elementType);
    }

    @Override
    public void addChoiceElement(String xpath, String elementTypeName) {
        XMLField field = new XMLField(xpath);
        addChoiceElement(field, elementTypeName);
    }


    public void addChoiceElement(XMLField xmlField, Class elementType) {
        getFieldToClassMappings().put(xmlField, elementType);
        if(!(this.fieldToClassNameMappings.containsKey(xmlField))) {
            this.fieldToClassNameMappings.put(xmlField, elementType.getName());
        }
        if (classToFieldMappings.get(elementType) == null) {
            classToFieldMappings.put(elementType, xmlField);
        }
        addChoiceElementMapping(xmlField, elementType);
    }

    public void addChoiceElement(List<XMLField> srcFields, Class elementType, List<XMLField> tgtFields) {
        for(XMLField sourceField:srcFields) {
            getFieldToClassMappings().put(sourceField, elementType);
            this.fieldToClassNameMappings.put(sourceField, elementType.getName());
        }
        if (getClassToSourceFieldsMappings().get(elementType) == null) {
            getClassToSourceFieldsMappings().put(elementType, srcFields);
        }
        addChoiceElementMapping(srcFields, elementType, tgtFields);
    }

    @Override
    public void addChoiceElement(List<XMLField> srcFields, String elementTypeName, List<XMLField> tgtFields) {
        for(XMLField sourceField:srcFields) {
            this.fieldToClassNameMappings.put(sourceField, elementTypeName);
        }
        if (getClassNameToSourceFieldsMappings().get(elementTypeName) == null) {
            getClassNameToSourceFieldsMappings().put(elementTypeName, srcFields);
        }
        addChoiceElementMapping(srcFields, elementTypeName, tgtFields);
    }

    public void addChoiceElement(String srcXPath, Class elementType, String tgtXPath) {
        XMLField srcField = new XMLField(srcXPath);
        XMLField tgtField = new XMLField(tgtXPath);
        addChoiceElement(srcField, elementType, tgtField);
    }

    @Override
    public void addChoiceElement(String srcXpath, String elementTypeName, String tgtXpath) {
        XMLField field = new XMLField(srcXpath);
        XMLField tgtField = new XMLField(tgtXpath);
        this.fieldToClassNameMappings.put(field, elementTypeName);
        if(this.classNameToFieldMappings.get(elementTypeName) == null) {
            this.classNameToFieldMappings.put(elementTypeName, field);
        }
        addChoiceElementMapping(field, elementTypeName, tgtField);
    }

    public void addChoiceElement(XMLField sourceField, Class elementType, XMLField targetField) {
        getFieldToClassMappings().put(sourceField, elementType);
        this.fieldToClassNameMappings.put(sourceField, elementType.getName());
        if (classToFieldMappings.get(elementType) == null) {
            classToFieldMappings.put(elementType, sourceField);
        }
        addChoiceElementMapping(sourceField, elementType, targetField);
    }

    private void addChoiceElementMapping(List<XMLField> sourceFields, Class theClass, List<XMLField> targetFields) {
        XMLCollectionReferenceMapping xmlMapping = new XMLCollectionReferenceMapping();
        xmlMapping.setReferenceClass(theClass);
        xmlMapping.setAttributeAccessor(temporaryAccessor);
        for(int i = 0; i < sourceFields.size(); i++) {
            XMLField sourceField = sourceFields.get(i);
            xmlMapping.addSourceToTargetKeyFieldAssociation(sourceField, targetFields.get(i));
            this.choiceElementMappings.put(sourceField, xmlMapping);
        }
        this.choiceElementMappingsByClass.put(theClass, xmlMapping);
    }

    private void addChoiceElementMapping(List<XMLField> sourceFields, String theClass, List<XMLField> targetFields) {
        XMLCollectionReferenceMapping xmlMapping = new XMLCollectionReferenceMapping();
        xmlMapping.setReferenceClassName(theClass);
        xmlMapping.setAttributeAccessor(temporaryAccessor);
        for(int i = 0; i < sourceFields.size(); i++) {
            XMLField sourceField = sourceFields.get(i);
            xmlMapping.addSourceToTargetKeyFieldAssociation(sourceField, targetFields.get(i));
            this.choiceElementMappings.put(sourceField, xmlMapping);
        }
        this.choiceElementMappingsByClassName.put(theClass, xmlMapping);
    }

    private void addChoiceElementMapping(XMLField sourceField, Class theClass, XMLField targetField) {
        XMLCollectionReferenceMapping mapping = new XMLCollectionReferenceMapping();
        mapping.setReferenceClass(theClass);
        mapping.setAttributeAccessor(temporaryAccessor);
        mapping.addSourceToTargetKeyFieldAssociation(sourceField, targetField);
        this.choiceElementMappings.put(sourceField, mapping);
        this.choiceElementMappingsByClass.put(theClass, mapping);
    }

    private void addChoiceElementMapping(XMLField sourceField, String className, XMLField targetField) {
        XMLCollectionReferenceMapping mapping = new XMLCollectionReferenceMapping();
        mapping.setReferenceClassName(className);
        mapping.setAttributeAccessor(temporaryAccessor);
        mapping.addSourceToTargetKeyFieldAssociation(sourceField, targetField);
        this.choiceElementMappings.put(sourceField, mapping);
        this.choiceElementMappingsByClassName.put(className, mapping);
    }

    @Override
    public void addChoiceElement(XMLField field, String elementTypeName) {
        this.fieldToClassNameMappings.put(field, elementTypeName);
        if (classNameToFieldMappings.get(elementTypeName) == null) {
            classNameToFieldMappings.put(elementTypeName, field);
        }
        addChoiceElementMapping(field, elementTypeName);
    }


    @Override
    public Map<XMLField, Class> getFieldToClassMappings() {
        return fieldToClassMappings;
    }

    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
        super.initialize(session);

        if (this.converter != null) {
            this.converter.initialize(this, session);
        }
        ArrayList<XMLMapping> mappingsList = new ArrayList<>();
        mappingsList.addAll(getChoiceElementMappings().values());
        for(XMLMapping next:getChoiceElementMappingsByClass().values()) {
            if(!(mappingsList.contains(next))) {
                mappingsList.add(next);
            }
        }

        if(isAny){
            //anyMapping = new XMLAnyCollectionMapping();
            mappingsList.add(anyMapping);
        }
        Iterator<XMLMapping> mappings = mappingsList.iterator();
        while(mappings.hasNext()){
            DatabaseMapping nextMapping = (DatabaseMapping)mappings.next();
            Converter converter = null;
            if(fieldsToConverters != null) {
                converter = fieldsToConverters.get(nextMapping.getField());
            }
            if(nextMapping.isAbstractCompositeDirectCollectionMapping()){
                XMLConversionManager xmlConversionManager = (XMLConversionManager) session.getDatasourcePlatform().getConversionManager();
                QName schemaType = xmlConversionManager.schemaType(((AbstractCompositeDirectCollectionMapping)nextMapping).getAttributeElementClass());
                if(schemaType != null) {
                 ((XMLField)nextMapping.getField()).setSchemaType(schemaType);
                }

                if(converter != null){
                    ((AbstractCompositeDirectCollectionMapping)nextMapping).setValueConverter(converter);
                }
                ((AbstractCompositeDirectCollectionMapping)nextMapping).setContainerPolicy(getContainerPolicy());
            }else if(nextMapping.isAbstractCompositeCollectionMapping()){
                if(converter != null){
                    ((AbstractCompositeCollectionMapping)nextMapping).setConverter(converter);
                }
                ((AbstractCompositeCollectionMapping)nextMapping).setContainerPolicy(getContainerPolicy());
            } else if(nextMapping instanceof XMLBinaryDataCollectionMapping) {
                ((XMLBinaryDataCollectionMapping)nextMapping).setContainerPolicy(getContainerPolicy());
                if(converter != null) {
                    ((XMLBinaryDataCollectionMapping)nextMapping).setValueConverter(converter);
                }
            } else if (nextMapping instanceof XMLAnyCollectionMapping){
                ((XMLAnyCollectionMapping)nextMapping).setContainerPolicy(getContainerPolicy());
                if(converter != null && converter instanceof XMLConverter) {
                    ((XMLAnyCollectionMapping)nextMapping).setConverter((XMLConverter)converter);
                }
            }else{
                ((XMLCollectionReferenceMapping)nextMapping).setContainerPolicy(getContainerPolicy());
                ((XMLCollectionReferenceMapping)nextMapping).setReuseContainer(true);
            }

            nextMapping.initialize(session);
        }
    }

    @Override
    public Map<Class, XMLField> getClassToFieldMappings() {
        return classToFieldMappings;
    }

    @Override
    public Map<XMLField, XMLMapping> getChoiceElementMappings() {
        return choiceElementMappings;
    }

    @Override
    public ContainerPolicy getContainerPolicy() {
        return containerPolicy;
    }

    public void setContainerPolicy(ContainerPolicy cp) {
        this.containerPolicy = cp;
    }

    public void useCollectionClass(Class concreteContainerClass) {
        this.setContainerPolicy(ContainerPolicy.buildPolicyFor(concreteContainerClass));
    }

    @Override
    public void useCollectionClassName(String concreteContainerClassName) {
        this.setContainerPolicy(new CollectionContainerPolicy(concreteContainerClassName));
    }

    @Override
    public void convertClassNamesToClasses(ClassLoader classLoader) {
        Iterator<Entry<XMLField, String>> entries = fieldToClassNameMappings.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<XMLField, String> entry = entries.next();
            String className = entry.getValue();
            Class elementType = null;
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                    try {
                        elementType = AccessController.doPrivileged(new PrivilegedClassForName(className, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(className, exception.getException());
                    }
                } else {
                    elementType = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(className, true, classLoader);
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(className, exc);
            }
            XMLMapping mapping = this.choiceElementMappings.get(entry.getKey());
            mapping.convertClassNamesToClasses(classLoader);

            if(fieldToClassMappings.get(entry.getKey()) == null) {
                fieldToClassMappings.put(entry.getKey(), elementType);
            }
        }
        for(Entry<String, XMLField> next: this.classNameToFieldMappings.entrySet()) {
            String className = next.getKey();
            Class elementType = null;
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                    try {
                        elementType = AccessController.doPrivileged(new PrivilegedClassForName(className, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(className, exception.getException());
                    }
                } else {
                    elementType = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(className, true, classLoader);
                }
            } catch (ClassNotFoundException exc) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(className, exc);
            }
            classToFieldMappings.put(elementType, next.getValue());
        }
        if(classNameToSourceFieldsMappings != null) {
            Iterator<Entry<String, List<XMLField>>> sourceFieldEntries = classNameToSourceFieldsMappings.entrySet().iterator();
            while(sourceFieldEntries.hasNext()) {
                Entry<String, List<XMLField>> nextEntry = sourceFieldEntries.next();
                String className = nextEntry.getKey();
                List<XMLField> fields = nextEntry.getValue();
                Class elementType = null;
                try {
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                        try {
                            elementType = AccessController.doPrivileged(new PrivilegedClassForName(className, true, classLoader));
                        } catch (PrivilegedActionException exception) {
                            throw ValidationException.classNotFoundWhileConvertingClassNames(className, exception.getException());
                        }
                    } else {
                        elementType = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(className, true, classLoader);
                    }
                } catch (ClassNotFoundException exc) {
                    throw ValidationException.classNotFoundWhileConvertingClassNames(className, exc);
                }
                this.getClassToSourceFieldsMappings().put(elementType,fields);
            }
        }
        if(!choiceElementMappingsByClassName.isEmpty()) {
            for(Entry<String, XMLMapping> next:choiceElementMappingsByClassName.entrySet()) {
                Class elementType = null;
                String className = next.getKey();
                try {
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                        try {
                            elementType = AccessController.doPrivileged(new PrivilegedClassForName(className, true, classLoader));
                        } catch (PrivilegedActionException exception) {
                            throw ValidationException.classNotFoundWhileConvertingClassNames(className, exception.getException());
                        }
                    } else {
                        elementType = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(className, true, classLoader);
                    }
                } catch (ClassNotFoundException exc) {
                    throw ValidationException.classNotFoundWhileConvertingClassNames(className, exc);
                }
                if(this.choiceElementMappingsByClass.get(elementType) == null) {
                    this.choiceElementMappingsByClass.put(elementType, next.getValue());
                }
                next.getValue().convertClassNamesToClasses(classLoader);
            }
        }
    }

    @Override
    public void addConverter(XMLField field, Converter converter) {
        if(this.fieldsToConverters == null) {
            fieldsToConverters = new HashMap<>();
        }
        fieldsToConverters.put(field, converter);
    }

    @Override
    public Converter getConverter(XMLField field) {
        if(null != this.fieldsToConverters) {
            Converter converter = fieldsToConverters.get(field);
            if(null != converter) {
                return converter;
            }
            if(null != this.choiceElementMappings) {
                DatabaseMapping mapping = (DatabaseMapping) this.choiceElementMappings.get(field);
                if(null == mapping) {
                    return null;
                }
                if(mapping.isAbstractCompositeDirectCollectionMapping()) {
                    return ((XMLCompositeDirectCollectionMapping)mapping).getValueConverter();
                } else if(mapping.isAbstractDirectMapping()) {
                    return ((XMLDirectMapping)mapping).getConverter();
                }
            }
        }
        return null;
    }

    @Override
    public ArrayList getChoiceFieldToClassAssociations() {
        ArrayList associations = new ArrayList();
        if(this.fieldToClassNameMappings.size() > 0) {

            Set<Entry<XMLField, String>> entries = fieldToClassNameMappings.entrySet();
            Iterator<Entry<XMLField, String>> iter = entries.iterator();
            while(iter.hasNext()){
                Entry<XMLField, String> nextEntry = iter.next();
                XMLField xmlField = nextEntry.getKey();
                String className = nextEntry.getValue();
                XMLChoiceFieldToClassAssociation association = new XMLChoiceFieldToClassAssociation(xmlField, className);
                associations.add(association);
            }
        }
        return associations;
    }


    public void setChoiceFieldToClassAssociations(ArrayList associations) {
        if(associations.size() > 0) {
            for(Object next:associations) {
                XMLChoiceFieldToClassAssociation<Converter, XMLField> association = (XMLChoiceFieldToClassAssociation)next;
                this.addChoiceElement(association.getXmlField(), association.getClassName());
                if(association.getConverter() != null) {
                    this.addConverter(association.getXmlField(), association.getConverter());
                }
            }
        }
    }

    private void addChoiceElementMapping(XMLField xmlField, String className){
         if (xmlField.getLastXPathFragment().nameIsText() || xmlField.getLastXPathFragment().isAttribute()) {
             XMLCompositeDirectCollectionMapping xmlMapping = new XMLCompositeDirectCollectionMapping();
             xmlMapping.setAttributeElementClassName(className);
             xmlMapping.setField(xmlField);
             xmlMapping.setAttributeAccessor(temporaryAccessor);
             this.choiceElementMappings.put(xmlField, xmlMapping);
             this.choiceElementMappingsByClassName.put(className, xmlMapping);
         } else {
             if(isBinaryType(className)) {
                 XMLBinaryDataCollectionMapping xmlMapping = new XMLBinaryDataCollectionMapping();
                 xmlMapping.setField(xmlField);
                 xmlMapping.setAttributeAccessor(temporaryAccessor);
                 Class theClass = XMLConversionManager.getDefaultXMLManager().convertClassNameToClass(className);
                 xmlMapping.setAttributeElementClass(theClass);
                 this.choiceElementMappings.put(xmlField, xmlMapping);
                 this.choiceElementMappingsByClassName.put(className, xmlMapping);
             } else {
                 XMLCompositeCollectionMapping xmlMapping = new XMLCompositeCollectionMapping();
                 if(!className.equals("java.lang.Object")){
                     xmlMapping.setReferenceClassName(className);
                 }
                 xmlMapping.setField(xmlField);
                 xmlMapping.setAttributeAccessor(temporaryAccessor);
                 this.choiceElementMappings.put(xmlField, xmlMapping);
                 this.choiceElementMappingsByClassName.put(className, xmlMapping);
             }
         }
    }

    private void addChoiceElementMapping(XMLField xmlField, Class theClass){

        if (xmlField.getLastXPathFragment().nameIsText() || xmlField.getLastXPathFragment().isAttribute()) {
            XMLCompositeDirectCollectionMapping xmlMapping = new XMLCompositeDirectCollectionMapping();
            xmlMapping.setAttributeElementClass(theClass);
            xmlMapping.setField(xmlField);
            xmlMapping.setAttributeAccessor(temporaryAccessor);
            this.choiceElementMappings.put(xmlField, xmlMapping);
            this.choiceElementMappingsByClass.put(theClass, xmlMapping);
        } else {
            if(isBinaryType(theClass)) {
                XMLBinaryDataCollectionMapping xmlMapping = new XMLBinaryDataCollectionMapping();
                xmlMapping.setField(xmlField);
                xmlMapping.setAttributeElementClass(theClass);
                xmlMapping.setAttributeAccessor(temporaryAccessor);
                this.fieldsToConverters.put(xmlField, xmlMapping.getValueConverter());
                this.choiceElementMappings.put(xmlField, xmlMapping);
                this.choiceElementMappingsByClass.put(theClass, xmlMapping);
            } else {
                XMLCompositeCollectionMapping xmlMapping = new XMLCompositeCollectionMapping();
                if(!theClass.equals(ClassConstants.OBJECT)){
                    xmlMapping.setReferenceClass(theClass);
                }
                xmlMapping.setField(xmlField);
                xmlMapping.setAttributeAccessor(temporaryAccessor);
                this.choiceElementMappings.put(xmlField, xmlMapping);
                this.choiceElementMappingsByClass.put(theClass, xmlMapping);
            }
        }
    }

    @Override
    public boolean isWriteOnly() {
        return this.isWriteOnly;
    }

    @Override
    public void setIsWriteOnly(boolean b) {
        this.isWriteOnly = b;
    }

    @Override
    public boolean isAny() {
        return this.isAny;
    }

    public void setIsAny(boolean b) {
        this.isAny = b;
    }

    @Override
    public void preInitialize(AbstractSession session) throws DescriptorException {
        getAttributeAccessor().setIsWriteOnly(this.isWriteOnly());
        getAttributeAccessor().setIsReadOnly(this.isReadOnly());
        super.preInitialize(session);
        //Collection<XMLMapping> allMappings = new ArrayList<XMLMapping>();
        ArrayList<XMLMapping> mappingsList = new ArrayList<>();
        mappingsList.addAll(getChoiceElementMappings().values());
        if(isAny){
            anyMapping = new XMLAnyCollectionMapping();
            //if(mixedGroupingElement != null){
            //    anyMapping.setField(new XMLField(mixedGroupingElement));
            //}
            anyMapping.setMixedContent(false);
            anyMapping.setKeepAsElementPolicy(UnmarshalKeepAsElementPolicy.KEEP_UNKNOWN_AS_ELEMENT);
            anyMapping.setUseXMLRoot(true);
            mappingsList.add(anyMapping);
        }
        for(XMLMapping next:getChoiceElementMappingsByClass().values()) {
            if(!(mappingsList.contains(next))) {
                mappingsList.add(next);
            }
        }
        for(XMLMapping next:getChoiceElementMappingsByClass().values()) {
            if(!(mappingsList.contains(next))) {
                mappingsList.add(next);
            }
        }
        Iterator<XMLMapping> mappings = mappingsList.iterator();
        while(mappings.hasNext()){
            DatabaseMapping nextMapping = (DatabaseMapping)mappings.next();
            nextMapping.setAttributeName(this.getAttributeName());
            if(nextMapping.getAttributeAccessor() == temporaryAccessor){
                nextMapping.setAttributeAccessor(getAttributeAccessor());
            }
            nextMapping.setIsReadOnly(this.isReadOnly());
            ((XMLMapping)nextMapping).setIsWriteOnly(this.isWriteOnly());

            nextMapping.setDescriptor(getDescriptor());

            nextMapping.preInitialize(session);
        }
    }

    @Override
    public void setAttributeValueInObject(Object object, Object value) throws DescriptorException {
        if(isWriteOnly()) {
            return;
        }
        super.setAttributeValueInObject(object, value);
    }

    /**
     * Return true if the original container on the object should be used if
     * present.  If it is not present then the container policy will be used to
     * create the container.
     */
    @Override
    public boolean getReuseContainer() {
        return reuseContainer;
    }

    /**
     * Specify whether the original container on the object should be used if
     * present.  If it is not present then the container policy will be used to
     * create the container.
     */
    @Override
    public void setReuseContainer(boolean reuseContainer) {
        this.reuseContainer = reuseContainer;
    }

    @Override
    public Map<Class, List<XMLField>> getClassToSourceFieldsMappings() {
        if(this.classToSourceFieldsMappings == null) {
            this.classToSourceFieldsMappings = new HashMap<>();
        }
        return this.classToSourceFieldsMappings;
    }

    private Map<String, List<XMLField>> getClassNameToSourceFieldsMappings() {
        if(this.classNameToSourceFieldsMappings == null) {
            this.classNameToSourceFieldsMappings = new HashMap<>();
        }
        return this.classNameToSourceFieldsMappings;
    }

    private boolean isBinaryType(String className) {
        if(className.equals(byte[].class.getName()) || className.equals(Byte[].class.getName()) || className.equals(DATA_HANDLER)
                || className.equals(IMAGE) || className.equals(MIME_MULTIPART)) {
            return true;
        }
        return false;
    }

    private boolean isBinaryType(Class theClass) {
        String className = theClass.getName();
        if(className.equals(byte[].class.getName()) || className.equals(Byte[].class.getName()) || className.equals(DATA_HANDLER)
                || className.equals(IMAGE) || className.equals(MIME_MULTIPART)) {
            return true;
        }
        return false;
    }

    @Override
    public Map<String, XMLField> getClassNameToFieldMappings() {
        return classNameToFieldMappings;
    }

    @Override
    public boolean isMixedContent() {
       // return this.mixedContentMapping != null;
        return isMixedContent;
    }

    /**
     * PUBLIC:
     * Allows the user to indicate that this mapping should also allow for mixed content in addition to
     * any of the elements in the choice. The grouping element parameter is used in the case that there is
     * a common grouping element to all the other elements in this choice. If so, that grouping element can
     * be specified here to allow the mixed content to be written/detected inside the wrapper element.
     * @since EclipseLink 2.3.1
     */
    @Override
    public void setMixedContent(String groupingElement) {
        isMixedContent = true;

        String xpath = groupingElement;
        if(groupingElement.length() == 0) {
            xpath = "text()";
        } else {
            xpath += "/" + "text()";
        }
        XMLField field = new XMLField(xpath);
        XMLCompositeDirectCollectionMapping xmlMapping = new XMLCompositeDirectCollectionMapping();
        Class theClass = ClassConstants.STRING;
        xmlMapping.setAttributeElementClass(theClass);
        xmlMapping.setField(field);
        xmlMapping.setAttributeAccessor(temporaryAccessor);
        this.mixedContentMapping = xmlMapping;
        this.choiceElementMappings.put(field, xmlMapping);

    }

    /**
     * PUBLIC:
     * Allows the user to indicate that this mapping should also allow for mixed content in addition to
     * any of the elements in the choice.
     * @since EclipseLink 2.3.1
     */
    @Override
    public void setMixedContent(boolean mixed) {
       if(!mixed) {
            this.mixedContentMapping = null;
        } else {
            setMixedContent("");
        }
        isMixedContent = mixed;
    }

    @Override
    public XMLCompositeDirectCollectionMapping getMixedContentMapping() {
        return this.mixedContentMapping;
    }

    @Override
    public XMLAnyCollectionMapping getAnyMapping(){
        return anyMapping;
    }

    /**
     * INTERNAL
     * Return true if an empty container should be set on the object if there
     * is no presence of the collection in the XML document.
     * @since EclipseLink 2.3.3
     */
    @Override
    public boolean isDefaultEmptyContainer() {
        return isDefaultEmptyContainer;
    }

    /**
     * INTERNAL
     * Indicate whether by default an empty container should be set on the
     * field/property if the collection is not present in the XML document.
     * @since EclipseLink 2.3.3
     */
    @Override
    public void setDefaultEmptyContainer(boolean defaultEmptyContainer) {
        this.isDefaultEmptyContainer = defaultEmptyContainer;
    }

    @Override
    public AbstractNullPolicy getWrapperNullPolicy() {
        return this.wrapperNullPolicy;
    }

    @Override
    public void setWrapperNullPolicy(AbstractNullPolicy policy) {
        this.wrapperNullPolicy = policy;
    }

    @Override
    public Map<Class, XMLMapping> getChoiceElementMappingsByClass() {
        return choiceElementMappingsByClass;
    }

    public void setChoiceElementMappingsByClass(Map<Class, XMLMapping> choiceElementMappingsByClass) {
        this.choiceElementMappingsByClass = choiceElementMappingsByClass;
    }

    /**
     * INTERNAL
     * @since EclipseLink 2.5.0
     */
    @Override
    public Object convertObjectValueToDataValue(Object value, Session session, XMLMarshaller marshaller) {
        if (null != converter) {
            if (converter instanceof XMLConverter) {
                return ((XMLConverter)converter).convertObjectValueToDataValue(value, session, marshaller);
            } else {
                return converter.convertObjectValueToDataValue(value, session);
            }
        }
        return value;
    }

    /**
     * INTERNAL
     * @since EclipseLink 2.5.0
     */
    @Override
    public Object convertDataValueToObjectValue(Object fieldValue, Session session, XMLUnmarshaller unmarshaller) {
        if (null != converter) {
            if (converter instanceof XMLConverter) {
                return ((XMLConverter)converter).convertDataValueToObjectValue(fieldValue, session, unmarshaller);
            } else {
                return converter.convertDataValueToObjectValue(fieldValue, session);
            }
        }
        return fieldValue;
    }
}
