KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > query > QueryByCriteria


1 package org.apache.ojb.broker.query;
2
3 /* Copyright 2002-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import org.apache.ojb.broker.metadata.ClassDescriptor;
26 import org.apache.ojb.broker.metadata.FieldDescriptor;
27 import org.apache.ojb.broker.metadata.FieldHelper;
28 import org.apache.ojb.broker.metadata.MetadataManager;
29 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
30 import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
31 import org.apache.ojb.broker.util.logging.LoggerFactory;
32
33 /**
34  * represents a search by criteria.
35  * "find all articles where article.price > 100"
36  * could be represented as:
37  *
38  * Criteria crit = new Criteria();
39  * crit.addGreaterThan("price", new Double(100));
40  * Query qry = new QueryByCriteria(Article.class, crit);
41  *
42  * The PersistenceBroker can retrieve Objects by Queries as follows:
43  *
44  * PersistenceBroker broker = PersistenceBrokerFactory.createPersistenceBroker();
45  * Collection col = broker.getCollectionByQuery(qry);
46  *
47  * Creation date: (24.01.2001 21:45:46)
48  * @author Thomas Mahler
49  * @version $Id: QueryByCriteria.java,v 1.26.2.4 2005/12/21 22:27:09 tomdz Exp $
50  */

51 public class QueryByCriteria extends AbstractQueryImpl
52 {
53     private Criteria m_criteria;
54     private boolean m_distinct = false;
55     private Map JavaDoc m_pathClasses;
56     private Criteria m_havingCriteria;
57     private String JavaDoc m_objectProjectionAttribute;
58
59     // holding FieldHelper for orderBy and groupBy
60
private List JavaDoc m_orderby = null;
61     private List JavaDoc m_groupby = null;
62
63     // list of names of prefetchable relationships
64
private List JavaDoc m_prefetchedRelationships = null;
65
66     private Collection JavaDoc m_pathOuterJoins = null;
67
68     /**
69      * handy criteria that can be used to select all instances of
70      * a class.
71      */

72     public static final Criteria CRITERIA_SELECT_ALL = null;
73
74     /**
75      * Build a Query for class targetClass with criteria.
76      * Criteriy may be null (will result in a query returning ALL objects from a table)
77      */

78     public QueryByCriteria(Class JavaDoc targetClass, Criteria whereCriteria, Criteria havingCriteria, boolean distinct)
79     {
80         super (targetClass);
81
82         setCriteria(whereCriteria);
83         setHavingCriteria(havingCriteria);
84
85         m_distinct = distinct;
86         m_pathClasses = new HashMap JavaDoc();
87         m_groupby = new ArrayList JavaDoc();
88         m_orderby = new ArrayList JavaDoc();
89         m_prefetchedRelationships = new ArrayList JavaDoc();
90         m_pathOuterJoins = new HashSet JavaDoc();
91     }
92
93     /**
94      * Build a Query for class targetClass with criteria.
95      * Criteriy may be null (will result in a query returning ALL objects from a table)
96      */

97     public QueryByCriteria(Class JavaDoc targetClass, Criteria whereCriteria, Criteria havingCriteria)
98     {
99         this(targetClass, whereCriteria, havingCriteria, false);
100     }
101
102
103     /**
104      * Build a Query for class targetClass with criteria.
105      * Criteriy may be null (will result in a query returning ALL objects from a table)
106      */

107     public QueryByCriteria(Class JavaDoc targetClass, Criteria criteria)
108     {
109         this(targetClass, criteria, false);
110     }
111
112     /**
113      * Build a Query for class targetClass with criteria.
114      * Criteriy may be null (will result in a query returning ALL objects from a table)
115      */

116     public QueryByCriteria(Class JavaDoc targetClass, Criteria criteria, boolean distinct)
117     {
118         this(targetClass, criteria, null, distinct);
119     }
120
121     /**
122      * Build a Query based on anObject <br>
123      * all non null values are used as EqualToCriteria
124      */

125     public QueryByCriteria(Object JavaDoc anObject, boolean distinct)
126     {
127         this(anObject.getClass(), buildCriteria(anObject), distinct);
128     }
129
130     /**
131      * Build a Query based on anObject <br>
132      * all non null values are used as EqualToCriteria
133      */

134     public QueryByCriteria(Object JavaDoc anObject)
135     {
136         this(anObject.getClass(), buildCriteria(anObject));
137     }
138
139     /**
140      * Build a Query based on a Class Object. This
141      * Query will return all instances of the given class.
142      * @param aClassToSearchFrom the class to search from
143      */

144     public QueryByCriteria(Class JavaDoc aClassToSearchFrom)
145     {
146         this(aClassToSearchFrom, CRITERIA_SELECT_ALL);
147     }
148
149     /**
150      * Build Criteria based on example object<br>
151      * all non null values are used as EqualToCriteria
152      */

153     private static Criteria buildCriteria(Object JavaDoc anExample)
154     {
155         Criteria criteria = new Criteria();
156         ClassDescriptor cld = MetadataManager.getInstance().getRepository().getDescriptorFor(anExample.getClass());
157         FieldDescriptor[] fds = cld.getFieldDescriptions();
158         PersistentField f;
159         Object JavaDoc value;
160
161         for (int i = 0; i < fds.length; i++)
162         {
163             try
164             {
165                 f = fds[i].getPersistentField();
166                 value = f.get(anExample);
167                 if (value != null)
168                 {
169                     criteria.addEqualTo(f.getName(), value);
170                 }
171             }
172             catch (Throwable JavaDoc ex)
173             {
174                 LoggerFactory.getDefaultLogger().error(ex);
175             }
176         }
177
178         return criteria;
179     }
180
181     /**
182      * Add a hint Class for a path. Used for relationships to extents.<br>
183      * SqlStatment will use these hint classes when resolving the path.
184      * Without these hints SqlStatment will use the base class the
185      * relationship points to ie: Article instead of CdArticle.
186      *
187      * @param aPath the path segment ie: allArticlesInGroup
188      * @param aClass the Class ie: CdArticle
189      * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
190      */

191     public void addPathClass(String JavaDoc aPath, Class JavaDoc aClass)
192     {
193         List JavaDoc pathClasses = (List JavaDoc) m_pathClasses.get(aPath);
194         if(pathClasses == null)
195         {
196             setPathClass(aPath, aClass);
197         }
198         else
199         {
200             pathClasses.add(aClass);
201         }
202     }
203
204     /**
205      * Set the Class for a path. Used for relationships to extents.<br>
206      * SqlStatment will use this class when resolving the path.
207      * Without this hint SqlStatment will use the base class the
208      * relationship points to ie: Article instead of CdArticle.
209      * Using this method is the same as adding just one hint
210      *
211      * @param aPath the path segment ie: allArticlesInGroup
212      * @param aClass the Class ie: CdArticle
213      * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
214      * @see #addPathClass
215      */

216     public void setPathClass(String JavaDoc aPath, Class JavaDoc aClass)
217     {
218         List JavaDoc pathClasses = new ArrayList JavaDoc();
219         pathClasses.add(aClass);
220         m_pathClasses.put(aPath, pathClasses);
221     }
222
223     /**
224      * Get the a List of Class objects used as hints for a path
225      *
226      * @param aPath the path segment ie: allArticlesInGroup
227      * @return a List o Class objects to be used in SqlStatment
228      * @see #addPathClass
229      * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
230      */

231     public List JavaDoc getClassesForPath(String JavaDoc aPath)
232     {
233         return (List JavaDoc)m_pathClasses.get(aPath);
234     }
235
236     /**
237      * Answer true if outer join for path should be used.
238      * @param aPath the path to query the outer join setting for
239      * @return true for outer join
240      */

241     public boolean isPathOuterJoin(String JavaDoc aPath)
242     {
243         return getOuterJoinPaths().contains(aPath);
244     }
245
246     /**
247      * Force outer join for the last segment of the path.
248      * ie. path = 'a.b.c' the outer join will be applied only to the relationship from B to C.
249      * if multiple segments need an outer join, setPathOuterJoin needs to be called for each segement.
250      * @param aPath force outer join to the last segment of this path
251      */

252     public void setPathOuterJoin(String JavaDoc aPath)
253     {
254         getOuterJoinPaths().add(aPath);
255     }
256
257     /* (non-Javadoc)
258      * @see org.apache.ojb.broker.query.Query#getCriteria()
259      */

260     public Criteria getCriteria()
261     {
262         return m_criteria;
263     }
264
265     /* (non-Javadoc)
266      * @see org.apache.ojb.broker.query.Query#getHavingCriteria()
267      */

268     public Criteria getHavingCriteria()
269     {
270         return m_havingCriteria;
271     }
272
273     /**
274      * Insert the method's description here.
275      * Creation date: (07.02.2001 22:01:55)
276      * @return java.lang.String
277      */

278     public String JavaDoc toString()
279     {
280         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("QueryByCriteria from ");
281         buf.append(getSearchClass()).append(" ");
282         if (getCriteria() != null && !getCriteria().isEmpty())
283         {
284             buf.append(" where ").append(getCriteria());
285         }
286         return buf.toString();
287     }
288
289     /**
290      * Gets the distinct.
291      * @return Returns a boolean
292      */

293     public boolean isDistinct()
294     {
295         return m_distinct;
296     }
297
298     /**
299      * Sets the distinct.
300      * @param distinct The distinct to set
301      */

302     public void setDistinct(boolean distinct)
303     {
304         this.m_distinct = distinct;
305     }
306
307     /**
308      * Gets the pathClasses.
309      * A Map containing hints about what Class to be used for what path segment
310      * @return Returns a Map
311      */

312     public Map JavaDoc getPathClasses()
313     {
314         return m_pathClasses;
315     }
316
317     /**
318      * Sets the criteria.
319      * @param criteria The criteria to set
320      */

321     public void setCriteria(Criteria criteria)
322     {
323         m_criteria = criteria;
324         if (m_criteria != null)
325         {
326             m_criteria.setQuery(this);
327         }
328     }
329
330     /**
331      * Sets the havingCriteria.
332      * @param havingCriteria The havingCriteria to set
333      */

334     public void setHavingCriteria(Criteria havingCriteria)
335     {
336         m_havingCriteria = havingCriteria;
337         if (m_havingCriteria != null)
338         {
339             m_havingCriteria.setQuery(this);
340         }
341     }
342
343     /**
344      * Adds a groupby fieldName for ReportQueries.
345      * @param fieldName The groupby to set
346      */

347     public void addGroupBy(String JavaDoc fieldName)
348     {
349         if (fieldName != null)
350         {
351             m_groupby.add(new FieldHelper(fieldName, false));
352         }
353     }
354
355     /**
356      * Adds a field for groupby
357      * @param aField
358      */

359     public void addGroupBy(FieldHelper aField)
360     {
361         if (aField != null)
362         {
363             m_groupby.add(aField);
364         }
365     }
366
367     /**
368      * Adds an array of groupby fieldNames for ReportQueries.
369      * @param fieldNames The groupby to set
370      */

371     public void addGroupBy(String JavaDoc[] fieldNames)
372     {
373         for (int i = 0; i < fieldNames.length; i++)
374         {
375             addGroupBy(fieldNames[i]);
376         }
377     }
378
379     /**
380      * @see org.apache.ojb.broker.query.Query#getGroupBy()
381      */

382     public List JavaDoc getGroupBy()
383     {
384         // BRJ:
385
// combine data from query and criteria
386
// TODO: to be removed when Criteria#addGroupBy is removed
387
ArrayList JavaDoc temp = new ArrayList JavaDoc();
388         temp.addAll(m_groupby);
389
390         if (getCriteria() != null)
391         {
392             temp.addAll(getCriteria().getGroupby());
393         }
394
395         return temp;
396     }
397
398     /**
399      * Adds a field for orderBy
400      * @param fieldName The field name to be used
401      * @param sortAscending true for ASCENDING, false for DESCENDING
402      */

403     public void addOrderBy(String JavaDoc fieldName, boolean sortAscending)
404     {
405         if (fieldName != null)
406         {
407             m_orderby.add(new FieldHelper(fieldName, sortAscending));
408         }
409     }
410
411     /**
412      * Adds a field for orderBy, order is ASCENDING
413      * @param fieldName The field name to be used
414      * @deprecated use #addOrderByAscending(String fieldName)
415      */

416     public void addOrderBy(String JavaDoc fieldName)
417     {
418         addOrderBy(fieldName, true);
419     }
420
421     /**
422      * Adds a field for orderBy
423      * @param aField
424      */

425     public void addOrderBy(FieldHelper aField)
426     {
427         if (aField != null)
428         {
429             m_orderby.add(aField);
430         }
431     }
432
433     /**
434      * Adds a field for orderBy ASCENDING
435      * @param fieldName The field name to be used
436      */

437     public void addOrderByAscending(String JavaDoc fieldName)
438     {
439         addOrderBy(fieldName, true);
440     }
441
442     /**
443      * Adds a field for orderBy DESCENDING
444      * @param fieldName The field name to be used
445      */

446     public void addOrderByDescending(String JavaDoc fieldName)
447     {
448         addOrderBy(fieldName, false);
449     }
450
451     /**
452      * @see org.apache.ojb.broker.query.Query#getOrderBy()
453      */

454     public List JavaDoc getOrderBy()
455     {
456         // BRJ:
457
// combine data from query and criteria
458
// TODO: to be removed when Criteria#addOrderBy is removed
459
ArrayList JavaDoc temp = new ArrayList JavaDoc();
460         temp.addAll(m_orderby);
461
462         if (getCriteria() != null)
463         {
464             temp.addAll(getCriteria().getOrderby());
465         }
466
467         return temp;
468     }
469
470     /**
471      * add the name of aRelationship for prefetched read
472      */

473     public void addPrefetchedRelationship(String JavaDoc aName)
474     {
475         m_prefetchedRelationships.add(aName);
476     }
477
478     /* (non-Javadoc)
479      * @see org.apache.ojb.broker.query.Query#getPrefetchedRelationships()
480      */

481     public List JavaDoc getPrefetchedRelationships()
482     {
483         // BRJ:
484
// combine data from query and criteria
485
// TODO: to be removed when Criteria#addPrefetchedRelationship is removed
486
ArrayList JavaDoc temp = new ArrayList JavaDoc();
487         temp.addAll(m_prefetchedRelationships);
488
489         if (getCriteria() != null)
490         {
491             temp.addAll(getCriteria().getPrefetchedRelationships());
492         }
493
494         return temp;
495     }
496
497     /**
498      * Get a Collection containing all Paths having an Outer-Joins-Setting
499      * @return a Collection containing the Paths (Strings)
500      */

501     public Collection JavaDoc getOuterJoinPaths()
502     {
503         return m_pathOuterJoins;
504     }
505
506     public String JavaDoc getObjectProjectionAttribute()
507     {
508         return m_objectProjectionAttribute;
509     }
510
511     /**
512      * Use this method to query some related class by object references,
513      * for example query.setObjectProjectionAttribute("ref1.ref2.ref3");
514      */

515     public void setObjectProjectionAttribute(String JavaDoc objectProjectionAttribute)
516     {
517         ClassDescriptor baseCld = MetadataManager.getInstance().getRepository().getDescriptorFor(m_baseClass);
518         ArrayList JavaDoc descs = baseCld.getAttributeDescriptorsForPath(objectProjectionAttribute);
519         int pathLen = descs.size();
520
521         if ((pathLen > 0) && (descs.get(pathLen - 1) instanceof ObjectReferenceDescriptor))
522         {
523             ObjectReferenceDescriptor ord =
524                     ((ObjectReferenceDescriptor) descs.get(pathLen - 1));
525             setObjectProjectionAttribute(objectProjectionAttribute,
526                                          ord.getItemClass());
527         }
528     }
529
530     public void setObjectProjectionAttribute(String JavaDoc objectProjectionAttribute,
531                                              Class JavaDoc objectProjectionClass)
532     {
533         m_objectProjectionAttribute = objectProjectionAttribute;
534         m_searchClass = objectProjectionClass;
535     }
536 }
Popular Tags