KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.*;
26 import oracle.toplink.essentials.exceptions.*;
27 import oracle.toplink.essentials.mappings.*;
28 import oracle.toplink.essentials.queryframework.*;
29 import oracle.toplink.essentials.internal.helper.*;
30 import oracle.toplink.essentials.expressions.*;
31 import oracle.toplink.essentials.internal.sessions.AbstractRecord;
32 import oracle.toplink.essentials.internal.sessions.AbstractSession;
33 import oracle.toplink.essentials.descriptors.ClassDescriptor;
34
35 /**
36  * Used for parameterized expressions, such as expression defined in mapping queries.
37  */

38 public class ParameterExpression extends Expression {
39
40     /** The parameter field or name. */
41     protected DatabaseField field;
42
43     /** The opposite side of the relation, this is used for conversion of the parameter using the others mapping. */
44     protected Expression localBase;
45
46     /** The base expression is what the parameter was derived from, used for nested parameters. */
47     protected Expression baseExpression;
48
49     /** The infered type of the parameter.
50      * Please note that the type might not be always initialized to correct value.
51      * It might be null if not initialized correctly.
52      */

53     Object JavaDoc type;
54
55     public ParameterExpression() {
56         super();
57     }
58
59     public ParameterExpression(String JavaDoc fieldName) {
60         this(new DatabaseField(fieldName));
61     }
62
63     public ParameterExpression(DatabaseField field) {
64         super();
65         this.field = field;
66     }
67
68     // For bug 3107049 ParameterExpression will now be built with a
69
// default localBase, same as with ConstantExpression.
70
public ParameterExpression(String JavaDoc fieldName, Expression baseExpression, Object JavaDoc type) {
71         this(new DatabaseField(fieldName), baseExpression);
72         this.type = type;
73     }
74
75     public ParameterExpression(DatabaseField field, Expression baseExpression) {
76         super();
77         this.field = field;
78         localBase = baseExpression;
79     }
80
81     /**
82      * Return description.
83      * Used for toString.
84      */

85     public String JavaDoc basicDescription() {
86         return String.valueOf(getField());
87     }
88
89     /**
90      * INTERNAL:
91      * Used for debug printing.
92      */

93     public String JavaDoc descriptionOfNodeType() {
94         return "Parameter";
95     }
96
97     /**
98      * This allows for nesting of parametrized expression.
99      * This is used for parameterizing object comparisons.
100      */

101     public Expression get(String JavaDoc attributeOrQueryKey) {
102         ParameterExpression expression = new ParameterExpression(attributeOrQueryKey);
103         expression.setBaseExpression(this);
104
105         return expression;
106     }
107
108     /**
109      * The base expression is what the parameter was derived from.
110      * This is used for nested parameters.
111      */

112     public Expression getBaseExpression() {
113         return baseExpression;
114     }
115
116     /**
117      * Return the expression builder which is the ultimate base of this expression, or
118      * null if there isn't one (shouldn't happen if we start from a root)
119      */

120     public ExpressionBuilder getBuilder() {
121         if (localBase == null) {
122             //Bug#5097278 Need to return the builder from the base expression if nested.
123
if (getBaseExpression() != null) {
124                 return ((ParameterExpression)getBaseExpression()).getBuilder();
125             } else {
126                 return null;
127             }
128         }
129         return localBase.getBuilder();
130     }
131
132     public DatabaseField getField() {
133         return field;
134     }
135
136     /**
137      * This allows for nesting of parametrized expression.
138      * This is used for parameterizing object comparisons.
139      */

140     public Expression getField(DatabaseField field) {
141         ParameterExpression expression = new ParameterExpression(field);
142         expression.setBaseExpression(this);
143
144         return expression;
145     }
146
147     /**
148      * The opposite side of the relation, this is used for conversion of the parameter using the others mapping.
149      */

150     public Expression getLocalBase() {
151         return localBase;
152     }
153
154     /**
155      * The infered type of this parameter.
156      * Please note that the type might not be always initialized to correct value.
157      * It might be null if not initialized correctly
158      */

159     public Object JavaDoc getType() { return type; }
160
161     /**
162      * Extract the value from the row.
163      * This may require recusion if it is a nested parameter.
164      */

165     public Object JavaDoc getValue(AbstractRecord translationRow, AbstractSession session) {
166         if (getField() == null) {
167             return null;
168         }
169
170         Object JavaDoc value = null;
171
172         // Check for nested parameters.
173
if (getBaseExpression() != null) {
174             value = ((ParameterExpression)getBaseExpression()).getValue(translationRow, session);
175             if (value == null) {
176                 return null;
177             }
178
179             ClassDescriptor descriptor = session.getDescriptor(value);
180             //Bug4924639 Aggregate descriptors have to be acquired from their mapping as they are cloned and initialized by each mapping
181
if (descriptor.isAggregateDescriptor() && ((ParameterExpression)getBaseExpression()).getLocalBase().isObjectExpression()) {
182                 descriptor = ((ObjectExpression)((ParameterExpression)getBaseExpression()).getLocalBase()).getDescriptor();
183             }
184             if (descriptor != null) {
185                 // For bug 2990493 must unwrap for EJBQL "Select Person(p) where p = ?1"
186
//if we had to unwrap it make sure we replace the argument with this value
187
//incase it is needed again, say in conforming.
188
//bug 3750793
189
value = descriptor.getObjectBuilder().unwrapObject(value, session);
190                 translationRow.put(((ParameterExpression)getBaseExpression()).getField(), value);
191
192                 // The local parameter is either a field or attribute of the object.
193
DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForField(getField());
194                 if (mapping != null) {
195                     value = mapping.valueFromObject(value, getField(), session);
196                 } else {
197                     mapping = descriptor.getObjectBuilder().getMappingForAttributeName(getField().getName());
198                     if (mapping != null) {
199                         value = mapping.getRealAttributeValueFromObject(value, session);
200                     } else {
201                         DatabaseField queryKeyField = descriptor.getObjectBuilder().getFieldForQueryKeyName(getField().getName());
202                         if (queryKeyField != null) {
203                             mapping = descriptor.getObjectBuilder().getMappingForField(getField());
204                             if (mapping != null) {
205                                 value = mapping.valueFromObject(value, getField(), session);
206                             }
207                         }
208                     }
209                 }
210             }
211         } else {
212             value = translationRow.getIndicatingNoEntry(getField());
213             //Throw an exception if the field is not mapped
214
if (value == oracle.toplink.essentials.internal.sessions.AbstractRecord.noEntry) {
215                 throw QueryException.parameterNameMismatch(getField().getName());
216             }
217         }
218
219         // Convert the value to the correct type, i.e. object type mappings.
220
if (getLocalBase() != null) {
221             value = getLocalBase().getFieldValue(value);
222         }
223
224         return value;
225     }
226
227     public boolean isParameterExpression() {
228         return true;
229     }
230
231     /**
232      * INTERNAL:
233      */

234     public boolean isValueExpression() {
235         return true;
236     }
237
238     /**
239      * INTERNAL:
240      * Used for cloning.
241      */

242     protected void postCopyIn(Dictionary alreadyDone) {
243         super.postCopyIn(alreadyDone);
244         if (getLocalBase() != null) {
245             setLocalBase(getLocalBase().copiedVersionFrom(alreadyDone));
246         }
247         if (getBaseExpression() != null) {
248             setBaseExpression(getBaseExpression().copiedVersionFrom(alreadyDone));
249         }
250     }
251
252     /**
253      * INTERNAL:
254      * Print SQL onto the stream, using the ExpressionPrinter for context
255      */

256     public void printSQL(ExpressionSQLPrinter printer) {
257         if (printer.shouldPrintParameterValues()) {
258             Object JavaDoc value = getValue(printer.getTranslationRow(), printer.getSession());
259             if(getField() == null) {
260                 printer.printPrimitive(value);
261             } else {
262                 if (value instanceof Vector) {
263                     printer.printValuelist((Vector)value);
264                 } else {
265                     printer.printParameter(this);
266                 }
267             }
268         } else {
269             if (getField() != null) {
270                 printer.printParameter(this);
271             }
272         }
273     }
274
275     /**
276      * INTERNAL:
277      * Print java for project class generation
278      */

279     public void printJava(ExpressionJavaPrinter printer) {
280         ((DataExpression)getLocalBase()).getBaseExpression().printJava(printer);
281         printer.printString(".getParameter(\"" + getField().getQualifiedName() + "\")");
282     }
283
284     /**
285      * INTERNAL:
286      * This expression is built on a different base than the one we want. Rebuild it and
287      * return the root of the new tree
288      */

289     public Expression rebuildOn(Expression newBase) {
290         ParameterExpression result = (ParameterExpression)clone();
291         result.setLocalBase(localBase.rebuildOn(newBase));
292         return result;
293     }
294
295     /**
296      * The base expression is what the parameter was derived from.
297      * This is used for nested parameters.
298      */

299     protected void setBaseExpression(Expression baseExpression) {
300         this.baseExpression = baseExpression;
301     }
302
303     /**
304      * The opposite side of the relation, this is used for conversion of the parameter using the others mapping.
305      */

306     public void setLocalBase(Expression localBase) {
307         this.localBase = localBase;
308     }
309
310     /**
311      * INTERNAL:
312      * Rebuild against the base, with the values of parameters supplied by the context
313      * expression. This is used for transforming a standalone expression (e.g. the join criteria of a mapping)
314      * into part of some larger expression. You normally would not call this directly, instead calling twist,
315      * (see the comment there for more details).
316      */

317     public Expression twistedForBaseAndContext(Expression newBase, Expression context) {
318         return context.getField(getField());
319     }
320
321     /**
322      * INTERNAL:
323      * Return the value for in memory comparison.
324      * This is only valid for valueable expressions.
325      */

326     public Object JavaDoc valueFromObject(Object JavaDoc object, AbstractSession session, AbstractRecord translationRow, InMemoryQueryIndirectionPolicy valueHolderPolicy, boolean isObjectUnregistered) {
327         // Run ourselves through the translation row to find the desired value
328
if (getField() != null) {
329             return getValue(translationRow, session);
330         }
331
332         throw QueryException.cannotConformExpression();
333     }
334
335     /**
336      * INTERNAL:
337      * Used to print a debug form of the expression tree.
338      */

339     public void writeDescriptionOn(BufferedWriter writer) throws IOException {
340         writer.write(basicDescription());
341     }
342
343     /**
344      * Print the base for debuggin purposes.
345      */

346     public void writeSubexpressionsTo(BufferedWriter writer, int indent) throws IOException {
347         if (getBaseExpression() != null) {
348             getBaseExpression().toString(writer, indent);
349         }
350     }
351 }
352
Popular Tags