KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > expressions > ObjectExpression


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.internal.expressions;
23
24 import java.util.*;
25 import oracle.toplink.essentials.exceptions.*;
26 import oracle.toplink.essentials.querykeys.*;
27 import oracle.toplink.essentials.expressions.*;
28 import oracle.toplink.essentials.internal.helper.*;
29 import oracle.toplink.essentials.descriptors.ClassDescriptor;
30
31 /**
32  * Superclass for any object type expressions.
33  */

34 public abstract class ObjectExpression extends DataExpression {
35     transient public ClassDescriptor descriptor;
36     public Vector derivedExpressions;
37
38     /** indicates whether subclasses should be joined */
39     protected boolean shouldUseOuterJoinForMultitableInheritance;
40
41     /** Is this query key to be resolved using an outer join or not. Does not apply to attributes. */
42     protected boolean shouldUseOuterJoin;
43
44     public ObjectExpression() {
45         this.shouldUseOuterJoin = false;
46     }
47
48     public void addDerivedExpression(Expression addThis) {
49         if (derivedExpressions == null) {
50             derivedExpressions = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance();
51         }
52         derivedExpressions.addElement(addThis);
53     }
54
55     /**
56      * INTERNAL:
57      * Return the expression to join the main table of this node to any auxiliary tables.
58      */

59     public Expression additionalExpressionCriteria() {
60         if (getDescriptor() == null) {
61             return null;
62         }
63
64         Expression criteria = getDescriptor().getQueryManager().getAdditionalJoinExpression();
65         if(getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) {
66             if(isUsingOuterJoinForMultitableInheritance()) {
67                 Expression childrenCriteria = getDescriptor().getInheritancePolicy().getChildrenJoinExpression();
68                 childrenCriteria = getBaseExpression().twist(childrenCriteria, this);
69                 childrenCriteria.convertToUseOuterJoin();
70                 if(criteria == null) {
71                     criteria = childrenCriteria;
72                 } else {
73                     criteria = criteria.and(childrenCriteria);
74                 }
75             }
76         }
77
78         return criteria;
79     }
80
81     /**
82      * INTERNAL:
83      * Used in case outer joins should be printed in FROM clause.
84      * Each of the additional tables mapped to expressions that joins it.
85      */

86     public Map additionalExpressionCriteriaMap() {
87         if (getDescriptor() == null) {
88             return null;
89         }
90
91         HashMap tablesJoinExpressions = null;
92         if(isUsingOuterJoinForMultitableInheritance()) {
93             Vector tables = getDescriptor().getTables();
94             tablesJoinExpressions = new HashMap();
95             List childrenTables = getDescriptor().getInheritancePolicy().getChildrenTables();
96             for( int i=0; i < childrenTables.size(); i++) {
97                 DatabaseTable table = (DatabaseTable)childrenTables.get(i);
98                 Expression joinExpression = (Expression)getDescriptor().getInheritancePolicy().getChildrenTablesJoinExpressions().get(table);
99                 if (getBaseExpression() != null){
100                     joinExpression = getBaseExpression().twist(joinExpression, this);
101                 } else {
102                     joinExpression = twist(joinExpression, this);
103                 }
104                 tablesJoinExpressions.put(table, joinExpression);
105             }
106         }
107         
108         return tablesJoinExpressions;
109     }
110
111     /**
112      * PUBLIC:
113      * Return an expression representing traversal of a 1:many or many:many relationship.
114      * This allows you to query whether any of the "many" side of the relationship satisfies the remaining criteria.
115      * <p>Example:
116      * <pre><blockquote>
117      * TopLink: employee.anyOf("managedEmployees").get("firstName").equal("Bob")
118      * Java: no direct equivalent
119      * SQL: SELECT DISTINCT ... WHERE (t2.MGR_ID = t1.ID) AND (t2.F_NAME = 'Bob')
120      * </pre></blockquote>
121      */

122     public Expression anyOf(String JavaDoc attributeName) {
123         QueryKeyExpression queryKey = (QueryKeyExpression)newDerivedExpressionNamed(attributeName);
124
125         queryKey.doQueryToManyRelationship();
126         return queryKey;
127
128     }
129
130     public QueryKeyExpression derivedExpressionNamed(String JavaDoc attributeName) {
131         QueryKeyExpression existing = existingDerivedExpressionNamed(attributeName);
132         if (existing != null) {
133             return existing;
134         }
135         return newDerivedExpressionNamed(attributeName);
136
137     }
138
139     public Expression derivedManualExpressionNamed(String JavaDoc attributeName, ClassDescriptor aDescriptor) {
140         Expression existing = existingDerivedExpressionNamed(attributeName);
141         if (existing != null) {
142             return existing;
143         }
144         return newManualDerivedExpressionNamed(attributeName, aDescriptor);
145
146     }
147
148     protected void doNotUseOuterJoin() {
149         shouldUseOuterJoin = false;
150     }
151
152     protected void doUseOuterJoin() {
153         shouldUseOuterJoin = true;
154     }
155
156     public QueryKeyExpression existingDerivedExpressionNamed(String JavaDoc attributeName) {
157         if (derivedExpressions == null) {
158             return null;
159         }
160         for (Enumeration e = derivedExpressions.elements(); e.hasMoreElements();) {
161             QueryKeyExpression exp = (QueryKeyExpression)e.nextElement();
162             if (exp.getName().equals(attributeName)) {
163                 return exp;
164             }
165         }
166         return null;
167
168     }
169
170     public Expression get(String JavaDoc attributeName, Vector arguments) {
171         Expression operatorExpression = super.get(attributeName, arguments);
172         if (operatorExpression != null) {
173             return operatorExpression;
174         }
175
176         QueryKeyExpression result = derivedExpressionNamed(attributeName);
177         result.doNotUseOuterJoin();
178         return result;
179
180     }
181
182     public Expression getAllowingNull(String JavaDoc attributeName, Vector arguments) {
183         ObjectExpression exp = (ObjectExpression)existingDerivedExpressionNamed(attributeName);
184
185         // The same (aliased) table cannot participate in a normal join and an outer join.
186
// To help enforce this, if the node already exists
187
if (exp != null) {
188             return exp;
189         }
190         exp = (ObjectExpression)derivedExpressionNamed(attributeName);
191         exp.doUseOuterJoin();
192         return exp;
193
194     }
195
196     public ClassDescriptor getDescriptor() {
197         if (isAttribute()) {
198             return null;
199         }
200         if (descriptor == null) {
201             // Look first for query keys, then mappings. Ultimately we should have query keys
202
// for everything and can dispense with the mapping part.
203
ForeignReferenceQueryKey queryKey = (ForeignReferenceQueryKey)getQueryKeyOrNull();
204             if (queryKey != null) {
205                 descriptor = getSession().getDescriptor(queryKey.getReferenceClass());
206                 return descriptor;
207             }
208             if (getMapping() == null) {
209                 throw QueryException.invalidQueryKeyInExpression(this);
210             }
211
212             // We assume this is either a foreign reference or an aggregate mapping
213
descriptor = getMapping().getReferenceDescriptor();
214             if (getMapping().isVariableOneToOneMapping()) {
215                 throw QueryException.cannotQueryAcrossAVariableOneToOneMapping(getMapping(), descriptor);
216             }
217         }
218         return descriptor;
219
220     }
221
222     /**
223      * INTERNAL: Not to be confused with the public getField(String)
224      * This returns a collection of all fields associated with this object. Really
225      * only applies to query keys representing an object or to expression builders.
226      */

227     public Vector getFields() {
228         if (getDescriptor() == null) {
229             return new Vector(1);
230         }
231         if ((descriptor.hasInheritance() && ! descriptor.getInheritancePolicy().hasMultipleTableChild()) || (shouldUseOuterJoinForMultitableInheritance())){
232             // return all fields because we can.
233
return descriptor.getAllFields();
234         }else{
235             return descriptor.getFields();
236         }
237     }
238
239     /**
240      * INTERNAL:
241      * Returns the first field from each of the owned tables, used for
242      * fine-grained pessimistic locking.
243      */

244     protected Vector getForUpdateOfFields() {
245         Vector allFields = getFields();
246         int expected = getTableAliases().size();
247         Vector firstFields = new Vector(expected);
248         DatabaseTable lastTable = null;
249         DatabaseField field = null;
250         int i = 0;
251
252         // The following loop takes O(n*m) time. n=# of fields. m=#tables.
253
// However, in the m=1 case this will take one pass only.
254
// Also assuming that fields are generally sorted by table, this will
255
// take O(n) time.
256
// An even faster way may be to go getDescriptor().getAdditionalPrimaryKeyFields.
257
while ((i < allFields.size()) && (firstFields.size() < expected)) {
258             field = (DatabaseField)allFields.elementAt(i++);
259             if ((lastTable == null) || !field.getTable().equals(lastTable)) {
260                 lastTable = field.getTable();
261                 int j = 0;
262                 while (j < firstFields.size()) {
263                     if (lastTable.equals(((DatabaseField)firstFields.elementAt(j)).getTable())) {
264                         break;
265                     }
266                     j++;
267                 }
268                 if (j == firstFields.size()) {
269                     firstFields.addElement(field);
270                 }
271             }
272         }
273         return firstFields;
274     }
275
276     public Expression getManualQueryKey(String JavaDoc attributeName, ClassDescriptor aDescriptor) {
277         return derivedManualExpressionNamed(attributeName, aDescriptor);
278     }
279
280     /**
281      * INTERNAL:
282      */

283     public Vector getOwnedTables() {
284         if(isUsingOuterJoinForMultitableInheritance()) {
285             return getDescriptor().getInheritancePolicy().getAllTables();
286         } else {
287             return super.getOwnedTables();
288         }
289     }
290
291     protected boolean hasDerivedExpressions() {
292         return derivedExpressions != null;
293     }
294
295     public boolean isObjectExpression() {
296         return true;
297     }
298
299     /**
300      * INTERNAL:
301      * indicates whether additional expressions for multitable inheritance should be used and are available
302      */

303     public boolean isUsingOuterJoinForMultitableInheritance() {
304         return shouldUseOuterJoinForMultitableInheritance() &&
305                 getDescriptor() != null && getDescriptor().hasInheritance() &&
306                 getDescriptor().getInheritancePolicy().hasMultipleTableChild() &&
307                 getDescriptor().getInheritancePolicy().shouldReadSubclasses();
308     }
309     
310     public QueryKeyExpression newDerivedExpressionNamed(String JavaDoc attributeName) {
311         QueryKeyExpression result = new QueryKeyExpression(attributeName, this);
312         addDerivedExpression(result);
313         return result;
314
315     }
316
317     public Expression newManualDerivedExpressionNamed(String JavaDoc attributeName, ClassDescriptor aDescriptor) {
318         QueryKeyExpression result = new ManualQueryKeyExpression(attributeName, this, aDescriptor);
319         addDerivedExpression(result);
320         return result;
321
322     }
323
324     /**
325      * INTERNAL:
326      * Used for cloning.
327      */

328     protected void postCopyIn(Dictionary alreadyDone) {
329         super.postCopyIn(alreadyDone);
330         derivedExpressions = copyCollection(derivedExpressions, alreadyDone);
331     }
332
333     /**
334      * INTERNAL:
335      * The method was added to circumvent derivedFields and derivedTables being
336      * protected.
337      * @see oracle.toplink.essentials.expressions.ExpressionBuilder#registerIn(Dictionary alreadyDone)
338      * @bug 2637484 INVALID QUERY KEY EXCEPTION THROWN USING BATCH READS AND PARALLEL EXPRESSIONS
339      */

340     public void postCopyIn(Dictionary alreadyDone, Vector oldDerivedFields, Vector oldDerivedTables) {
341         if (oldDerivedFields != null) {
342             if (derivedFields == null) {
343                 derivedFields = copyCollection(oldDerivedFields, alreadyDone);
344             } else {
345                 derivedFields.addAll(copyCollection(oldDerivedFields, alreadyDone));
346             }
347         }
348         if (oldDerivedTables != null) {
349             if (derivedTables == null) {
350                 derivedTables = copyCollection(oldDerivedTables, alreadyDone);
351             } else {
352                 derivedTables.addAll(copyCollection(oldDerivedTables, alreadyDone));
353             }
354         }
355     }
356
357     /**
358      * INTERNAL:
359      * set the flag indicating whether subclasses should be joined
360      */

361     public void setShouldUseOuterJoinForMultitableInheritance(boolean shouldUseOuterJoinForMultitableInheritance) {
362         this.shouldUseOuterJoinForMultitableInheritance = shouldUseOuterJoinForMultitableInheritance;
363     }
364
365     public boolean shouldUseOuterJoin() {
366         return shouldUseOuterJoin;
367     }
368
369     public boolean shouldUseOuterJoinForMultitableInheritance() {
370         return shouldUseOuterJoinForMultitableInheritance;
371     }
372     
373     /**
374      * INTERNAL:
375      * writes the first field from each of the owned tables, used for
376      * fine-grained pessimistic locking.
377      */

378     protected void writeForUpdateOfFields(ExpressionSQLPrinter printer, SQLSelectStatement statement) {
379         for (Enumeration fieldsEnum = getForUpdateOfFields().elements();
380                  fieldsEnum.hasMoreElements();) {
381             DatabaseField field = (DatabaseField)fieldsEnum.nextElement();
382             writeField(printer, field, statement);
383         }
384     }
385 }
386
Popular Tags