KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > spi > persistence > support > sqlstore > query > jqlc > ParameterTable


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 in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
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 Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * ParameterTable.java
26  *
27  * Created on April 12, 2000
28  */

29
30 package com.sun.jdo.spi.persistence.support.sqlstore.query.jqlc;
31
32 import java.util.ArrayList JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.List JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.ResourceBundle JavaDoc;
37
38 import com.sun.jdo.api.persistence.support.JDOQueryException;
39 import com.sun.jdo.api.persistence.support.JDOFatalInternalException;
40 import com.sun.jdo.spi.persistence.support.sqlstore.query.util.type.Type;
41 import com.sun.jdo.spi.persistence.support.sqlstore.query.util.type.StringType;
42 import com.sun.jdo.spi.persistence.support.sqlstore.query.util.type.PrimitiveType;
43 import com.sun.jdo.spi.persistence.support.sqlstore.query.util.type.WrapperClassType;
44 import com.sun.jdo.spi.persistence.support.sqlstore.query.util.type.MathType;
45 import com.sun.jdo.spi.persistence.support.sqlstore.query.util.type.DateType;
46
47 import com.sun.jdo.spi.persistence.support.sqlstore.ValueFetcher;
48 import com.sun.jdo.spi.persistence.utility.I18NHelper;
49 import com.sun.jdo.spi.persistence.utility.JavaTypeHelper;
50 import com.sun.jdo.spi.persistence.utility.ParameterInfo;
51
52 /**
53  * The query parameter table
54  *
55  * @author Michael Bouschen
56  * @version 0.1
57  */

58 public class ParameterTable
59 {
60     /** Query parameter names */
61     List JavaDoc names = null;
62
63     /** Query parameter types */
64     List JavaDoc types = null;
65
66     /** Query Parameter values */
67     transient List JavaDoc values = null;
68     
69     /** null key */
70     private static final String JavaDoc NULL_ = "null"; //NOI18N
71

72     /** true key */
73     private static final String JavaDoc TRUE_ = "true"; //NOI18N
74

75     /** false key */
76     private static final String JavaDoc FALSE_ = "false"; //NOI18N
77

78     /** other key */
79     private static final String JavaDoc OTHER_ = "other"; //NOI18N
80

81     /** noparams key */
82     private static final String JavaDoc NOPARAMS_ = "noparams"; //NOI18N
83

84     /** key parameter separator */
85     private static final char PARAMKEY_SEPARATOR = '/';
86
87     /**
88      * Objects of this class represent the value for an unbound query parameter
89      */

90     static class Unbound { }
91
92     /**
93      * Singleton representing the value for an unbound query parameter
94      */

95     static final Unbound unbound = new Unbound();
96
97     /** I18N support */
98     protected final static ResourceBundle JavaDoc messages =
99         I18NHelper.loadBundle(ParameterTable.class);
100
101     /**
102      *
103      */

104     public ParameterTable()
105     {}
106
107     /**
108      * Copy constructor.
109      * @param other the ParameterTable to be copied
110      */

111     public ParameterTable(ParameterTable other)
112     {
113         this.names = other.names;
114         this.types = other.types;
115         this.values = other.values;
116     }
117
118     /**
119      * Adds a new query parameter with the specified type to the query
120      * parameter table.
121      */

122     public void add(String JavaDoc name, Type type)
123     {
124         names.add(name);
125         types.add(type);
126     }
127
128     /**
129      * Initializes the parameter declarations (names and types list).
130      * Needs to be called prior to any add call.
131      */

132     public void init()
133     {
134         this.names = new ArrayList JavaDoc();
135         this.types = new ArrayList JavaDoc();
136     }
137
138     /**
139      * Initializes the parameter values. This methods sets the values for all
140      * declared parameters to unbound.
141      */

142     public void initValueHandling()
143     {
144         values = new ArrayList JavaDoc(names.size());
145         final int size = names.size();
146         for (int i = 0; i < size; i++) {
147             values.add(unbound);
148         }
149     }
150     
151     /**
152      * Check actual query parameters specified as array and return the
153      * ValueFetcher for the inputparameters.
154      * @param actualParams
155      * @return the parameters wrapped in the ValueFetcher
156      */

157     public void setValues(Object JavaDoc[] actualParams)
158     {
159         if (actualParams != null)
160         {
161             for (int i = 0; i < actualParams.length; i++)
162             {
163                 Object JavaDoc value = actualParams[i];
164                 defineValueByIndex(i, value);
165             }
166         }
167     }
168
169     /**
170      * Checks whether all parameters have an actual value.
171      */

172     public void checkUnboundParams()
173     {
174         final int size = values.size();
175         for (int i = 0; i < size; i++)
176         {
177             if (values.get(i) == unbound)
178             {
179                 throw new JDOQueryException(
180                     I18NHelper.getMessage(messages, "jqlc.parametertable.checkunboundparams.unboundparam", //NOI18N
181
names.get(i)));
182             }
183         }
184     }
185
186     /**
187      * Check actual query parameters specified as map and return the
188      * ValueFetcher for the inputparameters.
189      * @param actualParams
190      * @return the parameters wrapped in the ValueFetcher
191      */

192     public void setValues(Map JavaDoc actualParams)
193     {
194         if (actualParams != null)
195         {
196             for (Iterator JavaDoc i = actualParams.entrySet().iterator(); i.hasNext();)
197             {
198                 Map.Entry JavaDoc actualParam = (Map.Entry JavaDoc)i.next();
199                 String JavaDoc name = (String JavaDoc)actualParam.getKey();
200                 Object JavaDoc value = actualParam.getValue();
201                 defineValueByName(name, value);
202             }
203         }
204     }
205
206     /**
207      * Returns the value of the parameter with the specified name.
208      */

209     public Object JavaDoc getValueByName(String JavaDoc name)
210     {
211         int index = names.indexOf(name);
212         if (index == -1)
213             throw new JDOFatalInternalException(I18NHelper.getMessage(
214                 messages,
215                 "jqlc.parametertable.getvaluebyname.undefined", //NOI18N
216
name));
217
218         return getValueByIndex(index);
219     }
220
221     /**
222      * Returns the value of the parameter with the specified index.
223      */

224     public Object JavaDoc getValueByIndex(int index)
225     {
226         if ((index < 0) || (index >= values.size()))
227             throw new JDOFatalInternalException(I18NHelper.getMessage(
228                 messages,
229                 "jqlc.parametertable.getvaluebyindex.wrongindex", //NOI18N
230
String.valueOf(index)));
231
232         return values.get(index);
233     }
234
235     /** Returns the list of parameter values. */
236     public List JavaDoc getValues()
237     {
238         return values;
239     }
240
241     /**
242      * Wraps the actual parameter array into a ValueFetcher instnace.
243      * @return
244      */

245     public ValueFetcher getValueFetcher()
246     {
247         return new QueryValueFetcher(values.toArray(new Object JavaDoc[values.size()]));
248     }
249
250     /**
251      * Calculates and returns the key for the RetrieveDesc cache based,
252      * on the actual parameter values.
253      * A <code>null</code> return means, the RetrieveDesc should not be
254      * cached.
255      * Note, this method needs to be in sync with method inline.
256      */

257     public String JavaDoc getKeyForRetrieveDescCache()
258     {
259         StringBuffer JavaDoc key = new StringBuffer JavaDoc();
260         final int size = values.size();
261         for (int i = 0; i < size; i++) {
262             // Do not cache RetrieveDesc if the parameter type is pc class
263
// or java.lang.Object => return null
264
if (isInlineType(types.get(i)))
265                 return null;
266
267             Object JavaDoc item = values.get(i);
268             if (item == null) {
269                 key.append(ParameterTable.NULL_);
270             }
271             else if (item instanceof Boolean JavaDoc) {
272                 if (((Boolean JavaDoc)item).booleanValue()) {
273                     key.append(ParameterTable.TRUE_);
274                 } else {
275                     key.append(ParameterTable.FALSE_);
276                 }
277             } else {
278                 key.append(ParameterTable.OTHER_);
279             }
280             key.append(ParameterTable.PARAMKEY_SEPARATOR);
281         }
282
283         // If the key is 0 in length, the Query does not use any parameters.
284
// But nevertheless we want cache the RD, thus we return a key for
285
// no-parameter-queries
286
if (key.length() == 0) {
287             key.append(ParameterTable.NOPARAMS_);
288         }
289
290         return key.toString();
291     }
292
293     /**
294      * Returns true if the parameter with the specified index should be inlined
295      * by the optimizer.
296      * Note, this method needs to be in sync with method
297      * getKeyForRetrieveDescCache.
298      * @param paramName the parameter
299      * @return true if the specified parameter should be inlined.
300      */

301     public boolean inline(String JavaDoc paramName)
302     {
303         int index = names.indexOf(paramName);
304         Object JavaDoc value = values.get(index);
305
306         if (isInlineType(types.get(index))) return true;
307
308         if (value == null) return true;
309
310         if (value instanceof Boolean JavaDoc) return true;
311
312         return false;
313     }
314
315     /**
316      * Returns <code>true</code> if the specified parameter denotes a type
317      * whose values should be inlined by the query optimizer if a query
318      * parameter s is declared with such a type.
319      */

320     private boolean isInlineType(Object JavaDoc type)
321     {
322         // Check for types that are supported by JDBC, such that the
323
// parameter can be mapped to a JDBC parameter, these are:
324
// - String
325
// - primitive types (int, float, etc.)
326
// - wrapper class types (Integer, Float, etc.)
327
// - BigDecimal, BigInteger
328
// - Date class types
329
// All other types including pc classes, java.lang.Object, etc.
330
// should be inlined.
331
if ((type instanceof StringType) ||
332             (type instanceof PrimitiveType) ||
333             (type instanceof WrapperClassType) ||
334             (type instanceof MathType) ||
335             (type instanceof DateType))
336             return false;
337         return true;
338     }
339
340     /**
341      * Returns the parameter index for the specified parameter name.
342      * @deprecated
343      */

344     public Integer JavaDoc getIndexForParamName(String JavaDoc paramName)
345     {
346         return new Integer JavaDoc(names.indexOf(paramName));
347     }
348
349     /**
350      * Returns the parameter info for the specified parameter name.
351      * @param paramName
352      * @return corresponding parameterInfo
353      */

354     public ParameterInfo getParameterInfoForParamName(String JavaDoc paramName)
355     {
356         return getParameterInfoForParamName(paramName, null);
357     }
358
359     /**
360      * Returns the parameter info for the specified parameter name
361      * and associated field.
362      * If the associated field is not known, then null is used as
363      * input parameter.
364      * @param paramName
365      * @param associatedField
366      * @return corresponding parameterInfo
367      */

368     public ParameterInfo getParameterInfoForParamName(String JavaDoc paramName,
369             String JavaDoc associatedField)
370     {
371         int index = names.indexOf(paramName);
372         Type type = (Type)types.get(index);
373         return new ParameterInfo(index, type.getEnumType(), associatedField);
374     }
375
376     /**
377      *
378      */

379     private void defineValueByName(String JavaDoc name, Object JavaDoc value)
380     {
381         int index = names.indexOf(name);
382         if (index == -1)
383             throw new JDOQueryException(
384                 I18NHelper.getMessage(messages, "jqlc.parametertable.definevaluebyname.undefinedparam", name)); //NOI18N
385
defineValueByIndex(index, value);
386     }
387
388     /**
389      *
390      */

391     private void defineValueByIndex(int index, Object JavaDoc value)
392     {
393         // index < 0 => implementation error
394
if (index < 0)
395             throw new JDOFatalInternalException(I18NHelper.getMessage(
396                 messages,
397                 "jqlc.parametertable.definevaluebyindex.wrongindex", //NOI18N
398
String.valueOf(index)));
399
400         // index > type.size => too many actual parameters
401
if (index >= types.size())
402             throw new JDOQueryException(
403                 I18NHelper.getMessage(messages, "jqlc.parametertable.definevaluebyindex.wrongnumberofargs")); //NOI18N
404

405         // check type compatibility of actual and formal parameter
406
Class JavaDoc formalType = ((Type)types.get(index)).getJavaClass();
407         if (!isCompatibleValue(formalType, value))
408         {
409             String JavaDoc actualTypeName = ((value==null) ? "<type of null>" : value.getClass().getName());
410             throw new JDOQueryException(
411                 I18NHelper.getMessage(messages, "jqlc.parametertable.definevaluebyindex.typemismatch", //NOI18N
412
actualTypeName, formalType.getName()));
413         }
414
415         // everything is ok => set the actual parameters's value
416
values.set(index, value);
417     }
418
419     /**
420      * Checks whether the type of the specified value is compatible with the
421      * specified formal type.
422      * @param name the formal type.
423      * @param the value to be checked
424      * @return <code>true</code> if the type of the value is compatible with the
425      * formal type; <code>false</code> otherwise.
426      */

427     private boolean isCompatibleValue(Class JavaDoc formalType, Object JavaDoc value)
428     {
429         boolean isCompatible = true;
430
431         // handle value == null
432
if (value == null) {
433             isCompatible = !formalType.isPrimitive();
434         }
435         else {
436             Class JavaDoc actualType = value.getClass();
437             if (formalType.isPrimitive())
438                 formalType = JavaTypeHelper.getWrapperClass(formalType);
439
440             isCompatible = formalType.isAssignableFrom(actualType);
441         }
442         return isCompatible;
443     }
444
445 }
446
447
Popular Tags