/*
 * 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
//     08/23/2010-2.2 Michael O'Brien
//        - 323043: application.xml module ordering may cause weaving not to occur causing an NPE.
//                       warn if expected "_persistence_//_vh" method not found
//                       instead of throwing NPE during deploy validation.
package org.eclipse.persistence.mappings.foundation;

import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.databaseaccess.FieldTypeDefinition;
import org.eclipse.persistence.internal.descriptors.DescriptorIterator;
import org.eclipse.persistence.internal.descriptors.FieldTransformation;
import org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor;
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
import org.eclipse.persistence.internal.descriptors.MethodBasedFieldTransformation;
import org.eclipse.persistence.internal.descriptors.TransformerBasedFieldTransformation;
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.indirection.BasicIndirectionPolicy;
import org.eclipse.persistence.internal.indirection.ContainerIndirectionPolicy;
import org.eclipse.persistence.internal.indirection.DatabaseValueHolder;
import org.eclipse.persistence.internal.indirection.IndirectionPolicy;
import org.eclipse.persistence.internal.indirection.NoIndirectionPolicy;
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.security.PrivilegedNewInstanceFromClass;
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.TransformationMappingChangeRecord;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.internal.sessions.remote.RemoteValueHolder;
import org.eclipse.persistence.mappings.Association;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.transformers.AttributeTransformer;
import org.eclipse.persistence.mappings.transformers.FieldTransformer;
import org.eclipse.persistence.mappings.transformers.MethodBasedAttributeTransformer;
import org.eclipse.persistence.mappings.transformers.MethodBasedFieldTransformer;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.WriteObjectQuery;
import org.eclipse.persistence.sessions.CopyGroup;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.remote.DistributedSession;

/**
 * <p><b>Purpose</b>: A transformation mapping is used for a specialized translation between how
 * a value is represented in Java and its representation on the databae. Transformation mappings
 * should only be used when other mappings are inadequate.
 *
 * @author Sati
 * @since TOPLink/Java 1.0
 */
public abstract class AbstractTransformationMapping extends DatabaseMapping {

    /** Name of the class which implements AttributeTransformer to be used to retrieve the attribute value */
    protected String attributeTransformerClassName;

    /** attributeTransformerClassName is converter to an instance of AttributeTransformer */
    protected AttributeTransformer attributeTransformer;

    /** Stores field name and the class name of a FieldTransformer in a vector to preserve order */
    protected List<FieldTransformation> fieldTransformations;

    /** The TransformerClassNames are converted into instances of FieldTransformer */
    protected List<Object[]> fieldToTransformers;

    /** PERF: Indicates if this mapping's attribute is a simple value which cannot be modified only replaced. */
    protected boolean isMutable;

    /** Implements indirection behaviour */
    protected IndirectionPolicy indirectionPolicy;

    /**
     * PUBLIC:
     * Default constructor.
     */
    protected AbstractTransformationMapping() {
        fieldTransformations = new ArrayList();
        fieldToTransformers = new ArrayList();
        setIsMutable(true);
        dontUseIndirection();
        this.setWeight(WEIGHT_TRANSFORM);
    }

    /**
     * PUBLIC:
     * Add the field and the name of the method
     * that returns the value to be placed in said field
     * when the object is written to the database.
     * The method may take zero arguments, or it may
     * take a single argument of type
     * <code>org.eclipse.persistence.sessions.Session</code>.
     */
    public void addFieldTransformation(DatabaseField field, String methodName) {
        MethodBasedFieldTransformation transformation = new MethodBasedFieldTransformation();
        transformation.setField(field);
        transformation.setMethodName(methodName);
        getFieldTransformations().add(transformation);
    }

    /**
     * PUBLIC:
     * Add the name of field and the name of the method
     * that returns the value to be placed in said field
     * when the object is written to the database.
     * The method may take zero arguments, or it may
     * take a single argument of type
     * <code>org.eclipse.persistence.sessions.Session</code>.
     */
    public void addFieldTransformation(String fieldName, String methodName) {
        addFieldTransformation(new DatabaseField(fieldName), methodName);
    }

    /**
     * INTERNAL:
     * Add the name of a field and the name of a class which implements
     * the FieldTransformer interface. When the object is written, the transform
     * method will be called on the FieldTransformer to acquire the value to put
     * in the field.
     */
    public void addFieldTransformerClassName(String fieldName, String className) {
        addFieldTransformerClassName(new DatabaseField(fieldName), className);
    }

    /**
     * INTERNAL:
     * Add the name of a field and the name of a class which implements
     * the FieldTransformer interface. When the object is written, the transform
     * method will be called on the FieldTransformer to acquire the value to put
     * in the field.
     */
    public void addFieldTransformerClassName(DatabaseField field, String className) {
        TransformerBasedFieldTransformation transformation = new TransformerBasedFieldTransformation();
        transformation.setField(field);
        transformation.setTransformerClassName(className);

        getFieldTransformations().add(transformation);
    }

    /**
     * PUBLIC:
     * Add the name of field and the transformer
     * that returns the value to be placed in the field
     * when the object is written to the database.
     */
    public void addFieldTransformer(String fieldName, FieldTransformer transformer) {
        this.addFieldTransformer(new DatabaseField(fieldName), transformer);
    }

    /**
     * PUBLIC:
     * Add the field and the transformer
     * that returns the value to be placed in the field
     * when the object is written to the database.
     */
    public void addFieldTransformer(DatabaseField field, FieldTransformer transformer) {
        TransformerBasedFieldTransformation transformation = new TransformerBasedFieldTransformation(transformer);
        transformation.setField(field);

        getFieldTransformations().add(transformation);
    }

    /**
     * INTERNAL:
     * The referenced object is checked if it is instantiated or not
     */
    protected boolean areObjectsToBeProcessedInstantiated(Object object) {
        return this.indirectionPolicy.objectIsInstantiated(getAttributeValueFromObject(object));
    }

    /**
     * INTERNAL:
     * Clone the attribute from the clone and assign it to the backup.
     */
    @Override
    public void buildBackupClone(Object clone, Object backup, UnitOfWorkImpl unitOfWork) {
        // If mapping is a no-attribute transformation mapping, do nothing
        if (isWriteOnly()) {
            return;
        }
        Object attributeValue = getAttributeValueFromObject(clone);
        Object clonedAttributeValue = this.indirectionPolicy.backupCloneAttribute(attributeValue, clone, backup, unitOfWork);
        setAttributeValueInObject(backup, clonedAttributeValue);
    }

    /**
     * INTERNAL
     * Build a phantom row that contains only the fields
     * for the mapping, populated with the values generated by
     * invoking the field methods on the specified object.
     */
    protected AbstractRecord buildPhantomRowFrom(Object domainObject, AbstractSession session) {
        AbstractRecord row = new DatabaseRecord(this.fieldToTransformers.size());
        for (Object[] pair : this.fieldToTransformers) {
            DatabaseField field = (DatabaseField)pair[0];
            FieldTransformer transformer = (FieldTransformer)pair[1];
            Object fieldValue = this.invokeFieldTransformer(field, transformer, domainObject, session);
            row.put(field, fieldValue);
        }
        return row;
    }

    /**
     * INTERNAL:
     * Builds a shallow original object.  Only direct attributes and primary
     * keys are populated.  In this way the minimum original required for
     * instantiating a working copy clone can be built without placing it in
     * the shared cache (no concern over cycles).
     * @param original later the input to buildCloneFromRow
     */
    @Override
    public void buildShallowOriginalFromRow(AbstractRecord record, Object original, JoinedAttributeManager joinManager, ObjectBuildingQuery query, AbstractSession executionSession) {
        // In this case we know it is a primary key mapping, so hope that it
        // is essentially a direct mapping.  If it is a 1-1 with a
        // no-indirection pointer back to original, then will get a stack
        // overflow.
        // Only solution to this is to trigger the transformation using the root
        // session.
        UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)query.getSession();
        query.setSession(unitOfWork.getParent());
        try {
            readFromRowIntoObject(record, joinManager, original, null, query, executionSession, false);
        } finally {
            query.setSession(unitOfWork);
        }
    }

    /**
     * INTERNAL:
     * Used during building the backup shallow copy to copy the vector without re-registering the target objects.
     * For 1-1 or ref the reference is from the clone so it is already registered.
     */
    @Override
    public Object buildBackupCloneForPartObject(Object attributeValue, Object clone, Object backup, UnitOfWorkImpl unitOfWork) {
        return buildCloneForPartObject(attributeValue, clone, null, backup, unitOfWork, null, true, true);
    }

    /**
     * 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) {
        // If mapping is a no-attribute transformation mapping, do nothing
        if (isWriteOnly()) {
            return;
        }
        Object attributeValue = getAttributeValueFromObject(original);
        Object clonedAttributeValue = this.indirectionPolicy.cloneAttribute(attributeValue, original, cacheKey, clone, refreshCascade, cloningSession, false);// building clone from an original not a row.
        setAttributeValueInObject(clone, clonedAttributeValue);
    }

    /**
     * INTERNAL:
     * Extract value from the row and set the attribute to this value in the
     * working copy clone.
     * In order to bypass the shared cache when in transaction a UnitOfWork must
     * be able to populate working copies directly from the row.
     */
    @Override
    public void buildCloneFromRow(AbstractRecord record, JoinedAttributeManager joinManager, Object clone, CacheKey sharedCacheKey, ObjectBuildingQuery sourceQuery, UnitOfWorkImpl unitOfWork, AbstractSession executionSession) {
        // If mapping is a no-attribute transformation mapping, do nothing
        if (isWriteOnly()) {
            return;
        }

        // This will set the value in the clone automatically.
        Object attributeValue = readFromRowIntoObject(record, joinManager, clone, sharedCacheKey, sourceQuery, executionSession, true);
        if (usesIndirection()) {
            boolean wasCacheUsed = this.isCacheable && sharedCacheKey != null && this.descriptor.getCachePolicy().isProtectedIsolation()
                && sharedCacheKey.getObject() != null;
            //it would be better if wasCacheUsed could be calculated within readFromRowIntoObject but that would require changing the signature of all mappings just for
            //transformation mapping.
            if (!wasCacheUsed){
                //if the cache was used then the attribute has already been cloned by readFromRowIntoObject
                attributeValue = this.indirectionPolicy.cloneAttribute(attributeValue, null,// no original
                        null, clone, null, unitOfWork, true);// build clone directly from row.
            }
            setAttributeValueInObject(clone, attributeValue);
        }
    }

    /**
     * INTERNAL:
     * Require for cloning, the part must be cloned.
     * Ignore the attribute value, go right to the object itself.
     */
    @Override
    public Object buildCloneForPartObject(Object attributeValue, Object original, CacheKey cacheKey, Object clone, AbstractSession cloningSession, Integer refreshCascade, boolean isExisting, boolean isFromSharedCache) {
        if (isReadOnly() || !isMutable()) {
            return attributeValue;
        }
        AbstractRecord row = buildPhantomRowFrom(original, cloningSession);
        return invokeAttributeTransformer(row, clone, cloningSession);
    }

    /**
     * INTERNAL:
     * Copy of the attribute of the object.
     * This is NOT used for unit of work but for templatizing an object.
     */
    @Override
    public void buildCopy(Object copy, Object original, CopyGroup group) {
        // If mapping is a no-attribute transformation mapping, do nothing
        if (isWriteOnly()) {
            return;
        }

        Object clonedAttributeValue;
        // If the mapping is read-only, a direct pass through of the value will be performed.
        // This is done because the method invocation is not possible as the row will be
        // empty and we have no way to clone the value.
        // Since the value cannot change anyway we just pass it through.
        if (isReadOnly() || !isMutable()) {
            clonedAttributeValue = getRealAttributeValueFromObject(original, group.getSession());
        } else {
            AbstractRecord row = buildPhantomRowFrom(original, group.getSession());
            clonedAttributeValue = invokeAttributeTransformer(row, copy, group.getSession());
        }
        this.indirectionPolicy.reset(copy);
        setRealAttributeValueInObject(copy, clonedAttributeValue);
    }

    /**
     * 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){
        //Objects referenced through transformation mappings are not registered as
        // they have no identity, this is a no-op.
    }

    /**
     * INTERNAL:
     * The mapping clones itself to create deep copy.
     */
    @Override
    public Object clone() {
        AbstractTransformationMapping clone = (AbstractTransformationMapping)super.clone();
        clone.setFieldToTransformers(new ArrayList(this.fieldToTransformers.size()));

        for (Object[] pair : this.fieldToTransformers) {
            Object[] transformation = new Object[2];
            transformation[0] = pair[0];
            transformation[1] = pair[1];
            clone.getFieldToTransformers().add(transformation);
        }

        clone.setIndirectionPolicy((IndirectionPolicy)indirectionPolicy.clone());

        return clone;
    }

    /**
     * INTERNAL:
     * Return all the fields with this mapping.
     */
    @Override
    protected Vector collectFields() {
        Vector databaseFields = new Vector(this.fieldToTransformers.size());
        for (Object[] pair : this.fieldToTransformers) {
            databaseFields.add(pair[0]);
        }
        return databaseFields;
    }

    /**
     * INTERNAL:
     * Compare the attributes belonging to this mapping for the objects.
     */
    @Override
    public ChangeRecord compareForChange(Object clone, Object backUp, ObjectChangeSet owner, AbstractSession session) {
        if (isReadOnly() || isWriteOnly()) {
            return null;
        }
        Object cloneAttribute = getAttributeValueFromObject(clone);
        Object backUpAttribute = null;
        if ((cloneAttribute != null) && (!this.indirectionPolicy.objectIsInstantiated(cloneAttribute))) {
            return null;
        }
        boolean difference = false;
        Object backupValue = null;
        if (owner.isNew()) {
            difference = true;
        } else {
            if (backUp != null) {
                backUpAttribute = getAttributeValueFromObject(backUp);
                backupValue = this.indirectionPolicy.getRealAttributeValueFromObject(backUp, backUpAttribute);
            }
            boolean backUpIsInstantiated = ((backUpAttribute == null) || (this.indirectionPolicy.objectIsInstantiated(backUpAttribute)));
            Object cloneValue = this.indirectionPolicy.getRealAttributeValueFromObject(clone, cloneAttribute);
            if (backUpIsInstantiated) {
                if (cloneValue == backupValue) {
                    return null;
                }
                if (((cloneValue != null && (backupValue != null)) && cloneValue.equals(backupValue))) {
                    return null;
                }
            }

            for (Object[] pair : this.fieldToTransformers) {
                DatabaseField field = (DatabaseField)pair[0];
                FieldTransformer transformer = (FieldTransformer)pair[1];
                Object cloneFieldValue = null;
                Object backUpFieldValue = null;
                if (clone != null) {
                    cloneFieldValue = invokeFieldTransformer(field, transformer, clone, session);
                }
                if ((backUpIsInstantiated) && (backUp != null)) {
                    backUpFieldValue = invokeFieldTransformer(field, transformer, backUp, session);
                }

                if (cloneFieldValue == backUpFieldValue) {
                    continue; // skip this iteration, go to the next one
                }
                if ((cloneFieldValue == null) || (backUpFieldValue == null)) {
                    difference = true;
                    break; // There is a difference.
                }
                if (cloneFieldValue.equals(backUpFieldValue)) {
                    continue; // skip this iteration, go to the next one
                }
                if (Helper.comparePotentialArrays(cloneFieldValue, backUpFieldValue)) {
                    continue; // skip this iteration, go to the next one
                }
                difference = true;
                break; // There is a difference.
            }
        }
        if (difference) {
            return internalBuildChangeRecord(clone, backupValue, owner, session);
        }
        return null;
    }

    /**
     * INTERNAL:
     * Directly build a change record without comparison
     */
    @Override
    public ChangeRecord buildChangeRecord(Object clone, ObjectChangeSet owner, AbstractSession session) {
        return internalBuildChangeRecord(clone, null, owner, session);
    }

    /**
     * INTERNAL:
     * Build a change record.
     */
    public ChangeRecord internalBuildChangeRecord(Object clone, Object oldValue, ObjectChangeSet owner, AbstractSession session) {
        TransformationMappingChangeRecord changeRecord = new TransformationMappingChangeRecord(owner);
        changeRecord.setRow(buildPhantomRowFrom(clone, session));
        changeRecord.setAttribute(getAttributeName());
        changeRecord.setMapping(this);
        changeRecord.setOldValue(oldValue);
        return changeRecord;
    }

    /**
     * INTERNAL:
     * Compare the attributes belonging to this mapping for the objects.
     */
    @Override
    public boolean compareObjects(Object firstObject, Object secondObject, AbstractSession session) {
        if (!isWriteOnly()) {
            // PERF: Checks if attribute values are equal first before apply field translation.
            Object firstValue = getRealAttributeValueFromObject(firstObject, session);
            Object secondValue = getRealAttributeValueFromObject(secondObject, session);
            if (firstValue == secondValue) {
                return true;
            }
            if ((firstValue == null) || (secondValue == null)) {
                return false;
            }
            if (firstValue.equals(secondValue)) {
                return true;
            }
        }

        for (Object[] pair : this.fieldToTransformers) {
            DatabaseField field = (DatabaseField)pair[0];
            FieldTransformer transformer = (FieldTransformer)pair[1];
            Object firstFieldValue = invokeFieldTransformer(field, transformer, firstObject, session);
            Object secondFieldValue = invokeFieldTransformer(field, transformer, secondObject, session);

            if (firstFieldValue == secondFieldValue) {
                continue; // skip this iteration, go to the next one
            }
            if ((firstFieldValue == null) || (secondFieldValue == null)) {
                return false;
            }
            if (!firstFieldValue.equals(secondFieldValue)) {
                if (!Helper.comparePotentialArrays(firstFieldValue, secondFieldValue)) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this mapping to actual class-based
     * settings
     */
    @Override
    public void convertClassNamesToClasses(ClassLoader classLoader){
        super.convertClassNamesToClasses(classLoader);

        if (attributeTransformerClassName != null) {
            Class attributeTransformerClass = null;
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                    try {
                        attributeTransformerClass = AccessController.doPrivileged(new PrivilegedClassForName(attributeTransformerClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(attributeTransformerClassName, exception.getException());
                    }
                } else {
                    attributeTransformerClass = PrivilegedAccessHelper.getClassForName(attributeTransformerClassName, true, classLoader);
                }
            } catch (ClassNotFoundException exc){
                throw ValidationException.classNotFoundWhileConvertingClassNames(attributeTransformerClassName, exc);
            }

            this.setAttributeTransformerClass(attributeTransformerClass);
        }

        for (FieldTransformation transformation : getFieldTransformations()) {
            if (transformation instanceof TransformerBasedFieldTransformation) {
                TransformerBasedFieldTransformation transformer = (TransformerBasedFieldTransformation)transformation;
                String transformerClassName = transformer.getTransformerClassName();
                if (transformerClassName == null) {
                    return;
                }
                Class transformerClass = null;
                try {
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                        try {
                            transformerClass = AccessController.doPrivileged(new PrivilegedClassForName(transformerClassName, true, classLoader));
                        } catch (PrivilegedActionException exception) {
                            throw ValidationException.classNotFoundWhileConvertingClassNames(transformerClassName, exception.getException());
                        }
                    } else {
                        transformerClass = PrivilegedAccessHelper.getClassForName(transformerClassName, true, classLoader);
                    }
                } catch (ClassNotFoundException exc){
                    throw ValidationException.classNotFoundWhileConvertingClassNames(transformerClassName, exc);
                }
                transformer.setTransformerClass(transformerClass);
            }
        }
    }

    /**
     * INTERNAL:
     * Builder the unit of work value holder.
     * Ignore the original object.
     * @param buildDirectlyFromRow indicates that we are building the clone directly
     * from a row as opposed to building the original from the row, putting it in
     * the shared cache, and then cloning the original.
     */
    @Override
    public DatabaseValueHolder createCloneValueHolder(ValueHolderInterface attributeValue, Object original, Object clone, AbstractRecord row, AbstractSession cloningSession, boolean buildDirectlyFromRow) {
        return cloningSession.createCloneTransformationValueHolder(attributeValue, original, clone, this);
    }

    /**
     * PUBLIC:
     * Indirection means that a ValueHolder will be put in-between the attribute and the real object.
     * This defaults to false and only required for transformations that perform database access.
     */
    public void dontUseIndirection() {
        setIndirectionPolicy(new NoIndirectionPolicy());
    }

    /**
     * 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) {
        this.indirectionPolicy.fixObjectReferences(object, objectDescriptors, processedObjects, query, session);
    }

    /**
     * INTERNAL:
     * The attributeTransformer stores an instance of the class which implements
     * AttributeTransformer.
     */
    public AttributeTransformer getAttributeTransformer() {
        return attributeTransformer;
    }

    /**
     * PUBLIC:
     * Return the attribute transformation method name.
     */
    public String getAttributeMethodName() {
        if (this.attributeTransformer instanceof MethodBasedAttributeTransformer) {
            return ((MethodBasedAttributeTransformer)this.attributeTransformer).getMethodName();
        }
        return null;
    }

    /**
     * INTERNAL:
     * Return the attribute transformer's class.
     * This is used to map to XML.
     */
    public Class getAttributeTransformerClass() {
        if ((this.attributeTransformer == null) || (this.attributeTransformer instanceof MethodBasedAttributeTransformer)) {
            return null;
        }
        return this.attributeTransformer.getClass();
    }

    /**
     * INTERNAL:
     * Set the attribute transformer's class.
     * This is used to map from XML.
     */
    public void setAttributeTransformerClass(Class attributeTransformerClass) {
        if (attributeTransformerClass == null) {
            return;
        }
        try {
            Object instance = null;
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                try {
                    instance = AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(attributeTransformerClass));
                } catch (PrivilegedActionException ex) {
                    throw (Exception)ex.getCause();
                }
            } else {
                instance = PrivilegedAccessHelper.newInstanceFromClass(attributeTransformerClass);
            }
            setAttributeTransformer((AttributeTransformer)instance);
        } catch (Exception exception) {
            throw DescriptorException.attributeTransformerClassInvalid(attributeTransformerClass.getName(), this, exception);
        }
    }

    /**
     * INTERNAL:
     * Return the attribute transformer class name
     */
    public String getAttributeTransformerClassName() {
        return attributeTransformerClassName;
    }

    /**
     * INTERNAL:
     * Check for write-only, one-way transformation.
     */
    @Override
    public Object getAttributeValueFromObject(Object object) throws DescriptorException {
        if (isWriteOnly()) {
            return null;
        }
        Object attributeValue = super.getAttributeValueFromObject(object);
        return this.indirectionPolicy.validateAttributeOfInstantiatedObject(attributeValue);
    }

    /**
     * INTERNAL:
     * Returns a Vector which stores fieldnames and the respective method/transformer names.
     */
    public List<FieldTransformation> getFieldTransformations() {
        return fieldTransformations;
    }

    /**
     * INTERNAL:
     * @return a vector which stores fields and their respective transformers.
     */
    public List<Object[]> getFieldToTransformers() {
        return fieldToTransformers;
    }

    /**
     * INTERNAL:
     * Return the mapping's indirection policy.
     */
    public IndirectionPolicy getIndirectionPolicy() {
        return indirectionPolicy;
    }

    /**
     * INTERNAL:
     * Returns the real attribute value from the reference object's attribute value.
     * If the attribute is using indirection the value of the value-holder is returned.
     * If the value holder is not instantiated then it is instantiated.
     */
    @Override
    public Object getRealAttributeValueFromAttribute(Object attributeValue, Object object, AbstractSession session) {
        return this.indirectionPolicy.getRealAttributeValueFromObject(object, attributeValue);
    }

    /**
     * INTERNAL:
     * Trigger the instantiation of the attribute if lazy.
     */
    @Override
    public void instantiateAttribute(Object object, AbstractSession session) {
        this.indirectionPolicy.instantiateObject(object, getAttributeValueFromObject(object));
    }

    /**
     * INTERNAL:
     * Extract and return the appropriate value from the
     * specified remote value holder.
     */
    @Override
    public Object getValueFromRemoteValueHolder(RemoteValueHolder remoteValueHolder) {
        return this.indirectionPolicy.getValueFromRemoteValueHolder(remoteValueHolder);
    }

    /**
     * INTERNAL:
     * The mapping is initialized with the given session.
     */
    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
        super.initialize(session);
        initializeAttributeTransformer(session);
        initializeFieldToTransformers(session);
        setFields(collectFields());
        this.indirectionPolicy.initialize();
        if (usesIndirection()) {
            for (DatabaseField field : this.fields) {
                field.setKeepInRow(true);
            }
        }
    }

    /**
     * INTERNAL:
     * Convert the attribute transformer class name into an AttributeTransformer
    * If the old-style method name in set, then use a MethodBasedAttributeTRansformer
     */
    protected void initializeAttributeTransformer(AbstractSession databaseSession) throws DescriptorException {
        if (isWriteOnly()) {
            return;
        }
        this.attributeTransformer.initialize(this);
    }

    /**
     * INTERNAL:
     * Required for reverse compatibility and test cases:
     * @return a hash table containing the fieldName and their respective method names
     */
    public Hashtable getFieldNameToMethodNames() {
        Hashtable table = new Hashtable(getFieldTransformations().size());
        Iterator transformations = getFieldTransformations().iterator();
        while (transformations.hasNext()) {
            FieldTransformation transformation = (FieldTransformation)transformations.next();
            if (transformation instanceof MethodBasedFieldTransformation) {
                table.put(transformation.getField().getQualifiedName(), ((MethodBasedFieldTransformation)transformation).getMethodName());
            }
        }
        return table;
    }

    /**
     * INTERNAL:
     * Convert the field names and their corresponding method names to
     * DatabaseFields and Methods.
     */
    protected void initializeFieldToTransformers(AbstractSession session) throws DescriptorException {
        for (Object[] pair : this.fieldToTransformers) {
            pair[0] = getDescriptor().buildField(((DatabaseField)pair[0]));
            ((FieldTransformer)pair[1]).initialize(this);
        }
        for (FieldTransformation transformation : getFieldTransformations()) {
            DatabaseField field = getDescriptor().buildField(transformation.getField());
            String transformerClassName = "MethodBasedFieldTransformer";
            FieldTransformer transformer = null;
            try {
                transformer = transformation.buildTransformer();
            } catch (ConversionException ex) {
                if (transformation instanceof TransformerBasedFieldTransformation) {
                    transformerClassName = ((TransformerBasedFieldTransformation)transformation).getTransformerClassName();
                }

                throw DescriptorException.fieldTransformerClassNotFound(transformerClassName, this, ex);
            } catch (Exception ex) {
                if (transformation instanceof TransformerBasedFieldTransformation) {
                    transformerClassName = ((TransformerBasedFieldTransformation)transformation).getTransformerClassName();
                }

                throw DescriptorException.fieldTransformerClassInvalid(transformerClassName, this, ex);
            }

            transformer.initialize(this);
            // Attempt to ensure a type is set on the field.
            if (field.getType() == null) {
                if (transformer instanceof MethodBasedFieldTransformer) {
                    field.setType(((MethodBasedFieldTransformer)transformer).getFieldType());
                } else if (field.getColumnDefinition() != null) {
                    // Search for the type for this field definition.
                    if (session.getDatasourcePlatform() instanceof DatabasePlatform) {
                        Iterator iterator = session.getPlatform().getFieldTypes().entrySet().iterator();
                        while (iterator.hasNext()) {
                            Map.Entry entry = (Map.Entry)iterator.next();
                            if (((FieldTypeDefinition)entry.getValue()).getName().equals(field.getColumnDefinition())) {
                                field.setType((Class)entry.getKey());
                                break;
                            }
                        }
                    }
                }
            }
            Object[] fieldToTransformer = new Object[2];
            fieldToTransformer[0] = field;
            fieldToTransformer[1] = transformer;

            this.fieldToTransformers.add(fieldToTransformer);
        }
    }

    /**
     * INTERNAL:
     * Invoke the buildAttributeValue method on the AttributeTransformer
     */
    public Object invokeAttributeTransformer(AbstractRecord record, Object domainObject, AbstractSession session) throws DescriptorException {
        return this.attributeTransformer.buildAttributeValue(record, domainObject, session);
    }

    /**
     * INTERNAL:
    * Invoke the buildFieldValue on the appropriate FieldTransformer
    */
    protected Object invokeFieldTransformer(DatabaseField field, FieldTransformer transformer, Object domainObject, AbstractSession session) throws DescriptorException {
        return transformer.buildFieldValue(domainObject, field.getName(), session);
    }

    protected Object invokeFieldTransformer(DatabaseField field, Object domainObject, AbstractSession session) {
        for (Object[] pair : this.fieldToTransformers) {
            if (field.equals(pair[0])) {
                return invokeFieldTransformer(field, (FieldTransformer)pair[1], domainObject, session);
            }
        }
        return null;
    }

    /**
     * PUBLIC:
     * Return true if the attribute for this mapping is not a simple atomic value that cannot be modified,
     * only replaced.
     * This is true by default for non-primitives, but can be set to false to avoid cloning
     * and change comparison in the unit of work.
     */
    public boolean isMutable() {
        return isMutable;
    }

    /**
     * INTERNAL:
     * Return true if read-only is explicitly set to true;
     * otherwise return whether the transformation has no fields
     * (no fields = read-only)
     */
    @Override
    public boolean isReadOnly() {
        if (super.isReadOnly()) {
            return true;
        } else {
            return getFieldTransformations().isEmpty() && this.fieldToTransformers.isEmpty();
        }
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean isTransformationMapping() {
        return true;
    }

    /**
     * INTERNAL:
     * Return if the transformation has no attribute, is write only.
     */
    @Override
    public boolean isWriteOnly() {
        return (getAttributeName() == null) && ((this.attributeTransformer == null) && (this.attributeTransformerClassName == null));
    }

    /**
     * INTERNAL:
     * Perform the iteration opperation on the iterators current objects attributes.
     * Only require if primitives are desired.
     */
    @Override
    public void iterate(DescriptorIterator iterator) {
        Object attributeValue = getAttributeValueFromObject(iterator.getVisitedParent());
        this.indirectionPolicy.iterateOnAttributeValue(iterator, attributeValue);
    }

    /**
     * INTERNAL:
     * Iterate on the attribute value.
     * The value holder has already been processed.
     */
    @Override
    public void iterateOnRealAttributeValue(DescriptorIterator iterator, Object realAttributeValue) {
        iterator.iteratePrimitiveForMapping(realAttributeValue, this);
    }

    /**
     * INTERNAL:
     * Merge changes from the source to the target object. Which is the original from the parent UnitOfWork
     */
    @Override
    public void mergeChangesIntoObject(Object target, ChangeRecord changeRecord, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        if (isWriteOnly()) {
            return;
        }
        // PERF: If not mutable then just set the value from the source.
        if (!isMutable() && (source != null)) {
            setRealAttributeValueInObject(target, getRealAttributeValueFromObject(source, mergeManager.getSession()));
            return;
        }
        AbstractRecord record = (AbstractRecord)((TransformationMappingChangeRecord)changeRecord).getRecord();
        Object attributeValue = invokeAttributeTransformer(record, target, targetSession);
        setRealAttributeValueInObject(target, attributeValue);
    }

    /**
     * INTERNAL:
     * Merge changes from the source to the target object.
     */
    @Override
    public void mergeIntoObject(Object target, boolean isTargetUnInitialized, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        if (isWriteOnly()) {
            return;
        }

        // do refresh check first as I may need to reset remote value holder
        if (mergeManager.shouldRefreshRemoteObject() && usesIndirection()) {
            this.indirectionPolicy.mergeRemoteValueHolder(target, source, mergeManager);
            return;
        }

        if (mergeManager.isForRefresh()) {
            if (!areObjectsToBeProcessedInstantiated(target)) {
                // This will occur when the clone's value has not been instantiated yet and we do not need
                // the refresh that attribute
                return;
            }
        } else if (!areObjectsToBeProcessedInstantiated(source)) {
            // I am merging from a clone into an original.  No need to do merge if the attribute was never
            // modified
            return;
        }

        if (isTargetUnInitialized) {
            // This will happen if the target object was removed from the cache before the commit was attempted
            if (mergeManager.shouldMergeWorkingCopyIntoOriginal() && (!areObjectsToBeProcessedInstantiated(source))) {
                setAttributeValueInObject(target, this.indirectionPolicy.getOriginalIndirectionObject(getAttributeValueFromObject(source), targetSession));
                return;
            }
        }
        if (isReadOnly()) {
            // if it is read only then we do not have any fields specified for the
            // transformer, without fields we can not build the row, so just copy
            // over the value  alternatively we could build the entire row for the object.
            setRealAttributeValueInObject(target, getRealAttributeValueFromObject(source, mergeManager.getSession()));
            return;
        }
        if (!isMutable()) {
            Object attribute = getRealAttributeValueFromObject(source, mergeManager.getSession());
            if (this.descriptor.getObjectChangePolicy().isObjectChangeTrackingPolicy()) {
                // Object level or attribute level so lets see if we need to raise the event?
                Object targetAttribute = getRealAttributeValueFromObject(target, mergeManager.getSession());
                if ((mergeManager.shouldMergeCloneIntoWorkingCopy() || mergeManager.shouldMergeCloneWithReferencesIntoWorkingCopy())  && !mergeManager.isForRefresh()
                        && (((targetAttribute == null) && (attribute != null)) || ((targetAttribute != null) && ((attribute == null) || ((!targetAttribute.equals(attribute)) && (!Helper.comparePotentialArrays(targetAttribute, attribute))))))) {
                    this.descriptor.getObjectChangePolicy().raiseInternalPropertyChangeEvent(target, getAttributeName(), targetAttribute, attribute);
                }
            }
            setRealAttributeValueInObject(target, attribute);
            return;
        }

        // This dumps the attribute into the row and back.
        AbstractRecord row = buildPhantomRowFrom(source, mergeManager.getSession());
        Object attributeValue = invokeAttributeTransformer(row, source, mergeManager.getSession());
        AbstractRecord targetRow = buildPhantomRowFrom(target, mergeManager.getSession());
        setRealAttributeValueInObject(target, attributeValue);
        //set the change after the set on the object as this mapping uses the object to build the change record.
        if (this.descriptor.getObjectChangePolicy().isObjectChangeTrackingPolicy()) {
            for (Enumeration keys = targetRow.keys(); keys.hasMoreElements(); ){
                Object field = keys.nextElement();
                if ((mergeManager.shouldMergeCloneIntoWorkingCopy() || mergeManager.shouldMergeCloneWithReferencesIntoWorkingCopy())
                        && (!row.get(field).equals(targetRow.get(field)))) {
                    this.descriptor.getObjectChangePolicy().raiseInternalPropertyChangeEvent(target, getAttributeName(), invokeAttributeTransformer(targetRow, source, mergeManager.getSession()), attributeValue);
                    break;
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Allow for initialization of properties and validation.
     */
    @Override
    public void preInitialize(AbstractSession session) throws DescriptorException {
        if (isWriteOnly()) {
            return;// Allow for one-way transformations.
        }

        super.preInitialize(session);

        // PERF: Also auto-set mutable to false is the attribute type is a primitive.
        // This means it is not necessary to clone the value (through double transformation).
        if ((getAttributeClassification() != null) && (getAttributeClassification().isPrimitive() || Helper.isPrimitiveWrapper(getAttributeClassification()) || getAttributeClassification().equals(ClassConstants.STRING) || getAttributeClassification().equals(ClassConstants.BIGDECIMAL) || getAttributeClassification().equals(ClassConstants.NUMBER))) {
            setIsMutable(false);
        }
    }

    /**
     * INTERNAL:
     * Extracts value from return row and set the attribute to the value in the object.
     * Return row is merged into object after execution of insert or update call
     * according to ReturningPolicy.
     */
    public Object readFromReturnRowIntoObject(AbstractRecord row, Object object, ReadObjectQuery query, Collection handledMappings, ObjectChangeSet changeSet) throws DatabaseException {
        int size = this.fields.size();
        AbstractRecord transformationRow = new DatabaseRecord(size);
        for (int i = 0; i < size; i++) {
            DatabaseField field = this.fields.get(i);
            Object value;
            if (row.containsKey(field)) {
                value = row.get(field);
            } else {
                value = valueFromObject(object, field, query.getSession());
            }
            transformationRow.add(field, value);
        }

        if(changeSet != null && (!changeSet.isNew() || (query.getDescriptor() != null && query.getDescriptor().shouldUseFullChangeSetsForNewObjects()))) {
            TransformationMappingChangeRecord record = (TransformationMappingChangeRecord)changeSet.getChangesForAttributeNamed(attributeName);
            if (record == null) {
                record = new TransformationMappingChangeRecord(changeSet);
                record.setAttribute(attributeName);
                record.setMapping(this);
                record.setOldValue(getAttributeValueFromObject(object));
                changeSet.addChange(record);
            }
            record.setRow(transformationRow);
        }

        Object attributeValue = readFromRowIntoObject(transformationRow, null, object, null, query, query.getSession(), true);
        if (handledMappings != null) {
            handledMappings.add(this);
        }

        return attributeValue;
    }

    /**
     * INTERNAL:
     * Extract value from the row and set the attribute to the value in the object.
     */
    @Override
    public Object readFromRowIntoObject(AbstractRecord row, JoinedAttributeManager joinManager, Object object, CacheKey parentCacheKey, ObjectBuildingQuery query, AbstractSession executionSession, boolean isTargetProtected) throws DatabaseException {
        if (isWriteOnly()) {
            return null;
        }
        if (this.descriptor.getCachePolicy().isProtectedIsolation()) {
            if (this.isCacheable && isTargetProtected && parentCacheKey != null) {
                Object cached = parentCacheKey.getObject();
                if (cached != null) {
                    Object attributeValue =  getAttributeValueFromObject(cached);
                    Integer refreshCascade = null;
                    if (query != null && query.shouldRefreshIdentityMapResult()){
                        refreshCascade = query.getCascadePolicy();
                    }
                    return this.indirectionPolicy.cloneAttribute(attributeValue, cached, parentCacheKey, object, refreshCascade, executionSession, false);
                }
                return null;
            }
        }
        if (row != null && row.hasSopObject()) {
            return getAttributeValueFromObject(row.getSopObject());
        }
        Object attributeValue = this.indirectionPolicy.valueFromMethod(object, row, query.getSession());
        Object oldAttribute = null;
        if (executionSession.isUnitOfWork() && query.shouldRefreshIdentityMapResult()){
            oldAttribute = this.getAttributeValueFromObject(object);
        }
        try {
            this.attributeAccessor.setAttributeValueInObject(object, attributeValue);
        } catch (DescriptorException exception) {
            exception.setMapping(this);
            throw exception;
        }
        if (executionSession.isUnitOfWork() && query.shouldRefreshIdentityMapResult()){
            if (this.indirectionPolicy.objectIsInstantiatedOrChanged(oldAttribute)){
                this.indirectionPolicy.instantiateObject(object, attributeValue);
            }
        }
        return attributeValue;
    }

    /**
     * INTERNAL:
     * Needed for backwards compatibility
     */
    public Vector getFieldNameToMethodNameAssociations() {
        Vector associations = new Vector();
        for (Iterator source = getFieldTransformations().iterator(); source.hasNext();) {
            FieldTransformation tf = (FieldTransformation)source.next();
            if (tf instanceof MethodBasedFieldTransformation) {
                Association ass = new Association();
                ass.setKey(tf.getField().getQualifiedName());
                ass.setValue(((MethodBasedFieldTransformation)tf).getMethodName());
                associations.addElement(ass);
            }
        }
        return associations;
    }

    /**
     * INTERNAL:
     * needed for backwards compatibility
     */
    public void setFieldNameToMethodNameAssociations(Vector associations) {
        setFieldTransformations(org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(associations.size()));
        for (Iterator source = associations.iterator(); source.hasNext();) {
            Association ass = (Association)source.next();
            MethodBasedFieldTransformation tf = new MethodBasedFieldTransformation();
            tf.setField(new DatabaseField((String)ass.getKey()));
            tf.setMethodName((String)ass.getValue());
            getFieldTransformations().add(tf);
        }
    }

    /**
     * INTERNAL:
     * Once descriptors are serialized to the remote session. All its mappings and reference descriptors are traversed. Usually
     * mappings are initialized and serialized reference descriptors are replaced with local descriptors if they already exist on the
     * remote session.
     */
    @Override
    public void remoteInitialization(DistributedSession session) {
        setFieldToTransformers(new Vector());

        // Remote mappings is initialized here again because while serializing only the uninitialized data is passed
        // as the initialized data is not serializable.
        if (!isWriteOnly()) {
            super.remoteInitialization(session);
            initializeAttributeTransformer(session);
        }
        initializeFieldToTransformers(session);
    }

    /**
      * PUBLIC:
      * Set the AttributeTransformer, this transformer will be used to extract the value for the
      * object's attribute from the database row.
      */
    public void setAttributeTransformer(AttributeTransformer transformer) {
        attributeTransformer = transformer;
        if ((transformer != null) && !(transformer instanceof MethodBasedAttributeTransformer)) {
            attributeTransformerClassName = transformer.getClass().getName();
        }
    }

    /**
     * INTERNAL:
     * Set the Attribute Transformer Class Name
     */
    public void setAttributeTransformerClassName(String className) {
        attributeTransformerClassName = className;
    }


    /**
     * PUBLIC:
     * To set the attribute method name. The method is invoked internally by TopLink
     * to retrieve the value to store in the domain object. The method receives Record
     * as its parameter and optionally Session, and should extract the value from the
     * record to set into the object, but should not set the value on the object, only return it.
     */
    public void setAttributeTransformation(String methodName) {
        if ((methodName != null) && (!methodName.isEmpty())) {
            setAttributeTransformer(new MethodBasedAttributeTransformer(methodName));
        } else {
            setAttributeTransformer(null);
        }
    }

    /**
     * INTERNAL:
     * Check for write-only, one-way transformations.
     */
    @Override
    public void setAttributeValueInObject(Object object, Object value) {
        if (isWriteOnly()) {
            return;
        }

        super.setAttributeValueInObject(object, value);
    }

    /**
     * PUBLIC:
     * Set if the value of the attribute is atomic or a complex mutable object and can be modified without replacing the entire object.
     * This defaults to true for non-primitives, but can be set to false to optimize object cloning and change comparison.
     */
    public void setIsMutable(boolean mutable) {
        this.isMutable = mutable;
    }

    /**
     * INTERNAL:
     * Set the value of the attribute mapped by this mapping,
     * placing it inside a value holder if necessary.
     * If the value holder is not instantiated then it is instantiated.
     * Check for write-only, one-way transformations.
     */
    @Override
    public void setRealAttributeValueInObject(Object object, Object value) throws DescriptorException {
        if (isWriteOnly()) {
            return;
        }
        this.indirectionPolicy.setRealAttributeValueInObject(object, value);
    }

    /**
     * INTERNAL:
     * Set the field to method name associations.
     */
    public void setFieldTransformations(List<FieldTransformation> fieldTransformations) {
        this.fieldTransformations = fieldTransformations;
    }

    protected void setFieldToTransformers(List<Object[]> fieldToTransformers) {
        this.fieldToTransformers = fieldToTransformers;
    }

    /**
     * ADVANCED:
     * Set the indirection policy.
     */
    public void setIndirectionPolicy(IndirectionPolicy indirectionPolicy) {
        this.indirectionPolicy = indirectionPolicy;
        indirectionPolicy.setMapping(this);
    }

    /**
     * INTERNAL:
     * Will be used by Gromit. For details see usesIndirection().
     * @see #useBasicIndirection()
     * @see #dontUseIndirection()
     */
    public void setUsesIndirection(boolean usesIndirection) {
        if (usesIndirection) {
            useBasicIndirection();
        } else {
            dontUseIndirection();
        }
    }

    /**
     * INTERNAL:
     * Either create a new change record or update the change record with the new value.
     * This is used by attribute change tracking.
     */
    @Override
    public void updateChangeRecord(Object clone, Object newValue, Object oldValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) {
        TransformationMappingChangeRecord changeRecord = (TransformationMappingChangeRecord)objectChangeSet.getChangesForAttributeNamed(this.getAttributeName());
        Object updatedObject = descriptor.getInstantiationPolicy().buildNewInstance();
        this.setAttributeValueInObject(updatedObject, newValue);
        if (!isWriteOnly()) {
            if (changeRecord == null) {
                objectChangeSet.addChange(internalBuildChangeRecord(updatedObject, oldValue, objectChangeSet, uow));
            } else {
                changeRecord.setRow(this.buildPhantomRowFrom(updatedObject, uow));
            }
        }
    }

    /**
     * INTERNAL:
     * Return if this mapping supports change tracking.
     */
    @Override
    public boolean isChangeTrackingSupported(Project project) {
        return ! isMutable();
    }

    /**
     * INTERNAL:
     * Return whether the specified object is instantiated.
     */
    @Override
    public boolean isAttributeValueFromObjectInstantiated(Object object) {
        return this.indirectionPolicy.objectIsInstantiated(object);
    }

    /**
     * PUBLIC:
     * Indirection means that a ValueHolder will be put in-between the attribute and the real object.
     * This defaults to false and only required for transformations that perform database access.
     */
    public void useBasicIndirection() {
        setIndirectionPolicy(new BasicIndirectionPolicy());
    }

    /**
     * PUBLIC:
     * Indirection means that a IndirectContainer (wrapping a ValueHolder) will be put in-between
     * the attribute and the real object.
     * This allows for the reading of the target from the database to be delayed until accessed.
     * This defaults to true and is strongly suggested as it give a huge performance gain.
     */
    public void useContainerIndirection(Class containerClass) {
        ContainerIndirectionPolicy policy = new ContainerIndirectionPolicy();
        policy.setContainerClass(containerClass);
        setIndirectionPolicy(policy);
    }

    /**
     * PUBLIC:
     * Indirection means that a ValueHolder will be put in-between the attribute and the real object.
     * This defaults to false and only required for transformations that perform database access.
     * @see #useBasicIndirection()
     */
    public void useIndirection() {
        useBasicIndirection();
    }

    /**
     * PUBLIC:
     * Indirection means that a ValueHolder will be put in-between the attribute and the real object.
     * This defaults to false and only required for transformations that perform database access.
     * @see org.eclipse.persistence.internal.indirection.IndirectionPolicy
     */
    public boolean usesIndirection() {
        return this.indirectionPolicy.usesIndirection();
    }

    /**
     * INTERNAL:
     * Validate mapping declaration
     */
    @Override
    public void validateBeforeInitialization(AbstractSession session) throws DescriptorException {
        super.validateBeforeInitialization(session);

        if (isWriteOnly()) {
            return;
        }

        if ((this.attributeTransformer == null) && (this.attributeTransformerClassName == null)) {
            session.getIntegrityChecker().handleError(DescriptorException.noAttributeTransformationMethod(this));
        }

        if (getAttributeAccessor() instanceof InstanceVariableAttributeAccessor) {
            Class attributeType = ((InstanceVariableAttributeAccessor)getAttributeAccessor()).getAttributeType();
            this.indirectionPolicy.validateDeclaredAttributeType(attributeType, session.getIntegrityChecker());
        } else if (getAttributeAccessor().isMethodAttributeAccessor()) {
            // 323403
            Class returnType = ((MethodAttributeAccessor)getAttributeAccessor()).getGetMethodReturnType();
            this.indirectionPolicy.validateGetMethodReturnType(returnType, session.getIntegrityChecker());

            Class parameterType = ((MethodAttributeAccessor)getAttributeAccessor()).getSetMethodParameterType();
            this.indirectionPolicy.validateSetMethodParameterType(parameterType, session.getIntegrityChecker());
        }
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     */
    @Override
    public Object valueFromObject(Object object, DatabaseField field, AbstractSession session) {
        return invokeFieldTransformer(field, object, session);
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     */
    @Override
    public void writeFromObjectIntoRow(Object object, AbstractRecord row, AbstractSession session, WriteType writeType) {
        if (isReadOnly()) {
            return;
        }

        for (Object[] pair : this.fieldToTransformers) {
            DatabaseField field = (DatabaseField)pair[0];
            FieldTransformer transformer = (FieldTransformer)pair[1];
            Object fieldValue = invokeFieldTransformer(field, transformer, object, session);
            row.put(field, fieldValue);
        }
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     */
    @Override
    public void writeFromObjectIntoRowWithChangeRecord(ChangeRecord changeRecord, AbstractRecord row, AbstractSession session, WriteType writeType) {
        if (isReadOnly()) {
            return;
        }

        for (Object[] pair : this.fieldToTransformers) {
            DatabaseField field = (DatabaseField)pair[0];
            Object fieldValue = ((TransformationMappingChangeRecord)changeRecord).getRecord().get(field);
            row.put(field, fieldValue);
        }
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     * But before that check if the reference object is instantiated or not.
     */
    @Override
    public void writeFromObjectIntoRowForUpdate(WriteObjectQuery query, AbstractRecord record) {
        if (!areObjectsToBeProcessedInstantiated(query.getObject())) {
            return;
        }

        if (query.getSession().isUnitOfWork()) {
            if (compareObjects(query.getBackupClone(), query.getObject(), query.getSession())) {
                return;
            }
        }

        writeFromObjectIntoRow(query.getObject(), record, query.getSession(), WriteType.UPDATE);
    }

    /**
     * INTERNAL:
     * Write fields needed for insert into the template for with null values.
     */
    @Override
    public void writeInsertFieldsIntoRow(AbstractRecord record, AbstractSession session) {
        if (isReadOnly()) {
            return;
        }

        for (Object[] pair : this.fieldToTransformers) {
            DatabaseField field = (DatabaseField)pair[0];
            record.put(field, null);
        }
    }
}
