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

oracle.toplink.essentials.mappings.DatabaseMapping Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * // Copyright (c) 1998, 2007, Oracle. All rights reserved.
 * 
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package oracle.toplink.essentials.mappings;

import java.io.*;
import java.util.*;
import oracle.toplink.essentials.descriptors.ClassDescriptor;
import oracle.toplink.essentials.exceptions.*;
import oracle.toplink.essentials.expressions.*;
import oracle.toplink.essentials.indirection.*;
import oracle.toplink.essentials.internal.descriptors.*;
import oracle.toplink.essentials.internal.expressions.*;
import oracle.toplink.essentials.internal.helper.*;
import oracle.toplink.essentials.internal.indirection.*;
import oracle.toplink.essentials.internal.queryframework.*;
import oracle.toplink.essentials.internal.sessions.*;
import oracle.toplink.essentials.queryframework.*;
import oracle.toplink.essentials.sessions.ObjectCopyingPolicy;
import oracle.toplink.essentials.internal.sessions.AbstractRecord;
import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
import oracle.toplink.essentials.internal.sessions.AbstractSession;

/**
 * 

Purpose: Defines how an attribute of an object maps to and from the database * *

Responsibilities:

    *
  • Define type of relationship (1:1/1:M/M:M/etc.) *
  • Define instance variable name and fields names required *
  • Define any additional properties (ownership, indirection, read only, etc.) *
  • Control building the value for the instance variable from the database row *
  • Control building the database fields from the object *
  • Control any pre/post updating/inserting/deleting required to maintain the relationship *
  • Merges object changes for unit of work. *
  • Clones objects for unit of work. *
  • cache computed information to optimize performance *
* * @author Sati * @since TOPLink/Java 1.0 */ public abstract class DatabaseMapping implements Cloneable, Serializable { /** Used to reduce memory for mappings with no fields. */ protected static final Vector NO_FIELDS = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(0); /** Used to share integer instance to reduce memory. */ protected static final Integer NO_WEIGHT = new Integer(Integer.MAX_VALUE); protected static final Integer WEIGHT_1 = new Integer(1); /** Descriptor to which this mapping belongs to */ protected ClassDescriptor descriptor; /** Wrapper to store the reference objects. */ protected AttributeAccessor attributeAccessor; /** Makes this mapping read only. No write are performed on it. Default is false */ protected boolean isReadOnly; /** Specifies whether this mapping is optional (i.e. field may be null). Used for DDL generation. */ protected boolean isOptional; /** Fields associated with the mappings are cached */ protected Vector fields; /** It is needed only in remote initialization and mapping is in parent descriptor */ protected boolean isRemotelyInitialized; /** This is a TopLink defined attribute that allows us to sort the mappings */ protected Integer weight = NO_WEIGHT; /** used as a temporary store for custom SDK usage */ protected Map properties; /** used as a quick check to see if this mapping is a primary key mapping, * set by the object builder during initialization. */ protected boolean primaryKeyMapping = false; /** * PUBLIC: * Default constructor. */ public DatabaseMapping() { this.isOptional = true; this.isReadOnly = false; this.attributeAccessor = new InstanceVariableAttributeAccessor(); } /** * INTERNAL: * Clone the attribute from the clone and assign it to the backup. */ public abstract void buildBackupClone(Object clone, Object backup, UnitOfWorkImpl unitOfWork); /** * INTERNAL: * Require for cloning, the part must be cloned. */ public Object buildBackupCloneForPartObject(Object attributeValue, Object clone, Object backup, UnitOfWorkImpl unitOfWork) { throw DescriptorException.invalidMappingOperation(this, "buildBackupCloneForPartObject"); } /** * INTERNAL: * Clone the attribute from the original and assign it to the clone. */ public abstract void buildClone(Object original, Object clone, UnitOfWorkImpl unitOfWork); /** * INTERNAL: * A combination of readFromRowIntoObject and buildClone. *

* buildClone assumes the attribute value exists on the original and can * simply be copied. *

* readFromRowIntoObject assumes that one is building an original. *

* Both of the above assumptions are false in this method, and actually * attempts to do both at the same time. *

* 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. */ public abstract void buildCloneFromRow(AbstractRecord databaseRow, JoinedAttributeManager joinManager, Object clone, ObjectBuildingQuery sourceQuery, UnitOfWorkImpl unitOfWork, AbstractSession executionSession); /** * 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). */ public void buildShallowOriginalFromRow(AbstractRecord databaseRow, Object original, ObjectBuildingQuery query, AbstractSession executionSession) { return; } /** * INTERNAL: * Require for cloning, the part must be cloned. */ public Object buildCloneForPartObject(Object attributeValue, Object original, Object clone, UnitOfWorkImpl unitOfWork, boolean isExisting) { throw DescriptorException.invalidMappingOperation(this, "buildCloneForPartObject"); } /** * INTERNAL: * Copy of the attribute of the object. * This is NOT used for unit of work but for templatizing an object. */ public void buildCopy(Object copy, Object original, ObjectCopyingPolicy policy) { } /** * INTERNAL: * Used to allow object level comparisons. */ public Expression buildObjectJoinExpression(Expression base, Object value, AbstractSession session) { throw QueryException.unsupportedMappingForObjectComparison(this, base); } /** * INTERNAL: * Used to allow object level comparisons. */ public Expression buildObjectJoinExpression(Expression base, Expression argument, AbstractSession session) { throw QueryException.unsupportedMappingForObjectComparison(this, base); } /** * INTERNAL: * Cascade registerNew for Create through mappings that require the cascade */ abstract public void cascadePerformRemoveIfRequired(Object object, UnitOfWorkImpl uow, IdentityHashtable visitedObjects); /** * INTERNAL: * Cascade registerNew for Create through mappings that require the cascade */ abstract public void cascadeRegisterNewIfRequired(Object object, UnitOfWorkImpl uow, IdentityHashtable visitedObjects); /** * INTERNAL: * Used by AttributeLevelChangeTracking to update a changeRecord with calculated changes * as apposed to detected changes. If an attribute can not be change tracked it's * changes can be detected through this process. */ public void calculateDeferredChanges(ChangeRecord changeRecord, AbstractSession session){ throw DescriptorException.invalidMappingOperation(this, "calculatedDeferredChanges"); } /** * INTERNAL: * Cascade the merge to the component object, if appropriate. */ public void cascadeMerge(Object sourceElement, MergeManager mergeManager) { throw DescriptorException.invalidMappingOperation(this, "cascadeMerge"); } /** * INTERNAL: * Clones itself. */ public Object clone() { // Bug 3037701 - clone the AttributeAccessor DatabaseMapping mapping = null; try { mapping = (DatabaseMapping)super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(); } mapping.setAttributeAccessor((AttributeAccessor)attributeAccessor.clone()); return mapping; } /** * INTERNAL: * Helper method to clone vector of fields (used in aggregate initialization cloning). */ protected Vector cloneFields(Vector fields) { Vector clonedFields = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(); for (Enumeration fieldsEnum = fields.elements(); fieldsEnum.hasMoreElements();) { clonedFields.addElement(((DatabaseField)fieldsEnum.nextElement()).clone()); } return clonedFields; } /** * This method must be overwritten in the subclasses to return a vector of all the * fields this mapping represents. */ protected Vector collectFields() { return NO_FIELDS; } /** * INTERNAL: * This method was created in VisualAge. * @return prototype.changeset.ChangeRecord */ abstract public ChangeRecord compareForChange(Object clone, Object backup, ObjectChangeSet owner, AbstractSession session); /** * INTERNAL: * Compare the attributes belonging to this mapping for the objects. */ public abstract boolean compareObjects(Object firstObject, Object secondObject, AbstractSession session); /** * INTERNAL: * Convert all the class-name-based settings in this mapping to actual class-based * settings * This method is implemented by subclasses as necessary. * @param classLoader */ public void convertClassNamesToClasses(ClassLoader classLoader){}; /** * INTERNAL: * Builder the unit of work value holder. * @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 UnitOfWorkValueHolder createUnitOfWorkValueHolder(ValueHolderInterface attributeValue, Object original, Object clone, AbstractRecord row, UnitOfWorkImpl unitOfWork, boolean buildDirectlyFromRow) { throw DescriptorException.invalidMappingOperation(this, "createUnitOfWorkValueHolder"); } /** * INTERNAL: * Extract the nested attribute expressions that apply to this mapping. * This is used for partial objects and joining. * @param rootExpressionsAllowed true if newRoot itself can be one of the * expressions returned */ protected Vector extractNestedExpressions(List expressions, ExpressionBuilder newRoot, boolean rootExpressionsAllowed) { Vector nestedExpressions = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(expressions.size()); for (Iterator expressionsEnum = expressions.iterator(); expressionsEnum.hasNext();) { Expression next = (Expression)expressionsEnum.next(); // The expressionBuilder can be one of the locked expressions in // the ForUpdateOfClause. if (!next.isQueryKeyExpression()) { continue; } QueryKeyExpression expression = (QueryKeyExpression)next; QueryKeyExpression base = expression; boolean afterBase = false; while (!base.getBaseExpression().isExpressionBuilder()) { afterBase = true; base = (QueryKeyExpression)base.getBaseExpression(); } if (afterBase && base.getName().equals(getAttributeName())) { nestedExpressions.addElement(expression.rebuildOn(base, newRoot)); } else if (rootExpressionsAllowed && expression.getBaseExpression().isExpressionBuilder() && expression.getName().equals(getAttributeName())) { nestedExpressions.addElement(newRoot); } } return nestedExpressions; } /** * ADVANCED: * Return the attributeAccessor. * The attribute accessor is responsible for setting and retrieving the attribute value * from the object for this mapping. */ public AttributeAccessor getAttributeAccessor() { return attributeAccessor; } /** * PUBLIC: * The classification type for the attribute this mapping represents */ public Class getAttributeClassification() { return null; } /** * PUBLIC: * Return the name of the attribute set in the mapping. */ public String getAttributeName() { return getAttributeAccessor().getAttributeName(); } /** * INTERNAL: * Return the value of an attribute which this mapping represents for an object. */ public Object getAttributeValueFromObject(Object object) throws DescriptorException { try { return getAttributeAccessor().getAttributeValueFromObject(object); } catch (DescriptorException exception) { exception.setMapping(this); throw exception; } } /** * INTERNAL: * Return the mapping's containerPolicy. */ public ContainerPolicy getContainerPolicy() { throw DescriptorException.invalidMappingOperation(this, "getContainerPolicy"); } /** * INTERNAL: * Return the descriptor to which this mapping belongs */ public ClassDescriptor getDescriptor() { return descriptor; } /** * INTERNAL: * Return the field associated with this mapping if there is exactly one. * This is required for object relational mapping to print them, but because * they are defined in Enterprise they cannot be cast to. * Mappings that have a field include direct mappings and object relational mappings. */ public DatabaseField getField() { return null; } /** * INTERNAL: * Return the classifiction for the field contained in the mapping. * This is used to convert the row value to a consistent java value. * By default this is unknown. */ public Class getFieldClassification(DatabaseField fieldToClassify) { return null; } /** * INTERNAL: * Returns a vector of all the fields this mapping represents. */ public Vector getFields() { return this.fields; } /** * PUBLIC: * This method is invoked reflectively on the reference object to return the value of the * attribute in the object. This method returns the name of the getMethodName or null if not using method access. */ public String getGetMethodName() { if (!(getAttributeAccessor() instanceof MethodAttributeAccessor)) { return null; } return ((MethodAttributeAccessor)getAttributeAccessor()).getGetMethodName(); } /** * INTERNAL: * used as a temporary store for custom SDK usage */ public Map getProperties() { if (properties == null) {//Lazy initialize to conserve space and allocation time. properties = new HashMap(5); } return properties; } /** * INTERNAL: * used as a temporary store for custom SDK usage */ public Object getProperty(Object property) { if (properties == null) { return null; } return getProperties().get(property); } /** * INTERNAL: * Return the value of an attribute unwrapping value holders if required. */ public Object getRealAttributeValueFromObject(Object object, AbstractSession session) throws DescriptorException { return getAttributeValueFromObject(object); } /** * INTERNAL: * Return the value of an attribute, unwrapping value holders if necessary. * If the value is null, build a new container. */ public Object getRealCollectionAttributeValueFromObject(Object object, AbstractSession session) throws DescriptorException { throw DescriptorException.invalidMappingOperation(this, "getRealCollectionAttributeValueFromObject"); } /** * INTERNAL: * Return the referenceDescriptor. This is a descriptor which is associated with * the reference class. * Replaced by {@link #getReferenceClassDescriptor()} */ public ClassDescriptor getReferenceDescriptor() { return null; } /** * PUBLIC: * Return the referenceDescriptor. This is a descriptor which is associated with * the reference class. */ public ClassDescriptor getReferenceClassDescriptor() { ClassDescriptor desc = getReferenceDescriptor(); if (desc instanceof ClassDescriptor) { return (ClassDescriptor)desc; } else { throw ValidationException.cannotCastToClass(desc, desc.getClass(), ClassDescriptor.class); } } /** * INTERNAL: * Return the relationshipPartner mapping for this bi-directional mapping. If the relationshipPartner is null then * this is a uni-directional mapping. */ public DatabaseMapping getRelationshipPartner() { return null; } /** * PUBLIC: * This method is invoked reflectively on the reference object to set the value of the * attribute in the object. This method returns the name of the setMethodName or null if not using method access. */ public String getSetMethodName() { if (!(getAttributeAccessor() instanceof MethodAttributeAccessor)) { return null; } return ((MethodAttributeAccessor)getAttributeAccessor()).getSetMethodName(); } /** * INTERNAL: * Return the weight of the mapping, used to sort mappings to ensure that * DirectToField Mappings get merged first */ public Integer getWeight() { return this.weight; } /** * INTERNAL: * The returns if the mapping has any constraint dependencies, such as foreign keys and join tables. */ public boolean hasConstraintDependency() { return false; } /** * PUBLIC: * Return if method access is used. */ public boolean isUsingMethodAccess() { return getAttributeAccessor() instanceof MethodAttributeAccessor; } /** * INTERNAL: * Return if the mapping has any ownership or other dependency over its target object(s). */ public boolean hasDependency() { return isPrivateOwned(); } /** * INTERNAL: * The returns if the mapping has any inverse constraint dependencies, such as foreign keys and join tables. */ public boolean hasInverseConstraintDependency() { return false; } /** * INTERNAL: * Allow for initialization of properties and validation. */ public void initialize(AbstractSession session) throws DescriptorException { ; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isAggregateCollectionMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isAggregateMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isAggregateObjectMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isCollectionMapping() { return false; } /** * INTERNAL: */ public boolean isDatabaseMapping() { return true; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isDirectCollectionMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isDirectMapMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isDirectToFieldMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isForeignReferenceMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isManyToManyMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isNestedTableMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isObjectReferenceMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isObjectTypeMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isOneToManyMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isOneToOneMapping() { return false; } /** * INTERNAL: * Return whether the value of this mapping is optional (that is, can be * null). This is a hint and is used when generating DDL. It should be * disregarded for primitive types. */ public boolean isOptional() { return isOptional; } /** * INTERNAL: * All EIS mappings should implement this method to return true. */ public boolean isEISMapping() { return false; } /** * INTERNAL: * All relational mappings should implement this method to return true. */ public boolean isRelationalMapping() { return false; } /** * INTERNAL: * All relational mappings should implement this method to return true. */ public boolean isXMLMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isAbstractDirectMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isAbstractCompositeDirectCollectionMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isAbstractCompositeObjectMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isAbstractCompositeCollectionMapping() { return false; } /** * INTERNAL: * Return if this mapping support joining. */ public boolean isJoiningSupported() { return false; } /** * INTERNAL: * Return if this mapping requires its attribute value to be cloned. */ public boolean isCloningRequired() { return true; } /** * INTERNAL: * Set by the Object builder during initialization returns true if this mapping * is used as a primary key mapping. */ public boolean isPrimaryKeyMapping() { return this.primaryKeyMapping; } /** * INTERNAL: * Used when determining if a mapping supports cascaded version optimistic * locking. */ public boolean isCascadedLockingSupported() { return false; } /** * INTERNAL: * Return if this mapping supports change tracking. */ public boolean isChangeTrackingSupported() { return false; } /** * INTERNAL: * Return if the mapping has ownership over its target object(s). */ public boolean isPrivateOwned() { return false; } /** * INTERNAL: * Returns true if mapping is read only else false. */ public boolean isReadOnly() { return isReadOnly; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isReferenceMapping() { return false; } protected boolean isRemotelyInitialized() { return isRemotelyInitialized; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isSerializedObjectMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isStructureMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isTransformationMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isTypeConversionMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isVariableOneToOneMapping() { return false; } /** * INTERNAL: * Related mapping should implement this method to return true. */ public boolean isDirectToXMLTypeMapping() { return false; } /** * INTERNAL: * Some mappings support no attribute (transformation). */ public boolean isWriteOnly() { return false; } /** * INTERNAL: * Iterate on the appropriate attribute value. */ public abstract void iterate(DescriptorIterator iterator); /** * INTERNAL: * Iterate on the attribute value. * The value holder has already been processed. */ public void iterateOnRealAttributeValue(DescriptorIterator iterator, Object realAttributeValue) { throw DescriptorException.invalidMappingOperation(this, "iterateOnRealAttributeValue"); } /** * INTERNAL: * Merge changes from the source to the target object. */ public abstract void mergeChangesIntoObject(Object target, ChangeRecord changeRecord, Object source, MergeManager mergeManager); /** * INTERNAL: * Merge changes from the source to the target object. */ public abstract void mergeIntoObject(Object target, boolean isTargetUninitialized, Object source, MergeManager mergeManager); /** * INTERNAL: * Perform the commit event. * This is used in the uow to delay data modifications. */ public void performDataModificationEvent(Object[] event, AbstractSession session) throws DatabaseException, DescriptorException { throw DescriptorException.invalidDataModificationEvent(this); } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Recurse thru the parts to delete the reference objects after the actual object is deleted. */ public void postDelete(WriteObjectQuery query) throws DatabaseException { return; } /** * INTERNAL: * Allow for initialization of properties and validation that have dependecies no the descriptor * being initialized. */ public void postInitialize(AbstractSession session) throws DescriptorException { // Nothing by default. } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Recurse thru the parts to insert the reference objects after the actual object is inserted. */ public void postInsert(WriteObjectQuery query) throws DatabaseException { return; } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Recurse thru the parts to update the reference objects after the actual object is updated. */ public void postUpdate(WriteObjectQuery query) throws DatabaseException { return; } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Recurse thru the parts to delete the reference objects before the actual object is deleted. */ public void preDelete(WriteObjectQuery query) throws DatabaseException { return; } /** * INTERNAL: * Allow for initialization of properties and validation. */ public void preInitialize(AbstractSession session) throws DescriptorException { try { getAttributeAccessor().initializeAttributes(getDescriptor().getJavaClass()); } catch (DescriptorException exception) { exception.setMapping(this); session.getIntegrityChecker().handleError(exception); } } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Recurse thru the parts to insert the reference objects before the actual object is inserted. */ public void preInsert(WriteObjectQuery query) throws DatabaseException { return; } /** * INTERNAL: * A subclass that supports cascade version optimistic locking should * implement this method to properly prepare the locking policy for their * mapping type. */ public void prepareCascadeLockingPolicy() { return; } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Recurse thru the parts to update the reference objects before the actual object is updated. */ public void preUpdate(WriteObjectQuery query) throws DatabaseException { return; } /** * INTERNAL: * Extract value from the row and set the attribute to this value in the object. * return value as this value will have been converted to the appropriate type for * the object. */ public Object readFromRowIntoObject(AbstractRecord databaseRow, JoinedAttributeManager joinManager, Object targetObject, ObjectBuildingQuery sourceQuery) throws DatabaseException { // This version can be called directly for reading a sequence number // field, a write lock value, or a return row into an object, and hence // the query is just a placeholder. Getting the correct execution // session will generate an exception, so just pass in any session. // In general call this version only if no field conversion needed. return readFromRowIntoObject(databaseRow, joinManager, targetObject, sourceQuery, sourceQuery.getSession()); } /** * INTERNAL: * Extract value from the row and set the attribute to this value in the object. * return value as this value will have been converted to the appropriate type for * the object. */ public Object readFromRowIntoObject(AbstractRecord databaseRow, JoinedAttributeManager joinManager, Object targetObject, ObjectBuildingQuery sourceQuery, AbstractSession executionSession) throws DatabaseException { Object attributeValue = valueFromRow(databaseRow, joinManager, sourceQuery, executionSession); setAttributeValueInObject(targetObject, attributeValue); return attributeValue; } /** * PUBLIC: * To make mapping read only. * Read-only mappings can be used if two attributes map to the same field. * Read-only mappings cannot be used for the primary key or other required fields. */ public void readOnly() { setIsReadOnly(true); } /** * PUBLIC: * The mapping can be dynamically made either readOnly or readWriteOnly. This makes mapping go back to * default mode. */ public void readWrite() { setIsReadOnly(false); } /** * INTERNAL: * Rehash any hashtables based on fields. * This is used to clone descriptors for aggregates, which hammer field names, * it is probably better not to hammer the field name and this should be refactored. */ public void rehashFieldDependancies(AbstractSession session) { // Should be overwritten by any mapping with fields. } /** * ADVANCED: * Set the attributeAccessor. * The attribute accessor is responsible for setting and retrieving the attribute value * from the object for this mapping. * This can be set to an implementor of AttributeAccessor if the attribute * requires advanced conversion of the mapping value, or a real attribute does not exist. */ public void setAttributeAccessor(AttributeAccessor attributeAccessor) { String attributeName = getAttributeName(); this.attributeAccessor = attributeAccessor; if (attributeAccessor.getAttributeName() == null) { attributeAccessor.setAttributeName(attributeName); } } /** * PUBLIC: * Sets the name of the attribute in the mapping. */ public void setAttributeName(String attributeName) { getAttributeAccessor().setAttributeName(attributeName); } /** * INTERNAL: * Set the value of the attribute mapped by this mapping. */ public void setAttributeValueInObject(Object object, Object value) throws DescriptorException { // PERF: Direct variable access. try { this.attributeAccessor.setAttributeValueInObject(object, value); } catch (DescriptorException exception) { exception.setMapping(this); throw exception; } } /** * INTERNAL: * Set the value of the attribute mapped by this mapping, * placing it inside a value holder if necessary. */ public void setRealAttributeValueInObject(Object object, Object value) throws DescriptorException { try { this.setAttributeValueInObject(object, value); } catch (DescriptorException exception) { exception.setMapping(this); throw exception; } } /** * INTERNAL: * Set the descriptor to which this mapping belongs */ public void setDescriptor(ClassDescriptor descriptor) { this.descriptor = descriptor; } /** * INTERNAL: * Set the mapping's field collection. */ protected void setFields(Vector fields) { this.fields = fields; } /** * PUBLIC: * This method is invoked reflectively on the reference object to return the value of the * attribute in the object. This method sets the name of the getMethodName. */ public void setGetMethodName(String methodName) { if (methodName == null) { return; } // This is done because setting attribute name by defaults create InstanceVariableAttributeAccessor if (getAttributeAccessor() instanceof InstanceVariableAttributeAccessor) { String attributeName = this.attributeAccessor.getAttributeName(); setAttributeAccessor(new MethodAttributeAccessor()); getAttributeAccessor().setAttributeName(attributeName); } ((MethodAttributeAccessor)getAttributeAccessor()).setGetMethodName(methodName); } /** * INTERNAL: * Used to specify whether the value of this mapping may be null. It is * used when generating DDL. */ public void setIsOptional(boolean isOptional) { this.isOptional = isOptional; } /** * INTERNAL: * Set by the Object builder during initialization returns true if this mapping * is used as a primary key mapping. */ public void setIsPrimaryKeyMapping(boolean pkMapping) { this.primaryKeyMapping = pkMapping; } /** * PUBLIC: * Set this mapping to be read only. * Read-only mappings can be used if two attributes map to the same field. * Read-only mappings cannot be used for the primary key or other required fields. */ public void setIsReadOnly(boolean aBoolean) { isReadOnly = aBoolean; } /** * INTERNAL: * used as a temporary store for custom SDK usage */ public void setProperties(Map properties) { this.properties = properties; } /** * ADVANCED: * Allow user defined properties. */ public void setProperty(Object property, Object value) { getProperties().put(property, value); } /** * PUBLIC: * This method is invoked reflectively on the reference object to get the value of the attribute. * The method defined on the object should actually return the value that needs to be set in the * attribute accessor. */ public void setSetMethodName(String methodName) { if (methodName == null) { return; } // This is done because setting attribute name by defaults create InstanceVariableAttributeAccessor if (!(getAttributeAccessor() instanceof MethodAttributeAccessor)) { String attributeName = this.attributeAccessor.getAttributeName(); setAttributeAccessor(new MethodAttributeAccessor()); getAttributeAccessor().setAttributeName(attributeName); } ((MethodAttributeAccessor)getAttributeAccessor()).setSetMethodName(methodName); } /** * ADVANCED: * Set the weight of the mapping, used to sort mappings * DirectToField Mappings have a default weight of 1 while all other Mappings have a * default weight of MAXINT. Ordering of Mappings can be achieved by setting the weight of * a particular mapping to a value within the above mentioned limits. By ordering mappings * the user can control what order relationships are processed by TopLink. */ // CR 4097 public void setWeight(Integer newWeight) { this.weight = newWeight; } /** * ADVANCED: * This method is used to add an object to a collection once the changeSet is applied. * The referenceKey parameter should only be used for direct Maps. */ public void simpleAddToCollectionChangeRecord(Object referenceKey, Object changeSetToAdd, ObjectChangeSet changeSet, AbstractSession session) throws DescriptorException { throw DescriptorException.invalidMappingOperation(this, "simpleAddToCollectionChangeRecord"); } /** * ADVANCED: * This method is used to remove an object from a collection once the changeSet is applied. * The referenceKey parameter should only be used for direct Maps. */ public void simpleRemoveFromCollectionChangeRecord(Object referenceKey, Object changeSetToAdd, ObjectChangeSet changeSet, AbstractSession session) throws DescriptorException { throw DescriptorException.invalidMappingOperation(this, "simpleRemoveFromCollectionChangeRecord"); } /** * INTERNAL: * Print the mapping attribute name, this is used in error messages. */ public String toString() { return getClass().getName() + "[" + getAttributeName() + "]"; } /** * INTERNAL: * Allow for subclasses to perform validation. */ public void validateAfterInitialization(AbstractSession session) throws DescriptorException { } /** * INTERNAL: * Allow for subclasses to perform validation. */ public void validateBeforeInitialization(AbstractSession session) throws DescriptorException { } /** * INTERNAL: * A subclass should extract the value from the object for the field, if it does not map the field then * it should return null. * Return the Value from the object. */ public Object valueFromObject(Object anObject, DatabaseField field, AbstractSession session) { return null; } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Returns the value for the mapping from the database row. */ public Object valueFromRow(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery query) throws DatabaseException { return valueFromRow(row, joinManager, query, query.getSession().getExecutionSession(query)); } /** * INTERNAL: * */ public Object valueFromRow(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery query, AbstractSession session) throws DatabaseException { return null; } /** * INTERNAL: * To verify if the specified object has been deleted or not. */ public boolean verifyDelete(Object object, AbstractSession session) throws DatabaseException { return true; } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Write the foreign key values from the attribute to the row. */ public void writeFromAttributeIntoRow(Object attribute, AbstractRecord row, AbstractSession session) { // Do nothing by default. } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Write the attribute value from the object to the row. */ public void writeFromObjectIntoRow(Object object, AbstractRecord row, AbstractSession session) { // Do nothing by default. } /** * INTERNAL: * This row is built for shallow insert which happens in case of of circular dependencies bidirectional inserts. */ public void writeFromObjectIntoRowForShallowInsert(Object object, AbstractRecord row, AbstractSession session) { writeFromObjectIntoRow(object, row, session); } /** * INTERNAL: * This row is built for shallow delete which happens in case of circular dependencies for bidirectional deletes. */ public void writeFromObjectIntoRowForShallowDelete(Object object, AbstractRecord row, AbstractSession session) { // Do nothing by default. } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Write the attribute value from the object to the row. */ public void writeFromObjectIntoRowWithChangeRecord(ChangeRecord changeRecord, AbstractRecord row, AbstractSession session) { // Do nothing by default. } /** * INTERNAL: * This row is built for shallow insert which happens in case of bidirectional inserts. */ public void writeFromObjectIntoRowForShallowInsertWithChangeRecord(ChangeRecord changeRecord, AbstractRecord row, AbstractSession session) { writeFromObjectIntoRowWithChangeRecord(changeRecord, row, session); } /** * INTERNAL: * Write the attribute value from the object to the row for update. */ public void writeFromObjectIntoRowForUpdate(WriteObjectQuery query, AbstractRecord row) { writeFromObjectIntoRow(query.getObject(), row, query.getSession()); } /** * INTERNAL: * A subclass should implement this method if it wants different behaviour. * Write the attribute value from the object to the row. */ public void writeFromObjectIntoRowForWhereClause(ObjectLevelModifyQuery query, AbstractRecord row) { Object object; if (query.isDeleteObjectQuery()) { object = query.getObject(); } else { object = query.getBackupClone(); } writeFromObjectIntoRow(object, row, query.getSession()); } /** * INTERNAL: * Write fields needed for insert into the template for with null values. */ public void writeInsertFieldsIntoRow(AbstractRecord databaseRow, AbstractSession session) { // Do nothing by default. } /** * INTERNAL: * Write fields needed for update into the template for with null values. * By default inserted fields are used. */ public void writeUpdateFieldsIntoRow(AbstractRecord databaseRow, AbstractSession session) { writeInsertFieldsIntoRow(databaseRow, session); } /** * INTERNAL: * Either create a new change record or update the change record with the new value. * This is used by attribute change tracking. */ public void updateChangeRecord(Object clone, Object newValue, Object oldValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) throws DescriptorException { throw DescriptorException.invalidMappingOperation(this, "updateChangeRecord"); } /** * INTERNAL: * Add a new value and its change set to the collection change record. This is used by * attribute change tracking. */ public void addToCollectionChangeRecord(Object newKey, Object newValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) throws DescriptorException { throw DescriptorException.invalidMappingOperation(this, "addToCollectionChangeRecord"); } /** * INTERNAL: * Remove a value and its change set from the collection change record. This is used by * attribute change tracking. */ public void removeFromCollectionChangeRecord(Object newKey, Object newValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) throws DescriptorException { throw DescriptorException.invalidMappingOperation(this, "removeFromCollectionChangeRecord"); } /** * INTERNAL: * Directly build a change record without comparison */ public ChangeRecord buildChangeRecord(Object newValue, ObjectChangeSet owner, AbstractSession session) throws DescriptorException { throw DescriptorException.invalidMappingOperation(this, "buildChangeRecord"); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy