View Javadoc

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;
19  import java.util.Collection;
20  import java.util.Enumeration;
21  import java.util.HashMap;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.Vector;
26  
27  import org.apache.ojb.broker.PersistenceBrokerFactory;
28  import org.apache.ojb.broker.metadata.FieldHelper;
29  import org.apache.ojb.broker.core.PersistenceBrokerConfiguration;
30  import org.apache.ojb.broker.util.configuration.ConfigurationException;
31  
32  /**
33   * Persistent Criteria can be used to retrieve sets of objects based on their attributes
34   * Normally each attribute is ANDed together, an OR can be performed by creating a new
35   * PersistentCriteria and adding it.
36   * <P>
37   * Criteria are used, rather than a simple string, because they can be precompiled for
38   * efficiency.
39   *
40   * This code is based on stuff from
41   * COBRA - Java Object Persistence Layer
42   * Copyright (C) 1997, 1998    DB Harvey-George
43   * eMail: cobra@lowrent.org
44   *
45   * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
46   * @version $Id: Criteria.java,v 1.1 2007-08-24 22:17:36 ewestfal Exp $
47   */
48  public class Criteria implements java.io.Serializable
49  {
50      static final long serialVersionUID = 7384550404778187808L;
51  
52      /** criteria is OR-ed with it's parent */
53      public static final int OR = 0;
54      /** criteria is AND-ed with it's parent */
55      public static final int AND = 1;
56      /** criteria has no parent */
57      public static final int NONE = 9;
58  
59      /** prefix to identify attributes referencing enclosing query */
60      public static final String PARENT_QUERY_PREFIX = "parentQuery.";
61  
62      private Vector m_criteria;
63      private int m_type;
64      private boolean m_embraced;
65      private boolean m_negative = false;
66  
67      // holding CriteriaFields for orderBy and groupBy
68      private List orderby = null;
69      private List groupby = null;
70      private List prefetchedRelationships = null;
71  
72  	// an optional alias to be used for this criteria
73  	private String m_alias = null;
74  
75  	// PAW
76  	// an aliasPath to be used for this criteria
77  	private String m_aliasPath = null;
78  
79  	// holds the path segment(s) to which the alias applies
80  	private UserAlias m_userAlias = null;
81  
82  	/** the max. number of parameters in a IN-statement */
83      protected static final int IN_LIMIT = getSqlInLimit();
84  
85      private QueryByCriteria m_query;
86      private Criteria m_parentCriteria;
87  
88      // PAW
89  	// hint classes for paths of this criteria
90  	private Map m_pathClasses;
91  
92      /**
93       * Constructor declaration
94       */
95      public Criteria()
96      {
97          m_criteria = new Vector();
98          groupby = new ArrayList();
99          orderby = new ArrayList();
100         prefetchedRelationships = new ArrayList();
101         m_type = NONE;
102         m_embraced = false;
103         // PAW
104 		m_pathClasses = new HashMap();
105     }
106 
107     /**
108      * Constructor with a SelectionCriteria
109      * @param aSelectionCriteria SelectionCriteria
110      */
111     public Criteria(SelectionCriteria aSelectionCriteria)
112     {
113         this();
114         addSelectionCriteria(aSelectionCriteria);
115     }
116 
117     /**
118      * make a copy of the criteria
119      * @param includeGroupBy if true
120      * @param includeOrderBy if ture
121      * @param includePrefetchedRelationships if true
122      * @return a copy of the criteria
123      */
124     public Criteria copy(boolean includeGroupBy, boolean includeOrderBy, boolean includePrefetchedRelationships)
125     {
126         Criteria copy = new Criteria();
127 
128         copy.m_criteria = new Vector(this.m_criteria);
129         copy.m_negative = this.m_negative;
130 
131         if (includeGroupBy)
132         {
133             copy.groupby = this.groupby;
134         }
135         if (includeOrderBy)
136         {
137             copy.orderby = this.orderby;
138         }
139         if (includePrefetchedRelationships)
140         {
141             copy.prefetchedRelationships = this.prefetchedRelationships;
142         }
143 
144         return copy;
145     }
146 
147     protected void addSelectionCriteria(SelectionCriteria selectionCrit)
148     {
149         selectionCrit.setCriteria(this);
150         m_criteria.addElement(selectionCrit);
151     }
152 
153     protected void addCriteria(Criteria crit)
154     {
155         crit.setParentCriteria(this);
156         m_criteria.addElement(crit);
157     }
158 
159     protected void addCriteria(Vector criteria)
160     {
161         Object crit;
162 
163         for (int i = 0; i < criteria.size(); i++)
164         {
165             crit = criteria.elementAt(i);
166             if (crit instanceof SelectionCriteria)
167             {
168                 addSelectionCriteria((SelectionCriteria) crit);
169             }
170             else if (crit instanceof Criteria)
171             {
172                 addCriteria((Criteria) crit);
173             }
174         }
175     }
176 
177     /**
178      * Answer a List of InCriteria based on values, each InCriteria
179      * contains only inLimit values
180      * @param attribute
181      * @param values
182      * @param negative
183      * @param inLimit the maximum number of values for IN (-1 for no limit)
184      * @return List of InCriteria
185      */
186     protected List splitInCriteria(Object attribute, Collection values, boolean negative, int inLimit)
187     {
188         List result = new ArrayList();
189         Collection inCollection = new ArrayList();
190 
191         if (values == null || values.isEmpty())
192         {
193             // OQL creates empty Criteria for late binding
194             result.add(buildInCriteria(attribute, negative, values));
195         }
196         else
197         {
198             Iterator iter = values.iterator();
199 
200             while (iter.hasNext())
201             {
202                 inCollection.add(iter.next());
203                 if (inCollection.size() == inLimit || !iter.hasNext())
204                 {
205                     result.add(buildInCriteria(attribute, negative, inCollection));
206                     inCollection = new ArrayList();
207                 }
208             }
209         }
210         return result;
211     }
212 
213     private InCriteria buildInCriteria(Object attribute, boolean negative, Collection values)
214     {
215         if (negative)
216         {
217         	// PAW
218 			// return ValueCriteria.buildNotInCriteria(attribute, values, getAlias());
219 			return ValueCriteria.buildNotInCriteria(attribute, values, getUserAlias(attribute));
220         }
221         else
222         {
223 			// PAW
224 			// return ValueCriteria.buildInCriteria(attribute, values, getAlias());
225 			return ValueCriteria.buildInCriteria(attribute, values, getUserAlias(attribute));
226         }
227     }
228 
229     /**
230      * Get an Enumeration with all sub criteria
231      * @return Enumeration
232      */
233     public Enumeration getElements()
234     {
235         return getCriteria().elements();
236     }
237 
238     /**
239      * Get a Vector with all sub criteria
240      * @return Vector
241      */
242     protected Vector getCriteria()
243     {
244         return m_criteria;
245     }
246 
247     /**
248      * Answer the type
249      * @return int
250      */
251     public int getType()
252     {
253         return m_type;
254     }
255 
256     /**
257      * Set the type
258      * @param type OR, AND, NONE
259      */
260     public void setType(int type)
261     {
262         m_type = type;
263     }
264 
265     /**
266      * ANDed criteria are embraced
267      * @return true if embraced,
268      */
269     public boolean isEmbraced()
270     {
271         return m_embraced;
272     }
273 
274     /**
275      * Set embraced
276      * @param embraced true if criteria is to be surrounded by braces
277      */
278     public void setEmbraced(boolean embraced)
279     {
280         m_embraced = embraced;
281     }
282 
283     /**
284      * Adds and equals (=) criteria,
285      * customer_id = 10034
286      *
287      * @param  attribute   The field name to be used
288      * @param  value       An object representing the value of the field
289      */
290     public void addEqualTo(String attribute, Object value)
291     {
292     	// PAW
293 //		addSelectionCriteria(ValueCriteria.buildEqualToCriteria(attribute, value, getAlias()));
294 		addSelectionCriteria(ValueCriteria.buildEqualToCriteria(attribute, value, getUserAlias(attribute)));
295     }
296 
297     /**
298      * Adds and equals (=) criteria,
299      * CUST_ID = 10034
300      * attribute will NOT be translated into column name
301      *
302      * @param  column   The column name to be used without translation
303      * @param  value    An object representing the value of the column
304      */
305     public void addColumnEqualTo(String column, Object value)
306     {
307     	// PAW
308 //		SelectionCriteria c = ValueCriteria.buildEqualToCriteria(column, value, getAlias());
309 		SelectionCriteria c = ValueCriteria.buildEqualToCriteria(column, value, getUserAlias(column));
310         c.setTranslateAttribute(false);
311         addSelectionCriteria(c);
312     }
313 
314     /**
315      * Adds and equals (=) criteria for field comparison.
316      * The field name will be translated into the appropriate columnName by SqlStatement.
317      * The attribute will NOT be translated into column name
318      *
319      * @param  column       The column name to be used without translation
320      * @param  fieldName    An object representing the value of the field
321      */
322     public void addColumnEqualToField(String column, Object fieldName)
323     {
324     	// PAW
325 		//SelectionCriteria c = FieldCriteria.buildEqualToCriteria(column, fieldName, getAlias());
326 		SelectionCriteria c = FieldCriteria.buildEqualToCriteria(column, fieldName, getUserAlias(column));
327         c.setTranslateAttribute(false);
328         addSelectionCriteria(c);
329     }
330 
331     /**
332      * Adds and equals (=) criteria for field comparison.
333      * The field name will be translated into the appropriate columnName by SqlStatement.
334      * <br>
335      * name = boss.name
336      *
337      * @param  attribute   The field name to be used
338      * @param  fieldName   The field name to compare with
339      */
340     public void addEqualToField(String attribute, String fieldName)
341     {
342 		// PAW
343 		// FieldCriteria c = FieldCriteria.buildEqualToCriteria(attribute, fieldName, getAlias());
344 		FieldCriteria c = FieldCriteria.buildEqualToCriteria(attribute, fieldName, getUserAlias(attribute));
345         addSelectionCriteria(c);
346     }
347 
348     /**
349      * Adds and equals (=) criteria for field comparison.
350      * The field name will be translated into the appropriate columnName by SqlStatement.
351      * <br>
352      * name <> boss.name
353      *
354      * @param  attribute   The field name to be used
355      * @param  fieldName   The field name to compare with
356      */
357     public void addNotEqualToField(String attribute, String fieldName)
358     {
359         // PAW
360 		// SelectionCriteria c = FieldCriteria.buildNotEqualToCriteria(attribute, fieldName, getAlias());
361 		SelectionCriteria c = FieldCriteria.buildNotEqualToCriteria(attribute, fieldName, getUserAlias(attribute));
362         addSelectionCriteria(c);
363     }
364 
365     /**
366      * Adds and equals (<>) criteria for column comparison.
367      * The column Name will NOT be translated.
368      * <br>
369      * name <> T_BOSS.LASTNMAE
370      *
371      * @param  attribute   The field name to be used
372      * @param  colName     The name of the column to compare with
373      */
374     public void addNotEqualToColumn(String attribute, String colName)
375     {
376         // PAW
377 		// FieldCriteria c = FieldCriteria.buildNotEqualToCriteria(attribute, colName, getAlias());
378 		FieldCriteria c = FieldCriteria.buildNotEqualToCriteria(attribute, colName, getUserAlias(attribute));
379         c.setTranslateField(false);
380         addSelectionCriteria(c);
381     }
382 
383     /**
384      * Adds and equals (=) criteria for column comparison.
385      * The column Name will NOT be translated.
386      * <br>
387      * name = T_BOSS.LASTNMAE
388      *
389      * @param  attribute   The field name to be used
390      * @param  colName     The name of the column to compare with
391      */
392     public void addEqualToColumn(String attribute, String colName)
393     {
394 		// FieldCriteria c = FieldCriteria.buildEqualToCriteria(attribute, colName, getAlias());
395 		FieldCriteria c = FieldCriteria.buildEqualToCriteria(attribute, colName, getUserAlias(attribute));
396         c.setTranslateField(false);
397         addSelectionCriteria(c);
398     }
399 
400     /**
401      * Adds GreaterOrEqual Than (>=) criteria,
402      * customer_id >= 10034
403      *
404      * @param  attribute   The field name to be used
405      * @param  value       An object representing the value of the field
406      */
407     public void addGreaterOrEqualThan(Object attribute, Object value)
408     {
409 		// PAW
410 		// addSelectionCriteria(ValueCriteria.buildNotLessCriteria(attribute, value, getAlias()));
411 		addSelectionCriteria(ValueCriteria.buildNotLessCriteria(attribute, value, getUserAlias(attribute)));
412     }
413 
414     /**
415      * Adds GreaterOrEqual Than (>=) criteria,
416      * customer_id >= person_id
417      *
418      * @param  attribute   The field name to be used
419      * @param  value       The field name to compare with
420      */
421     public void addGreaterOrEqualThanField(String attribute, Object value)
422     {
423 		// PAW
424 		// addSelectionCriteria(FieldCriteria.buildNotLessCriteria(attribute, value, getAlias()));
425 		addSelectionCriteria(FieldCriteria.buildNotLessCriteria(attribute, value, getUserAlias(attribute)));
426     }
427 
428     /**
429      * Adds LessOrEqual Than (<=) criteria,
430      * customer_id <= 10034
431      *
432      * @param  attribute   The field name to be used
433      * @param  value       An object representing the value of the field
434      */
435     public void addLessOrEqualThan(Object attribute, Object value)
436     {
437 		// PAW
438 		// addSelectionCriteria(ValueCriteria.buildNotGreaterCriteria(attribute, value, getAlias()));
439 		addSelectionCriteria(ValueCriteria.buildNotGreaterCriteria(attribute, value, getUserAlias(attribute)));
440     }
441 
442     /**
443      * Adds LessOrEqual Than (<=) criteria,
444      * customer_id <= person_id
445      *
446      * @param  attribute   The field name to be used
447      * @param  value       The field name to compare with
448      */
449     public void addLessOrEqualThanField(String attribute, Object value)
450     {
451 		// PAW
452 		// addSelectionCriteria(FieldCriteria.buildNotGreaterCriteria(attribute, value, getAlias()));
453 		addSelectionCriteria(FieldCriteria.buildNotGreaterCriteria(attribute, value, getUserAlias(attribute)));
454     }
455 
456     /**
457      * Adds Like (LIKE) criteria,
458      * customer_name LIKE "m%ller"
459      *
460      * @see LikeCriteria
461      * @param  attribute   The field name to be used
462      * @param  value       An object representing the value of the field
463      */
464     public void addLike(Object attribute, Object value)
465     {
466 		// PAW
467 		// addSelectionCriteria(ValueCriteria.buildLikeCriteria(attribute, value, getAlias()));
468 		addSelectionCriteria(ValueCriteria.buildLikeCriteria(attribute, value, getUserAlias(attribute)));
469     }
470 
471     /**
472      * Adds Like (NOT LIKE) criteria,
473      * customer_id NOT LIKE 10034
474      *
475      * @see LikeCriteria
476      * @param  attribute   The field name to be used
477      * @param  value       An object representing the value of the field
478      */
479     public void addNotLike(String attribute, Object value)
480     {
481 		// PAW
482 		// addSelectionCriteria(ValueCriteria.buildNotLikeCriteria(attribute, value, getAlias()));
483 		addSelectionCriteria(ValueCriteria.buildNotLikeCriteria(attribute, value, getUserAlias(attribute)));
484     }
485 
486     /**
487      * Adds NotEqualTo (<>) criteria,
488      * customer_id <> 10034
489      *
490      * @param  attribute   The field name to be used
491      * @param  value       An object representing the value of the field
492      */
493     public void addNotEqualTo(Object attribute, Object value)
494     {
495 		// PAW
496 		// addSelectionCriteria(ValueCriteria.buildNotEqualToCriteria(attribute, value, getAlias()));
497 		addSelectionCriteria(ValueCriteria.buildNotEqualToCriteria(attribute, value, getUserAlias(attribute)));
498     }
499 
500     /**
501      * Adds Greater Than (>) criteria,
502      * customer_id > 10034
503      *
504      * @param  attribute   The field name to be used
505      * @param  value       An object representing the value of the field
506      */
507     public void addGreaterThan(Object attribute, Object value)
508     {
509 		// PAW
510 		// addSelectionCriteria(ValueCriteria.buildGreaterCriteria(attribute, value, getAlias()));
511 		addSelectionCriteria(ValueCriteria.buildGreaterCriteria(attribute, value, getUserAlias(attribute)));
512     }
513 
514     /**
515      * Adds Greater Than (>) criteria,
516      * customer_id > person_id
517      *
518      * @param  attribute   The field name to be used
519      * @param  value       The field to compare with
520      */
521     public void addGreaterThanField(String attribute, Object value)
522     {
523 		// PAW
524 		// addSelectionCriteria(FieldCriteria.buildGreaterCriteria(attribute, value, getAlias()));
525 		addSelectionCriteria(FieldCriteria.buildGreaterCriteria(attribute, value, getUserAlias(attribute)));
526     }
527 
528     /**
529      * Adds Less Than (<) criteria,
530      * customer_id < 10034
531      *
532      * @param  attribute   The field name to be used
533      * @param  value       An object representing the value of the field
534      */
535     public void addLessThan(Object attribute, Object value)
536     {
537 		// PAW
538 		// addSelectionCriteria(ValueCriteria.buildLessCriteria(attribute, value, getAlias()));
539 		addSelectionCriteria(ValueCriteria.buildLessCriteria(attribute, value, getUserAlias(attribute)));
540     }
541 
542     /**
543      * Adds Less Than (<) criteria,
544      * customer_id < person_id
545      *
546      * @param  attribute   The field name to be used
547      * @param  value       The field to compare with
548      */
549     public void addLessThanField(String attribute, Object value)
550     {
551 		// PAW
552 		// addSelectionCriteria(FieldCriteria.buildLessCriteria(attribute, value, getAlias()));
553 		addSelectionCriteria(FieldCriteria.buildLessCriteria(attribute, value, getUserAlias(attribute)));
554     }
555 
556     /**
557      * Adds a field for orderBy, order is ASCENDING
558      * @param  fieldName The field name to be used
559      * @deprecated use #addOrderByAscending(String fieldName)
560      */
561     public void addOrderBy(String fieldName)
562     {
563         addOrderBy(fieldName, true);
564     }
565 
566     /**
567      * Adds a field for orderBy
568      * @param  fieldName the field name to be used
569      * @param  sortAscending true for ASCENDING, false for DESCENDING
570      * @deprecated use QueryByCriteria#addOrderBy
571      */
572     public void addOrderBy(String fieldName, boolean sortAscending)
573     {
574         if (fieldName != null)
575         {
576             _getOrderby().add(new FieldHelper(fieldName, sortAscending));
577         }
578     }
579 
580     /**
581      * Adds a field for orderBy
582      * @param aField the Field
583      * @deprecated use QueryByCriteria#addOrderBy
584      */
585     public void addOrderBy(FieldHelper aField)
586     {
587         if (aField != null)
588         {
589             _getOrderby().add(aField);
590         }
591     }
592 
593     /**
594      * Adds a field for orderBy ASCENDING
595      * @param  fieldName The field name to be used
596      * @deprecated use QueryByCriteria#addOrderByAscending
597      */
598     public void addOrderByAscending(String fieldName)
599     {
600         addOrderBy(fieldName, true);
601     }
602 
603     /**
604      * Adds a field for orderBy DESCENDING
605      * @param  fieldName The field name to be used
606      * @deprecated use QueryByCriteria#addOrderByDescending
607      */
608     public void addOrderByDescending(String fieldName)
609     {
610         addOrderBy(fieldName, false);
611     }
612 
613     /**
614      * Answer the orderBy of all Criteria and Sub Criteria
615      * the elements are of class Criteria.FieldHelper
616      * @return List
617      */
618     List getOrderby()
619     {
620         List result = _getOrderby();
621         Iterator iter = getCriteria().iterator();
622         Object crit;
623 
624         while (iter.hasNext())
625         {
626             crit = iter.next();
627             if (crit instanceof Criteria)
628             {
629                 result.addAll(((Criteria) crit).getOrderby());
630             }
631         }
632 
633         return result;
634     }
635 
636     /**
637      * Answer the Vector with all orderBy,
638      * the elements are of class Criteria.FieldHelper
639      * @return List
640      */
641     protected List _getOrderby()
642     {
643         return orderby;
644     }
645 
646     /**
647      * ORs two sets of criteria together:
648      * <pre>
649      * active = true AND balance < 0 OR active = true AND overdraft = 0
650      * </pre>
651      * @param pc criteria
652      */
653     public void addOrCriteria(Criteria pc)
654     {
655         if (!m_criteria.isEmpty())
656         {
657             pc.setEmbraced(true);
658             pc.setType(OR);
659             addCriteria(pc);
660         }
661         else
662         {
663             setEmbraced(false);
664             pc.setType(OR);
665             addCriteria(pc);
666         }
667     }
668 
669     /**
670      * Adds is Null criteria,
671      * customer_id is Null
672      *
673      * @param  attribute   The field name to be used
674      */
675     public void addIsNull(String attribute)
676     {
677 		// PAW
678 		//addSelectionCriteria(ValueCriteria.buildNullCriteria(attribute, getAlias()));
679 		addSelectionCriteria(ValueCriteria.buildNullCriteria(attribute, getUserAlias(attribute)));
680     }
681 
682     /**
683      * Adds is Null criteria,
684      * customer_id is Null
685      * The attribute will NOT be translated into column name
686      *
687      * @param  column   The column name to be used without translation
688      */
689     public void addColumnIsNull(String column)
690     {
691 		// PAW
692 		//SelectionCriteria c = ValueCriteria.buildNullCriteria(column, getAlias());
693 		SelectionCriteria c = ValueCriteria.buildNullCriteria(column, getUserAlias(column));
694         c.setTranslateAttribute(false);
695         addSelectionCriteria(c);
696     }
697 
698     /**
699      * Adds not Null criteria,
700      * customer_id is not Null
701      *
702      * @param  attribute   The field name to be used
703      */
704     public void addNotNull(String attribute)
705     {
706 		// PAW
707 		//addSelectionCriteria(ValueCriteria.buildNotNullCriteria(attribute, getAlias()));
708 		addSelectionCriteria(ValueCriteria.buildNotNullCriteria(attribute, getUserAlias(attribute)));
709     }
710 
711     /**
712      * Adds not Null criteria,
713      * customer_id is not Null
714      * The attribute will NOT be translated into column name
715      *
716      * @param  column   The column name to be used without translation
717      */
718     public void addColumnNotNull(String column)
719     {
720 		// PAW
721 		// SelectionCriteria c = ValueCriteria.buildNotNullCriteria(column, getAlias());
722 		SelectionCriteria c = ValueCriteria.buildNotNullCriteria(column, getUserAlias(column));
723         c.setTranslateAttribute(false);
724         addSelectionCriteria(c);
725     }
726 
727     /**
728      * Adds BETWEEN criteria,
729      * customer_id between 1 and 10
730      *
731      * @param  attribute   The field name to be used
732      * @param  value1   The lower boundary
733      * @param  value2   The upper boundary
734      */
735     public void addBetween(Object attribute, Object value1, Object value2)
736     {
737 		// PAW
738 		// addSelectionCriteria(ValueCriteria.buildBeweenCriteria(attribute, value1, value2, getAlias()));
739 		addSelectionCriteria(ValueCriteria.buildBeweenCriteria(attribute, value1, value2, getUserAlias(attribute)));
740     }
741 
742     /**
743      * Adds NOT BETWEEN criteria,
744      * customer_id not between 1 and 10
745      *
746      * @param  attribute   The field name to be used
747      * @param  value1   The lower boundary
748      * @param  value2   The upper boundary
749      */
750     public void addNotBetween(Object attribute, Object value1, Object value2)
751     {
752         // PAW
753 		// addSelectionCriteria(ValueCriteria.buildNotBeweenCriteria(attribute, value1, value2, getAlias()));
754 		addSelectionCriteria(ValueCriteria.buildNotBeweenCriteria(attribute, value1, value2, getUserAlias(attribute)));
755     }
756 
757     /**
758      * Adds IN criteria,
759      * customer_id in(1,10,33,44)
760      * large values are split into multiple InCriteria
761      * IN (1,10) OR IN(33, 44)
762      *
763      * @param  attribute   The field name to be used
764      * @param  values   The value Collection
765      */
766     public void addIn(String attribute, Collection values)
767     {
768         List list = splitInCriteria(attribute, values, false, IN_LIMIT);
769         int index = 0;
770         InCriteria inCrit;
771         Criteria allInCritaria;
772 
773         inCrit = (InCriteria) list.get(index);
774         allInCritaria = new Criteria(inCrit);
775 
776         for (index = 1; index < list.size(); index++)
777         {
778             inCrit = (InCriteria) list.get(index);
779             allInCritaria.addOrCriteria(new Criteria(inCrit));
780         }
781 
782         addAndCriteria(allInCritaria);
783     }
784 
785     /**
786      * Adds IN criteria,
787      * customer_id in(1,10,33,44)
788      * large values are split into multiple InCriteria
789      * IN (1,10) OR IN(33, 44) </br>
790      * The attribute will NOT be translated into column name
791      *
792      * @param  column   The column name to be used without translation
793      * @param  values   The value Collection
794      */
795     public void addColumnIn(String column, Collection values)
796     {
797         List list = splitInCriteria(column, values, false, IN_LIMIT);
798         int index = 0;
799         InCriteria inCrit;
800         Criteria allInCritaria;
801 
802         inCrit = (InCriteria) list.get(index);
803         inCrit.setTranslateAttribute(false);
804         allInCritaria = new Criteria(inCrit);
805 
806         for (index = 1; index < list.size(); index++)
807         {
808             inCrit = (InCriteria) list.get(index);
809             inCrit.setTranslateAttribute(false);
810             allInCritaria.addOrCriteria(new Criteria(inCrit));
811         }
812 
813         addAndCriteria(allInCritaria);
814     }
815 
816     /**
817      * Adds NOT IN criteria,
818      * customer_id not in(1,10,33,44)
819      * large values are split into multiple InCriteria
820      * NOT IN (1,10) AND NOT IN(33, 44)
821      *
822      * @param  attribute   The field name to be used
823      * @param  values   The value Collection
824      */
825     public void addNotIn(String attribute, Collection values)
826     {
827         List list = splitInCriteria(attribute, values, true, IN_LIMIT);
828         InCriteria inCrit;
829         for (int index = 0; index < list.size(); index++)
830         {
831             inCrit = (InCriteria) list.get(index);
832             addSelectionCriteria(inCrit);
833         }
834     }
835 
836     /**
837      * IN Criteria with SubQuery
838      * @param attribute The field name to be used
839      * @param subQuery  The subQuery
840      */
841     public void addIn(Object attribute, Query subQuery)
842     {
843         // PAW
844 		// addSelectionCriteria(ValueCriteria.buildInCriteria(attribute, subQuery, getAlias()));
845 		addSelectionCriteria(ValueCriteria.buildInCriteria(attribute, subQuery, getUserAlias(attribute)));
846     }
847 
848     /**
849      * NOT IN Criteria with SubQuery
850      * @param attribute The field name to be used
851      * @param subQuery  The subQuery
852      */
853     public void addNotIn(String attribute, Query subQuery)
854     {
855 		// PAW
856 		// addSelectionCriteria(ValueCriteria.buildNotInCriteria(attribute, subQuery, getAlias()));
857 		addSelectionCriteria(ValueCriteria.buildNotInCriteria(attribute, subQuery, getUserAlias(attribute)));
858     }
859 
860     /**
861      * Adds freeform SQL criteria,
862      * REVERSE(name) like 're%'
863      *
864      * @param  anSqlStatment   The free form SQL-Statement
865      */
866     public void addSql(String anSqlStatment)
867     {
868         addSelectionCriteria(new SqlCriteria(anSqlStatment));
869     }
870 
871     /**
872      * ANDs two sets of criteria together:
873      *
874      * @param  pc criteria
875      */
876     public void addAndCriteria(Criteria pc)
877     {
878         // by combining a second criteria by 'AND' the existing criteria needs to be enclosed
879         // in parenthesis
880         if (!m_criteria.isEmpty())
881         {
882             this.setEmbraced(true);
883             pc.setEmbraced(true);
884             pc.setType(AND);
885             addCriteria(pc);
886         }
887         else
888         {
889             setEmbraced(false);
890             pc.setType(AND);
891             addCriteria(pc);
892         }
893     }
894 
895     /**
896      * Adds an exists(sub query)
897      *
898      * @param subQuery sub-query
899      */
900     public void addExists(Query subQuery)
901     {
902         addSelectionCriteria(new ExistsCriteria(subQuery, false));
903     }
904 
905     /**
906      * Adds a not exists(sub query)
907      *
908      * @param subQuery sub-query
909      */
910     public void addNotExists(Query subQuery)
911     {
912         addSelectionCriteria(new ExistsCriteria(subQuery, true));
913     }
914 
915     /**
916      * Answer true if no sub criteria available
917      * @return boolean
918      */
919     public boolean isEmpty()
920     {
921         return m_criteria.isEmpty();
922     }
923 
924     /**
925      * Gets the groupby for ReportQueries of all Criteria and Sub Criteria
926      * the elements are of class FieldHelper
927      * @return List of FieldHelper
928      */
929     List getGroupby()
930     {
931         List result = _getGroupby();
932         Iterator iter = getCriteria().iterator();
933         Object crit;
934 
935         while (iter.hasNext())
936         {
937             crit = iter.next();
938             if (crit instanceof Criteria)
939             {
940                 result.addAll(((Criteria) crit).getGroupby());
941             }
942         }
943 
944         return result;
945     }
946 
947     /**
948      * Gets the groupby for ReportQueries,
949      * the elements are of class Criteria.FieldHelper
950      * @return List of Criteria.FieldHelper
951      */
952     protected List _getGroupby()
953     {
954         return groupby;
955     }
956 
957     /**
958      * Adds a groupby fieldName for ReportQueries.
959      * @param fieldName The groupby to set
960      * @deprecated use QueryByCriteria#addGroupBy
961      */
962     public void addGroupBy(String fieldName)
963     {
964         if (fieldName != null)
965         {
966             _getGroupby().add(new FieldHelper(fieldName, false));
967         }
968     }
969 
970     /**
971      * Adds a field for groupby
972      * @param aField the Field
973      * @deprecated use QueryByCriteria#addGroupBy
974      */
975     public void addGroupBy(FieldHelper aField)
976     {
977         if (aField != null)
978         {
979             _getGroupby().add(aField);
980         }
981     }
982 
983     /**
984      * Adds an array of groupby fieldNames for ReportQueries.
985      * @param fieldNames The groupby to set
986      * @deprecated use QueryByCriteria#addGroupBy
987      */
988     public void addGroupBy(String[] fieldNames)
989     {
990         for (int i = 0; i < fieldNames.length; i++)
991         {
992             addGroupBy(fieldNames[i]);
993         }
994     }
995 
996     /**
997      * Returns the prefetchedRelationships.
998      * @return List
999      */
1000     List getPrefetchedRelationships()
1001     {
1002         return prefetchedRelationships;
1003     }
1004 
1005     /**
1006      * add the name of a Relationship for prefetch read
1007      * @param aName the name of the relationship
1008      * @deprecated use QueryByCriteria#addPrefetchedRelationship
1009      */
1010     public void addPrefetchedRelationship(String aName)
1011     {
1012         getPrefetchedRelationships().add(aName);
1013     }
1014 
1015     /**
1016      * read the prefetchInLimit from Config based on OJB.properties
1017      */
1018     private static int getSqlInLimit()
1019     {
1020         try
1021         {
1022             PersistenceBrokerConfiguration config = (PersistenceBrokerConfiguration) PersistenceBrokerFactory
1023                     .getConfigurator().getConfigurationFor(null);
1024             return config.getSqlInLimit();
1025         }
1026         catch (ConfigurationException e)
1027         {
1028             return 200;
1029         }
1030     }
1031 
1032 	/**
1033 	 * @return String
1034 	 */
1035 	public String getAlias()
1036 	{
1037 		return m_alias;
1038 	}
1039 
1040 	/**
1041 	 * @return String
1042 	 */
1043 	// PAW
1044 	public UserAlias getUserAlias()
1045 	{
1046 		return m_userAlias;
1047 	}
1048 
1049 	// PAW
1050 	/**
1051 	 * Retrieves or if necessary, creates a user alias to be used
1052 	 * by a child criteria
1053 	 * @param attribute The alias to set
1054 	 */
1055 	private UserAlias getUserAlias(Object attribute)
1056 	{
1057 		if (m_userAlias != null)
1058 		{
1059 			return m_userAlias;
1060 		}
1061 		if (!(attribute instanceof String))
1062 		{
1063 			return null;
1064 		}
1065 		if (m_alias == null)
1066 		{
1067 			return null;
1068 		}
1069 		if (m_aliasPath == null)
1070 		{
1071 			boolean allPathsAliased = true;
1072 			return new UserAlias(m_alias, (String)attribute, allPathsAliased);
1073 		}
1074 		return new UserAlias(m_alias, (String)attribute, m_aliasPath);
1075 	}
1076 
1077 
1078 	/**
1079 	 * Sets the alias. Empty String is regarded as null.
1080 	 * @param alias The alias to set
1081 	 */
1082 	public void setAlias(String alias)
1083 	{
1084 		if (alias == null || alias.trim().equals(""))
1085 		{
1086 			m_alias = null;
1087 		}
1088 		else
1089 		{
1090 			m_alias = alias;
1091 		}
1092 
1093 		// propagate to SelectionCriteria,not to Criteria
1094 		for (int i = 0; i < m_criteria.size(); i++)
1095 		{
1096 			if (!(m_criteria.elementAt(i) instanceof Criteria))
1097 			{
1098 				((SelectionCriteria) m_criteria.elementAt(i)).setAlias(m_alias);
1099 			}
1100 		}
1101 	}
1102 
1103 	// PAW
1104 	/**
1105 	 * Sets the alias. Empty String is regarded as null.
1106 	 * @param alias The alias to set
1107 	 * @param aliasPath The path segment(s) to which the alias applies
1108 	 */
1109 	public void setAlias(String alias, String aliasPath)
1110 	{
1111 		if (alias == null || alias.trim().equals(""))
1112 		{
1113 			m_alias = null;
1114 		}
1115 		else
1116 		{
1117 			m_alias = alias;
1118 			m_aliasPath = aliasPath;
1119 		}
1120 
1121 		// propagate to SelectionCriteria,not to Criteria
1122 		for (int i = 0; i < m_criteria.size(); i++)
1123 		{
1124 			if (!(m_criteria.elementAt(i) instanceof Criteria))
1125 			{
1126 				((SelectionCriteria) m_criteria.elementAt(i)).setAlias(m_alias, aliasPath);
1127 			}
1128 		}
1129 	}
1130 
1131 	// PAW
1132 	/**
1133 	 * Sets the alias using a userAlias object.
1134 	 * @param userAlias The alias to set
1135 	 */
1136 	public void setAlias(UserAlias userAlias)
1137 	{
1138 		m_alias = userAlias.getName();
1139 
1140 		// propagate to SelectionCriteria,not to Criteria
1141 		for (int i = 0; i < m_criteria.size(); i++)
1142 		{
1143 			if (!(m_criteria.elementAt(i) instanceof Criteria))
1144 			{
1145 				((SelectionCriteria) m_criteria.elementAt(i)).setAlias(userAlias);
1146 			}
1147 		}
1148 	}
1149 
1150 
1151     /**
1152      * @return the query containing the criteria
1153      */
1154     public QueryByCriteria getQuery()
1155     {
1156         if (getParentCriteria() != null)
1157         {
1158             return getParentCriteria().getQuery();
1159         }
1160         else
1161         {
1162             return m_query;
1163         }
1164 
1165     }
1166 
1167     /**
1168      * @param query
1169      */
1170     void setQuery(QueryByCriteria query)
1171     {
1172         m_query = query;
1173     }
1174 
1175     /**
1176      * @return the parent criteria
1177      */
1178     public Criteria getParentCriteria()
1179     {
1180         return m_parentCriteria;
1181     }
1182 
1183     /**
1184      * @param criteria
1185      */
1186     void setParentCriteria(Criteria criteria)
1187     {
1188         m_parentCriteria = criteria;
1189     }
1190 
1191     /**
1192      * @see Object#toString()
1193      */
1194     public String toString()
1195     {
1196         if (isNegative())
1197         {
1198             return "-" + m_criteria.toString();
1199         }
1200         else
1201         {
1202             return m_criteria.toString();
1203         }
1204     }
1205 
1206     /**
1207      * @return Returns the negative.
1208      */
1209     public boolean isNegative()
1210     {
1211         return m_negative;
1212     }
1213 
1214     /**
1215      * Flags the whole Criteria as negative.
1216      * @param negative The negative to set.
1217      */
1218     public void setNegative(boolean negative)
1219     {
1220         m_negative = negative;
1221     }
1222 
1223 	// PAW
1224 	/**
1225 	 * Add a hint Class for a path. Used for relationships to extents.<br>
1226 	 * SqlStatment will use these hint classes when resolving the path.
1227 	 * Without these hints SqlStatment will use the base class the
1228 	 * relationship points to ie: Article instead of CdArticle.
1229 	 *
1230 	 * @param aPath the path segment ie: allArticlesInGroup
1231 	 * @param aClass the Class ie: CdArticle
1232 	 * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
1233 	 */
1234 	public void addPathClass(String aPath, Class aClass)
1235 	{
1236 		List pathClasses = (List) m_pathClasses.get(aPath);
1237 		if(pathClasses == null)
1238 		{
1239 			setPathClass(aPath,aClass);
1240 		}
1241 		else
1242 		{
1243 			pathClasses.add(aClass);
1244 			//m_pathClasses.put(aPath, pathClasses);
1245 		}
1246 	}
1247 
1248 	/**
1249 	 * Set the Class for a path. Used for relationships to extents.<br>
1250 	 * SqlStatment will use this class when resolving the path.
1251 	 * Without this hint SqlStatment will use the base class the
1252 	 * relationship points to ie: Article instead of CdArticle.
1253 	 * Using this method is the same as adding just one hint
1254 	 *
1255 	 * @param aPath the path segment ie: allArticlesInGroup
1256 	 * @param aClass the Class ie: CdArticle
1257 	 * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
1258 	 * @see #addPathClass
1259 	 */
1260 	public void setPathClass(String aPath, Class aClass)
1261 	{
1262 		List pathClasses = new ArrayList(1);
1263 		pathClasses.add(aClass);
1264 		m_pathClasses.put(aPath, pathClasses);
1265 	}
1266 
1267 	/**
1268 	 * Get the a List of Class objects used as hints for a path
1269 	 *
1270 	 * @param aPath the path segment ie: allArticlesInGroup
1271 	 * @return a List o Class objects to be used in SqlStatment
1272 	 * @see #addPathClass
1273 	 * @see org.apache.ojb.broker.QueryTest#testInversePathExpression()
1274 	 */
1275 	public List getClassesForPath(String aPath)
1276 	{
1277 		return (List)getPathClasses().get(aPath);
1278 	}
1279 
1280 	/**
1281 	 * Gets the pathClasses.
1282 	 * A Map containing hints about what Class to be used for what path segment
1283 	 * If local instance not set, try parent Criteria's instance.  If this is
1284 	 * the top-level Criteria, try the m_query's instance
1285 	 * @return Returns a Map
1286 	 */
1287 	public Map getPathClasses()
1288 	{
1289 		if (m_pathClasses.isEmpty())
1290 		{
1291 			if (m_parentCriteria == null)
1292 			{
1293 				if (m_query == null)
1294 				{
1295 					return m_pathClasses;
1296 				}
1297 				else
1298 				{
1299 					return m_query.getPathClasses();
1300 				}
1301 			}
1302 			else
1303 			{
1304 				return m_parentCriteria.getPathClasses();
1305 			}
1306 		}
1307 		else
1308 		{
1309 			return m_pathClasses;
1310 		}
1311 	}
1312 
1313 
1314 
1315 }