KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > queryframework > DoesExistQuery


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, 2006, Oracle. All rights reserved.
22
package oracle.toplink.essentials.queryframework;
23
24 import java.util.*;
25 import oracle.toplink.essentials.descriptors.ClassDescriptor;
26 import oracle.toplink.essentials.exceptions.*;
27 import oracle.toplink.essentials.internal.helper.*;
28 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
29 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl;
30 import oracle.toplink.essentials.internal.sessions.AbstractSession;
31
32 /**
33  * <p><b>Purpose</b>:
34  * This should only be used by the descriptor, this should not be executed directly.
35  * Used to determine if an object resides on the database.
36  * DoesExistQuery is normally used to determine whether to make an update
37  * or insert statement when writing an object.
38  *
39  * <p><b>Responsibilities</b>:
40  * Verify the existence of an object. Used only by a write object query.
41  *
42  * @author Yvon Lavoie
43  * @since TOPLink/Java 1.0
44  */

45 public class DoesExistQuery extends DatabaseQuery {
46     public static final int AssumeNonExistence = 1;
47     public static final int AssumeExistence = 2;
48     public static final int CheckCache = 3;
49     public static final int CheckDatabase = 4;
50
51     /** Query that is performing the does exist check. */
52     protected Vector primaryKey;
53     protected Object JavaDoc object;
54
55     /** Flag to determine existence check policy. */
56     protected int existencePolicy;
57     
58     /** Flag to determine cache invalidation policy support. This overrides
59      * checkcache existence settings if the object is set to be invalid or if
60      * the cache cannot be trusted
61      * */

62     protected boolean checkDatabaseIfInvalid;//default to true, allows users to override
63
/** Flag to get checkearlyreturn to override assume(non)existence and database checks with a cache check */
64     public boolean checkCacheFirst;//default to false, set in uow to true
65

66     /**
67      * PUBLIC:
68      * Initialize the state of the query .
69      * By default the cache is checked, if non cache is used the descriptor should throw a exception and validate.
70      */

71     public DoesExistQuery() {
72         this.existencePolicy = CheckCache;
73         this.checkDatabaseIfInvalid = true;
74         this.checkCacheFirst = false;
75     }
76
77     /**
78      * PUBLIC:
79      * Create a query to check if the object exists.
80      */

81     public DoesExistQuery(Object JavaDoc object) {
82         this();
83         this.object = object;
84     }
85
86     /**
87      * PUBLIC:
88      * Create a query to check if the object exists.
89      */

90     public DoesExistQuery(Call call) {
91         this();
92         setCall(call);
93     }
94
95     /**
96      * PUBLIC:
97      * Assume that if the objects primary key does not include null then it must exist.
98      * This may be used if the user's system garentees that an object with non-null key exists.
99      */

100     public void assumeExistenceForDoesExist() {
101         setExistencePolicy(AssumeExistence);
102     }
103
104     /**
105      * PUBLIC:
106      * Assume that the object does not exist.
107      * This may be used if the user's system garentees objects must always be inserted.
108      */

109     public void assumeNonExistenceForDoesExist() {
110         setExistencePolicy(AssumeNonExistence);
111     }
112
113     /**
114      * PUBLIC:
115      * Assume that if the objects primary key does not include null
116      * and it is in the cache, then is must exist.
117      * This should only be used if a full identity map is being used,
118      * and a new object in the client cannot have been inserted by another client.
119      */

120     public void checkCacheForDoesExist() {
121         setExistencePolicy(CheckCache);
122     }
123
124     /**
125      * PUBLIC:
126      * Perform does exist check on the database through slecting the primary key.
127      */

128     public void checkDatabaseForDoesExist() {
129         setExistencePolicy(CheckDatabase);
130     }
131
132     /**
133      * INTERNAL:
134      * Check if existence can be determined without going to the database.
135      * Note that custom query check is not require for does exist as the custom is always used.
136      * Used by unit of work, and will return null if checkDatabaseIfInvalid is set and the cachekey is invalidated
137      */

138     public Object JavaDoc checkEarlyReturn(Object JavaDoc object, Vector primaryKey, AbstractSession session, AbstractRecord translationRow) {
139         // For bug 3136413/2610803 building the selection criteria from an EJBQL string or
140
// an example object is done just in time.
141
buildSelectionCriteria(session);
142         ClassDescriptor descriptor = session.getDescriptor(object.getClass());
143         // Return false on null since it can't exist. Little more done incase PK not set in the query
144
if (object == null){
145             return Boolean.FALSE;
146         }else if (primaryKey == null) {
147             primaryKey = this.getPrimaryKey();
148             if ( primaryKey == null ){
149                 primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, session);
150             }
151                 
152         }
153         if ((primaryKey == null)|| (primaryKey.contains(null)) ) {
154             return Boolean.FALSE;
155         }
156         
157         //need to do the cache check first if flag set or if we should check the cache only for existence
158
if (shouldCheckCacheForDoesExist() ||(checkCacheFirst)) {
159         
160             //if this is a UOW and modification queries have been executed, the cache cannot be trusted
161
if ( checkDatabaseIfInvalid && (session.isUnitOfWork() &&
162                     ((UnitOfWorkImpl)session).shouldReadFromDB() ) ){
163                 return null;
164             }
165                 
166             oracle.toplink.essentials.internal.identitymaps.CacheKey cacheKey;
167             Class JavaDoc objectClass = object.getClass();
168             if (session.isUnitOfWork()){
169                 cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey,objectClass, descriptor);
170                 if (cacheKey!=null){ //if in the UOW cache, it exists and can't be invalid
171
return Boolean.TRUE;
172                 }
173                 cacheKey = ((UnitOfWorkImpl)session).getParent().getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey,objectClass, descriptor);
174             }else{
175                 cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey,objectClass, descriptor);
176             }
177                 
178             if ((cacheKey !=null)){
179                 //assume that if there is a cachekey, object exists
180
boolean invalid;
181                 if ( checkDatabaseIfInvalid ){
182                     long currentTimeInMillis = System.currentTimeMillis();
183                     invalid = session.getDescriptor(objectClass).getCacheInvalidationPolicy().isInvalidated(cacheKey, currentTimeInMillis);
184                 }else {
185                     invalid = false;
186                 }
187                 
188                 if (!invalid){
189                     Object JavaDoc objectFromCache = cacheKey.getObject();
190                     if ((session instanceof oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork)&&
191                             (((oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork)session).getUnregisteredDeletedCloneForOriginal(objectFromCache)!=null)){
192                   //session.isUnitOfWork() && objectFromCache!=null && ((UnitOfWorkImpl)session).isObjectDeleted(objectFromCache)){
193
if(shouldCheckCacheForDoesExist()){
194                             return Boolean.FALSE;
195                         }
196                     }else {
197                         return Boolean.TRUE;
198                     }
199                     
200                 }else {
201                     //We know it is invalid, and checkDatabaseIfInvalid policy so skip to the database
202
return null;
203                 }
204             }else if(shouldCheckCacheForDoesExist()){
205                 //We know its not in cache, and a checkcache policy so return false
206
return Boolean.FALSE;
207             }
208         }
209         // Check if we have to assume that the object does not exist.
210
if (shouldAssumeNonExistenceForDoesExist()) {
211             return Boolean.FALSE;
212         }
213
214         // Check to see if we only need to check that the object contains a primary key.
215
if (shouldAssumeExistenceForDoesExist()) {
216             return Boolean.TRUE;
217         }
218
219         return null;
220     }
221
222     /**
223      * INTERNAL:
224      * Check if existence can be determined without going to the database.
225      * Note that custom query check is not require for does exist as the custom is always used.
226      */

227     public Object JavaDoc checkEarlyReturn(AbstractSession session, AbstractRecord translationRow) {
228         return checkEarlyReturn(getObject(), getPrimaryKey(), session, translationRow);
229     }
230
231     /**
232      * INTERNAL:
233      * Return if the object exists on the database.
234      * This must be a Boolean object to conform with returning an object.
235      * If using optimistic locking, check that the value matches.
236      * @exception DatabaseException - an error has occurred on the database.
237      */

238     public Object JavaDoc executeDatabaseQuery() throws DatabaseException {
239         // Get the required fields for does exist check.
240
DatabaseField field = getDoesExistField();
241
242         // Get row from database
243
AbstractRecord databaseRow = getQueryMechanism().selectRowForDoesExist(field);
244
245         // Null means no row was returned.
246
return new Boolean JavaDoc(databaseRow != null);
247     }
248
249     /**
250      * INTERNAL:
251      * Return the write lock field or the first primary key field if not using locking.
252      */

253     protected DatabaseField getDoesExistField() {
254         return (DatabaseField)(getDescriptor().getPrimaryKeyFields().get(0));
255     }
256
257     /**
258      * INTERNAL:
259      * Return the existence policy for this existence Query
260      */

261     public int getExistencePolicy() {
262         return this.existencePolicy;
263     }
264
265     /**
266      * PUBLIC:
267      * Return the object.
268      */

269     public Object JavaDoc getObject() {
270         return object;
271     }
272
273     /**
274      * INTERNAL:
275      * Return the primaryKey.
276      */

277     public Vector getPrimaryKey() {
278         return primaryKey;
279     }
280
281     /**
282      * Return the domain class associated with this query.
283      */

284     public Class JavaDoc getReferenceClass() {
285         return getObject().getClass();
286     }
287
288     /**
289      * INTERNAL:
290      * Return the name of the reference class for this query
291      * Note: Although the API is designed to avoid requirement of classes being on the classpath,
292      * this is not a user defined query type, so it is ok to access the class.
293      */

294     public String JavaDoc getReferenceClassName() {
295         return getReferenceClass().getName();
296     }
297
298     /**
299      * INTERNAL:
300      * Prepare the receiver for execution in a session.
301      */

302     protected void prepare() throws QueryException {
303         if (getDescriptor() == null) {
304             //Bug#3947714 Pass the object instead of class in case object is proxy
305
setDescriptor(getSession().getDescriptor(getObject()));
306         }
307
308         if (getObject() != null) {// Prepare can be called without the object set yet.
309
setObject(getDescriptor().getObjectBuilder().unwrapObject(getObject(), getSession()));
310         }
311
312         super.prepare();
313
314         // It will only get to prepare if check database if required.
315
getQueryMechanism().prepareDoesExist(getDoesExistField());
316     }
317
318     /**
319      * INTERNAL:
320      * Prepare the receiver for execution in a session.
321      */

322     public void prepareForExecution() throws QueryException {
323         super.prepareForExecution();
324
325         if (getObject() == null) {
326             throw QueryException.objectToModifyNotSpecified(this);
327         }
328         setObject(getDescriptor().getObjectBuilder().unwrapObject(getObject(), getSession()));
329
330         if (getDescriptor() == null) {
331             setDescriptor(getSession().getDescriptor(getObject().getClass()));
332         }
333
334         if (getPrimaryKey() == null) {
335             setPrimaryKey(getDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(getObject(), getSession()));
336         }
337
338         if ((getTranslationRow() == null) || (getTranslationRow().isEmpty())) {
339             setTranslationRow(getDescriptor().getObjectBuilder().buildRowForTranslation(getObject(), getSession()));
340         }
341     }
342
343     /**
344      * INTERNAL:
345      * Set if the existence policy, this must be set to one of the constants.
346      */

347     public void setExistencePolicy(int existencePolicy) {
348         this.existencePolicy = existencePolicy;
349     }
350
351     /**
352      * PUBLIC:
353      * Set the object.
354      */

355     public void setObject(Object JavaDoc object) {
356         this.object = object;
357     }
358
359     /**
360      * INTERNAL:
361      * Set the primaryKey.
362      */

363     public void setPrimaryKey(Vector primaryKey) {
364         this.primaryKey = primaryKey;
365     }
366
367     /**
368      * PUBLIC:
369      * Returns true if the does exist check should be based only
370      * on whether the primary key of the object is set
371      */

372     public boolean shouldAssumeExistenceForDoesExist() {
373         return existencePolicy == AssumeExistence;
374     }
375
376     /**
377      * PUBLIC:
378      * Returns true if the does exist check should assume non existence.
379      */

380     public boolean shouldAssumeNonExistenceForDoesExist() {
381         return existencePolicy == AssumeNonExistence;
382     }
383
384     /**
385      * PUBLIC:
386      * Returns true if the does exist check should be based only
387      * on a cache check. Default behavior.
388      */

389     public boolean shouldCheckCacheForDoesExist() {
390         return existencePolicy == CheckCache;
391     }
392
393     /**
394      * PUBLIC:
395      * Returns true if the does exist check should query the database.
396      */

397     public boolean shouldCheckDatabaseForDoesExist() {
398         return existencePolicy == CheckDatabase;
399     }
400     
401     /**
402      * INTERNAL:
403      * Sets checkCacheFirst flag. If true, existence check will first go to the
404      * cache. It will then check other options if it is not found in the cache
405      * @param checkCacheFirst
406      */

407     public void setCheckCacheFirst(boolean checkCacheFirst){
408         this.checkCacheFirst = checkCacheFirst;
409     }
410     /**
411      * INTERNAL:
412      * @param checkCacheFirst
413      */

414     public boolean getCheckCacheFirst(){
415         return this.checkCacheFirst;
416     }
417     
418     /**
419      * INTERNAL:
420      * Sets checkDatabaseIfInvalid flag. If true, query will go to the
421      * database when it finds the object in the cache and it is invalid.
422      * This is only valid when it checks the cache, and is true by default
423      * @param checkDatabaseIfInvalid
424      */

425     public void setCheckDatabaseIfInvalid(boolean checkCacheFirst){
426         this.checkCacheFirst = checkCacheFirst;
427     }
428     /**
429      * INTERNAL:
430      * @param checkDatabaseIfInvalid
431      */

432     public boolean getCheckDatabaseIfInvalid(){
433         return this.checkCacheFirst;
434     }
435 }
436
Popular Tags