All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.internal.indirection.IndirectionPolicy Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.internal.indirection;

import java.io.Serializable;
import java.util.Map;

import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.IntegrityChecker;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.descriptors.DescriptorIterator;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.MergeManager;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.internal.sessions.remote.RemoteValueHolder;
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.foundation.AbstractTransformationMapping;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.sessions.remote.DistributedSession;

/**
 * 

Purpose

: * An IndirectionPolicy acts as a 'rules' holder that determines * the behavior of a ForeignReferenceMapping (or TransformationMapping) * with respect to indirection, or lack thereof. *

*

Description

: * IndirectionPolicy is an abstract class that defines the protocol to be implemented by * subclasses so that the assorted DatabaseMappings can use an assortment of * indirection policies:
    *
  • no indirection policy (read everything from database) *
  • basic indirection policy (use ValueHolders) *
  • transparent indirection policy (collections only) *
  • proxy indirection policy (transparent 1:1 indirection using JDK 1.3's Proxy) *
* *

*

Responsibilities

: *
    *
  • instantiate the various IndirectionPolicies *
*

* * @see ForeignReferenceMapping * @author Mike Norman * @since TOPLink/Java 2.5 */ public abstract class IndirectionPolicy implements Cloneable, Serializable { protected DatabaseMapping mapping; /** * INTERNAL: * Construct a new indirection policy. */ public IndirectionPolicy() { super(); } /** * INTERNAL: * Return a backup clone of the attribute. */ public Object backupCloneAttribute(Object attributeValue, Object clone, Object backup, UnitOfWorkImpl unitOfWork) { return this.mapping.buildBackupCloneForPartObject(attributeValue, clone, backup, unitOfWork); } /** * INTERNAL * Return true if the refresh should refresh on this mapping or not. */ protected ReadObjectQuery buildCascadeQuery(MergeManager mergeManager) { ReadObjectQuery query = new ReadObjectQuery(); if (this.mapping.getReferenceDescriptor() != null) { query.setReferenceClass(this.mapping.getReferenceDescriptor().getJavaClass()); } if (mergeManager.shouldCascadeAllParts()) { query.cascadeAllParts(); query.refreshIdentityMapResult(); } if (mergeManager.shouldCascadePrivateParts() && getForeignReferenceMapping().isPrivateOwned()) { query.cascadePrivateParts(); query.refreshIdentityMapResult(); } return query; } /** * INTERNAL: This method can be used when an Indirection Object is required * to be built from a provided ValueHolderInterface object. This may be used * for custom value holder types. Certain policies like the * TransparentIndirectionPolicy may wrap the valueholder in another object. */ public abstract Object buildIndirectObject(ValueHolderInterface valueHolder); /** * INTERNAL: * Clones itself. */ @Override public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } } /** * INTERNAL: * Return a clone of the attribute. * @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. */ public abstract Object cloneAttribute(Object attributeValue, Object original, CacheKey cacheKey, Object clone, Integer refreshCascade, AbstractSession cloningSession, boolean buildDirectlyFromRow); /** * INTERNAL: * Return the primary key for the reference object (i.e. the object * object referenced by domainObject and specified by mapping). * This key will be used by a RemoteValueHolder. */ public Object extractPrimaryKeyForReferenceObject(Object referenceObject, AbstractSession session) { return getOneToOneMapping().extractPrimaryKeysFromRealReferenceObject(referenceObject, session); } /** * INTERNAL: * Return the reference row for the reference object. * This allows the new row to be built without instantiating * the reference object. * Return null if the object has already been instantiated. */ public abstract AbstractRecord extractReferenceRow(Object referenceObject); /** * 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. */ public abstract void fixObjectReferences(Object object, Map objectDescriptors, Map processedObjects, ObjectLevelReadQuery query, DistributedSession session); /** * INTERNAL: * Reduce casting clutter.... */ protected CollectionMapping getCollectionMapping() { return (CollectionMapping)this.mapping; } /** * INTERNAL: * Reduce casting clutter.... */ protected ForeignReferenceMapping getForeignReferenceMapping() { return (ForeignReferenceMapping)this.mapping; } /** * INTERNAL: * Return the database mapping that uses the indirection policy. */ public DatabaseMapping getMapping() { return mapping; } /** * INTERNAL: * Reduce casting clutter.... */ protected ObjectReferenceMapping getOneToOneMapping() { return (ObjectReferenceMapping)this.mapping; } /** * INTERNAL: * Return the original indirection object for a unit of work indirection object. */ public abstract Object getOriginalIndirectionObject(Object unitOfWorkIndirectionObject, AbstractSession session); /** * INTERNAL: * Return the original indirection object for a unit of work indirection object. */ public Object getOriginalIndirectionObjectForMerge(Object unitOfWorkIndirectionObject, AbstractSession session){ return getOriginalIndirectionObject(unitOfWorkIndirectionObject, session); } /** * INTERNAL: Return the original valueHolder object. Access to the * underlying valueholder may be required when serializing the valueholder * or converting the valueHolder to another type. */ public abstract Object getOriginalValueHolder(Object unitOfWorkIndirectionObject, AbstractSession session); /** * INTERNAL: * Return the "real" attribute value, as opposed to any wrapper. * This will trigger the wrapper to instantiate the value. */ public abstract Object getRealAttributeValueFromObject(Object object, Object attribute); /** * INTERNAL: * Trigger the instantiation of the value. */ public void instantiateObject(Object object, Object attribute) { getRealAttributeValueFromObject(object, attribute); } /** * INTERNAL: * Reduce casting clutter.... */ protected AbstractTransformationMapping getTransformationMapping() { return (AbstractTransformationMapping)this.mapping; } /** * INTERNAL: * Extract and return the appropriate value from the * specified remote value holder. */ public abstract Object getValueFromRemoteValueHolder(RemoteValueHolder remoteValueHolder); /** * INTERNAL: * The method validateAttributeOfInstantiatedObject(Object attributeValue) fixes the value of the attributeValue * in cases where it is null and indirection requires that it contain some specific data structure. Return whether this will happen. * This method is used to help determine if indirection has been triggered * @param attributeValue * @return * @see validateAttributeOfInstantiatedObject(Object attributeValue) */ public boolean isAttributeValueFullyBuilt(Object attributeValue){ return true; } /** * INTERNAL: * Initialize the indirection policy (Do nothing by default) */ public void initialize() { } /** * INTERNAL: */ public boolean isWeavedObjectBasicIndirectionPolicy() { return false; } /** * INTERNAL: * Iterate over the specified attribute value, * heeding the settings in the iterator. */ public void iterateOnAttributeValue(DescriptorIterator iterator, Object attributeValue) { if (attributeValue != null) { this.mapping.iterateOnRealAttributeValue(iterator, attributeValue); } } /** * INTERNAL * Replace the client value holder with the server value holder, * after copying some of the settings from the client value holder. */ protected void mergeClientIntoServerValueHolder(RemoteValueHolder serverValueHolder, MergeManager mergeManager) { serverValueHolder.setMapping(this.mapping); serverValueHolder.setSession(mergeManager.getSession()); if (this.mapping.isForeignReferenceMapping()) { ObjectLevelReadQuery query = buildCascadeQuery(mergeManager); serverValueHolder.setQuery(query); } } /** * INTERNAL * Replace the client value holder with the server value holder, * after copying some of the settings from the client value holder. */ public abstract void mergeRemoteValueHolder(Object clientSideDomainObject, Object serverSideDomainObject, MergeManager mergeManager); /** * INTERNAL: * Return the null value of the appropriate attribute. That is, the * field from the database is NULL, return what should be * placed in the object's attribute as a result. */ public abstract Object nullValueFromRow(); /** * INTERNAL: * Return whether the specified object is instantiated. */ public abstract boolean objectIsInstantiated(Object object); /** * INTERNAL: * Return whether the specified object can be instantiated without database access. */ public abstract boolean objectIsEasilyInstantiated(Object object); /** * INTERNAL: * Return whether the specified object is instantiated, or if it has changes. */ public boolean objectIsInstantiatedOrChanged(Object object) { return objectIsInstantiated(object); } /** * INTERNAL: * set the database mapping that uses the indirection policy. */ public void setMapping(DatabaseMapping mapping) { this.mapping = mapping; } /** * INTERNAL: * Set the value of the appropriate attribute of target to attributeValue. * In this case, simply place the value inside the target. */ public void setRealAttributeValueInObject(Object target, Object attributeValue) { this.mapping.setAttributeValueInObject(target, attributeValue); } /** * INTERNAL: * Same functionality as setRealAttributeValueInObject(Object target, Object attributeValue) but allows * overridden behavior for IndirectionPolicies that track changes * @param target * @param attributeValue * @param allowChangeTracking */ public void setRealAttributeValueInObject(Object target, Object attributeValue, boolean allowChangeTracking) { setRealAttributeValueInObject(target, attributeValue); } /** * INTERNAL: * set the source object into QueryBasedValueHolder. * Used only by transparent indirection. */ public void setSourceObject(Object sourceObject, Object attributeValue) { } /** * ADVANCED: * This method will only change the behavior of TransparentIndirectionPolicy. * * IndirectList and IndirectSet can be configured not to instantiate the list from the * database when you add and remove from them. IndirectList defaults to this behavior. When * Set to true, the collection associated with this TransparentIndirection will be setup so as * not to instantiate for adds and removes. The weakness of this setting for an IndirectSet is * that when the set is not instantiated, if a duplicate element is added, it will not be * detected until commit time. * */ public void setUseLazyInstantiation(Boolean useLazyInstantiation) { } /** * ADVANCED: * Returns false unless this is a transparent indirection policy * * IndirectList and IndirectSet can be configured not to instantiate the list from the * database when you add and remove from them. IndirectList defaults to this behavior. When * Set to true, the collection associated with this TransparentIndirection will be setup so as * not to instantiate for adds and removes. The weakness of this setting for an IndirectSet is * that when the set is not instantiated, if a duplicate element is added, it will not be * detected until commit time. */ public Boolean shouldUseLazyInstantiation() { return false; } /** * Reset the wrapper used to store the value. * This is only required if a wrapper is used. */ public void reset(Object target) { // Nothing by default. } /** * INTERNAL: * Return whether the indirection policy actually uses indirection. * The default is true. */ public boolean usesIndirection() { return true; } /** * INTERNAL: * Return whether the indirection policy uses transparent indirection. * The default is false. */ public boolean usesTransparentIndirection(){ return false; } /** * INTERNAL: * Verify that the value of the attribute within an instantiated object * is of the appropriate type for the indirection policy. * If it is incorrect, throw an exception. * If the value is null return a new indirection object to be used for the attribute. */ public Object validateAttributeOfInstantiatedObject(Object attributeValue) throws DescriptorException { return attributeValue; } /** * INTERNAL: * Verify that the container policy is compatible with the * indirection policy. If it is incorrect, add an exception to the * integrity checker. */ public void validateContainerPolicy(IntegrityChecker checker) throws DescriptorException { // by default, do nothing } /** * INTERNAL: * Verify that attributeType is correct for the * indirection policy. If it is incorrect, add an exception to the * integrity checker. */ public void validateDeclaredAttributeType(Class attributeType, IntegrityChecker checker) throws DescriptorException { // by default, do nothing } /** * INTERNAL: * Verify that attributeType is an appropriate collection type for the * indirection policy. If it is incorrect, add an exception to the integrity checker. */ public void validateDeclaredAttributeTypeForCollection(Class attributeType, IntegrityChecker checker) throws DescriptorException { // by default, do nothing } /** * INTERNAL: * Verify that getter returnType is correct for the * indirection policy. If it is incorrect, add an exception * to the integrity checker. */ public void validateGetMethodReturnType(Class returnType, IntegrityChecker checker) throws DescriptorException { // by default, do nothing } /** * INTERNAL: * Verify that getter returnType is an appropriate collection type for the * indirection policy. If it is incorrect, add an exception to the integrity checker. */ public void validateGetMethodReturnTypeForCollection(Class returnType, IntegrityChecker checker) throws DescriptorException { // by default, do nothing } /** * INTERNAL: * Verify that setter parameterType is correct for the * indirection policy. If it is incorrect, add an exception * to the integrity checker. */ public void validateSetMethodParameterType(Class parameterType, IntegrityChecker checker) throws DescriptorException { // by default, do nothing } /** * INTERNAL: * Verify that setter parameterType is an appropriate collection type for the * indirection policy. If it is incorrect, add an exception to the integrity checker. */ public void validateSetMethodParameterTypeForCollection(Class parameterType, IntegrityChecker checker) throws DescriptorException { // by default, do nothing } /** * INTERNAL: * Return the value to be stored in the object's attribute. * This value is determined by the batchQuery. */ public abstract Object valueFromBatchQuery(ReadQuery batchQuery, AbstractRecord row, ObjectLevelReadQuery originalQuery, CacheKey parentCacheKey); /** * INTERNAL: * Return the value to be stored in the object's attribute. * This value is determined by invoking the appropriate * method on the object and passing it the row and session. */ public abstract Object valueFromMethod(Object object, AbstractRecord row, AbstractSession session); /** * INTERNAL: * Return the value to be stored in the object's attribute. * This value is determined by the query. */ public abstract Object valueFromQuery(ReadQuery query, AbstractRecord row, Object sourceObject, AbstractSession session); /** * INTERNAL: * Return the value to be stored in the object's attribute. * This value is determined by the query. */ public abstract Object valueFromQuery(ReadQuery query, AbstractRecord row, AbstractSession session); /** * INTERNAL: * Return the value to be stored in the object's attribute. * This value is determined by the row. */ public abstract Object valueFromRow(Object object); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy