/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2010 Frank Schwarz. 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
//     11/23/2010-2.2 Frank Schwarz
//       - 328774: TABLE_PER_CLASS-mapped key of a java.util.Map does not work for querying
package org.eclipse.persistence.internal.queries;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.changetracking.CollectionChangeEvent;
import org.eclipse.persistence.descriptors.changetracking.MapChangeEvent;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetValueFromField;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.CollectionChangeRecord;
import org.eclipse.persistence.internal.sessions.MergeManager;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.mappings.Association;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.querykeys.QueryKey;
import org.eclipse.persistence.queries.DatabaseQuery;

/**
 * <p><b>Purpose</b>: A MapContainerPolicy is ContainerPolicy whose container class
 * implements the Map interface.
 * </p>
 * <p><b>Responsibilities</b>:
 * Provide the functionality to operate on an instance of a Map.</p>
 *
 * @see ContainerPolicy
 * @see CollectionContainerPolicy
 */
public class MapContainerPolicy extends InterfaceContainerPolicy {
    /** The Method which is called on each value added to the Map and whose result is used as key to the value. */
    protected String keyName;

    protected String elementClassName;
    protected Class elementClass;
    protected transient Field keyField;
    protected transient Method keyMethod;

    /**
     * INTERNAL:
     * Construct a new policy.
     */
    public MapContainerPolicy() {
        super();
    }

    /**
     * INTERNAL:
     * Construct a new policy for the specified class.
     */
    public MapContainerPolicy(Class containerClass) {
        super(containerClass);
    }

    /**
     * INTERNAL:
     * Construct a new policy for the specified class name.
     */
    public MapContainerPolicy(String containerClassName) {
        super(containerClassName);
    }

    /**
     * Prepare and validate.
     * Set the element class.
     */
    @Override
    public void prepare(DatabaseQuery query, AbstractSession session) throws QueryException {
        if ((getElementClass() == null) && (query.getDescriptor() != null)) {
            setElementClass(query.getDescriptor().getJavaClass());
        }
        super.prepare(query, session);
    }

    /**
     * INTERNAL:
     * Add element to container.
     * This is used to add to a collection independent of the collection type.
     * The session may be required to wrap for the wrapper policy.
     * Return whether the container changed.
     */
    @Override
    public boolean addInto(Object element, Object container, AbstractSession session){
        if (element instanceof Map.Entry){
            return addInto(((Map.Entry)element).getKey(), ((Map.Entry)element).getValue(), container, session);
        } else {
            return addInto(keyFrom(element, session), element, container, session);
        }
    }

    /**
     * INTERNAL:
     * Add element into container which implements the Map interface.
     */
    @Override
    public boolean addInto(Object key, Object element, Object container, AbstractSession session) {
        Object wrapped = element;
        if (hasElementDescriptor()) {
            wrapped = getElementDescriptor().getObjectBuilder().wrapObject(element, session);
        }
        try {
            if (key != null) {
                return ((Map)container).put(key, wrapped) != null;
            } else if (isKeyAvailableFromElement()){
                Object keyFromElement = keyFrom(element, session);

                try {
                    Object result = ((Map)container).put(keyFromElement, wrapped);
                    return null != result;
                } catch (NullPointerException e) {
                    // If the container Map is a concrete type that does not
                    // allow null keys then throw a QueryException. Note, a
                    // HashMap permits null keys.
                    if (keyFromElement == null) {
                        // TreeMap, HashTable, SortedMap do not permit null keys
                        throw QueryException.mapKeyIsNull(element, container);
                    } else {
                        // We got a null pointer exception for some other reason
                        // so re-throw the exception.
                        throw e;
                    }
                }
            } else {
                throw QueryException.cannotAddElementWithoutKeyToMap(element);
            }
        } catch (ClassCastException ex1) {
            throw QueryException.mapKeyNotComparable(key, container);
        }
    }

    /**
     * INTERNAL:
     * This method is used to add the next value from an iterator built using ContainerPolicy's iteratorFor() method
     * into the toCollection.  Since this ContainerPolicy represents a Map, the key and the value are extracted and added.
     */
    @Override
    public void addNextValueFromIteratorInto(Object valuesIterator, Object parent, CacheKey parentCacheKey, Object toCollection, CollectionMapping mapping, Integer refreshCascade, AbstractSession cloningSession, boolean isExisting, boolean isFromSharedCache) {
        Map.Entry entry = ((MapContainerPolicyIterator)valuesIterator).next();
        Object clonedKey = buildCloneForKey(entry.getKey(), parent, parentCacheKey, refreshCascade, cloningSession, isExisting, isFromSharedCache);
        Object clonedValue = buildCloneForValue(entry.getValue(), parent, parentCacheKey, mapping, refreshCascade, cloningSession, isExisting, isFromSharedCache);
        // add the object to the uow list of private owned objects if it is a candidate and the
        // uow should discover new objects
        if (cloningSession.isUnitOfWork() && mapping.isCandidateForPrivateOwnedRemoval() && ((UnitOfWorkImpl) cloningSession).shouldDiscoverNewObjects()) {
            if (clonedValue != null && ((UnitOfWorkImpl) cloningSession).isCloneNewObject(clonedValue)) {
                ((UnitOfWorkImpl) cloningSession).addPrivateOwnedObject(mapping, clonedValue);
            }
        }
        addInto(clonedKey, clonedValue, toCollection, cloningSession);
    }

    /**
     * INTERNAL:
     * Return an object representing an entry in the collection represented by this container policy
     * This method will returns an Association containing the key and the value for a Map
     */
    @Override
    public Object buildCollectionEntry(Object objectAdded, ObjectChangeSet changeSet){
        return new Association(changeSet.getNewKey(), objectAdded);
    }

    /**
     * INTERNAL:
     * This method will access the target relationship and create a list of information to rebuild the collection.
     * For the MapContainerPolicy this return will consist of an array with serial Map entry key and value elements.
     * @see ObjectReferenceMapping#buildReferencesPKList(Object, Object, AbstractSession)
     * @see ContainerPolicy#buildReferencesPKList(Object, AbstractSession)
     */
    @Override
    public Object[] buildReferencesPKList(Object container, AbstractSession session){
        Object[] result = new Object[this.sizeFor(container)*2];
        Iterator iterator = (Iterator)this.iteratorFor(container);
        int index = 0;
        while(iterator.hasNext()){
            Map.Entry entry = (Entry) iterator.next();
            result[index] = entry.getKey(); // record key for cases where it will be needed
            ++index;
            result[index] = elementDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(entry.getValue(), session);
            ++index;
        }
        return result;
    }

    /**
     * INTERNAL:
     * Ensure the new key is set for the change set for a new map object
     */
    @Override
    public void buildChangeSetForNewObjectInCollection(Object object, ClassDescriptor referenceDescriptor, UnitOfWorkChangeSet uowChangeSet, AbstractSession session){
        Object value = ((Map.Entry)object).getValue();
        ClassDescriptor valueDescriptor = referenceDescriptor;
        if (value != null){
            ClassDescriptor tempValueDescriptor = session.getDescriptor(value.getClass());
            if (tempValueDescriptor != null){
                valueDescriptor = tempValueDescriptor;
            }
        }
        ObjectChangeSet changeSet = valueDescriptor.getObjectBuilder().createObjectChangeSet(value, uowChangeSet, session);
        Object key = ((Map.Entry)object).getKey();
        changeSet.setNewKey(key);
    }

    /**
     * Build a clone for the value in a mapping.
     */
    protected Object buildCloneForValue(Object value, Object parent, CacheKey parentCacheKey, CollectionMapping mapping, Integer refreshCascade, AbstractSession cloningSession, boolean isExisting, boolean isFromSharedCache){
        return mapping.buildElementClone(value, parent, parentCacheKey, refreshCascade, cloningSession, isExisting, isFromSharedCache);

    }

    /**
     * INTERNAL:
     * Remove all the elements from container.
     */
    @Override
    public void clear(Object container) {
        try {
            ((Map)container).clear();
        } catch (UnsupportedOperationException ex) {
            throw QueryException.methodNotValid(container, "clear()");
        }
    }

    /**
     * INTERNAL:
     * Return a clone of the specified container.
     */
    @Override
    public Object cloneFor(Object container) {
        if (container == null) {
            return null;
        }
        if (container instanceof java.lang.Cloneable) {
            return super.cloneFor(container);
        }

        Map original = (Map)container;
        Map clone = (Map)containerInstance(original.size());
        clone.putAll(original);
        return clone;
    }

    /**
     * INTERNAL:
     * Return true if keys are the same in the source as the backup.  False otherwise
     * in the case of read-only compare against the original
     */
    @Override
    public boolean compareKeys(Object sourceValue, AbstractSession session) {
        if (session.isClassReadOnly(sourceValue.getClass())) {
            return true;
        }
        Object backUpVersion = ((UnitOfWorkImpl)session).getBackupClone(sourceValue, getElementDescriptor());
        Object backUpVersionKey = keyFrom(backUpVersion, session);
        Object sourceValueKey = keyFrom(sourceValue, session);
        if (backUpVersionKey == sourceValueKey) {
            // this conditional captures the same instances, as well as both being nulls
            // not sure if this semantics is correct
            return true;
        }
        if (backUpVersionKey == null && sourceValueKey != null) {
            return false;
        }
        return backUpVersionKey.equals(sourceValueKey);
    }


    /**
     * INTERNAL:
     * Build a new container, add the contents of each of the specified containers
     * to it, and return it.
     * Both of the containers must use the same container policy (namely, this one).
     */
    @Override
    public Object concatenateContainers(Object firstContainer, Object secondContainer, AbstractSession session) {
        Object container = containerInstance(sizeFor(firstContainer) + sizeFor(secondContainer));

        for (Object firstIter = iteratorFor(firstContainer); hasNext(firstIter);) {
            Map.Entry<?, ?> entry = (Entry<?, ?>) nextEntry(firstIter);
            addInto(entry.getKey(), entry.getValue(), container, session);
        }

        for (Object secondIter = iteratorFor(secondContainer); hasNext(secondIter);) {
            Map.Entry<?, ?> entry = (Entry<?, ?>) nextEntry(secondIter);
            addInto(entry.getKey(), entry.getValue(), container, session);
        }

        return container;
    }

    /**
     * INTERNAL:
     * Return the true if element exists in container.
     * @return boolean true if container 'contains' element
     */
    @Override
    protected boolean contains(Object element, Object container) {
        return ((Map)container).containsValue(element);
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this ContainerPolicy 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.
     * @param classLoader
     */
    @Override
    public void convertClassNamesToClasses(ClassLoader classLoader){
        super.convertClassNamesToClasses(classLoader);

        if (elementClassName == null){
            return;
        }

        try {
            Class elementClass = null;
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    elementClass = AccessController.doPrivileged(new PrivilegedClassForName(elementClassName, true, classLoader));
                } catch (PrivilegedActionException exception) {
                    throw ValidationException.classNotFoundWhileConvertingClassNames(containerClassName, exception.getException());
                }
            } else {
                elementClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(elementClassName, true, classLoader);
            }
            setElementClass(elementClass);
        } catch (ClassNotFoundException exc){
            throw ValidationException.classNotFoundWhileConvertingClassNames(containerClassName, exc);
        }
    }

    /**
     * INTERNAL:
     * Creates a CollectionChangeEvent for the container
     */
    @Override
    public CollectionChangeEvent createChangeEvent(Object collectionOwner, String propertyName, Object collectionChanged, Object elementChanged, int changeType, Integer index, boolean isChangeApplied) {
        if (elementChanged instanceof Map.Entry) {
            return new MapChangeEvent(collectionOwner,propertyName, collectionChanged,
                    ((Map.Entry)elementChanged).getKey(), ((Map.Entry)elementChanged).getValue(), changeType, isChangeApplied);
        }
        return super.createChangeEvent(collectionOwner, propertyName, collectionChanged, elementChanged, changeType, index, isChangeApplied);
    }

    /**
     * INTERNAL:
     * Create a query key that links to the map key.  MapContainerPolicy does not have a specific mapping for the
     * key, so return null.
     */
    @Override
    public QueryKey createQueryKeyForMapKey(){
        return null;
    }

    /**
     * INTERNAL:
     * This method will actually potentially wrap an object in two ways.  It will first wrap the object
     * based on the referenceDescriptor's wrapper policy.  It will also potentially do some wrapping based
     * on what is required by the container policy.
     */
    @Override
    public Object createWrappedObjectFromExistingWrappedObject(Object wrappedObject, Object parent, ClassDescriptor referenceDescriptor, MergeManager mergeManager, AbstractSession targetSession){
        Object key = ((Map.Entry)wrappedObject).getKey();
        Object value = referenceDescriptor.getObjectBuilder().wrapObject(mergeManager.getTargetVersionOfSourceObject(unwrapIteratorResult(wrappedObject), referenceDescriptor, targetSession), mergeManager.getSession());
        return new Association(key, value);
    }

    /**
     * INTERNAL:
     * Return the DatabaseField that represents the key in a DirectMapMapping.   MapContainerPolicy gets it fields from the reference descriptor
     * of the provided mappings.  It uses its keyName to lookup the appropriate mapping and returns the field from
     * that mapping.
     */
    @Override
    public DatabaseField getDirectKeyField(CollectionMapping baseMapping){
        if (baseMapping == null){
            return null;
        }
        ClassDescriptor descriptor = baseMapping.getReferenceDescriptor();
        DatabaseMapping mapping = descriptor.getMappingForAttributeName(Helper.getAttributeNameFromMethodName(keyName));
        if (mapping.isAbstractDirectMapping()){
            return mapping.getField();
        }
        return null;
    }

    /**
     * INTERNAL:
     * Returns the element class which defines the map key.
     */
    public Class getElementClass() {
        return elementClass;
    }

    /**
     * INTERNAL:
     * Returns the element class name which defines the map key.
     */
    public String getElementClassName() {
        return elementClassName;
    }

    /**
     * INTERNAL:
     */
    @Override
    public Class getInterfaceType() {
        return ClassConstants.Map_Class;
    }

    /**
     * INTERNAL:
     * Returns the key name which will return the value of the key to be used
     * in the container.
     */
    public String getKeyName() {
        return keyName;
    }

    /**
     * INTERNAL:
     * Return the type of the map key, this will be overridden by container policies that allow maps.
     */
    @Override
    public Object getKeyType(){
        initializeKey();
        if (keyField != null){
            return keyField.getType();
        } else if (keyMethod != null){
            return keyMethod.getReturnType();
        }else if (elementDescriptor != null){
            return elementDescriptor.getCMPPolicy().getPKClass();
        }
        return null;
    }

    /**
     * INTERNAL
     * Yes this is a MapPolicy
     */
    @Override
    public boolean isMapPolicy() {
        return true;
    }


    /**
     * MapContainerPolicy is for mappings where the key is stored in actual element.
     */
    protected boolean isKeyAvailableFromElement() {
        return true;
    }

    /**
     * INTERNAL:
     * Return whether a map key this container policy represents is an attribute.
     */
    @Override
    public boolean isMapKeyAttribute() {
        if (elementDescriptor != null && keyName != null){
            DatabaseMapping mapping = elementDescriptor.getMappingForAttributeName(Helper.getAttributeNameFromMethodName(keyName));
            if (mapping != null) {
                return mapping.isDirectToFieldMapping();
            }

        }
        initializeKey();
        if (keyField != null){
            if (keyField.getClass().isPrimitive()){
                return true;
            }
        } else if (keyMethod != null) {
            if (keyMethod.getClass().isPrimitive()) {
                return true;
            }
        }
        return false;
    }

    /**
     * INTERNAL:
     * Return whether the iterator has more objects.
     * The iterator is the one returned from #iteratorFor().
     *
     * @see ContainerPolicy#iteratorFor(java.lang.Object)
     */
    @Override
    public boolean hasNext(Object iterator) {
        return ((MapContainerPolicyIterator)iterator).hasNext();
    }

    /**
     * INTERNAL:
     * Set the keyMethod or keyField based on the keyName.
     */
    protected void initializeKey() {
        // Should only run through this once ...
        if (keyName != null && keyMethod == null && keyField == null) {
            try {
                keyMethod = Helper.getDeclaredMethod(elementClass, keyName, null);
            } catch (NoSuchMethodException ex) {
                try {
                    keyField = Helper.getField(elementClass, keyName);
                } catch (NoSuchFieldException e) {
                    throw ValidationException.mapKeyNotDeclaredInItemClass(keyName, elementClass);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Return an Iterator for the given container.
     */
    @Override
    public Object iteratorFor(Object container) {
        return new MapContainerPolicyIterator((Map)container);
    }

    /**
     * INTERNAL:
     * Return the key for the specified element.
     */
    @Override
    public Object keyFrom(Object element, AbstractSession session) {
        initializeKey();
        Object keyElement = element;
        if (hasElementDescriptor()) {
            keyElement = getElementDescriptor().getObjectBuilder().unwrapObject(element, session);
        }
        if (keyMethod != null) {
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        return AccessController.doPrivileged(new PrivilegedMethodInvoker(keyMethod, keyElement, null));
                    } catch (PrivilegedActionException exception) {
                        Exception throwableException = exception.getException();
                        if (throwableException instanceof IllegalAccessException) {
                            throw QueryException.cannotAccessMethodOnObject(keyMethod, keyElement);
                        } else {
                            throw QueryException.calledMethodThrewException(keyMethod, keyElement, throwableException);
                        }
                    }
                } else {
                    return PrivilegedAccessHelper.invokeMethod(keyMethod, keyElement, null);
                }
            } catch (IllegalAccessException e) {
                throw QueryException.cannotAccessMethodOnObject(keyMethod, keyElement);
            } catch (InvocationTargetException exception) {
                throw QueryException.calledMethodThrewException(keyMethod, keyElement, exception);
            }
        } else if (keyField != null) {
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        return AccessController.doPrivileged(new PrivilegedGetValueFromField(keyField, keyElement));
                    } catch (PrivilegedActionException exception) {
                        throw QueryException.cannotAccessFieldOnObject(keyField, keyElement);
                    }
                } else {
                    return org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getValueFromField(keyField, keyElement);
                }
            } catch (IllegalAccessException e) {
                throw QueryException.cannotAccessFieldOnObject(keyField, keyElement);
            }
        } else {
            // If we get this far I think it is safe to assume we have
            // an element descriptor.
            return getElementDescriptor().getCMPPolicy().createPrimaryKeyInstance(keyElement, session);
        }
    }


    /**
     * Get the key from the passed in Map.Entry.
     */
    @Override
    public Object keyFromEntry(Object entry){
        if (entry instanceof Map.Entry){
            return ((Map.Entry)entry).getKey();
        }
        return null;
    }

    @Override
    public Object keyFromIterator(Object iterator){
        return ((MapContainerPolicyIterator)iterator).getCurrentKey();
    }

    /**
     * INTERNAL:
     * Return the next object on the queue. The iterator is the one
     * returned from #iteratorFor().
     *
     * @see ContainerPolicy#iteratorFor(java.lang.Object)
     */
    @Override
    protected Object next(Object iterator){
        return ((MapContainerPolicyIterator)iterator).next().getValue();
    }

    /**
     * INTERNAL:
     * Return the next object on the queue. The iterator is the one
     * returned from #iteratorFor().
     *
     * This will return a MapEntry to allow use of the key
     *
     * @see ContainerPolicy#iteratorFor(java.lang.Object)
     * @see #unwrapIteratorResult(Object)
     */
    @Override
    public Object nextEntry(Object iterator){
        return ((MapContainerPolicyIterator)iterator).next();
    }

    /**
     * INTERNAL:
     * Return the next object on the queue. The iterator is the one
     * returned from #iteratorFor().
     *
     * This will return a MapEntry to allow use of the key
     *
     * @see ContainerPolicy#iteratorFor(Object)
     * @see #unwrapIteratorResult(Object)
     */
    @Override
    public Object nextEntry(Object iterator, AbstractSession session) {
        Map.Entry next = (Map.Entry)nextEntry(iterator);
        Object object = next.getValue();
        if (hasElementDescriptor()) {
            object = getElementDescriptor().getObjectBuilder().unwrapObject(object, session);
        }
        Object key = next.getKey();
        key = unwrapKey(key, session);
        next = new Association(key, object);
        return next;
    }

    /**
     * INTERNAL:
     * MapContainerPolicy's iterator iterates on the Entries of a Map.
     * This method returns the object from the iterator
     *
     * @see #unwrapIteratorResult(Object)
     */
    @Override
    public Object unwrapElement(Object object) {
        if (object instanceof Association) {
            return ((Association)object).getValue();
        } else {
            return object;
        }
    }

    /**
     * INTERNAL:
     * MapContainerPolicy's iterator iterates on the Entries of a Map.
     * This method returns the object from the iterator
     *
     * @see #nextEntry(Object)
     */
    @Override
    public Object unwrapIteratorResult(Object object) {
        if (object instanceof Map.Entry) {
            return ((Map.Entry)object).getValue();
        } else {
            return object;
        }
    }


    /**
     * INTERNAL:
     * Allow the key to be unwrapped.  This will be overridden by container policies that
     * allow keys that are entities.
     */
    public Object unwrapKey(Object key, AbstractSession session) {
        return key;
    }

    /**
     * This method is used to bridge the behavior between Attribute Change Tracking and
     * deferred change tracking with respect to adding the same instance multiple times.
     * Each ContainerPolicy type will implement specific behavior for the collection
     * type it is wrapping.  These methods are only valid for collections containing object references
     */
    @Override
    public void recordUpdateToCollectionInChangeRecord(CollectionChangeEvent event, ObjectChangeSet changeSet, CollectionChangeRecord collectionChangeRecord){

        Object key = null;
        //This is to allow non-MapChangeEvent.  Not sure how one could get here, but wasn't willing to remove the chance that it could
        if (event.getClass().equals(ClassConstants.MapChangeEvent_Class)){
            key = ((MapChangeEvent)event).getKey();
        }
        if (event.getChangeType() == CollectionChangeEvent.ADD) {
            recordAddToCollectionInChangeRecord(changeSet, collectionChangeRecord);
            changeSet.setNewKey(key);
        } else if (event.getChangeType() == CollectionChangeEvent.REMOVE) {
            recordRemoveFromCollectionInChangeRecord(changeSet, collectionChangeRecord);
            changeSet.setOldKey(key);
        } else {
            throw ValidationException.wrongCollectionChangeEventType(event.getChangeType());
        }
    }

    /**
     * INTERNAL:
     * Remove element from container which implements the Map interface.
     */
    @Override
    public boolean removeFrom(Object key, Object element, Object container, AbstractSession session) {
        try {
            Object returnValue = null;
            if (key != null) {
                returnValue = ((Map)container).remove(key);
            } else if (element != null) {
                returnValue = ((Map)container).remove(keyFrom(element, session));
            }
            if (returnValue == null) {
                return false;
            } else {
                return true;
            }
        } catch (UnsupportedOperationException ex) {
            throw QueryException.methodNotValid(container, "remove(Object element)");
        }
    }

    /**
     * INTERNAL:
     * Sets the element class which defines the method.
     */
    public void setElementClass(Class elementClass) {
        if (elementClass != null) {
            elementClassName = elementClass.getName();
        }

        this.elementClass = elementClass;
    }

    /**
     * INTERNAL:
     * Validate the container type.
     */
    @Override
    public boolean isValidContainer(Object container) {
        // PERF: Use instanceof which is inlined, not isAssignable which is very inefficient.
        return container instanceof Map;
    }

    /**
     * INTERNAL:
     * Sets the key name to be used to generate the key in a Map type container
     * class. The key name, may be the name of a field or method.
     */
    @Override
    public void setKeyName(String keyName, String elementClassName) {
        // The key name and class name must be held as the policy is used
        // directly from the mapping.
        this.keyName = keyName;
        this.elementClassName = elementClassName;
    }

    /**
     * INTERNAL:
     * Sets the key name to be used to generate the key in a Map type container
     * class. The key name, may be the name of a field or method.
     * An instance of the class is provided in the case when the descriptor is being
     * built in code.
     */
    @Override
    public void setKeyName(String keyName, Class elementClass) {
        // The key name and class name must be held as the policy is used
        // directly from the mapping.
        this.keyName = keyName;
        this.elementClass = elementClass;
    }

    /**
     * INTERNAL:
     * Sets the key name to be used to generate the key in a Map type container
     * class. The key name, maybe the name of a field or method.
     */
    public void setKeyName(String keyName) {
        this.keyName = keyName;
    }

    /**
     * INTERNAL:
     * Sets the Method to be used to generate the key in a Map type container class.
     */
    public void setKeyMethod(String keyMethodName, Class elementClass) {
        this.setKeyName(keyMethodName, elementClass);
    }

    /**
     * INTERNAL:
     * Sets the Method to be used to generate the key in a Map type container class.
     */
    public void setKeyMethod(String keyMethodName, String elementClassName) {
        this.setKeyName(keyMethodName, elementClassName);
    }

    /**
     * INTERNAL:
     * Sets the Method to be used to generate the key in a Map type container class.
     */
    public void setKeyMethodName(String keyMethodName) {
        this.setKeyName(keyMethodName);
    }

    /**
     * INTERNAL:
     * Return the size of container.
     */
    @Override
    public int sizeFor(Object container) {
        return ((Map)container).size();
    }

    /**
     * INTERNAL:
     * This method is used to load a relationship from a list of PKs. This list
     * may be available if the relationship has been cached.
     */
    @Override
    public Object valueFromPKList(Object[] pks, AbstractRecord foreignKeys, ForeignReferenceMapping mapping, AbstractSession session){
        // pks contains both keys and values, but only values are required because keys could be obtained from corresponding values.
        Object[] pksOnly = new Object[pks.length / 2];
        for (int i=0; i<pks.length/2; i++) {
            pksOnly[i] = pks[2*i + 1];
        }
        return super.valueFromPKList(pksOnly, foreignKeys, mapping, session);
    }

    /**
     * INTERNAL:
     * This inner class is used to iterate through the Map.Entry s of a Map.
     * It maintains a pointer to the current entry to allow access to the key and the value.
     * @author tware
     */
    public static class MapContainerPolicyIterator implements Iterator {

        private Iterator iterator;
        private Map.Entry currentEntry;

        public MapContainerPolicyIterator(Map container) {
            this.iterator = container.entrySet().iterator();
        }

        @Override
        public boolean hasNext() {
            return iterator.hasNext();
        }

        @Override
        public Map.Entry next() {
            currentEntry = (Map.Entry)iterator.next();
            return currentEntry;
        }

        public Object getCurrentKey() {
            if (currentEntry != null) {
                return currentEntry.getKey();
            }
            return null;
        }

        public Object getCurrentValue() {
            if (currentEntry != null) {
                return currentEntry.getValue();
            }
            return null;
        }

        @Override
        public void remove() {
            this.iterator.remove();
        }
    }

}
