KickJava   Java API By Example, From Geeks To Geeks.

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


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
22 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
23
package oracle.toplink.essentials.internal.expressions;
24
25 import java.io.*;
26 import java.util.*;
27 import oracle.toplink.essentials.exceptions.*;
28 import oracle.toplink.essentials.expressions.*;
29 import oracle.toplink.essentials.internal.databaseaccess.*;
30 import oracle.toplink.essentials.internal.helper.*;
31 import oracle.toplink.essentials.queryframework.*;
32 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
33 import oracle.toplink.essentials.internal.sessions.AbstractSession;
34
35 /**
36  * Used for expressions that have 0 to n children.
37  * These include not, between and all functions.
38  */

39 public class FunctionExpression extends Expression {
40     protected Expression baseExpression;
41     protected Vector children;
42     protected ExpressionOperator operator;
43     protected transient ExpressionOperator platformOperator;
44     protected Class JavaDoc resultType;
45
46     public FunctionExpression() {
47         this.children = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(2);
48         this.resultType = null;
49     }
50
51     public void addChild(Expression child) {
52         getChildren().addElement(child);
53     }
54
55     /**
56      * INTERNAL:
57      * Find the alias for a given table
58      */

59     public DatabaseTable aliasForTable(DatabaseTable table) {
60         return getBaseExpression().aliasForTable(table);
61     }
62
63     /**
64      * INTERNAL:
65      */

66     public Expression create(Expression base, Object JavaDoc singleArgument, ExpressionOperator operator) {
67         baseExpression = base;
68         addChild(base);
69         Expression arg = Expression.from(singleArgument, base);
70         addChild(arg);
71         setOperator(operator);
72         return this;
73     }
74     
75     /**
76      * INTERNAL:
77      * added for Trim support. TRIM([trim_character FROM] string_primary)
78      */

79     public Expression createWithBaseLast(Expression base, Object JavaDoc singleArgument, ExpressionOperator anOperator) {
80         baseExpression = base;
81         Expression arg = Expression.from(singleArgument, base);
82         addChild(arg);
83         addChild(base);
84         setOperator(anOperator);
85         return this;
86     }
87
88     /**
89      * INTERNAL:
90      */

91     public Expression create(Expression base, Vector arguments, ExpressionOperator operator) {
92         baseExpression = base;
93         addChild(base);
94         for (Enumeration e = arguments.elements(); e.hasMoreElements();) {
95             Expression arg = Expression.from(e.nextElement(), base);
96             addChild(arg);
97         }
98         setOperator(operator);
99         return this;
100     }
101
102     /**
103      * INTERNAL:
104      * Used for debug printing.
105      */

106     public String JavaDoc descriptionOfNodeType() {
107         return "Function";
108     }
109
110     /**
111      * INTERNAL:
112      * Check if the object conforms to the expression in memory.
113      * This is used for in-memory querying.
114      * If the expression in not able to determine if the object conform throw a not supported exception.
115      */

116     public boolean doesConform(Object JavaDoc object, AbstractSession session, AbstractRecord translationRow, InMemoryQueryIndirectionPolicy valueHolderPolicy, boolean isObjectUnregistered) {
117         // Must check for NOT and negate entire base expression.
118
if (getOperator().getSelector() == ExpressionOperator.Not) {
119             return !getBaseExpression().doesConform(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);
120         }
121
122         // Conform between or in function.
123
if ((getOperator().getSelector() == ExpressionOperator.Between) || (getOperator().getSelector() == ExpressionOperator.NotBetween)
124                 ||(getOperator().getSelector() == ExpressionOperator.In) || (getOperator().getSelector() == ExpressionOperator.NotIn)) {
125             // Extract the value from the left side.
126
Object JavaDoc leftValue = getBaseExpression().valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);
127
128             // Extract the value from the arguments, skip the first child which is the base.
129
Vector rightValue = new Vector(getChildren().size());
130             for (int index = 1; index < getChildren().size(); index++) {
131                 Object JavaDoc valueFromRight;
132                 if (getChildren().elementAt(index) instanceof Expression) {
133                     valueFromRight = ((Expression)getChildren().elementAt(index)).valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);
134                 } else {
135                     valueFromRight = getChildren().elementAt(index);
136                 }
137                 //If valueFromRight is a Vector, then there is only one child other than the base, e.g. valueFromRight is a collection of constants.
138
//Then it should be the vector to be compared with. Don't add it to another collection.
139
if (valueFromRight instanceof Vector) {
140                     rightValue = (Vector)valueFromRight;
141                 //Single values should be added to the rightValue, which will be compared with leftValue.
142
} else {
143                     rightValue.addElement(valueFromRight);
144                 }
145
146             }
147
148             // If left is anyof collection of values, check each one.
149
// If the right had an anyof not supported will be thrown from the operator.
150
if (leftValue instanceof Vector) {
151                 for (Enumeration leftEnum = (Enumeration)((Vector)leftValue).elements();
152                          leftEnum.hasMoreElements();) {
153                     Object JavaDoc tempLeft = leftEnum.nextElement();
154                     if (getOperator().doesRelationConform(tempLeft, rightValue)) {
155                         return true;
156                     }
157                 }
158
159                 // Only return false if none of the values match.
160
return false;
161             } else {
162                 return getOperator().doesRelationConform(leftValue, rightValue);
163             }
164         } else if ((getOperator().getSelector() == ExpressionOperator.IsNull) || (getOperator().getSelector() == ExpressionOperator.NotNull)) {
165             // Extract the value from the left side.
166
Object JavaDoc leftValue = getBaseExpression().valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);
167
168             // If left is anyof collection of values, check each one.
169
if (leftValue instanceof Vector) {
170                 for (Enumeration leftEnum = (Enumeration)((Vector)leftValue).elements();
171                          leftEnum.hasMoreElements();) {
172                     Object JavaDoc tempLeft = leftEnum.nextElement();
173                     if (getOperator().doesRelationConform(tempLeft, null)) {
174                         return true;
175                     }
176                 }
177
178                 // Only return false if none of the values match.
179
return false;
180             } else {
181                 return getOperator().doesRelationConform(leftValue, null);
182             }
183         }
184
185         // No other relation functions are supported.
186
// Non-relation functions are supported through valueFromObject().
187
throw QueryException.cannotConformExpression();
188     }
189
190     public Expression getBaseExpression() {
191         return baseExpression;
192     }
193
194     /**
195      * Return the expression builder which is the ultimate base of this expression, or
196      * null if there isn't one (shouldn't happen if we start from a root)
197      */

198     public ExpressionBuilder getBuilder() {
199         if (getBaseExpression() == null) {
200             return null;
201         }
202         return getBaseExpression().getBuilder();
203     }
204
205     public Vector getChildren() {
206         return children;
207     }
208
209     /**
210      * INTERNAL: Not to be confused with the public getField(String)
211      * This returns a collection of all fields associated with this object. Really
212      * only applies to query keys representing an object or to expression builders.
213      *
214      */

215     public Vector getFields() {
216         return getBaseExpression().getFields();
217     }
218
219     public ExpressionOperator getOperator() {
220         return operator;
221     }
222
223     public ExpressionOperator getPlatformOperator(DatabasePlatform platform) {
224         if (platformOperator == null) {
225             initializePlatformOperator(platform);
226         }
227         return platformOperator;
228     }
229     
230     public Class JavaDoc getResultType() {
231         return resultType;
232     }
233
234     public boolean hasResultType() {
235         return resultType != null;
236     }
237     
238     /**
239      * INTERNAL:
240      */

241     public void initializePlatformOperator(DatabasePlatform platform) {
242         if (getOperator().isComplete()) {
243             platformOperator = getOperator();
244             return;
245         }
246         platformOperator = platform.getOperator(getOperator().getSelector());
247         if (platformOperator == null) {
248             throw QueryException.invalidOperator(getOperator().toString());
249         }
250     }
251
252     public boolean isFunctionExpression() {
253         return true;
254     }
255
256     /**
257      * INTERNAL:
258      * Return if the represents an object comparison.
259      */

260     protected boolean isObjectComparison() {
261         if (getChildren().size() != 1) {
262             return false;
263         }
264
265         int selector = getOperator().getSelector();
266         if ((selector != ExpressionOperator.IsNull) && (selector != ExpressionOperator.NotNull)) {
267             return false;
268         }
269
270         Expression base = getBaseExpression();
271         return (base.isObjectExpression() && (!((ObjectExpression)base).isAttribute()));
272     }
273
274     /**
275      * INTERNAL:
276      * For iterating using an inner class
277      */

278     public void iterateOn(ExpressionIterator iterator) {
279         super.iterateOn(iterator);
280         for (Enumeration childrenEnum = getChildren().elements(); childrenEnum.hasMoreElements();) {
281             Expression child = (Expression)childrenEnum.nextElement();
282             child.iterateOn(iterator);
283         }
284     }
285
286     /**
287      * INTERNAL:
288      * Normalize into a structure that is printable.
289      * Also compute printing information such as outer joins.
290      * This checks for object isNull and notNull comparisons.
291      */

292     public Expression normalize(ExpressionNormalizer normalizer) {
293         //This method has no validation but we should still make the method call for consistency
294
//bug # 2956674
295
//validation is moved into normalize to ensure that expressions are valid before we attempt to work with them
296
validateNode();
297         if (getChildren().isEmpty()) {
298             return this;
299         }
300
301         if (!isObjectComparison()) {
302             for (int index = 0; index < getChildren().size(); index++) {
303                 getChildren().setElementAt(((Expression)getChildren().elementAt(index)).normalize(normalizer), index);
304             }
305             return this;
306         } else {
307             //if not normalising we must still validate the corresponding node to make sure that they are valid
308
//bug # 2956674
309
for (int index = 0; index < getChildren().size(); index++) {
310                 ((Expression)getChildren().elementAt(index)).validateNode();
311             }
312         }
313
314         // This code is executed only in the case of an is[not]Null on an
315
// object attribute.
316
ObjectExpression base = (ObjectExpression)getBaseExpression();
317
318         // For cr2334, fix code so that normalize is first called on base expressions.
319
// I.e. if base itself had a base expression this expression would not be normalized.
320
base.getBaseExpression().normalize(normalizer);
321
322         // Switch to null foreign key comparison (i.e. get('c').isNull() to getField('C_ID').isNull()).
323
// For bug 3105559 also must handle aggregates: get("period").isNull();
324
Expression foreignKeyJoin = base.getMapping().buildObjectJoinExpression(base, (Object JavaDoc)null, getSession());
325
326         if (getOperator().getSelector() == ExpressionOperator.NotNull) {
327             foreignKeyJoin = foreignKeyJoin.not();
328         }
329         return foreignKeyJoin;
330     }
331
332     /**
333      * INTERNAL:
334      * Used for cloning.
335      */

336     protected void postCopyIn(Dictionary alreadyDone) {
337         super.postCopyIn(alreadyDone);
338
339         baseExpression = baseExpression.copiedVersionFrom(alreadyDone);
340         Vector oldChildren = children;
341         children = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance();
342         for (int i = 0; i < oldChildren.size(); i++) {
343             addChild((Expression)(((Expression)oldChildren.elementAt(i)).copiedVersionFrom(alreadyDone)));
344         }
345     }
346
347     /**
348      * INTERNAL:
349      * Print SQL
350      */

351     public void printSQL(ExpressionSQLPrinter printer) {
352         ExpressionOperator realOperator;
353         realOperator = getPlatformOperator(printer.getPlatform());
354         //In or NotIn operator only comes with " IN (" and ")" since the number of elements are unknown. Need to go through
355
//the collection to print out each element.
356
if (realOperator.getSelector() == ExpressionOperator.In || realOperator.getSelector() == ExpressionOperator.NotIn) {
357             printInCollection(getChildren(), printer, realOperator);
358         } else {
359             realOperator.printCollection(getChildren(), printer);
360         }
361     }
362
363     /**
364      * INTERNAL: Print the collection in "IN" onto the SQL stream. Go through the collection to print out each element.
365      */

366     public void printInCollection(Vector items, ExpressionSQLPrinter printer, ExpressionOperator operator) {
367         ((Expression)items.elementAt(0)).printSQL(printer);
368         printer.printString(operator.getDatabaseStrings()[0]);
369         
370         for (int i = 1; i < items.size() - 1; i++) {
371             Expression item = (Expression)items.elementAt(i);
372             item.printSQL(printer);
373             printer.printString(", ");
374         }
375         
376         ((Expression)items.elementAt(items.size() - 1)).printSQL(printer);
377         printer.printString(operator.getDatabaseStrings()[1]);
378     }
379
380     /**
381      * INTERNAL:
382      * Print java for project class generation
383      */

384     public void printJava(ExpressionJavaPrinter printer) {
385         ExpressionOperator realOperator = getPlatformOperator(printer.getPlatform());
386         realOperator.printJavaCollection(getChildren(), printer);
387     }
388
389     /**
390      * INTERNAL:
391      * This expression is built on a different base than the one we want. Rebuild it and
392      * return the root of the new tree
393      */

394     public Expression rebuildOn(Expression newBase) {
395         Expression newLocalBase = getBaseExpression().rebuildOn(newBase);
396         Vector newChildren = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(getChildren().size());
397         for (int i = 1; i < getChildren().size(); i++) {// Skip the first one, since it's also the base
398
newChildren.addElement(((Expression)children.elementAt(i)).rebuildOn(newBase));
399         }
400         newLocalBase.setSelectIfOrderedBy(getBaseExpression().selectIfOrderedBy());
401         FunctionExpression rebuilt = (FunctionExpression) newLocalBase.performOperator(getOperator(), newChildren);
402         rebuilt.setResultType(this.getResultType()); //copy over result type.
403
return rebuilt;
404     }
405
406     /**
407      * Sets the base of the expression
408      * Added to allow creation of functions which take the column name
409      * as something other than the first option.
410      * Creation date: (9/11/00 4:04:03 PM)
411      * @param expression oracle.toplink.essentials.expressions.Expression
412      */

413     public void setBaseExpression(Expression expression) {
414         baseExpression = expression;
415     }
416
417     // Set the local base expression, ie the one on the other side of the operator
418
// Most types will ignore this, since they don't need it.
419
public void setLocalBase(Expression exp) {
420         getBaseExpression().setLocalBase(exp);
421     }
422
423     public void setOperator(ExpressionOperator theOperator) {
424         operator = theOperator;
425     }
426     
427     public void setResultType(Class JavaDoc resultType) {
428         this.resultType = resultType;
429     }
430
431     /**
432      * INTERNAL:
433      * Rebuild myself against the base, with the values of parameters supplied by the context
434      * expression. This is used for transforming a standalone expression (e.g. the join criteria of a mapping)
435      * into part of some larger expression. You normally would not call this directly, instead calling twist
436      * See the comment there for more details"
437      */

438     public Expression twistedForBaseAndContext(Expression newBase, Expression context) {
439         if (getChildren().isEmpty()) {
440             return (Expression)clone();
441         }
442         Vector newChildren = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(getChildren().size());
443
444         // For functions the base is the first child, we only want the arguments so start at the second.
445
for (int index = 1; index < getChildren().size(); index++) {
446             newChildren.addElement(((Expression)children.elementAt(index)).twistedForBaseAndContext(newBase, context));
447         }
448
449         // Aply the function to the twisted old base.
450
Expression oldBase = (Expression)getChildren().elementAt(0);
451         return oldBase.twistedForBaseAndContext(newBase, context).performOperator(getOperator(), newChildren);
452     }
453
454     /**
455      * INTERNAL:
456      * Return the value for in memory comparison.
457      * This is only valid for valueable expressions.
458      */

459     public Object JavaDoc valueFromObject(Object JavaDoc object, AbstractSession session, AbstractRecord translationRow, InMemoryQueryIndirectionPolicy valueHolderPolicy, boolean isObjectUnregistered) {
460         Object JavaDoc baseValue = getBaseExpression().valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered);
461         Vector arguments = oracle.toplink.essentials.internal.helper.NonSynchronizedVector.newInstance(getChildren().size());
462         for (int index = 1; index < getChildren().size(); index++) {
463             if (getChildren().elementAt(index) instanceof Expression) {
464                 arguments.addElement(((Expression)getChildren().elementAt(index)).valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered));
465             } else {
466                 arguments.addElement(getChildren().elementAt(index));
467             }
468         }
469         if (baseValue instanceof Vector) {// baseValue might be a vector, so the individual values must be extracted before applying the function call to them
470
Vector baseVector = new Vector();
471             for (Enumeration valuesToCompare = (Enumeration)((Vector)baseValue).elements();
472                      valuesToCompare.hasMoreElements();) {
473                 Object JavaDoc baseObject = (Object JavaDoc)valuesToCompare.nextElement();
474                 if (baseObject == null) {
475                     baseVector.addElement(baseObject);
476                 } else {
477                     baseVector.addElement(getOperator().applyFunction(baseObject, arguments));
478                 }
479             }
480             return baseVector;
481         } else {
482             // Do not apply functions to null, just leave as null.
483
if (baseValue == null) {
484                 return null;
485             } else {
486                 return getOperator().applyFunction(baseValue, arguments);
487             }
488         }
489     }
490
491     /**
492      * INTERNAL:
493      * Used to print a debug form of the expression tree.
494      */

495     public void writeDescriptionOn(BufferedWriter writer) throws IOException {
496         writer.write(operator.toString());
497     }
498
499     /**
500      * INTERNAL: called from SQLSelectStatement.writeFieldsFromExpression(...)
501      */

502     public void writeFields(ExpressionSQLPrinter printer, Vector newFields, SQLSelectStatement statement) {
503         //print ", " before each selected field except the first one
504
if (printer.isFirstElementPrinted()) {
505             printer.printString(", ");
506         } else {
507             printer.setIsFirstElementPrinted(true);
508         }
509
510         if (getBaseExpression().isDataExpression()) {
511             DatabaseField field = ((DataExpression)getBaseExpression()).getField();
512             if (field == null) {
513                 // This means the select wants a *.
514
field = new DatabaseField("*");
515                 field.setType(getResultType());
516             } else {
517                 // Set the result type to the type specified for this function
518
// expression, if one has been set. Otherwise, use the mappings
519
// database field type.
520
if (hasResultType()) {
521                     field = (DatabaseField) field.clone();
522                     field.setType(getResultType());
523                 }
524             }
525             
526             newFields.addElement(field);
527         } else {
528             // This field is a complex function value so any name can be used.
529
DatabaseField field = new DatabaseField("*");
530             field.setType(getResultType());
531             newFields.addElement(field);
532         }
533
534         printSQL(printer);
535     }
536
537     /**
538      * INTERNAL:
539      * Used in SQL printing.
540      */

541     public void writeSubexpressionsTo(BufferedWriter writer, int indent) throws IOException {
542         if (baseExpression != null) {
543             baseExpression.toString(writer, indent);
544         }
545     }
546 }
Popular Tags