KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > triactive > jdo > store > Query


1 /*
2  * Copyright 2002 (C) TJDO.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the TJDO License version 1.0.
6  * See the terms of the TJDO License in the documentation provided with this software.
7  *
8  * $Id: Query.java,v 1.5 2003/08/11 16:03:57 pierreg0 Exp $
9  */

10
11 package com.triactive.jdo.store;
12
13 import com.triactive.jdo.PersistenceManager;
14 import com.triactive.jdo.util.Imports;
15 import java.sql.ResultSet JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import java.util.Collection JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.StringTokenizer JavaDoc;
23 import javax.jdo.Extent;
24 import javax.jdo.JDOUserException;
25
26
27 /**
28  * The Query interface allows applications to obtain persistent instances
29  * from the data store.
30  *
31  * @author <a HREF="mailto:mmartin5@austin.rr.com">Mike Martin</a>
32  * @version $Revision: 1.5 $
33  *
34  * @see javax.jdo.Query
35  */

36
37 public abstract class Query implements javax.jdo.Query
38 {
39     protected final transient PersistenceManager pm;
40     protected final transient StoreManager storeMgr;
41     protected final transient DatabaseAdapter dba;
42
43     protected Class JavaDoc candidateClass;
44     protected String JavaDoc filter;
45     protected String JavaDoc imports;
46     protected String JavaDoc variables;
47     protected String JavaDoc parameters;
48     protected String JavaDoc ordering;
49
50     protected transient boolean isCompiled = false;
51     protected transient Imports parsedImports = null;
52     protected transient List JavaDoc parameterNames = null;
53     protected transient Map JavaDoc parameterTypesByName = null;
54     protected transient List JavaDoc variableNames = null;
55     protected transient Map JavaDoc variableTypesByName = null;
56
57     protected transient HashSet JavaDoc queryResults = new HashSet JavaDoc();
58
59
60     /**
61      * Constructs a new query instance that uses the given persistence manager.
62      *
63      * @param pm the associated persistence manager for this query.
64      */

65
66     public Query(PersistenceManager pm, StoreManager storeMgr)
67     {
68         this.pm = pm;
69         this.storeMgr = storeMgr;
70
71         dba = storeMgr == null ? null : storeMgr.getDatabaseAdapter();
72     }
73
74
75     protected void discardCompiled()
76     {
77         isCompiled = false;
78         parsedImports = null;
79         parameterNames = null;
80         parameterTypesByName = null;
81         variableNames = null;
82         variableTypesByName = null;
83     }
84
85
86     public boolean equals(Object JavaDoc obj)
87     {
88         if (obj == this)
89             return true;
90
91         if (!(obj instanceof Query))
92             return false;
93
94         Query q = (Query)obj;
95
96         if (candidateClass == null) { if (q.candidateClass != null) return false; }
97         else if (!candidateClass.equals(q.candidateClass)) return false;
98
99         if (filter == null) { if (q.filter != null) return false; }
100         else if (!filter.equals(q.filter)) return false;
101
102         if (imports == null) { if (q.imports != null) return false; }
103         else if (!imports.equals(q.imports)) return false;
104
105         if (parameters == null) { if (q.parameters != null) return false; }
106         else if (!parameters.equals(q.parameters)) return false;
107
108         if (variables == null) { if (q.variables != null) return false; }
109         else if (!variables.equals(q.variables)) return false;
110
111         if (ordering == null) { if (q.ordering != null) return false; }
112         else if (!ordering.equals(q.ordering)) return false;
113
114         return true;
115     }
116
117
118     public int hashCode()
119     {
120         return (candidateClass == null ? 0 : candidateClass.hashCode())
121              ^ (filter == null ? 0 : filter.hashCode())
122              ^ (imports == null ? 0 : imports.hashCode())
123              ^ (parameters == null ? 0 : parameters.hashCode())
124              ^ (variables == null ? 0 : variables.hashCode())
125              ^ (ordering == null ? 0 : ordering.hashCode());
126     }
127
128
129     /**
130      * Get the StoreManager associated with this Query.
131      *
132      * @return the StoreManager associated with this Query.
133      */

134
135     public StoreManager getStoreManager()
136     {
137         return storeMgr;
138     }
139
140
141     /**
142      * Get the PersistenceManager associated with this Query.
143      *
144      * @return the PersistenceManager associated with this Query.
145      *
146      * @see javax.jdo.Query#getPersistenceManager
147      */

148
149     public javax.jdo.PersistenceManager getPersistenceManager()
150     {
151         return pm;
152     }
153
154
155     /**
156      * Get the class of the candidate instances of the query.
157      *
158      * @return the Class of the candidate instances.
159      *
160      * @see javax.jdo.Query#setClass
161      */

162
163     public Class JavaDoc getCandidateClass()
164     {
165         return candidateClass;
166     }
167
168
169     /**
170      * Set the class of the candidate instances of the query.
171      *
172      * @param candidateClass the Class of the candidate instances.
173      *
174      * @see javax.jdo.Query#setClass
175      */

176
177     public void setClass(Class JavaDoc candidateClass)
178     {
179         discardCompiled();
180
181         this.candidateClass = candidateClass;
182     }
183
184
185     /**
186      * Set the candidate Extent to query.
187      *
188      * @param pcs the Candidate Extent.
189      *
190      * @see javax.jdo.Query#setCandidates(javax.jdo.Extent)
191      */

192
193     public abstract void setCandidates(Extent pcs);
194
195
196     /**
197      * Set the candidate Collection to query.
198      *
199      * @param pcs the Candidate collection.
200      *
201      * @see javax.jdo.Query#setCandidates(java.util.Collection)
202      */

203
204     public abstract void setCandidates(Collection JavaDoc pcs);
205
206
207     /**
208      * Set the filter for the query.
209      *
210      * @param filter the query filter.
211      *
212      * @see javax.jdo.Query#setFilter
213      */

214
215     public void setFilter(String JavaDoc filter)
216     {
217         discardCompiled();
218
219         this.filter = filter;
220     }
221
222
223     /**
224      * Set the import statements to be used to identify the fully qualified
225      * name of variables or parameters.
226      *
227      * @param imports import statements separated by semicolons.
228      *
229      * @see javax.jdo.Query#declareImports
230      */

231
232     public void declareImports(String JavaDoc imports)
233     {
234         discardCompiled();
235
236         this.imports = imports;
237     }
238
239     /**
240      * Declare the list of parameters query execution.
241      *
242      * @param parameters the list of parameters separated by commas.
243      *
244      * @see javax.jdo.Query#declareParameters
245      */

246
247     public void declareParameters(String JavaDoc parameters)
248     {
249         discardCompiled();
250
251         this.parameters = parameters;
252     }
253
254
255     /**
256      * Declare the unbound variables to be used in the query.
257      *
258      * @param variables the variables separated by semicolons.
259      *
260      * @see javax.jdo.Query#declareVariables
261      */

262
263     public void declareVariables(String JavaDoc variables)
264     {
265         discardCompiled();
266
267         this.variables = variables;
268     }
269
270
271     /**
272      * Set the ordering specification for the result Collection.
273      *
274      * @param ordering the ordering specification.
275      *
276      * @see javax.jdo.Query#setOrdering
277      */

278
279     public void setOrdering(String JavaDoc ordering)
280     {
281         discardCompiled();
282
283         this.ordering = ordering;
284     }
285
286
287     /**
288      * Set the ignoreCache option.
289      *
290      * <p>This implementation does not support the ignore cache option, so this
291      * method does nothing.
292      *
293      * @param ignoreCache the setting of the ignoreCache option.
294      *
295      * @see javax.jdo.Query#setIgnoreCache
296      */

297
298     public void setIgnoreCache(boolean ignoreCache)
299     {
300         discardCompiled();
301
302         return;
303     }
304
305
306     /**
307      * Get the ignoreCache option setting.
308      *
309      * <p>This implementation does not support the ignore cache option, so this
310      * method always returns <tt>false</tt>.
311      *
312      * @return the ignoreCache option setting, always <tt>false</tt>.
313      *
314      * @see javax.jdo.Query#getIgnoreCache
315      * @see #setIgnoreCache
316      */

317
318     public boolean getIgnoreCache()
319     {
320         return false;
321     }
322
323
324     /**
325      * Verify the elements of the query and provide a hint to the query to
326      * prepare and optimize an execution plan.
327      *
328      * @see javax.jdo.Query#compile
329      */

330
331     public void compile()
332     {
333         if (isCompiled)
334             return;
335
336         if (pm == null)
337             throw new JDOUserException("Query has no associated PersistenceManager");
338
339         boolean done = false;
340
341         try
342         {
343             /*
344              * Parse imports list.
345              */

346
347             parsedImports = new Imports();
348             parsedImports.importPackage(candidateClass);
349
350             if (imports != null)
351                 parsedImports.parseImports(imports);
352
353             /*
354              * Parse parameters list.
355              */

356
357             parameterNames = new ArrayList JavaDoc();
358             parameterTypesByName = new HashMap JavaDoc();
359
360             if (parameters != null && parameters.length() > 0)
361             {
362                 StringTokenizer JavaDoc t1 = new StringTokenizer JavaDoc(parameters, ",");
363
364                 while (t1.hasMoreTokens())
365                 {
366                     StringTokenizer JavaDoc t2 = new StringTokenizer JavaDoc(t1.nextToken(), " ");
367
368                     if (t2.countTokens() != 2)
369                         throw new JDOUserException("Invalid parameter list: \"" + parameters + '"');
370
371                     String JavaDoc classDecl = t2.nextToken();
372                     String JavaDoc parameterName = t2.nextToken();
373
374                     if (!isValidJavaIdentifier(parameterName))
375                         throw new JDOUserException("Illegal parameter name \"" + parameterName + '"');
376
377                     if (parameterNames.contains(parameterName))
378                         throw new JDOUserException("Duplicate parameter name \"" + parameterName + '"');
379
380                     parameterNames.add(parameterName);
381                     parameterTypesByName.put(parameterName, resolveClassDeclaration(classDecl));
382                 }
383             }
384
385             /*
386              * Parse variables list.
387              */

388
389             variableNames = new ArrayList JavaDoc();
390             variableTypesByName = new HashMap JavaDoc();
391
392             if (variables != null && variables.length() > 0)
393             {
394                 StringTokenizer JavaDoc t1 = new StringTokenizer JavaDoc(variables, ";");
395
396                 while (t1.hasMoreTokens())
397                 {
398                     StringTokenizer JavaDoc t2 = new StringTokenizer JavaDoc(t1.nextToken(), " ");
399
400                     if (t2.countTokens() != 2)
401                         throw new JDOUserException("Invalid variable list: \"" + variables + '"');
402
403                     String JavaDoc classDecl = t2.nextToken();
404                     String JavaDoc variableName = t2.nextToken();
405
406                     if (!isValidJavaIdentifier(variableName))
407                         throw new JDOUserException("Illegal variable name \"" + variableName + '"');
408
409                     if (parameterNames.contains(variableName))
410                         throw new JDOUserException("Variable name conflicts with parameter name \"" + variableName + '"');
411
412                     if (variableNames.contains(variableName))
413                         throw new JDOUserException("Duplicate variable name \"" + variableName + '"');
414
415                     variableNames.add(variableName);
416                     variableTypesByName.put(variableName, resolveClassDeclaration(classDecl));
417                 }
418             }
419
420             done = true;
421         }
422         finally
423         {
424             if (!done)
425                 discardCompiled();
426         }
427     }
428
429
430     protected static boolean isValidJavaIdentifier(String JavaDoc s)
431     {
432         int len = s.length();
433
434         if (len < 1)
435             return false;
436
437         char[] c = new char[len];
438         s.getChars(0, len, c, 0);
439
440         if (!Character.isJavaIdentifierStart(c[0]))
441             return false;
442
443         for (int i = 1; i < len; ++i)
444         {
445             if (!Character.isJavaIdentifierPart(c[i]))
446                 return false;
447         }
448
449         return true;
450     }
451
452
453     public Class JavaDoc resolveClassDeclaration(String JavaDoc classDecl)
454     {
455         try
456         {
457             return parsedImports.resolveClassDeclaration(classDecl);
458         }
459         catch (ClassNotFoundException JavaDoc e)
460         {
461             throw new JDOUserException("Declared parameter or variable type not found: " + classDecl);
462         }
463     }
464
465
466     /**
467      * Execute the query and return the filtered Collection.
468      *
469      * @return the filtered Collection.
470      *
471      * @see javax.jdo.Query#execute()
472      * @see #executeWithArray(Object[] parameters)
473      */

474
475     public Object JavaDoc execute()
476     {
477         return executeWithArray(new Object JavaDoc[0]);
478     }
479
480
481     /**
482      * Execute the query and return the filtered Collection.
483      *
484      * @param p1 the value of the first parameter declared.
485      *
486      * @return the filtered Collection.
487      *
488      * @see javax.jdo.Query#execute(Object)
489      * @see #executeWithArray(Object[] parameters)
490      */

491
492     public Object JavaDoc execute(Object JavaDoc p1)
493     {
494         return executeWithArray(new Object JavaDoc[] { p1 });
495     }
496
497
498     /**
499      * Execute the query and return the filtered Collection.
500      *
501      * @param p1 the value of the first parameter declared.
502      * @param p2 the value of the second parameter declared.
503      *
504      * @return the filtered Collection.
505      *
506      * @see javax.jdo.Query#execute(Object,Object)
507      * @see #executeWithArray(Object[] parameters)
508      */

509
510     public Object JavaDoc execute(Object JavaDoc p1, Object JavaDoc p2)
511     {
512         return executeWithArray(new Object JavaDoc[] { p1, p2 });
513     }
514
515
516     /**
517      * Execute the query and return the filtered Collection.
518      *
519      * @param p1 the value of the first parameter declared.
520      * @param p2 the value of the second parameter declared.
521      * @param p3 the value of the third parameter declared.
522      *
523      * @return the filtered Collection.
524      *
525      * @see javax.jdo.Query#execute(Object,Object,Object)
526      * @see #executeWithArray(Object[] parameters)
527      */

528
529     public Object JavaDoc execute(Object JavaDoc p1, Object JavaDoc p2, Object JavaDoc p3)
530     {
531         return executeWithArray(new Object JavaDoc[] { p1, p2, p3 });
532     }
533
534
535     /**
536      * Execute the query and return the filtered Collection.
537      *
538      * @param parameters the Object array with all of the parameters.
539      *
540      * @return the filtered Collection.
541      *
542      * @see javax.jdo.Query#executeWithArray(Object[])
543      */

544
545     public Object JavaDoc executeWithArray(Object JavaDoc[] parameters)
546     {
547         compile();
548
549         if (parameters.length != parameterNames.size())
550             throw new JDOUserException("Incorrect number of parameters: " + parameters.length + ", s/b " + parameterNames.size());
551
552         HashMap JavaDoc parameterMap = new HashMap JavaDoc();
553
554         for (int i = 0; i < parameters.length; ++i)
555             parameterMap.put(parameterNames.get(i), parameters[i]);
556
557         return executeWithMap(parameterMap);
558     }
559
560
561     /**
562      * Execute the query and return the filtered Collection.
563      *
564      * @param parameters the Map containing all of the parameters.
565      *
566      * @return the filtered Collection.
567      *
568      * @see javax.jdo.Query#executeWithMap(Map)
569      * @see #executeWithArray(Object[] parameters)
570      */

571
572     public abstract Object JavaDoc executeWithMap(Map JavaDoc parameters);
573
574
575     /**
576      * Close a query result and release any resources associated with it.
577      *
578      * @param queryResult the result of execute(...) on this Query instance.
579      *
580      * @see javax.jdo.Query#close
581      */

582
583     public void close(Object JavaDoc queryResult)
584     {
585         if (queryResult != null)
586         {
587             ((QueryResult)queryResult).close();
588             queryResults.remove(queryResult);
589         }
590     }
591
592
593     /**
594      * Close all query results associated with this Query instance, and release all
595      * resources associated with them.
596      *
597      * @see javax.jdo.Query#closeAll
598      */

599
600     public void closeAll()
601     {
602         QueryResult[] qrs = (QueryResult[])queryResults.toArray(new QueryResult[queryResults.size()]);
603
604         for (int i = 0; i < qrs.length; ++i)
605             close(qrs[i]);
606     }
607
608
609     /**
610      * An object that reads result set rows and returns corresponding persistent
611      * objects from them. Different queries accomplish this in different ways,
612      * so a query supplies a suitable ResultObjectFactory to each QueryResult
613      * when it is executed. The QueryResult only uses it to turn ResultSet rows
614      * into objects and otherwise manages the ResultSet itself.
615      *
616      * @see QueryResult
617      */

618
619     public static interface ResultObjectFactory
620     {
621         /**
622          * Instantiates a persistent object instance from the current row of
623          * the given result set.
624          *
625          * @param rs The result set. The contents of the current row are
626          * used to locate or create a corresponding persistent
627          * object instance.
628          *
629          * @return A persistent object instance.
630          */

631
632         Object JavaDoc getObject(ResultSet JavaDoc rs);
633     }
634 }
635
Popular Tags