KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > indirection > BasicIndirectionPolicy


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2005, Oracle. All rights reserved.
22
package oracle.toplink.essentials.internal.indirection;
23
24 import java.util.*;
25 import oracle.toplink.essentials.queryframework.*;
26 import oracle.toplink.essentials.indirection.*;
27 import oracle.toplink.essentials.exceptions.*;
28 import oracle.toplink.essentials.internal.descriptors.*;
29 import oracle.toplink.essentials.internal.helper.*;
30 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
31 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
32 import oracle.toplink.essentials.internal.sessions.AbstractSession;
33
34 /**
35  * <h2>Purpose</h2>:
36  * BasicIndirectionPolicy implements the behavior necessary for a
37  * a ForeignReferenceMapping (or TransformationMapping) to
38  * use ValueHolders to delay the reading of objects from the database
39  * until they are actually needed.
40  *
41  * @see ForeignReferenceMapping
42  * @author Mike Norman
43  * @since TOPLink/Java 2.5
44  */

45 public class BasicIndirectionPolicy extends IndirectionPolicy {
46
47     /**
48      * INTERNAL:
49      * Construct a new indirection policy.
50      */

51     public BasicIndirectionPolicy() {
52         super();
53     }
54
55     /**
56      * INTERNAL:
57      * Return a backup clone of the attribute.
58      */

59     public Object JavaDoc backupCloneAttribute(Object JavaDoc attributeValue, Object JavaDoc clone, Object JavaDoc backup, UnitOfWorkImpl unitOfWork) {
60         //no need to check if the attribute is a valueholder because closeAttribute
61
// should always be called first
62
ValueHolderInterface valueHolder = (ValueHolderInterface)attributeValue;// cast the value
63
ValueHolder result = new ValueHolder();
64
65         // delay instantiation until absolutely necessary
66
if ((!(valueHolder instanceof UnitOfWorkValueHolder)) || valueHolder.isInstantiated()) {
67             result.setValue(super.backupCloneAttribute(valueHolder.getValue(), clone, backup, unitOfWork));
68         } else {
69             ((UnitOfWorkValueHolder)valueHolder).setBackupValueHolder(result);
70         }
71
72         return result;
73     }
74
75     /**
76      * INTERNAL:
77      * Return a clone of the attribute.
78      * @param buildDirectlyFromRow indicates that we are building the clone
79      * directly from a row as opposed to building the original from the
80      * row, putting it in the shared cache, and then cloning the original.
81      */

82     public Object JavaDoc cloneAttribute(Object JavaDoc attributeValue, Object JavaDoc original, Object JavaDoc clone, UnitOfWorkImpl unitOfWork, boolean buildDirectlyFromRow) {
83         ValueHolderInterface valueHolder = (ValueHolderInterface) attributeValue;
84         ValueHolderInterface result;
85         
86         if (!buildDirectlyFromRow && unitOfWork.isOriginalNewObject(original)) {
87             // CR#3156435 Throw a meaningful exception if a serialized/dead value holder is detected.
88
// This can occur if an existing serialized object is attempt to be registered as new.
89
if ((valueHolder instanceof DatabaseValueHolder)
90                     && (! ((DatabaseValueHolder) valueHolder).isInstantiated())
91                     && (((DatabaseValueHolder) valueHolder).getSession() == null)
92                     && (! ((DatabaseValueHolder) valueHolder).isSerializedRemoteUnitOfWorkValueHolder())) {
93                 throw DescriptorException.attemptToRegisterDeadIndirection(original, getMapping());
94             }
95             if (this.getMapping().getRelationshipPartner() == null) {
96                 result = new ValueHolder();
97                 result.setValue(this.getMapping().buildCloneForPartObject(valueHolder.getValue(), original, clone, unitOfWork, false));
98             } else {
99                 //if I have a relationsip partner trigger the indiretion so that the value will be inserted
100
// because of this call the entire tree should be recursively cloned
101
AbstractRecord row = null;
102                 if (valueHolder instanceof DatabaseValueHolder) {
103                     row = ((DatabaseValueHolder)valueHolder).getRow();
104                 }
105                 result = this.getMapping().createUnitOfWorkValueHolder(valueHolder, original, clone, row, unitOfWork, buildDirectlyFromRow);
106
107                 Object JavaDoc newObject = this.getMapping().buildCloneForPartObject(valueHolder.getValue(), original, clone, unitOfWork, false);
108                 ((UnitOfWorkValueHolder)result).privilegedSetValue(newObject);
109                 ((UnitOfWorkValueHolder)result).setInstantiated();
110             }
111         } else {
112             AbstractRecord row = null;
113             if (valueHolder instanceof DatabaseValueHolder) {
114                 row = ((DatabaseValueHolder)valueHolder).getRow();
115             }
116             result = this.getMapping().createUnitOfWorkValueHolder(valueHolder, original, clone, row, unitOfWork, buildDirectlyFromRow);
117         }
118         return result;
119     }
120
121     /**
122      * INTERNAL:
123      * Return the primary key for the reference object (i.e. the object
124      * object referenced by domainObject and specified by mapping).
125      * This key will be used by a RemoteValueHolder.
126      */

127     public Vector extractPrimaryKeyForReferenceObject(Object JavaDoc referenceObject, AbstractSession session) {
128         if (this.objectIsInstantiated(referenceObject)) {
129             return super.extractPrimaryKeyForReferenceObject(((ValueHolderInterface)referenceObject).getValue(), session);
130         } else {
131             return this.getOneToOneMapping().extractPrimaryKeysForReferenceObjectFromRow(this.extractReferenceRow(referenceObject));
132         }
133     }
134
135     /**
136      * INTERNAL:
137      * Return the reference row for the reference object.
138      * This allows the new row to be built without instantiating
139      * the reference object.
140      * Return null if the object has already been instantiated.
141      */

142     public AbstractRecord extractReferenceRow(Object JavaDoc referenceObject) {
143         if (this.objectIsInstantiated(referenceObject)) {
144             return null;
145         } else {
146             return ((DatabaseValueHolder)referenceObject).getRow();
147         }
148     }
149
150     /**
151      * INTERNAL:
152      * Return the original indirection object for a unit of work indirection object.
153      * This is used when building a new object from the unit of work when the original fell out of the cache.
154      */

155     public Object JavaDoc getOriginalIndirectionObject(Object JavaDoc unitOfWorkIndirectionObject, AbstractSession session) {
156         if (unitOfWorkIndirectionObject instanceof UnitOfWorkValueHolder) {
157             ValueHolderInterface valueHolder = ((UnitOfWorkValueHolder)unitOfWorkIndirectionObject).getWrappedValueHolder();
158             if ((valueHolder != null) && (valueHolder instanceof DatabaseValueHolder)) {
159                 ((DatabaseValueHolder)valueHolder).releaseWrappedValueHolder();
160             }
161             return valueHolder;
162         } else {
163             return unitOfWorkIndirectionObject;
164         }
165     }
166
167     /**
168      * INTERNAL:
169      * Return the "real" attribute value, as opposed to any wrapper.
170      * This will trigger the wrapper to instantiate the value.
171      */

172     public Object JavaDoc getRealAttributeValueFromObject(Object JavaDoc object) {
173         // Changed for CR 4245. Use a static reference instead of .class
174
if (ClassConstants.ValueHolderInterface_Class.isAssignableFrom(object.getClass())) {
175             return ((ValueHolderInterface)object).getValue();
176         } else {
177             return object;
178         }
179     }
180
181     /**
182      * INTERNAL:
183      * Iterate over the specified attribute value,
184      */

185     public void iterateOnAttributeValue(DescriptorIterator iterator, Object JavaDoc attributeValue) {
186         iterator.iterateValueHolderForMapping((ValueHolderInterface)attributeValue, this.getMapping());
187     }
188
189     /**
190      * INTERNAL:
191      * Return the null value of the appropriate attribute. That is, the
192      * field from the database is NULL, return what should be
193      * placed in the object's attribute as a result.
194      * In this case, return an empty ValueHolder.
195      */

196     public Object JavaDoc nullValueFromRow() {
197         return new ValueHolder();
198     }
199
200     /**
201      * INTERNAL:
202      * Return whether the specified object is instantiated.
203      */

204     public boolean objectIsInstantiated(Object JavaDoc object) {
205         return ((ValueHolderInterface)object).isInstantiated();
206     }
207
208     /**
209      * INTERNAL:
210      * Set the value of the appropriate attribute of target to attributeValue.
211      * In this case, place the value inside the target's ValueHolder.
212      */

213     public void setRealAttributeValueInObject(Object JavaDoc target, Object JavaDoc attributeValue) {
214         ValueHolderInterface holder = (ValueHolderInterface)this.getMapping().getAttributeValueFromObject(target);
215         if (holder == null) {
216             holder = new ValueHolder(attributeValue);
217         } else {
218             holder.setValue(attributeValue);
219         }
220         super.setRealAttributeValueInObject(target, holder);
221     }
222
223     /**
224      * INTERNAL:
225      * Return whether the type is appropriate for the indirection policy.
226      * In this case, the attribute type MUST be ValueHolderInterface.
227      */

228     protected boolean typeIsValid(Class JavaDoc attributeType) {
229         return attributeType == ClassConstants.ValueHolderInterface_Class;
230     }
231
232     /**
233      * INTERNAL:
234      * Verify that the value of the attribute within an instantiated object
235      * is of the appropriate type for the indirection policy.
236      * In this case, the attribute must be non-null and it must be a
237      * ValueHolderInterface.
238      * If the value is null return a new indirection object to be used for the attribute.
239      */

240     public Object JavaDoc validateAttributeOfInstantiatedObject(Object JavaDoc attributeValue) {
241         // PERF: If the value is null, create a new value holder instance for the attribute value,
242
// this allows for indirection attributes to not be instantiated in the constructor as they
243
// are typically replaced when reading or cloning so is very inefficent to initialize.
244
if (attributeValue == null) {
245             return new ValueHolder();
246         }
247         if (!(attributeValue instanceof ValueHolderInterface)) {
248             throw DescriptorException.valueHolderInstantiationMismatch(attributeValue, this.getMapping());
249         }
250         return attributeValue;
251     }
252
253     /**
254      * INTERNAL:
255      * Verify that attributeType is correct for the
256      * indirection policy. If it is incorrect, add an exception to the
257      * integrity checker.
258      * In this case, the attribute type MUST be ValueHolderInterface.
259      */

260     public void validateDeclaredAttributeType(Class JavaDoc attributeType, IntegrityChecker checker) throws DescriptorException {
261         super.validateDeclaredAttributeType(attributeType, checker);
262         if (!this.typeIsValid(attributeType)) {
263             checker.handleError(DescriptorException.attributeAndMappingWithIndirectionMismatch(this.getMapping()));
264         }
265     }
266
267     /**
268      * INTERNAL:
269      * Verify that getter returnType is correct for the
270      * indirection policy. If it is incorrect, add an exception
271      * to the integrity checker.
272      * In this case, the return type MUST be ValueHolderInterface.
273      */

274     public void validateGetMethodReturnType(Class JavaDoc returnType, IntegrityChecker checker) throws DescriptorException {
275         super.validateGetMethodReturnType(returnType, checker);
276         if (!this.typeIsValid(returnType)) {
277             checker.handleError(DescriptorException.returnAndMappingWithIndirectionMismatch(this.getMapping()));
278         }
279     }
280
281     /**
282      * INTERNAL:
283      * Verify that setter parameterType is correct for the
284      * indirection policy. If it is incorrect, add an exception
285      * to the integrity checker.
286      * In this case, the parameter type MUST be ValueHolderInterface.
287      */

288     public void validateSetMethodParameterType(Class JavaDoc parameterType, IntegrityChecker checker) throws DescriptorException {
289         super.validateSetMethodParameterType(parameterType, checker);
290         if (!this.typeIsValid(parameterType)) {
291             checker.handleError(DescriptorException.parameterAndMappingWithIndirectionMismatch(this.getMapping()));
292         }
293     }
294
295     /**
296      * INTERNAL:
297      * Return the value to be stored in the object's attribute.
298      * This value is determined by the query.
299      * In this case, wrap the query in a ValueHolder for later invocation.
300      */

301     public Object JavaDoc valueFromQuery(ReadQuery query, AbstractRecord row, AbstractSession session) {
302         return new QueryBasedValueHolder(query, row, session);
303     }
304
305     /**
306      * INTERNAL:
307      * Return the value to be stored in the object's attribute.
308      * This value is determined by the row.
309      * In this case, simply wrap the object in a ValueHolder.
310      */

311     public Object JavaDoc valueFromRow(Object JavaDoc object) {
312         return new ValueHolder(object);
313     }
314 }
315
Popular Tags