View Javadoc

1   package org.apache.torque.util;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.Serializable;
23  import java.math.BigDecimal;
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.GregorianCalendar;
29  import java.util.HashMap;
30  import java.util.Iterator;
31  import java.util.LinkedHashMap;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.Set;
35  
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  import org.apache.torque.Column;
39  import org.apache.torque.ColumnImpl;
40  import org.apache.torque.Torque;
41  import org.apache.torque.TorqueException;
42  import org.apache.torque.criteria.CriteriaInterface;
43  import org.apache.torque.criteria.Join;
44  import org.apache.torque.criteria.JoinType;
45  import org.apache.torque.criteria.SqlEnum;
46  import org.apache.torque.om.ObjectKey;
47  import org.apache.torque.sql.OrderBy;
48  import org.apache.torque.sql.Query;
49  import org.apache.torque.sql.SqlBuilder;
50  
51  /**
52   * Encapsulates conditions to access rows in database tables.
53   *
54   * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
55   * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
56   * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
57   * @author <a href="mailto:eric@dobbse.net">Eric Dobbs</a>
58   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
59   * @author <a href="mailto:sam@neurogrid.com">Sam Joseph</a>
60   * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
61   * @author <a href="mailto:fischer@seitenbau.de">Thomas Fischer</a>
62   * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
63   * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
64   * @version $Id: Criteria.java 1377463 2012-08-26 17:24:02Z tv $
65   *
66   * @deprecated This class will be removed in a future version of Torque.
67   *             Use org.apache.torque.criteria.Criteria instead; note that
68   *             that class has another semantics of the add.. and or.. methods.
69   */
70  @Deprecated
71  public class Criteria implements Serializable, CriteriaInterface<Criteria>
72  {
73      /** Serial version. */
74      private static final long serialVersionUID = -9001666575933085601L;
75  
76      /** Comparison type. */
77      public static final SqlEnum EQUAL = SqlEnum.EQUAL;
78  
79      /** Comparison type. */
80      public static final SqlEnum NOT_EQUAL = SqlEnum.NOT_EQUAL;
81  
82      /** Comparison type. */
83      public static final SqlEnum ALT_NOT_EQUAL = SqlEnum.ALT_NOT_EQUAL;
84  
85      /** Comparison type. */
86      public static final SqlEnum GREATER_THAN = SqlEnum.GREATER_THAN;
87  
88      /** Comparison type. */
89      public static final SqlEnum LESS_THAN = SqlEnum.LESS_THAN;
90  
91      /** Comparison type. */
92      public static final SqlEnum GREATER_EQUAL = SqlEnum.GREATER_EQUAL;
93  
94      /** Comparison type. */
95      public static final SqlEnum LESS_EQUAL = SqlEnum.LESS_EQUAL;
96  
97      /** Comparison type. */
98      public static final SqlEnum LIKE = SqlEnum.LIKE;
99  
100     /** Comparison type. */
101     public static final SqlEnum NOT_LIKE = SqlEnum.NOT_LIKE;
102 
103     /** Comparison type. */
104     public static final SqlEnum ILIKE = SqlEnum.ILIKE;
105 
106     /** Comparison type. */
107     public static final SqlEnum NOT_ILIKE = SqlEnum.NOT_ILIKE;
108 
109     /** Comparison type. */
110     public static final SqlEnum CUSTOM = SqlEnum.CUSTOM;
111 
112     /** Comparison type. */
113     public static final SqlEnum DISTINCT = SqlEnum.DISTINCT;
114 
115     /** Comparison type. */
116     public static final SqlEnum IN = SqlEnum.IN;
117 
118     /** Comparison type. */
119     public static final SqlEnum NOT_IN = SqlEnum.NOT_IN;
120 
121     /** Comparison type. */
122     public static final SqlEnum ALL = SqlEnum.ALL;
123 
124     /** Comparison type. */
125     public static final SqlEnum JOIN = SqlEnum.JOIN;
126 
127     /** &quot;IS NULL&quot; null comparison */
128     public static final SqlEnum ISNULL = SqlEnum.ISNULL;
129 
130     /** &quot;IS NOT NULL&quot; null comparison */
131     public static final SqlEnum ISNOTNULL = SqlEnum.ISNOTNULL;
132 
133     /** &quot;CURRENT_DATE&quot; ANSI SQL function */
134     public static final SqlEnum CURRENT_DATE = SqlEnum.CURRENT_DATE;
135 
136     /** &quot;CURRENT_TIME&quot; ANSI SQL function */
137     public static final SqlEnum CURRENT_TIME = SqlEnum.CURRENT_TIME;
138 
139     /** &quot;LEFT JOIN&quot; SQL statement */
140     public static final JoinType LEFT_JOIN = JoinType.LEFT_JOIN;
141 
142     /** &quot;RIGHT JOIN&quot; SQL statement */
143     public static final JoinType RIGHT_JOIN = JoinType.RIGHT_JOIN;
144 
145     /** &quot;INNER JOIN&quot; SQL statement */
146     public static final JoinType INNER_JOIN = JoinType.INNER_JOIN;
147 
148     /** Whether to ignore the case in all String conditions in the criteria. */
149     private boolean ignoreCase = false;
150 
151     /** Whether the result must be a single record. */
152     private boolean singleRecord = false;
153 
154     /** List of modifiers like DISTICT. */
155     private final UniqueList<String> selectModifiers = new UniqueList<String>();
156 
157     /** List of all columns to select. */
158     private final UniqueColumnList selectColumns = new UniqueColumnList();
159 
160     /** All "order by" clauses, containing the order ASC or DESC. */
161     private final UniqueList<OrderBy> orderByColumns = new UniqueList<OrderBy>();
162 
163     /** The names of columns to add to a groupBy clause */
164     private final UniqueColumnList groupByColumns = new UniqueColumnList();
165 
166     /** The having clause in a query. */
167     private Criterion having = null;
168 
169     /** The criterion objects, keyed by the column. */
170     private final Map<Column, Criteria.Criterion> criterionMap
171             = new HashMap<Column, Criteria.Criterion>();
172 
173     /**
174      * Maps column alias names to the real column names.
175      * The key of the map is the alias and the value is the real column.
176      */
177     private final Map<String, Column> asColumns
178             = new LinkedHashMap<String, Column>();
179 
180     /** Contains all joins. */
181     private final List<Join> joins = new ArrayList<Join>();
182 
183     /** The name of the database. */
184     private String dbName;
185 
186     /** The name of the database as given in the contructor. */
187     private final String originalDbName;
188 
189     /**
190      * To limit the number of rows to return.  <code>-1</code> means return all
191      * rows.
192      */
193     private int limit = -1;
194 
195     /** To start the results at a row other than the first one. */
196     private long offset = 0;
197 
198     /**
199      * Aliases for table names. The key of the map is the alias,
200      * and the value is the real name of the table.
201      */
202     private final Map<String, String> aliases = new HashMap<String, String>();
203 
204     /** the log. */
205     private static Log log = LogFactory.getLog(Criteria.class);
206 
207     /**
208      * Creates a new instance with the default capacity.
209      */
210     public Criteria()
211     {
212         this(Torque.getDefaultDB());
213     }
214 
215     /**
216      * Creates a new instance with the specified capacity.
217      *
218      * @param initialCapacity An int.
219      *
220      * @deprecated initialCapacity is disregarded
221      */
222     @Deprecated
223     public Criteria(int initialCapacity)
224     {
225         this(Torque.getDefaultDB());
226     }
227 
228     /**
229      * Creates a new instance with the default capacity which corresponds to
230      * the specified database.
231      *
232      * @param dbName The dabase name.
233      */
234     public Criteria(String dbName)
235     {
236         this.dbName = dbName;
237         this.originalDbName = dbName;
238     }
239 
240     /**
241      * Creates a new instance with the specified capacity which corresponds to
242      * the specified database.
243      *
244      * @param dbName          The dabase name.
245      * @param initialCapacity The initial capacity.
246      *
247      * @deprecated initialCapacity is disregarded
248      */
249     @Deprecated
250     public Criteria(String dbName, int initialCapacity)
251     {
252         this.dbName = dbName;
253         this.originalDbName = dbName;
254     }
255 
256     /**
257      * Brings this criteria back to its initial state, so that it
258      * can be reused as if it was new. Except if the criteria has grown in
259      * capacity, it is left at the current capacity.
260      */
261     public void clear()
262     {
263         criterionMap.clear();
264         ignoreCase = false;
265         singleRecord = false;
266         selectModifiers.clear();
267         selectColumns.clear();
268         orderByColumns.clear();
269         groupByColumns.clear();
270         having = null;
271         asColumns.clear();
272         joins.clear();
273         dbName = originalDbName;
274         offset = 0;
275         limit = -1;
276         aliases.clear();
277     }
278 
279     /**
280      * Add an AS clause to the select columns. Usage:
281      * <p>
282      * <code>
283      *
284      * Criteria myCrit = new Criteria();
285      * myCrit.addAsColumn(&quot;alias&quot;, &quot;ALIAS(&quot;+MyPeer.ID+&quot;)&quot;);
286      *
287      * </code>
288      *
289      * @param name wanted Name of the column
290      * @param clause SQL clause to select from the table
291      *
292      * If the name already exists, it is replaced by the new clause.
293      *
294      * @return A modified Criteria object.
295      */
296     public Criteria addAsColumn(String name, Column clause)
297     {
298         asColumns.put(name, clause);
299         return this;
300     }
301 
302     /**
303      * Add an AS clause to the select columns. Usage:
304      * <p>
305      * <code>
306      *
307      * Criteria myCrit = new Criteria();
308      * myCrit.addAsColumn(&quot;alias&quot;, &quot;ALIAS(&quot;+MyPeer.ID+&quot;)&quot;);
309      *
310      * </code>
311      *
312      * @param name wanted Name of the column
313      * @param clause SQL clause to select from the table
314      *
315      * If the name already exists, it is replaced by the new clause.
316      *
317      * @return A modified Criteria object.
318      */
319     public Criteria addAsColumn(String name, String clause)
320     {
321         asColumns.put(name, new ColumnImpl(clause));
322         return this;
323     }
324 
325     /**
326      * Get the column aliases.
327      *
328      * @return A Map which map the column alias names
329      * to the alias clauses.
330      */
331     public Map<String, Column> getAsColumns()
332     {
333         return asColumns;
334     }
335 
336     /**
337      * Get the table aliases.
338      *
339      * @return A Map which maps the table alias names to the actual table names.
340      */
341     public Map<String, String> getAliases()
342     {
343         return aliases;
344     }
345 
346     /**
347      * Allows one to specify an alias for a table that can
348      * be used in various parts of the SQL.
349      *
350      * @param alias a <code>String</code> value
351      * @param table a <code>String</code> value
352      */
353     public void addAlias(String alias, String table)
354     {
355         aliases.put(alias, table);
356     }
357 
358     /**
359      * Returns the table name associated with an alias.
360      *
361      * @param alias a <code>String</code> value
362      * @return a <code>String</code> value
363      */
364     public String getTableForAlias(String alias)
365     {
366         return aliases.get(alias);
367     }
368 
369     /**
370      * Does this Criteria Object contain the specified key?
371      *
372      * @param table The name of the table.
373      * @param column The name of the column.
374      * @return True if this Criteria Object contain the specified key.
375      *
376      * @deprecated this method does not check in all cases whether a matching
377      *             criterion is contained (e.g. if the criterion has been added
378      *             manually with another key).
379      */
380     @Deprecated
381     public boolean containsKey(String table, String column)
382     {
383         return containsTopLevelColumn(new ColumnImpl(table, column));
384     }
385 
386     /**
387      * Checks whether a Criteria contains a column with the given column's
388      * SQL expression a a top level Criterion.
389      *
390      * @param column the column to check, not null.
391      *
392      * @return true if a top-level criterion with the same column sql expression
393      *         is contained, false otherwise.
394      */
395     private boolean containsTopLevelColumn(Column column)
396     {
397         for (Column candidate : criterionMap.keySet())
398         {
399             if (candidate.getSqlExpression().equals(
400                     column.getSqlExpression()))
401             {
402                 return true;
403             }
404         }
405         return false;
406     }
407 
408     /**
409      * Return the criterion for a column.
410      *
411      * @param column the column to get the criterion for.
412      * @return the Criterion, or null if no criterion is defined
413      *         for this column.
414      */
415     public Criterion getCriterion(Column column)
416     {
417         for (Map.Entry<Column, Criterion> mapEntry : criterionMap.entrySet())
418         {
419             if (mapEntry.getKey().getSqlExpression().equals(
420                     column.getSqlExpression()))
421             {
422                 return mapEntry.getValue();
423             }
424         }
425         return null;
426     }
427 
428     /**
429      * Method to return criteria related to a column in a table.
430      *
431      * @param column the column to get the criterion for.
432      * @return A Criterion.
433      */
434     public Criterion getCriterion(String column)
435     {
436         return getCriterion(new ColumnImpl(column));
437     }
438 
439     /**
440      * Method to return criteria related to a column in a table.
441      *
442      * @param table String name of table.
443      * @param column String name of column.
444      * @return A Criterion.
445      */
446     public Criterion getCriterion(String table, String column)
447     {
448         return getCriterion(new ColumnImpl(table, column));
449     }
450 
451     /**
452      * Method to return criterion that is not added automatically
453      * to this Criteria.  This can be used to chain the
454      * Criterions to form a more complex where clause.
455      *
456      * @param column String full name of column (for example TABLE.COLUMN).
457      * @param value The value to compare to.
458      * @param comparison the comparison to use.
459      *
460      * @return A Criterion.
461      */
462     public Criterion getNewCriterion(Column column, Object value,
463             SqlEnum comparison)
464     {
465         return new Criterion(column, value, comparison);
466     }
467 
468     /**
469      * Method to return criterion that is not added automatically
470      * to this Criteria.  This can be used to chain the
471      * Criterions to form a more complex where clause.
472      *
473      * @param column String full name of column (for example TABLE.COLUMN).
474      * @param value The value to compare to.
475      * @param comparison the comparison to use.
476      *
477      * @return A Criterion.
478      */
479     public Criterion getNewCriterion(String column, Object value,
480             SqlEnum comparison)
481     {
482         return new Criterion(new ColumnImpl(column), value, comparison);
483     }
484 
485     /**
486      * Method to return criterion that is not added automatically
487      * to this Criteria.  This can be used to chain the
488      * Criterions to form a more complex where clause.
489      *
490      * @param table String name of table.
491      * @param column String name of column.
492      * @return A Criterion.
493      */
494     public Criterion getNewCriterion(String table, String column,
495             Object value, SqlEnum comparison)
496     {
497         return new Criterion(table, column, value, comparison);
498     }
499 
500     /**
501      * This method adds a prepared Criterion object to the Criteria.
502      * You can get a new, empty Criterion object with the
503      * getNewCriterion() method. If a criterion for the requested column
504      * already exists, it is replaced. This is used as follows:
505      *
506      * <p>
507      * <code>
508      * Criteria crit = new Criteria();
509      * Criteria.Criterion c = crit
510      * .getNewCriterion(XXXPeer.ID, new Integer(5), Criteria.LESS_THAN);
511      * crit.add(c);
512      * </code>
513      *
514      * @param c A Criterion object
515      *
516      * @return A modified Criteria object.
517      */
518     public Criteria add(Criterion c)
519     {
520         criterionMap.put(c.getColumn(), c);
521         return this;
522     }
523 
524     /**
525      * Method to return a comparison String.
526      *
527      * @param key String name of the key.
528      * @return A String with the value of the object at key.
529      */
530     public SqlEnum getComparison(Column key)
531     {
532         return getCriterion(key).getComparison();
533     }
534 
535     /**
536      * Method to return a comparison String.
537      *
538      * @param table String name of table.
539      * @param column String name of column.
540      * @return A String with the value of the object at key.
541      */
542     public SqlEnum getComparison(String table, String column)
543     {
544         return getComparison(new ColumnImpl(table, column));
545     }
546 
547     /**
548      * Get the Database(Map) name.
549      *
550      * @return A String with the Database(Map) name.  By default, this
551      * is PoolBrokerService.DEFAULT.
552      */
553     public String getDbName()
554     {
555         return dbName;
556     }
557 
558     /**
559      * Set the DatabaseMap name.  If <code>null</code> is supplied, uses value
560      * provided by <code>Torque.getDefaultDB()</code>.
561      *
562      * @param dbName A String with the Database(Map) name.
563      */
564     public void setDbName(String dbName)
565     {
566         this.dbName = (dbName == null ? Torque.getDefaultDB() : dbName.trim());
567     }
568 
569     /**
570      * Convenience method to return value as a boolean.
571      *
572      * @param column The column to retrieve the value for.
573      *
574      * @return A boolean.
575      */
576     public boolean getBoolean(Column column)
577     {
578         return ((Boolean) getCriterion(column).getValue()).booleanValue();
579     }
580 
581     /**
582      * Convenience method to return value as a boolean.
583      *
584      * @param table String name of table.
585      * @param column String name of column.
586      * @return A boolean.
587      */
588     public boolean getBoolean(String table, String column)
589     {
590         return getBoolean(new ColumnImpl(table, column));
591     }
592 
593     /**
594      * Convenience method to return a Date.
595      *
596      * @param column The column to retrieve the value for.
597      *
598      * @return A java.util.Date with the value of object at key.
599      */
600     public java.util.Date getDate(Column column)
601     {
602         return (java.util.Date) getCriterion(column).getValue();
603     }
604 
605     /**
606      * Convenience method to return a Date.
607      *
608      * @param table String name of table.
609      * @param column String name of column.
610      * @return A java.util.Date with the value of object at key.
611      */
612     public java.util.Date getDate(String table, String column)
613     {
614         return getDate(new ColumnImpl(table, column));
615     }
616 
617     /**
618      * Convenience method to return a double.
619      *
620      * @param column The column to retrieve the value for.
621      *
622      * @return A double with the value of object at key.
623      */
624     public double getDouble(Column column)
625     {
626         Object obj = getCriterion(column).getValue();
627         if (obj instanceof String)
628         {
629             return new Double((String) obj).doubleValue();
630         }
631         return ((Double) obj).doubleValue();
632     }
633 
634     /**
635      * Convenience method to return a double.
636      *
637      * @param table String name of table.
638      * @param column String name of column.
639      * @return A double with the value of object at key.
640      */
641     public double getDouble(String table, String column)
642     {
643         return getDouble(new ColumnImpl(table, column));
644     }
645 
646     /**
647      * Convenience method to return a float.
648      *
649      * @param column The column to retrieve the value for.
650      *
651      * @return A float with the value of object at key.
652      */
653     public float getFloat(Column column)
654     {
655         Object obj = getCriterion(column).getValue();
656         if (obj instanceof String)
657         {
658             return new Float((String) obj).floatValue();
659         }
660         return ((Float) obj).floatValue();
661     }
662 
663     /**
664      * Convenience method to return a float.
665      *
666      * @param table String name of table.
667      * @param column String name of column.
668      * @return A float with the value of object at key.
669      */
670     public float getFloat(String table, String column)
671     {
672         return getFloat(new ColumnImpl(table, column));
673     }
674 
675     /**
676      * Convenience method to return an Integer.
677      *
678      * @param column The column to retrieve the value for.
679      *
680      * @return An Integer with the value of object at key.
681      */
682     public Integer getInteger(Column column)
683     {
684         Object obj = getCriterion(column).getValue();
685         if (obj instanceof String)
686         {
687             return new Integer((String) obj);
688         }
689         return ((Integer) obj);
690     }
691 
692     /**
693      * Convenience method to return an Integer.
694      *
695      * @param table String name of table.
696      * @param column String name of column.
697      * @return An Integer with the value of object at key.
698      */
699     public Integer getInteger(String table, String column)
700     {
701         return getInteger(new ColumnImpl(table, column));
702     }
703 
704     /**
705      * Convenience method to return an int.
706      *
707      * @param column The column to retrieve the value for.
708      *
709      * @return An int with the value of object at key.
710      */
711     public int getInt(Column column)
712     {
713         Object obj = getCriterion(column).getValue();
714         if (obj instanceof String)
715         {
716             return new Integer((String) obj).intValue();
717         }
718         return ((Integer) obj).intValue();
719     }
720 
721     /**
722      * Convenience method to return an int.
723      *
724      * @param table String name of table.
725      * @param column String name of column.
726      * @return An int with the value of object at key.
727      */
728     public int getInt(String table, String column)
729     {
730         return getInt(new ColumnImpl(table, column));
731     }
732 
733     /**
734      * Convenience method to return a BigDecimal.
735      *
736      * @param column The column to retrieve the value for.
737      *
738      * @return A BigDecimal with the value of object at key.
739      */
740     public BigDecimal getBigDecimal(Column column)
741     {
742         Object obj = getCriterion(column).getValue();
743         if (obj instanceof String)
744         {
745             return new BigDecimal((String) obj);
746         }
747         return (BigDecimal) obj;
748     }
749 
750     /**
751      * Convenience method to return a BigDecimal.
752      *
753      * @param table String name of table.
754      * @param column String name of column.
755      * @return A BigDecimal with the value of object at key.
756      */
757     public BigDecimal getBigDecimal(String table, String column)
758     {
759         return getBigDecimal(new ColumnImpl(table, column));
760     }
761 
762     /**
763      * Convenience method to return a long.
764      *
765      * @param column The column to retrieve the value for.
766      *
767      * @return A long with the value of object at key.
768      */
769     public long getLong(Column column)
770     {
771         Object obj = getCriterion(column).getValue();
772         if (obj instanceof String)
773         {
774             return new Long((String) obj).longValue();
775         }
776         return ((Long) obj).longValue();
777     }
778 
779     /**
780      * Convenience method to return a long.
781      *
782      * @param table String name of table.
783      * @param column String name of column.
784      * @return A long with the value of object at key.
785      */
786     public long getLong(String table, String column)
787     {
788         return getLong(new ColumnImpl(table, column));
789     }
790 
791     /**
792      * Convenience method to return a String.
793      *
794      * @param column The column to retrieve the value for.
795      *
796      * @return A String with the value of object at key.
797      */
798     public String getString(Column column)
799     {
800         return (String) getCriterion(column).getValue();
801     }
802 
803     /**
804      * Convenience method to return a String.
805      *
806      * @param table String name of table.
807      * @param column String name of column.
808      * @return A String with the value of object at key.
809      */
810     public String getString(String table, String column)
811     {
812         return getString(new ColumnImpl(table, column));
813     }
814 
815     /**
816      * Convenience method to return a List.
817      *
818      * @param column The column to retrieve the value for.
819      *
820      * @return A List with the value of object at key.
821      */
822     @SuppressWarnings("unchecked")
823     public List<Object> getList(Column column)
824     {
825         return (List<Object>) getCriterion(column).getValue();
826     }
827 
828     /**
829      * Convenience method to return a List.
830      *
831      * @param table String name of table.
832      * @param column String name of column.
833      * @return A List with the value of object at key.
834      */
835     public List<Object> getList(String table, String column)
836     {
837         return getList(new ColumnImpl(table, column));
838     }
839 
840     /**
841      * Method to return the value that was added to Criteria.
842      *
843      * @param column The column to retrieve the value for.
844      *
845      * @return An Object with the value of object at key.
846      */
847     public Object getValue(Column column)
848     {
849         return getCriterion(column).getValue();
850     }
851 
852     /**
853      * Method to return the value that was added to Criteria.
854      *
855      * @param table String name of table.
856      * @param column String name of column.
857      * @return An Object with the value of object at key.
858      */
859     public Object getValue(String table, String column)
860     {
861         return getValue(new ColumnImpl(table, column));
862     }
863 
864     /**
865      * Convenience method to return an ObjectKey.
866      *
867      * @param column The column to retrieve the value for.
868      *
869      * @return An ObjectKey with the value of object at key.
870      */
871     public ObjectKey getObjectKey(Column column)
872     {
873         return (ObjectKey) getCriterion(column).getValue();
874     }
875 
876     /**
877      * Convenience method to return an ObjectKey.
878      *
879      * @param table String name of table.
880      * @param column String name of column.
881      * @return A String with the value of object at key.
882      */
883     public ObjectKey getObjectKey(String table, String column)
884     {
885         return getObjectKey(new ColumnImpl(table, column));
886     }
887 
888     /**
889      * Returns the value in the top-level criterion for the given key.
890      *
891      * @param key the key for the criterion.
892      *
893      * @return the value of the criterion.
894      *
895      * @throws NullPointerException if no Criterion is stored under the key.
896      *
897      * @deprecated this method only works if a criterion exists for the key.
898      */
899     @Deprecated
900     public Object get(Column key)
901     {
902         return getValue(key);
903     }
904 
905     /**
906      * Returns whether there are any criterions in this criteria.
907      *
908      * @return true if there are criterions, false otherwise.
909      */
910     public boolean isEmpty()
911     {
912         return criterionMap.isEmpty();
913     }
914 
915     /**
916      * Returns how many top-level criterions are in this criteria.
917      *
918      * @return the number of op-level criterions.
919      *
920      * @deprecated this method counts only top-level criterions, not all.
921      */
922     @Deprecated
923     public int size()
924     {
925         return criterionMap.size();
926     }
927 
928     /**
929      * Returns all the top-level Criterions in this criteria
930      * (but not the chained Criterions).
931      *
932      * @return all top-level Criterions, not null.
933      */
934     public Collection<Criterion> values()
935     {
936         return criterionMap.values();
937     }
938 
939     /**
940      * Equivalent to add(key, value).
941      *
942      * @param column the column.
943      * @param value An Object to which the column should be equal.
944      *
945      * @return Instance of self.
946      *
947      * @throws NullPointerException if key is null.
948      *
949      * @deprecated use add(String, Object) instead
950      */
951     @Deprecated
952     public Object put(Column column, Object value)
953     {
954         return add(column, value);
955     }
956 
957     /**
958      * Copies all of the mappings from the specified Map to this Criteria
959      * These mappings will replace any mappings that this Criteria had for any
960      * of the keys currently in the specified Map.
961      *
962      * @param t Objects to be stored in this criteria.
963      */
964     public synchronized void putAll(Map<Column, Criterion> t)
965     {
966         Iterator<Map.Entry<Column, Criterion>> i = t.entrySet().iterator();
967         while (i.hasNext())
968         {
969             Map.Entry<Column, Criterion> e = i.next();
970             Criterion val = e.getValue();
971             criterionMap.put(e.getKey(), val);
972         }
973     }
974 
975     /**
976      * This method adds a new criterion to the list of criterias. If a
977      * criterion for the requested column already exists, it is
978      * replaced. This is used as follows:
979      *
980      * <p>
981      * <code>
982      * Criteria crit = new Criteria().add(&quot;column&quot;,
983      *                                      &quot;value&quot;);
984      * </code>
985      *
986      * An EQUAL comparison is used for column and value.
987      *
988      * The name of the table must be used implicitly in the column name,
989      * so the Column name must be something like 'TABLE.id'. If you
990      * don't like this, you can use the add(table, column, value) method.
991      *
992      * @param column The column to run the comparison on
993      * @param value An Object.
994      *
995      * @return A modified Criteria object.
996      */
997     public Criteria add(Column column, Object value)
998     {
999         add(column, value, EQUAL);
1000         return this;
1001     }
1002 
1003     /**
1004      * This method adds a new criterion to the list of criterias.
1005      * If a criterion for the requested column already exists, it is
1006      * replaced. If is used as follow:
1007      *
1008      * <p>
1009      * <code>
1010      * Criteria crit = new Criteria().add(&quot;column&quot;,
1011      *                                      &quot;value&quot;
1012      *                                      Criteria.GREATER_THAN);
1013      * </code>
1014      *
1015      * Any comparison can be used.
1016      *
1017      * The name of the table must be used implicitly in the column name,
1018      * so the Column name must be something like 'TABLE.id'. If you
1019      * don't like this, you can use the add(table, column, value) method.
1020      *
1021      * @param column The column to run the comparison on
1022      * @param value An Object.
1023      * @param comparison A String.
1024      *
1025      * @return A modified Criteria object.
1026      */
1027     public Criteria add(Column column, Object value, SqlEnum comparison)
1028     {
1029         criterionMap.put(column, new Criterion(column, value, comparison));
1030         return this;
1031     }
1032 
1033     /**
1034      * This method adds a new criterion to the list of criterias. If a
1035      * criterion for the requested column already exists, it is
1036      * replaced. This is used as follows:
1037      *
1038      * <p>
1039      * <code>
1040      * Criteria crit = new Criteria().add(&quot;column&quot;,
1041      *                                      &quot;value&quot;);
1042      * </code>
1043      *
1044      * An EQUAL comparison is used for column and value.
1045      *
1046      * The name of the table must be used implicitly in the column name,
1047      * so the Column name must be something like 'TABLE.id'. If you
1048      * don't like this, you can use the add(table, column, value) method.
1049      *
1050      * @param column The column to run the comparison on
1051      * @param value An Object.
1052      *
1053      * @return A modified Criteria object.
1054      */
1055     public Criteria add(String column, Object value)
1056     {
1057         add(column, value, EQUAL);
1058         return this;
1059     }
1060 
1061     /**
1062      * This method adds a new criterion to the list of criterias.
1063      * If a criterion for the requested column already exists, it is
1064      * replaced. If is used as follow:
1065      *
1066      * <p>
1067      * <code>
1068      * Criteria crit = new Criteria().add(&quot;column&quot;,
1069      *                                      &quot;value&quot;
1070      *                                      Criteria.GREATER_THAN);
1071      * </code>
1072      *
1073      * Any comparison can be used.
1074      *
1075      * The name of the table must be used implicitly in the column name,
1076      * so the Column name must be something like 'TABLE.id'. If you
1077      * don't like this, you can use the add(table, column, value) method.
1078      *
1079      * @param column The column to run the comparison on
1080      * @param value An Object.
1081      * @param comparison A String.
1082      *
1083      * @return A modified Criteria object.
1084      */
1085     public Criteria add(String column, Object value, SqlEnum comparison)
1086     {
1087         Column columnImpl = new ColumnImpl(column);
1088         criterionMap.put(
1089                 columnImpl,
1090                 new Criterion(columnImpl, value, comparison));
1091         return this;
1092     }
1093 
1094     /**
1095      * This method adds a new criterion to the list of criterias.
1096      * If a criterion for the requested column already exists, it is
1097      * replaced. If is used as follows:
1098      *
1099      * <p>
1100      * <code>
1101      * Criteria crit = new Criteria().add(&quot;table&quot;,
1102      *                                      &quot;column&quot;,
1103      *                                      &quot;value&quot;);
1104      * </code>
1105      *
1106      * An EQUAL comparison is used for column and value.
1107      *
1108      * @param table Name of the table which contains the column
1109      * @param column The column to run the comparison on
1110      * @param value An Object.
1111      *
1112      * @return A modified Criteria object.
1113      */
1114     public Criteria add(String table, String column, Object value)
1115     {
1116         add(table, column, value, EQUAL);
1117         return this;
1118     }
1119 
1120     /**
1121      * This method adds a new criterion to the list of criterias.
1122      * If a criterion for the requested column already exists, it is
1123      * replaced. If is used as follows:
1124      *
1125      * <p>
1126      * <code>
1127      * Criteria crit = new Criteria().add(&quot;table&quot;,
1128      *                                      &quot;column&quot;,
1129      *                                      &quot;value&quot;,
1130      *                                      Criteria.GREATER_THAN);
1131      * </code>
1132      *
1133      * Any comparison can be used.
1134      *
1135      * @param table Name of table which contains the column
1136      * @param column The column to run the comparison on
1137      * @param value An Object.
1138      * @param comparison String describing how to compare the column with
1139      *        the value
1140      * @return A modified Criteria object.
1141      */
1142     public Criteria add(String table,
1143             String column,
1144             Object value,
1145             SqlEnum comparison)
1146     {
1147         Column columnImpl = new ColumnImpl(table, column);
1148         criterionMap.put(columnImpl,
1149                 new Criterion(columnImpl, value, comparison));
1150         return this;
1151     }
1152 
1153     /**
1154      * Convenience method to add a Date object specified by
1155      * year, month, and date into the Criteria.
1156      * Equal to
1157      *
1158      * <p>
1159      * <code>
1160      * add(column, new GregorianCalendar(year, month,date), EQUAL);
1161      * </code>
1162      *
1163      * @param column A String value to use as column.
1164      * @param year An int with the year.
1165      * @param month An int with the month. Month value is 0-based.
1166      *        e.g., 0 for January
1167      * @param day An int with the day.
1168      * @return A modified Criteria object.
1169      */
1170     public Criteria addDate(Column column, int year, int month, int day)
1171     {
1172         add(column, new GregorianCalendar(year, month, day).getTime());
1173         return this;
1174     }
1175 
1176     /**
1177      * Convenience method to add a Date object specified by
1178      * year, month, and date into the Criteria.
1179      * Equal to
1180      *
1181      * <p>
1182      * <code>
1183      * add(column, new GregorianCalendar(year, month,date), comparison);
1184      * </code>
1185      *
1186      * @param column The column to run the comparison on
1187      * @param year An int with the year.
1188      * @param month An int with the month. Month value is 0-based.
1189      *        e.g., 0 for January
1190      * @param date An int with the date.
1191      * @param comparison String describing how to compare the column with
1192      *        the value
1193      * @return A modified Criteria object.
1194      */
1195     public Criteria addDate(Column column, int year, int month, int date,
1196             SqlEnum comparison)
1197     {
1198         add(column, new GregorianCalendar(year, month, date).getTime(),
1199                 comparison);
1200         return this;
1201     }
1202 
1203     /**
1204      * Convenience method to add a Date object specified by
1205      * year, month, and date into the Criteria.
1206      * Equal to
1207      *
1208      * <p>
1209      * <code>
1210      * add(column, new GregorianCalendar(year, month,date), EQUAL);
1211      * </code>
1212      *
1213      * @param column A String value to use as column.
1214      * @param year An int with the year.
1215      * @param month An int with the month. Month value is 0-based.
1216      *        e.g., 0 for January
1217      * @param day An int with the day.
1218      * @return A modified Criteria object.
1219      */
1220     public Criteria addDate(String column, int year, int month, int day)
1221     {
1222         add(column, new GregorianCalendar(year, month, day).getTime());
1223         return this;
1224     }
1225 
1226     /**
1227      * Convenience method to add a Date object specified by
1228      * year, month, and date into the Criteria.
1229      * Equal to
1230      *
1231      * <p>
1232      * <code>
1233      * add(column, new GregorianCalendar(year, month,date), comparison);
1234      * </code>
1235      *
1236      * @param column The column to run the comparison on
1237      * @param year An int with the year.
1238      * @param month An int with the month. Month value is 0-based.
1239      *        e.g., 0 for January
1240      * @param date An int with the date.
1241      * @param comparison String describing how to compare the column with
1242      *        the value
1243      * @return A modified Criteria object.
1244      */
1245     public Criteria addDate(String column, int year, int month, int date,
1246             SqlEnum comparison)
1247     {
1248         add(column, new GregorianCalendar(year, month, date).getTime(),
1249                 comparison);
1250         return this;
1251     }
1252 
1253     /**
1254      * This is the way that you should add a join of two tables.  For
1255      * example:
1256      *
1257      * <p>
1258      * AND PROJECT.PROJECT_ID=FOO.PROJECT_ID
1259      * <p>
1260      *
1261      * left = PROJECT.PROJECT_ID
1262      * right = FOO.PROJECT_ID
1263      *
1264      * @param left A String with the left side of the join.
1265      * @param right A String with the right side of the join.
1266      * @return A modified Criteria object.
1267      */
1268     public Criteria addJoin(Column left, Column right)
1269     {
1270         return addJoin(left, right, null);
1271     }
1272 
1273     /**
1274      * This is the way that you should add a join of two tables.  For
1275      * example:
1276      *
1277      * <p>
1278      * PROJECT LEFT JOIN FOO ON PROJECT.PROJECT_ID=FOO.PROJECT_ID
1279      * <p>
1280      *
1281      * left = &quot;PROJECT.PROJECT_ID&quot;
1282      * right = &quot;FOO.PROJECT_ID&quot;
1283      * operator = Criteria.LEFT_JOIN
1284      *
1285      * @param left A String with the left side of the join.
1286      * @param right A String with the right side of the join.
1287      * @param operator The operator used for the join: must be one of null,
1288      *        Criteria.LEFT_JOIN, Criteria.RIGHT_JOIN, Criteria.INNER_JOIN
1289      * @return A modified Criteria object.
1290      */
1291     public Criteria addJoin(Column left, Column right, JoinType operator)
1292     {
1293         joins.add(new Join(left, right, Criteria.EQUAL, operator));
1294 
1295         return this;
1296     }
1297 
1298     /**
1299      * This is the way that you should add a join of two tables.  For
1300      * example:
1301      *
1302      * <p>
1303      * AND PROJECT.PROJECT_ID=FOO.PROJECT_ID
1304      * <p>
1305      *
1306      * left = PROJECT.PROJECT_ID
1307      * right = FOO.PROJECT_ID
1308      *
1309      * @param left A String with the left side of the join.
1310      * @param right A String with the right side of the join.
1311      * @return A modified Criteria object.
1312      */
1313     public Criteria addJoin(String left, String right)
1314     {
1315         return addJoin(left, right, null);
1316     }
1317 
1318     /**
1319      * This is the way that you should add a join of two tables.  For
1320      * example:
1321      *
1322      * <p>
1323      * PROJECT LEFT JOIN FOO ON PROJECT.PROJECT_ID=FOO.PROJECT_ID
1324      * <p>
1325      *
1326      * left = &quot;PROJECT.PROJECT_ID&quot;
1327      * right = &quot;FOO.PROJECT_ID&quot;
1328      * operator = Criteria.LEFT_JOIN
1329      *
1330      * @param left A String with the left side of the join.
1331      * @param right A String with the right side of the join.
1332      * @param operator The operator used for the join: must be one of null,
1333      *        Criteria.LEFT_JOIN, Criteria.RIGHT_JOIN, Criteria.INNER_JOIN
1334      * @return A modified Criteria object.
1335      */
1336     public Criteria addJoin(String left, String right, JoinType operator)
1337     {
1338         joins.add(new Join(
1339                 new ColumnImpl(left),
1340                 new ColumnImpl(right),
1341                 Criteria.EQUAL,
1342                 operator));
1343 
1344         return this;
1345     }
1346 
1347     /**
1348      * get the List of Joins.  This method is meant to
1349      * be called by BasePeerImpl.
1350      * @return a List which contains objects of type Join.
1351      *         If the criteria does not contains any joins, the list is empty
1352      */
1353     public List<Join> getJoins()
1354     {
1355         return joins;
1356     }
1357 
1358     /**
1359      * Adds an 'IN' clause with the criteria supplied as an Object
1360      * array.  For example:
1361      *
1362      * <p>
1363      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
1364      * <p>
1365      *
1366      * where 'values' contains three objects that evaluate to the
1367      * respective strings above when .toString() is called.
1368      *
1369      * If a criterion for the requested column already exists, it is
1370      * replaced.
1371      *
1372      * @param column The column to run the comparison on
1373      * @param values An Object[] with the allowed values.
1374      * @return A modified Criteria object.
1375      */
1376     public Criteria addIn(Column column, Object[] values)
1377     {
1378         add(column, values, Criteria.IN);
1379         return this;
1380     }
1381 
1382     /**
1383      * Adds an 'IN' clause with the criteria supplied as an Object
1384      * array.  For example:
1385      *
1386      * <p>
1387      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
1388      * <p>
1389      *
1390      * where 'values' contains three objects that evaluate to the
1391      * respective strings above when .toString() is called.
1392      *
1393      * If a criterion for the requested column already exists, it is
1394      * replaced.
1395      *
1396      * @param column The column to run the comparison on
1397      * @param values An Object[] with the allowed values.
1398      * @return A modified Criteria object.
1399      */
1400     public Criteria addIn(String column, Object[] values)
1401     {
1402         add(column, values, Criteria.IN);
1403         return this;
1404     }
1405 
1406     /**
1407      * Adds an 'IN' clause with the criteria supplied as a Collection.
1408      * For example:
1409      *
1410      * <p>
1411      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
1412      * <p>
1413      *
1414      * where 'values' contains three Strings "FOO", "BAR" and "ZOW".
1415      *
1416      * If a criterion for the requested column already exists, it is
1417      * replaced.
1418      *
1419      * @param column The column to run the comparison on
1420      * @param values A Collection with the allowed values.
1421      *
1422      * @return A modified Criteria object.
1423      */
1424     public Criteria addIn(Column column, Collection<?> values)
1425     {
1426         add(column, values, Criteria.IN);
1427         return this;
1428     }
1429 
1430     /**
1431      * Adds an 'IN' clause with the criteria supplied as a Collection.
1432      * For example:
1433      *
1434      * <p>
1435      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
1436      * <p>
1437      *
1438      * where 'values' contains three Strings "FOO", "BAR" and "ZOW".
1439      *
1440      * If a criterion for the requested column already exists, it is
1441      * replaced.
1442      *
1443      * @param column The column to run the comparison on
1444      * @param values A Collection with the allowed values.
1445      *
1446      * @return A modified Criteria object.
1447      */
1448     public Criteria addIn(String column, Collection<?> values)
1449     {
1450         add(column, values, Criteria.IN);
1451         return this;
1452     }
1453 
1454     /**
1455      * Adds a 'NOT IN' clause with the criteria supplied as an Object
1456      * array.  For example:
1457      *
1458      * <p>
1459      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
1460      * <p>
1461      *
1462      * where 'values' contains three objects that evaluate to the
1463      * respective strings above when .toString() is called.
1464      *
1465      * If a criterion for the requested column already exists, it is
1466      * replaced.
1467      *
1468      * @param column The column to run the comparison on
1469      * @param values An Object[] with the disallowed values.
1470      * @return A modified Criteria object.
1471      */
1472     public Criteria addNotIn(Column column, Object[] values)
1473     {
1474         add(column, values, Criteria.NOT_IN);
1475         return this;
1476     }
1477 
1478     /**
1479      * Adds a 'NOT IN' clause with the criteria supplied as an Object
1480      * array.  For example:
1481      *
1482      * <p>
1483      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
1484      * <p>
1485      *
1486      * where 'values' contains three objects that evaluate to the
1487      * respective strings above when .toString() is called.
1488      *
1489      * If a criterion for the requested column already exists, it is
1490      * replaced.
1491      *
1492      * @param column The column to run the comparison on
1493      * @param values An Object[] with the disallowed values.
1494      * @return A modified Criteria object.
1495      */
1496     public Criteria addNotIn(String column, Object[] values)
1497     {
1498         add(column, values, Criteria.NOT_IN);
1499         return this;
1500     }
1501 
1502     /**
1503      * Adds a 'NOT IN' clause with the criteria supplied as a Collection.
1504      * For example:
1505      *
1506      * <p>
1507      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
1508      * <p>
1509      *
1510      * where 'values' contains three Strings "FOO", "BAR" and "ZOW".
1511      *
1512      * If a criterion for the requested column already exists, it is
1513      * replaced.
1514      *
1515      * @param column The column to run the comparison on
1516      * @param values A Collection with the disallowed values.
1517      *
1518      * @return A modified Criteria object.
1519      */
1520     public Criteria addNotIn(Column column, Collection<?> values)
1521     {
1522         add(column, values, Criteria.NOT_IN);
1523         return this;
1524     }
1525 
1526     /**
1527      * Adds a 'NOT IN' clause with the criteria supplied as a Collection.
1528      * For example:
1529      *
1530      * <p>
1531      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
1532      * <p>
1533      *
1534      * where 'values' contains three Strings "FOO", "BAR" and "ZOW".
1535      *
1536      * If a criterion for the requested column already exists, it is
1537      * replaced.
1538      *
1539      * @param column The column to run the comparison on
1540      * @param values A Collection with the disallowed values.
1541      *
1542      * @return A modified Criteria object.
1543      */
1544     public Criteria addNotIn(String column, Collection<?> values)
1545     {
1546         add(column, values, Criteria.NOT_IN);
1547         return this;
1548     }
1549 
1550     /**
1551      * Adds &quot;ALL &quot; to the SQL statement.
1552      */
1553     public void setAll()
1554     {
1555         selectModifiers.add(ALL.toString());
1556     }
1557 
1558     /**
1559      * Adds &quot;DISTINCT &quot; to the SQL statement.
1560      */
1561     public void setDistinct()
1562     {
1563         selectModifiers.add(DISTINCT.toString());
1564     }
1565 
1566     /**
1567      * Sets whether case should be ignored in where clauses and order by
1568      * whenever String columns are encountered.
1569      *
1570      * @param b True if case should be ignored.
1571      * @return A modified Criteria object.
1572      */
1573     public Criteria setIgnoreCase(boolean b)
1574     {
1575         ignoreCase = b;
1576         return this;
1577     }
1578 
1579     /**
1580      * Returns whether case should be ignored in where clauses and order by
1581      * whenever String columns are encountered.
1582      *
1583      * @return True if case is ignored.
1584      */
1585     public boolean isIgnoreCase()
1586     {
1587         return ignoreCase;
1588     }
1589 
1590     /**
1591      * Set single record?  Set this to <code>true</code> if you expect the query
1592      * to result in only a single result record (the default behaviour is to
1593      * throw a TorqueException if multiple records are returned when the query
1594      * is executed).  This should be used in situations where returning multiple
1595      * rows would indicate an error of some sort.  If your query might return
1596      * multiple records but you are only interested in the first one then you
1597      * should be using setLimit(1).
1598      *
1599      * @param b set to <code>true</code> if you expect the query to select just
1600      * one record.
1601      * @return A modified Criteria object.
1602      */
1603     public Criteria setSingleRecord(boolean b)
1604     {
1605         singleRecord = b;
1606         return this;
1607     }
1608 
1609     /**
1610      * Is single record?
1611      *
1612      * @return True if a single record is being returned.
1613      */
1614     public boolean isSingleRecord()
1615     {
1616         return singleRecord;
1617     }
1618 
1619     /**
1620      * Set limit.
1621      *
1622      * @param limit An int with the value for limit.
1623      * @return A modified Criteria object.
1624      */
1625     public Criteria setLimit(int limit)
1626     {
1627         this.limit = limit;
1628         return this;
1629     }
1630 
1631     /**
1632      * Get limit.
1633      *
1634      * @return An int with the value for limit.
1635      */
1636     public int getLimit()
1637     {
1638         return limit;
1639     }
1640 
1641     /**
1642      * Set offset.
1643      *
1644      * @param offset An int with the value for offset.
1645      * @return A modified Criteria object.
1646      */
1647     public Criteria setOffset(long offset)
1648     {
1649         this.offset = offset;
1650         return this;
1651     }
1652 
1653     /**
1654      * Get offset.
1655      *
1656      * @return An int with the value for offset.
1657      */
1658     public long getOffset()
1659     {
1660         return offset;
1661     }
1662 
1663     /**
1664      * Add select column.
1665      *
1666      * @param column The select column to add.
1667      * @return A modified Criteria object.
1668      */
1669     public Criteria addSelectColumn(Column column)
1670     {
1671         selectColumns.add(column);
1672         return this;
1673     }
1674 
1675     /**
1676      * Add select column.
1677      *
1678      * @param column A String with the name of the select column.
1679      * @return A modified Criteria object.
1680      */
1681     public Criteria addSelectColumn(String column)
1682     {
1683         selectColumns.add(new ColumnImpl(column));
1684         return this;
1685     }
1686 
1687     /**
1688      * Get select columns.
1689      *
1690      * @return An List with the names of the select columns.
1691      */
1692     public UniqueColumnList getSelectColumns()
1693     {
1694         return selectColumns;
1695     }
1696 
1697     /**
1698      * Get select modifiers.
1699      *
1700      * @return An UniqueList with the select modifiers.
1701      */
1702     public UniqueList<String> getSelectModifiers()
1703     {
1704         return selectModifiers;
1705     }
1706 
1707     /**
1708      * Add group by column name.
1709      *
1710      * @param groupBy The name of the column to group by.
1711      * @return A modified Criteria object.
1712      */
1713     public Criteria addGroupByColumn(Column groupBy)
1714     {
1715         groupByColumns.add(groupBy);
1716         return this;
1717     }
1718 
1719     /**
1720      * Add group by column name.
1721      *
1722      * @param groupBy The name of the column to group by.
1723      * @return A modified Criteria object.
1724      */
1725     public Criteria addGroupByColumn(String groupBy)
1726     {
1727         groupByColumns.add(new ColumnImpl(groupBy));
1728         return this;
1729     }
1730 
1731     /**
1732      * Add order by column name, explicitly specifying ascending.
1733      *
1734      * @param column The column to order by.
1735      * @return A modified Criteria object.
1736      */
1737     public Criteria addAscendingOrderByColumn(Column column)
1738     {
1739         orderByColumns.add(new OrderBy(column, SqlEnum.ASC, false));
1740         return this;
1741     }
1742 
1743 
1744     /**
1745      * Add order by column name, explicitly specifying ascending.
1746      *
1747      * @param column The column to order by.
1748      * @param ignoreCase whether to ignore case on String columns.
1749      *
1750      * @return A modified Criteria object.
1751      */
1752     public Criteria addAscendingOrderByColumn(Column column, boolean ignoreCase)
1753     {
1754         orderByColumns.add(new OrderBy(column, SqlEnum.ASC, ignoreCase));
1755         return this;
1756     }
1757     /**
1758      * Add order by column name, explicitly specifying ascending.
1759      *
1760      * @param column The column to order by.
1761      * @return A modified Criteria object.
1762      */
1763     public Criteria addAscendingOrderByColumn(String column)
1764     {
1765         orderByColumns.add(
1766                 new OrderBy(new ColumnImpl(column), SqlEnum.ASC, false));
1767         return this;
1768     }
1769 
1770     /**
1771      * Add order by column name, explicitly specifying descending.
1772      *
1773      * @param column The column to order by.
1774      * @return A modified Criteria object.
1775      */
1776     public Criteria addDescendingOrderByColumn(Column column)
1777     {
1778         orderByColumns.add(new OrderBy(column, SqlEnum.DESC, false));
1779         return this;
1780     }
1781 
1782     /**
1783      * Add order by column name, explicitly specifying descending.
1784      *
1785      * @param column The column to order by.
1786      * @param ignoreCase whether to ignore case on String columns.
1787      *
1788      * @return A modified Criteria object.
1789      */
1790     public Criteria addDescendingOrderByColumn(
1791             Column column,
1792             boolean ignoreCase)
1793     {
1794         orderByColumns.add(new OrderBy(column, SqlEnum.DESC, ignoreCase));
1795         return this;
1796     }
1797 
1798     /**
1799      * Add order by column name, explicitly specifying descending.
1800      *
1801      * @param column The column to order by.
1802      * @return A modified Criteria object.
1803      */
1804     public Criteria addDescendingOrderByColumn(String column)
1805     {
1806         orderByColumns.add(
1807                 new OrderBy(new ColumnImpl(column), SqlEnum.DESC, false));
1808         return this;
1809     }
1810 
1811     /**
1812      * Get order by columns.
1813      *
1814      * @return An UniqueList with the name of the order columns, not null.
1815      */
1816     public UniqueList<OrderBy> getOrderByColumns()
1817     {
1818         return orderByColumns;
1819     }
1820 
1821     /**
1822      * Get group by columns.
1823      *
1824      * @return An UniqueList with the name of the groupBy clause, not null.
1825      */
1826     public UniqueColumnList getGroupByColumns()
1827     {
1828         return groupByColumns;
1829     }
1830 
1831     /**
1832      * Get Having Criterion.
1833      *
1834      * @return A Criterion that is the having clause.
1835      */
1836     public Criterion getHaving()
1837     {
1838         return having;
1839     }
1840 
1841     /**
1842      * Remove all objects with the given key from the criteria.
1843      *
1844      * @param key A String with the key to be removed.
1845      * @return The value of the removed criterion, or null.
1846      */
1847     public Object remove(Column key)
1848     {
1849         Iterator<Map.Entry<Column, Criterion>> entryIt
1850                 = criterionMap.entrySet().iterator();
1851         while (entryIt.hasNext())
1852         {
1853             Map.Entry<Column, Criterion> entry = entryIt.next();
1854             if (entry.getKey().getSqlExpression().equals(
1855                     key.getSqlExpression()))
1856             {
1857                 entryIt.remove();
1858                 return entry.getValue().getValue();
1859             }
1860         }
1861         return null;
1862     }
1863 
1864     /**
1865      * Build a string representation of the Criteria.
1866      *
1867      * @return A String with the representation of the Criteria.
1868      */
1869     @Override
1870     public String toString()
1871     {
1872         StringBuffer sb = new StringBuffer("Criteria:: ");
1873         Iterator<?> it = keySet().iterator();
1874         while (it.hasNext())
1875         {
1876             Object key = it.next();
1877             sb.append(key).append("<=>")
1878                     .append(criterionMap.get(key)).append(":  ");
1879         }
1880 
1881         try
1882         {
1883             Query query = SqlBuilder.buildQuery(this);
1884             sb.append("\nCurrent Query SQL (may not be complete or applicable): ")
1885                     .append(query.getDisplayString());
1886         }
1887         catch (Exception exc)
1888         {
1889             log.debug("Exception when evaluating a Criteria", exc);
1890         }
1891 
1892         return sb.toString();
1893     }
1894 
1895     /**
1896      * Returns all keys in the Criterion map.
1897      *
1898      * @return all keys, not null.
1899      */
1900     public Set<Column> keySet()
1901     {
1902         return criterionMap.keySet();
1903     }
1904 
1905     /**
1906      * Checks whether an object is equal to this Criteria.
1907      * This is the case if the other object is also a Criteria and has
1908      * the same attributes and criterions.
1909      *
1910      * @param object the other object to check, can be null.
1911      *
1912      * @return true if the object is equal to this Criteria, false otherwise.
1913      */
1914     @Override
1915     public boolean equals(Object object)
1916     {
1917         if (object == null)
1918         {
1919             return false;
1920         }
1921         if (this == object)
1922         {
1923             return true;
1924         }
1925         if (object.getClass() != this.getClass())
1926         {
1927             return false;
1928         }
1929         Criteria criteria = (Criteria) object;
1930         if (criterionMap.size() !=  criteria.criterionMap.size())
1931         {
1932             return false;
1933         }
1934         if (this.offset != criteria.getOffset()
1935                 || this.limit != criteria.getLimit()
1936                 || ignoreCase != criteria.isIgnoreCase()
1937                 || singleRecord != criteria.isSingleRecord()
1938                 || !dbName.equals(criteria.getDbName())
1939                 || !selectModifiers.equals(criteria.getSelectModifiers())
1940                 || !selectColumns.equals(criteria.getSelectColumns())
1941                 || !orderByColumns.equals(criteria.getOrderByColumns())
1942                 || !aliases.equals(criteria.getAliases())
1943                 || !asColumns.equals(criteria.getAsColumns())
1944                 || !joins.equals(criteria.getJoins())
1945             )
1946         {
1947             return false;
1948         }
1949         for (Iterator<Column> it = criteria.keySet().iterator(); it.hasNext();)
1950         {
1951             Column key = it.next();
1952             if (containsTopLevelColumn(key))
1953             {
1954                 Criterion a = this.getCriterion(key);
1955                 Criterion b = criteria.getCriterion(key);
1956                 if (!a.equals(b))
1957                 {
1958                     return false;
1959                 }
1960             }
1961             else
1962             {
1963                 return false;
1964             }
1965         }
1966         return true;
1967     }
1968 
1969     /**
1970      * Returns the hash code value for this Join.
1971      *
1972      * @return a hash code value for this object.
1973      */
1974     @Override
1975     public int hashCode()
1976     {
1977         int result = 16;
1978         result = 37 * result + Long.valueOf(offset).hashCode();
1979         result = 37 * result + limit;
1980         result = 37 * result + (ignoreCase ? 0 : 1);
1981         result = 37 * result + (singleRecord ? 0 : 1);
1982         result = 37 * result + dbName.hashCode();
1983         result = 37 * result + selectModifiers.hashCode();
1984         result = 37 * result + selectColumns.hashCode();
1985         result = 37 * result + orderByColumns.hashCode();
1986         result = 37 * result + aliases.hashCode();
1987         result = 37 * result + asColumns.hashCode();
1988         result = 37 * result + joins.hashCode();
1989         result = 37 * result + criterionMap.hashCode();
1990         return result;
1991     }
1992 
1993     /*
1994      * ------------------------------------------------------------------------
1995      *
1996      * Start of the "and" methods
1997      *
1998      * ------------------------------------------------------------------------
1999      */
2000 
2001     /**
2002      * This method adds a prepared Criterion object to the Criteria as a having
2003      * clause. You can get a new, empty Criterion object with the
2004      * getNewCriterion() method.
2005      *
2006      * <p>
2007      * <code>
2008      * Criteria crit = new Criteria();
2009      * Criteria.Criterion c = crit.getNewCriterion(XXXPeer.ID, new Integer(5),
2010      *         Criteria.LESS_THAN);
2011      * crit.addHaving(c);
2012      * </code>
2013      *
2014      * @param having A Criterion object
2015      * @return A modified Criteria object.
2016      */
2017     public Criteria addHaving(Criterion having)
2018     {
2019         this.having = having;
2020         return this;
2021     }
2022 
2023     /**
2024      * This method adds a prepared Criterion object to the Criteria.
2025      * You can get a new, empty Criterion object with the
2026      * getNewCriterion() method. If a criterion for the requested column
2027      * already exists, it is &quot;AND&quot;ed to the existing criterion.
2028      * This is used as follows:
2029      *
2030      * <p>
2031      * <code>
2032      * Criteria crit = new Criteria();
2033      * Criteria.Criterion c = crit.getNewCriterion(XXXPeer.ID, new Integer(5),
2034      *         Criteria.LESS_THAN);
2035      * crit.and(c);
2036      * </code>
2037      *
2038      * @param c A Criterion object
2039      * @return A modified Criteria object.
2040      */
2041     public Criteria and(Criterion c)
2042     {
2043         Criterion oc = getCriterion(c.getColumn());
2044 
2045         if (oc == null)
2046         {
2047             add(c);
2048         }
2049         else
2050         {
2051             oc.and(c);
2052         }
2053         return this;
2054     }
2055 
2056     /**
2057      * This method adds a new criterion to the list of criterias. If a
2058      * criterion for the requested column already exists, it is
2059      * &quot;AND&quot;ed to the existing criterion. This is used as follows:
2060      *
2061      * <p>
2062      * <code>
2063      * Criteria crit = new Criteria().and(&quot;column&quot;,
2064      *                                      &quot;value&quot;);
2065      * </code>
2066      *
2067      * An EQUAL comparison is used for column and value.
2068      *
2069      * The name of the table must be used implicitly in the column name,
2070      * so the Column name must be something like 'TABLE.id'. If you
2071      * don't like this, you can use the and(table, column, value) method.
2072      *
2073      * @param column The column to run the comparison on
2074      * @param value An Object.
2075      *
2076      * @return A modified Criteria object.
2077      */
2078     public Criteria and(Column column, Object value)
2079     {
2080         and(column, value, EQUAL);
2081         return this;
2082     }
2083 
2084     /**
2085      * This method adds a new criterion to the list of criterias.
2086      * If a criterion for the requested column already exists, it is
2087      * &quot;AND&quot;ed to the existing criterion. If is used as follow:
2088      *
2089      * <p>
2090      * <code>
2091      * Criteria crit = new Criteria().and(&quot;column&quot;,
2092      *                                      &quot;value&quot;
2093      *                                      Criteria.GREATER_THAN);
2094      * </code>
2095      *
2096      * Any comparison can be used.
2097      *
2098      * The name of the table must be used implicitly in the column name,
2099      * so the Column name must be something like 'TABLE.id'. If you
2100      * don't like this, you can use the and(table, column, value) method.
2101      *
2102      * @param column The column to run the comparison on
2103      * @param value An Object.
2104      * @param comparison A String.
2105      *
2106      * @return A modified Criteria object.
2107      */
2108     public Criteria and(Column column, Object value, SqlEnum comparison)
2109     {
2110         Criterion oc = getCriterion(column);
2111         Criterion nc = new Criterion(column, value, comparison);
2112 
2113         if (oc == null)
2114         {
2115             criterionMap.put(column, nc);
2116         }
2117         else
2118         {
2119             oc.and(nc);
2120         }
2121         return this;
2122     }
2123 
2124     /**
2125      * This method adds a new criterion to the list of criterias. If a
2126      * criterion for the requested column already exists, it is
2127      * &quot;AND&quot;ed to the existing criterion. This is used as follows:
2128      *
2129      * <p>
2130      * <code>
2131      * Criteria crit = new Criteria().and(&quot;column&quot;,
2132      *                                      &quot;value&quot;);
2133      * </code>
2134      *
2135      * An EQUAL comparison is used for column and value.
2136      *
2137      * The name of the table must be used implicitly in the column name,
2138      * so the Column name must be something like 'TABLE.id'. If you
2139      * don't like this, you can use the and(table, column, value) method.
2140      *
2141      * @param column The column to run the comparison on
2142      * @param value An Object.
2143      *
2144      * @return A modified Criteria object.
2145      */
2146     public Criteria and(String column, Object value)
2147     {
2148         return and(column, value, EQUAL);
2149     }
2150 
2151     /**
2152      * This method adds a new criterion to the list of criterias.
2153      * If a criterion for the requested column already exists, it is
2154      * &quot;AND&quot;ed to the existing criterion. If is used as follow:
2155      *
2156      * <p>
2157      * <code>
2158      * Criteria crit = new Criteria().and(&quot;column&quot;,
2159      *                                      &quot;value&quot;
2160      *                                      Criteria.GREATER_THAN);
2161      * </code>
2162      *
2163      * Any comparison can be used.
2164      *
2165      * The name of the table must be used implicitly in the column name,
2166      * so the Column name must be something like 'TABLE.id'. If you
2167      * don't like this, you can use the and(table, column, value) method.
2168      *
2169      * @param column The column to run the comparison on
2170      * @param value An Object.
2171      * @param comparison A String.
2172      *
2173      * @return A modified Criteria object.
2174      */
2175     public Criteria and(String column, Object value, SqlEnum comparison)
2176     {
2177         ColumnImpl columnImpl = new ColumnImpl(column);
2178         return and(columnImpl, value, comparison);
2179     }
2180 
2181     /**
2182      * This method adds a new criterion to the list of criterias.
2183      * If a criterion for the requested column already exists, it is
2184      * &quot;AND&quot;ed to the existing criterion. If is used as follows:
2185      *
2186      * <p>
2187      * <code>
2188      * Criteria crit = new Criteria().and(&quot;table&quot;,
2189      *                                      &quot;column&quot;,
2190      *                                      &quot;value&quot;);
2191      * </code>
2192      *
2193      * An EQUAL comparison is used for column and value.
2194      *
2195      * @param table Name of the table which contains the column
2196      * @param column The column to run the comparison on
2197      * @param value An Object.
2198      * @return A modified Criteria object.
2199      *
2200      * @deprecated use and(Column, Object) instead
2201      */
2202     @Deprecated
2203     public Criteria and(String table, String column, Object value)
2204     {
2205         and(table, column, value, EQUAL);
2206         return this;
2207     }
2208 
2209     /**
2210      * This method adds a new criterion to the list of criterias.
2211      * If a criterion for the requested column already exists, it is
2212      * &quot;AND&quot;ed to the existing criterion. If is used as follows:
2213      *
2214      * <p>
2215      * <code>
2216      * Criteria crit = new Criteria().and(&quot;table&quot;,
2217      *                                      &quot;column&quot;,
2218      *                                      &quot;value&quot;,
2219      *                                      &quot;Criterion.GREATER_THAN&quot;);
2220      * </code>
2221      *
2222      * Any comparison can be used.
2223      *
2224      * @param table Name of table which contains the column
2225      * @param column The column to run the comparison on
2226      * @param value An Object.
2227      * @param comparison String describing how to compare the column with
2228      *        the value
2229      * @return A modified Criteria object.
2230      *
2231      * @deprecated use and(Column, Object, comparison) instead
2232      */
2233     @Deprecated
2234     public Criteria and(String table, String column, Object value,
2235             SqlEnum comparison)
2236     {
2237         Criterion oc = getCriterion(table, column);
2238         Criterion nc = new Criterion(table, column, value, comparison);
2239 
2240         if (oc == null)
2241         {
2242             criterionMap.put(new ColumnImpl(table, column), nc);
2243         }
2244         else
2245         {
2246             oc.and(nc);
2247         }
2248         return this;
2249     }
2250 
2251     /**
2252      * Convenience method to add a Date object specified by
2253      * year, month, and date into the Criteria.
2254      * Equal to
2255      *
2256      * <p>
2257      * <code>
2258      * and(column, new GregorianCalendar(year, month,date), EQUAL);
2259      * </code>
2260      *
2261      * @param column A String value to use as column.
2262      * @param year An int with the year.
2263      * @param month An int with the month.
2264      * @param date An int with the date.
2265      * @return A modified Criteria object.
2266      */
2267     public Criteria andDate(Column column, int year, int month, int date)
2268     {
2269         and(column, new GregorianCalendar(year, month, date).getTime());
2270         return this;
2271     }
2272 
2273     /**
2274      * Convenience method to add a Date object specified by
2275      * year, month, and date into the Criteria.
2276      * Equal to
2277      *
2278      * <p>
2279      * <code>
2280      * and(column, new GregorianCalendar(year, month,date), comparison);
2281      * </code>
2282      *
2283      * @param column The column to run the comparison on
2284      * @param year An int with the year.
2285      * @param month An int with the month.
2286      * @param date An int with the date.
2287      * @param comparison String describing how to compare the column with
2288      *        the value
2289      * @return A modified Criteria object.
2290      */
2291     public Criteria andDate(Column column, int year, int month, int date,
2292             SqlEnum comparison)
2293     {
2294         and(column, new GregorianCalendar(year, month, date).getTime(), comparison);
2295         return this;
2296     }
2297 
2298     /**
2299      * Convenience method to add a Date object specified by
2300      * year, month, and date into the Criteria.
2301      * Equal to
2302      *
2303      * <p>
2304      * <code>
2305      * and(column, new GregorianCalendar(year, month,date), EQUAL);
2306      * </code>
2307      *
2308      * @param column A String value to use as column.
2309      * @param year An int with the year.
2310      * @param month An int with the month.
2311      * @param date An int with the date.
2312      * @return A modified Criteria object.
2313      */
2314     public Criteria andDate(String column, int year, int month, int date)
2315     {
2316         and(column, new GregorianCalendar(year, month, date).getTime());
2317         return this;
2318     }
2319 
2320     /**
2321      * Convenience method to add a Date object specified by
2322      * year, month, and date into the Criteria.
2323      * Equal to
2324      *
2325      * <p>
2326      * <code>
2327      * and(column, new GregorianCalendar(year, month,date), comparison);
2328      * </code>
2329      *
2330      * @param column The column to run the comparison on
2331      * @param year An int with the year.
2332      * @param month An int with the month.
2333      * @param date An int with the date.
2334      * @param comparison String describing how to compare the column with
2335      *        the value
2336      * @return A modified Criteria object.
2337      */
2338     public Criteria andDate(String column, int year, int month, int date,
2339             SqlEnum comparison)
2340     {
2341         and(column, new GregorianCalendar(year, month, date).getTime(), comparison);
2342         return this;
2343     }
2344 
2345     /**
2346      * Adds an 'IN' clause with the criteria supplied as an Object array.
2347      * For example:
2348      *
2349      * <p>
2350      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
2351      * <p>
2352      *
2353      * where 'values' contains three objects that evaluate to the
2354      * respective strings above when .toString() is called.
2355      *
2356      * If a criterion for the requested column already exists, it is
2357      * &quot;AND&quot;ed to the existing criterion.
2358      *
2359      * @param column The column to run the comparison on
2360      * @param values An Object[] with the allowed values.
2361      * @return A modified Criteria object.
2362      */
2363     public Criteria andIn(Column column, Object[] values)
2364     {
2365         and(column, values, Criteria.IN);
2366         return this;
2367     }
2368 
2369     /**
2370      * Adds an 'IN' clause with the criteria supplied as an Object array.
2371      * For example:
2372      *
2373      * <p>
2374      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
2375      * <p>
2376      *
2377      * where 'values' contains three objects that evaluate to the
2378      * respective strings above when .toString() is called.
2379      *
2380      * If a criterion for the requested column already exists, it is
2381      * &quot;AND&quot;ed to the existing criterion.
2382      *
2383      * @param column The column to run the comparison on
2384      * @param values An Object[] with the allowed values.
2385      * @return A modified Criteria object.
2386      */
2387     public Criteria andIn(String column, Object[] values)
2388     {
2389         return and(column, values, Criteria.IN);
2390     }
2391 
2392     /**
2393      * Adds an 'IN' clause with the criteria supplied as a List.
2394      * For example:
2395      *
2396      * <p>
2397      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
2398      * <p>
2399      *
2400      * where 'values' contains three objects that evaluate to the
2401      * respective strings above when .toString() is called.
2402      *
2403      * If a criterion for the requested column already exists, it is
2404      * &quot;AND&quot;ed to the existing criterion.
2405      *
2406      * @param column The column to run the comparison on
2407      * @param values A List with the allowed values.
2408      * @return A modified Criteria object.
2409      */
2410     public Criteria andIn(Column column, Collection<?> values)
2411     {
2412         and(column, values, Criteria.IN);
2413         return this;
2414     }
2415 
2416     /**
2417      * Adds an 'IN' clause with the criteria supplied as a List.
2418      * For example:
2419      *
2420      * <p>
2421      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
2422      * <p>
2423      *
2424      * where 'values' contains three objects that evaluate to the
2425      * respective strings above when .toString() is called.
2426      *
2427      * If a criterion for the requested column already exists, it is
2428      * &quot;AND&quot;ed to the existing criterion.
2429      *
2430      * @param column The column to run the comparison on
2431      * @param values A List with the allowed values.
2432      * @return A modified Criteria object.
2433      */
2434     public Criteria andIn(String column, Collection<?> values)
2435     {
2436         return and(column, values, Criteria.IN);
2437     }
2438 
2439     /**
2440      * Adds a 'NOT IN' clause with the criteria supplied as an Object
2441      * array.  For example:
2442      *
2443      * <p>
2444      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
2445      * <p>
2446      *
2447      * where 'values' contains three objects that evaluate to the
2448      * respective strings above when .toString() is called.
2449      *
2450      * If a criterion for the requested column already exists, it is
2451      * &quot;AND&quot;ed to the existing criterion.
2452      *
2453      * @param column The column to run the comparison on
2454      * @param values An Object[] with the disallowed values.
2455      * @return A modified Criteria object.
2456      */
2457     public Criteria andNotIn(Column column, Object[] values)
2458     {
2459         and(column, values, Criteria.NOT_IN);
2460         return this;
2461     }
2462 
2463     /**
2464      * Adds a 'NOT IN' clause with the criteria supplied as an Object
2465      * array.  For example:
2466      *
2467      * <p>
2468      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
2469      * <p>
2470      *
2471      * where 'values' contains three objects that evaluate to the
2472      * respective strings above when .toString() is called.
2473      *
2474      * If a criterion for the requested column already exists, it is
2475      * &quot;AND&quot;ed to the existing criterion.
2476      *
2477      * @param column The column to run the comparison on
2478      * @param values An Object[] with the disallowed values.
2479      * @return A modified Criteria object.
2480      */
2481     public Criteria andNotIn(String column, Object[] values)
2482     {
2483         ColumnImpl columnImpl = new ColumnImpl(column);
2484         return and(columnImpl, values, Criteria.NOT_IN);
2485     }
2486 
2487     /**
2488      * Adds a 'NOT IN' clause with the criteria supplied as a List.
2489      * For example:
2490      *
2491      * <p>
2492      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
2493      * <p>
2494      *
2495      * where 'values' contains three objects that evaluate to the
2496      * respective strings above when .toString() is called.
2497      *
2498      * If a criterion for the requested column already exists, it is
2499      * &quot;AND&quot;ed to the existing criterion.
2500      *
2501      * @param column The column to run the comparison on
2502      * @param values A List with the disallowed values.
2503      * @return A modified Criteria object.
2504      */
2505     public Criteria andNotIn(Column column, Collection<?> values)
2506     {
2507         and(column, values, Criteria.NOT_IN);
2508         return this;
2509     }
2510 
2511     /**
2512      * Adds a 'NOT IN' clause with the criteria supplied as a List.
2513      * For example:
2514      *
2515      * <p>
2516      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
2517      * <p>
2518      *
2519      * where 'values' contains three objects that evaluate to the
2520      * respective strings above when .toString() is called.
2521      *
2522      * If a criterion for the requested column already exists, it is
2523      * &quot;AND&quot;ed to the existing criterion.
2524      *
2525      * @param column The column to run the comparison on
2526      * @param values A List with the disallowed values.
2527      * @return A modified Criteria object.
2528      */
2529     public Criteria andNotIn(String column, Collection<?> values)
2530     {
2531         return and(column, values, Criteria.NOT_IN);
2532     }
2533 
2534     /*
2535      * ------------------------------------------------------------------------
2536      *
2537      * Start of the "or" methods
2538      *
2539      * ------------------------------------------------------------------------
2540      */
2541 
2542     /**
2543      * This method adds a prepared Criterion object to the Criteria.
2544      * You can get a new, empty Criterion object with the
2545      * getNewCriterion() method. If a criterion for the requested column
2546      * already exists, it is &quot;OR&quot;ed to the existing criterion.
2547      * This is used as follows:
2548      *
2549      * <p>
2550      * <code>
2551      * Criteria crit = new Criteria();
2552      * Criteria.Criterion c = crit.getNewCriterion(XXXPeer.ID, new Integer(5), Criteria.LESS_THAN);
2553      * crit.or(c);
2554      * </code>
2555      *
2556      * @param c A Criterion object
2557      * @return A modified Criteria object.
2558      */
2559     public Criteria or(Criterion c)
2560     {
2561         Criterion oc = getCriterion(c.getColumn());
2562 
2563         if (oc == null)
2564         {
2565             add(c);
2566         }
2567         else
2568         {
2569             oc.or(c);
2570         }
2571         return this;
2572     }
2573 
2574     /**
2575      * This method adds a new criterion to the list of criterias. If a
2576      * criterion for the requested column already exists, it is
2577      * &quot;OR&quot;ed to the existing criterion. This is used as follows:
2578      *
2579      * <p>
2580      * <code>
2581      * Criteria crit = new Criteria().or(&quot;column&quot;,
2582      *                                      &quot;value&quot;);
2583      * </code>
2584      *
2585      * An EQUAL comparison is used for column and value.
2586      *
2587      * The name of the table must be used implicitly in the column name,
2588      * so the Column name must be something like 'TABLE.id'. If you
2589      * don't like this, you can use the or(table, column, value) method.
2590      *
2591      * @param column The column to run the comparison on
2592      * @param value An Object.
2593      *
2594      * @return A modified Criteria object.
2595      */
2596     public Criteria or(Column column, Object value)
2597     {
2598         or(column, value, EQUAL);
2599         return this;
2600     }
2601 
2602     /**
2603      * This method adds a new criterion to the list of criterias. If a
2604      * criterion for the requested column already exists, it is
2605      * &quot;OR&quot;ed to the existing criterion. This is used as follows:
2606      *
2607      * <p>
2608      * <code>
2609      * Criteria crit = new Criteria().or(&quot;column&quot;,
2610      *                                      &quot;value&quot;);
2611      * </code>
2612      *
2613      * An EQUAL comparison is used for column and value.
2614      *
2615      * The name of the table must be used implicitly in the column name,
2616      * so the Column name must be something like 'TABLE.id'. If you
2617      * don't like this, you can use the or(table, column, value) method.
2618      *
2619      * @param column The column to run the comparison on
2620      * @param value An Object.
2621      *
2622      * @return A modified Criteria object.
2623      */
2624     public Criteria or(String column, Object value)
2625     {
2626         or(column, value, EQUAL);
2627         return this;
2628     }
2629 
2630     /**
2631      * This method adds a new criterion to the list of criterias.
2632      * If a criterion for the requested column already exists, it is
2633      * &quot;OR&quot;ed to the existing criterion. If is used as follow:
2634      *
2635      * <p>
2636      * <code>
2637      * Criteria crit = new Criteria().or(&quot;column&quot;,
2638      *                                      &quot;value&quot;
2639      *                                      &quot;Criterion.GREATER_THAN&quot;);
2640      * </code>
2641      *
2642      * Any comparison can be used.
2643      *
2644      * The name of the table must be used implicitly in the column name,
2645      * so the Column name must be something like 'TABLE.id'. If you
2646      * don't like this, you can use the or(table, column, value) method.
2647      *
2648      * @param column The column to run the comparison on
2649      * @param value An Object.
2650      * @param comparison A String.
2651      * @return A modified Criteria object.
2652      */
2653     public Criteria or(Column column, Object value, SqlEnum comparison)
2654     {
2655         Criterion oc = getCriterion(column);
2656         Criterion nc = new Criterion(column, value, comparison);
2657 
2658         if (oc == null)
2659         {
2660             criterionMap.put(column, nc);
2661         }
2662         else
2663         {
2664             oc.or(nc);
2665         }
2666         return this;
2667     }
2668 
2669     /**
2670      * This method adds a new criterion to the list of criterias.
2671      * If a criterion for the requested column already exists, it is
2672      * &quot;OR&quot;ed to the existing criterion. If is used as follow:
2673      *
2674      * <p>
2675      * <code>
2676      * Criteria crit = new Criteria().or(&quot;column&quot;,
2677      *                                      &quot;value&quot;
2678      *                                      &quot;Criterion.GREATER_THAN&quot;);
2679      * </code>
2680      *
2681      * Any comparison can be used.
2682      *
2683      * The name of the table must be used implicitly in the column name,
2684      * so the Column name must be something like 'TABLE.id'. If you
2685      * don't like this, you can use the or(table, column, value) method.
2686      *
2687      * @param column The column to run the comparison on
2688      * @param value An Object.
2689      * @param comparison A String.
2690      * @return A modified Criteria object.
2691      */
2692     public Criteria or(String column, Object value, SqlEnum comparison)
2693     {
2694         return or(new ColumnImpl(column), value, comparison);
2695     }
2696 
2697     /**
2698      * This method adds a new criterion to the list of criterias.
2699      * If a criterion for the requested column already exists, it is
2700      * &quot;OR&quot;ed to the existing criterion. If is used as follows:
2701      *
2702      * <p>
2703      * <code>
2704      * Criteria crit = new Criteria().or(&quot;table&quot;,
2705      *                                      &quot;column&quot;,
2706      *                                      &quot;value&quot;);
2707      * </code>
2708      *
2709      * An EQUAL comparison is used for column and value.
2710      *
2711      * @param table Name of the table which contains the column
2712      * @param column The column to run the comparison on
2713      * @param value An Object.
2714      * @return A modified Criteria object.
2715      *
2716      * @deprecated use or(Column, Object) instead
2717      */
2718     @Deprecated
2719     public Criteria or(String table, String column, Object value)
2720     {
2721         or(table, column, value, EQUAL);
2722         return this;
2723     }
2724 
2725     /**
2726      * This method adds a new criterion to the list of criterias.
2727      * If a criterion for the requested column already exists, it is
2728      * &quot;OR&quot;ed to the existing criterion. If is used as follows:
2729      *
2730      * <p>
2731      * <code>
2732      * Criteria crit = new Criteria().or(&quot;table&quot;,
2733      *                                      &quot;column&quot;,
2734      *                                      &quot;value&quot;,
2735      *                                      &quot;Criterion.GREATER_THAN&quot;);
2736      * </code>
2737      *
2738      * Any comparison can be used.
2739      *
2740      * @param table Name of table which contains the column
2741      * @param column The column to run the comparison on
2742      * @param value An Object.
2743      * @param comparison String describing how to compare the column with the value
2744      * @return A modified Criteria object.
2745      *
2746      * @deprecated use or(Column, Object, SqlEnum) instead
2747      */
2748     @Deprecated
2749     public Criteria or(String table, String column, Object value,
2750             SqlEnum comparison)
2751     {
2752         Criterion oc = getCriterion(table, column);
2753         Criterion nc = new Criterion(table, column, value, comparison);
2754         if (oc == null)
2755         {
2756             criterionMap.put(new ColumnImpl(table, column), nc);
2757         }
2758         else
2759         {
2760             oc.or(nc);
2761         }
2762         return this;
2763     }
2764 
2765     /**
2766      * Convenience method to add a Date object specified by
2767      * year, month, and date into the Criteria.
2768      * Equal to
2769      *
2770      * <p>
2771      * <code>
2772      * or(column, new GregorianCalendar(year, month,date), EQUAL);
2773      * </code>
2774      *
2775      * @param column A String value to use as column.
2776      * @param year An int with the year.
2777      * @param month An int with the month.
2778      * @param date An int with the date.
2779      * @return A modified Criteria object.
2780      */
2781     public Criteria orDate(Column column, int year, int month, int date)
2782     {
2783         or(column, new GregorianCalendar(year, month, date));
2784         return this;
2785     }
2786 
2787     /**
2788      * Convenience method to add a Date object specified by
2789      * year, month, and date into the Criteria.
2790      * Equal to
2791      *
2792      * <p>
2793      * <code>
2794      * or(column, new GregorianCalendar(year, month,date), EQUAL);
2795      * </code>
2796      *
2797      * @param column A String value to use as column.
2798      * @param year An int with the year.
2799      * @param month An int with the month.
2800      * @param date An int with the date.
2801      * @return A modified Criteria object.
2802      */
2803     public Criteria orDate(String column, int year, int month, int date)
2804     {
2805         return or(column, new GregorianCalendar(year, month, date));
2806     }
2807 
2808     /**
2809      * Convenience method to add a Date object specified by
2810      * year, month, and date into the Criteria.
2811      * Equal to
2812      *
2813      * <p>
2814      * <code>
2815      * or(column, new GregorianCalendar(year, month,date), comparison);
2816      * </code>
2817      *
2818      * @param column The column to run the comparison on
2819      * @param year An int with the year.
2820      * @param month An int with the month.
2821      * @param date An int with the date.
2822      * @param comparison String describing how to compare the column
2823      * with the value
2824      * @return A modified Criteria object.
2825      */
2826     public Criteria orDate(Column column, int year, int month, int date,
2827             SqlEnum comparison)
2828     {
2829         or(column, new GregorianCalendar(year, month, date), comparison);
2830         return this;
2831     }
2832 
2833     /**
2834      * Convenience method to add a Date object specified by
2835      * year, month, and date into the Criteria.
2836      * Equal to
2837      *
2838      * <p>
2839      * <code>
2840      * or(column, new GregorianCalendar(year, month,date), comparison);
2841      * </code>
2842      *
2843      * @param column The column to run the comparison on
2844      * @param year An int with the year.
2845      * @param month An int with the month.
2846      * @param date An int with the date.
2847      * @param comparison String describing how to compare the column
2848      * with the value
2849      * @return A modified Criteria object.
2850      */
2851     public Criteria orDate(String column, int year, int month, int date,
2852             SqlEnum comparison)
2853     {
2854         return or(column, new GregorianCalendar(year, month, date), comparison);
2855     }
2856 
2857     /**
2858      * Adds an 'IN' clause with the criteria supplied as an Object
2859      * array.  For example:
2860      *
2861      * <p>
2862      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
2863      * <p>
2864      *
2865      * where 'values' contains three objects that evaluate to the
2866      * respective strings above when .toString() is called.
2867      *
2868      * If a criterion for the requested column already exists, it is
2869      * &quot;OR&quot;ed to the existing criterion.
2870      *
2871      * @param column The column to run the comparison on
2872      * @param values An Object[] with the allowed values.
2873      * @return A modified Criteria object.
2874      */
2875     public Criteria orIn(Column column, Object[] values)
2876     {
2877         or(column, values, Criteria.IN);
2878         return this;
2879     }
2880 
2881     /**
2882      * Adds an 'IN' clause with the criteria supplied as an Object
2883      * array.  For example:
2884      *
2885      * <p>
2886      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
2887      * <p>
2888      *
2889      * where 'values' contains three objects that evaluate to the
2890      * respective strings above when .toString() is called.
2891      *
2892      * If a criterion for the requested column already exists, it is
2893      * &quot;OR&quot;ed to the existing criterion.
2894      *
2895      * @param column The column to run the comparison on
2896      * @param values An Object[] with the allowed values.
2897      * @return A modified Criteria object.
2898      */
2899     public Criteria orIn(String column, Object[] values)
2900     {
2901         return or(column, values, Criteria.IN);
2902     }
2903 
2904     /**
2905      * Adds an 'IN' clause with the criteria supplied as a List.
2906      * For example:
2907      *
2908      * <p>
2909      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
2910      * <p>
2911      *
2912      * where 'values' contains three objects that evaluate to the
2913      * respective strings above when .toString() is called.
2914      *
2915      * If a criterion for the requested column already exists, it is
2916      * &quot;OR&quot;ed to the existing criterion.
2917      *
2918      * @param column The column to run the comparison on
2919      * @param values A List with the allowed values.
2920      * @return A modified Criteria object.
2921      */
2922     public Criteria orIn(Column column, Collection<?> values)
2923     {
2924         or(column, values, Criteria.IN);
2925         return this;
2926     }
2927 
2928     /**
2929      * Adds an 'IN' clause with the criteria supplied as a List.
2930      * For example:
2931      *
2932      * <p>
2933      * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
2934      * <p>
2935      *
2936      * where 'values' contains three objects that evaluate to the
2937      * respective strings above when .toString() is called.
2938      *
2939      * If a criterion for the requested column already exists, it is
2940      * &quot;OR&quot;ed to the existing criterion.
2941      *
2942      * @param column The column to run the comparison on
2943      * @param values A List with the allowed values.
2944      * @return A modified Criteria object.
2945      */
2946     public Criteria orIn(String column, Collection<?> values)
2947     {
2948         return or(column, values, Criteria.IN);
2949     }
2950 
2951     /**
2952      * Adds a 'NOT IN' clause with the criteria supplied as an Object
2953      * array.  For example:
2954      *
2955      * <p>
2956      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
2957      * <p>
2958      *
2959      * where 'values' contains three objects that evaluate to the
2960      * respective strings above when .toString() is called.
2961      *
2962      * If a criterion for the requested column already exists, it is
2963      * &quot;OR&quot;ed to the existing criterion.
2964      *
2965      * @param column The column to run the comparison on
2966      * @param values An Object[] with the disallowed values.
2967      * @return A modified Criteria object.
2968      */
2969     public Criteria orNotIn(Column column, Object[] values)
2970     {
2971         or(column, values, Criteria.NOT_IN);
2972         return this;
2973     }
2974 
2975     /**
2976      * Adds a 'NOT IN' clause with the criteria supplied as an Object
2977      * array.  For example:
2978      *
2979      * <p>
2980      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
2981      * <p>
2982      *
2983      * where 'values' contains three objects that evaluate to the
2984      * respective strings above when .toString() is called.
2985      *
2986      * If a criterion for the requested column already exists, it is
2987      * &quot;OR&quot;ed to the existing criterion.
2988      *
2989      * @param column The column to run the comparison on
2990      * @param values An Object[] with the disallowed values.
2991      * @return A modified Criteria object.
2992      */
2993     public Criteria orNotIn(String column, Object[] values)
2994     {
2995         return or(column, values, Criteria.NOT_IN);
2996     }
2997 
2998     /**
2999      * Adds a 'NOT IN' clause with the criteria supplied as a List.
3000      * For example:
3001      *
3002      * <p>
3003      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
3004      * <p>
3005      *
3006      * where 'values' contains three objects that evaluate to the
3007      * respective strings above when .toString() is called.
3008      *
3009      * If a criterion for the requested column already exists, it is
3010      * &quot;OR&quot;ed to the existing criterion.
3011      *
3012      * @param column The column to run the comparison on
3013      * @param values A List with the disallowed values.
3014      * @return A modified Criteria object.
3015      */
3016     public Criteria orNotIn(Column column, Collection<?> values)
3017     {
3018         or(column, values, Criteria.NOT_IN);
3019         return this;
3020     }
3021 
3022     /**
3023      * Adds a 'NOT IN' clause with the criteria supplied as a List.
3024      * For example:
3025      *
3026      * <p>
3027      * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
3028      * <p>
3029      *
3030      * where 'values' contains three objects that evaluate to the
3031      * respective strings above when .toString() is called.
3032      *
3033      * If a criterion for the requested column already exists, it is
3034      * &quot;OR&quot;ed to the existing criterion.
3035      *
3036      * @param column The column to run the comparison on
3037      * @param values A List with the disallowed values.
3038      * @return A modified Criteria object.
3039      */
3040     public Criteria orNotIn(String column, Collection<?> values)
3041     {
3042         return or(column, values, Criteria.NOT_IN);
3043     }
3044 
3045     /**
3046      * This is an inner class that describes an object in the criteria.
3047      */
3048     public final class Criterion implements Serializable
3049     {
3050         /** Serial version. */
3051         private static final long serialVersionUID = 7157097965404611710L;
3052 
3053         /** Constant for thze operator " AND ". */
3054         public static final String AND = " AND ";
3055 
3056         /** Constant for thze operator " OR ". */
3057         public static final String OR = " OR ";
3058 
3059         /** Value of the CO. */
3060         private Object value;
3061 
3062         /** Comparison value. */
3063         private SqlEnum comparison;
3064 
3065         /** Column. */
3066         private Column column;
3067 
3068         /** flag to ignore case in comparision */
3069         private boolean ignoreStringCase = false;
3070 
3071         /**
3072          * other connected criteria.
3073          */
3074         private final List<Criterion> clauses = new ArrayList<Criterion>();
3075 
3076         /** The operators (AND, OR...) how the other Criteria are connected. */
3077         private final List<String> conjunctions = new ArrayList<String>();
3078 
3079         /**
3080          * Create a new instance.
3081          *
3082          * @param table A String with the name of the table,
3083          *        not null or blank.
3084          * @param column A String with the name of the column,
3085          *        not null or blank.
3086          * @param val An Object with the value for the Criteria.
3087          * @param comp A String with the comparison value.
3088          *
3089          * @throws NullPointerException if columnName or tableName are null.
3090          * @throws IllegalArgumentException if columnName or tableName are
3091          *         blank.
3092          */
3093         Criterion(String table, String column, Object val, SqlEnum comp)
3094         {
3095             this.value = val;
3096             setComparison(comp);
3097             this.column = new ColumnImpl(table, column);
3098         }
3099 
3100         /**
3101          * Create a new instance.
3102          *
3103          * @param column the column description, not null.
3104          * @param val An Object with the value for the Criteria, may be null.
3105          * @param comp A String with the comparison value, not null.
3106          *
3107          * @throws NullPointerException if column is null.
3108          */
3109         Criterion(Column column, Object val, SqlEnum comp)
3110         {
3111             this.value = val;
3112             setComparison(comp);
3113             setColumn(column);
3114         }
3115 
3116         /**
3117          * Create a new instance.
3118          *
3119          * @param table A String with the name of the table.
3120          * @param column A String with the name of the column.
3121          * @param val An Object with the value for the Criteria.
3122          */
3123         Criterion(String table, String column, Object val)
3124         {
3125             this(table, column, val, EQUAL);
3126         }
3127 
3128         /**
3129          * Create a new instance.
3130          *
3131          * @param tableColumn the column description.
3132          * @param val An Object with the value for the Criteria.
3133          */
3134         Criterion(Column column, Object val)
3135         {
3136             this(column, val, EQUAL);
3137         }
3138 
3139         /**
3140          * Sets the column.
3141          *
3142          * @param column the column, not null.
3143          *
3144          * @throws NullPointerException if column is null.
3145          */
3146         private void setColumn(Column column)
3147         {
3148             if (column == null)
3149             {
3150                 throw new NullPointerException("column must not be null");
3151             }
3152             this.column = column;
3153         }
3154 
3155         /**
3156          * Get the column.
3157          *
3158          * @return the column.
3159          */
3160         public Column getColumn()
3161         {
3162             return this.column;
3163         }
3164 
3165         /**
3166          * Sets the comparison.
3167          *
3168          * @param comparison the comparison, not null.
3169          *
3170          * @throws NullPointerException if comparison is null.
3171          */
3172         private void setComparison(SqlEnum comparison)
3173         {
3174             if (comparison == null)
3175             {
3176                 throw new NullPointerException("comparison must not be null");
3177             }
3178             this.comparison = comparison;
3179         }
3180         /**
3181          * Get the comparison.
3182          *
3183          * @return A String with the comparison.
3184          */
3185         public SqlEnum getComparison()
3186         {
3187             return this.comparison;
3188         }
3189 
3190         /**
3191          * Get the value.
3192          *
3193          * @return An Object with the value.
3194          */
3195         public Object getValue()
3196         {
3197             return this.value;
3198         }
3199 
3200         /**
3201          * Set the value of the criterion.
3202          *
3203          * @param value the new value.
3204          */
3205         public void setValue(Object value)
3206         {
3207             this.value = value;
3208         }
3209 
3210         /**
3211          * Sets ignore case.
3212          *
3213          * @param b True if case should be ignored.
3214          * @return A modified Criteria object.
3215          */
3216         public Criterion setIgnoreCase(boolean b)
3217         {
3218             ignoreStringCase = b;
3219             return this;
3220         }
3221 
3222         /**
3223          * Is ignore case on or off?
3224          *
3225          * @return True if case is ignored.
3226          */
3227         public boolean isIgnoreCase()
3228         {
3229             return ignoreStringCase;
3230         }
3231 
3232         /**
3233          * Returns the list of clauses in this Criterion.
3234          *
3235          * @return an unmodifiable list of the clauses, not null.
3236          */
3237         public List<Criterion> getClauses()
3238         {
3239             return Collections.unmodifiableList(clauses);
3240         }
3241 
3242         /**
3243          * Returns the list of conjunctions in this Criterion
3244          *
3245          * @return an unmodifiable list of the conjunctions, not null.
3246          */
3247         public List<String> getConjunctions()
3248         {
3249             return Collections.unmodifiableList(conjunctions);
3250         }
3251 
3252         /**
3253          * Append an AND Criterion onto this Criterion's list.
3254          */
3255         public Criterion and(Criterion criterion)
3256         {
3257             this.clauses.add(criterion);
3258             this.conjunctions.add(AND);
3259             return this;
3260         }
3261 
3262         /**
3263          * Append an OR Criterion onto this Criterion's list.
3264          */
3265         public Criterion or(Criterion criterion)
3266         {
3267             this.clauses.add(criterion);
3268             this.conjunctions.add(OR);
3269             return this;
3270         }
3271 
3272         /**
3273          * Appends a representation of the Criterion onto the buffer.
3274          */
3275         public void appendTo(StringBuffer sb) throws TorqueException
3276         {
3277             //
3278             // it is alright if value == null
3279             //
3280 
3281             if (column == null)
3282             {
3283                 return;
3284             }
3285 
3286             Criterion clause = null;
3287             for (int j = 0; j < this.clauses.size(); j++)
3288             {
3289                 sb.append('(');
3290             }
3291             if (CUSTOM == comparison)
3292             {
3293                 if (value != null && !"".equals(value))
3294                 {
3295                     sb.append((String) value);
3296                 }
3297             }
3298             else
3299             {
3300                 String field = column.getSqlExpression();
3301                 sb.append(field).append(comparison).append(value);
3302             }
3303 
3304             for (int i = 0; i < this.clauses.size(); i++)
3305             {
3306                 sb.append(this.conjunctions.get(i));
3307                 clause = this.clauses.get(i);
3308                 clause.appendTo(sb);
3309                 sb.append(')');
3310             }
3311         }
3312 
3313         /**
3314          * Build a string representation of the Criterion.
3315          *
3316          * @return A String with the representation of the Criterion.
3317          */
3318         @Override
3319         public String toString()
3320         {
3321             //
3322             // it is alright if value == null
3323             //
3324             if (column == null)
3325             {
3326                 return "";
3327             }
3328 
3329             StringBuffer expr = new StringBuffer();
3330             try
3331             {
3332                 appendTo(expr);
3333             }
3334             catch (TorqueException e)
3335             {
3336                 return "Criterion cannot be evaluated";
3337             }
3338             return expr.toString();
3339         }
3340 
3341         /**
3342          * This method checks another Criteria.Criterion to see if they contain
3343          * the same attributes.
3344          */
3345         @Override
3346         public boolean equals(Object obj)
3347         {
3348             if (this == obj)
3349             {
3350                 return true;
3351             }
3352 
3353             if ((obj == null) || !(obj instanceof Criterion))
3354             {
3355                 return false;
3356             }
3357 
3358             Criterion crit = (Criterion) obj;
3359 
3360             boolean isEquiv = column.getSqlExpression().equals(
3361                         crit.getColumn().getSqlExpression())
3362                     && comparison.equals(crit.getComparison());
3363 
3364             // we need to check for value equality
3365             if (isEquiv)
3366             {
3367                 Object b = crit.getValue();
3368                 if (value instanceof Object[] && b instanceof Object[])
3369                 {
3370                     isEquiv &= Arrays.equals((Object[]) value, (Object[]) b);
3371                 }
3372                 else if (value instanceof int[] && b instanceof int[])
3373                 {
3374                     isEquiv &= Arrays.equals((int[]) value, (int[]) b);
3375                 }
3376                 else
3377                 {
3378                     isEquiv &= value.equals(b);
3379                 }
3380             }
3381 
3382             // check chained criterion
3383 
3384             isEquiv &= this.clauses.size() == crit.getClauses().size();
3385             for (int i = 0; i < this.clauses.size(); i++)
3386             {
3387                 isEquiv &=  conjunctions.get(i)
3388                         .equals((crit.getConjunctions().get(i)));
3389                 isEquiv &=  clauses.get(i)
3390                         .equals(crit.getClauses().get(i));
3391             }
3392 
3393             return isEquiv;
3394         }
3395 
3396         /**
3397          * Returns a hash code value for the object.
3398          */
3399         @Override
3400         public int hashCode()
3401         {
3402             int h = value.hashCode() ^ comparison.hashCode();
3403 
3404             h ^= column.getSqlExpression().hashCode();
3405 
3406             for (int i = 0; i < this.clauses.size(); i++)
3407             {
3408                 h ^= (clauses.get(i)).hashCode();
3409             }
3410 
3411             return h;
3412         }
3413 
3414         /**
3415          * Get the name of all tables from nested criterion objects
3416          *
3417          * @return the list of tables
3418          */
3419         public List<String> getAllTables()
3420         {
3421             UniqueList<String> tables = new UniqueList<String>();
3422             addCriterionTable(this, tables);
3423             return tables;
3424         }
3425 
3426         /**
3427          * method supporting recursion through all criterions to give
3428          * us a StringStack of tables from each criterion
3429          */
3430         private void addCriterionTable(Criterion c, UniqueList<String> s)
3431         {
3432             if (c != null)
3433             {
3434                 s.add(c.getColumn().getTableName());
3435                 for (int i = 0; i < c.getClauses().size(); i++)
3436                 {
3437                     addCriterionTable((c.getClauses().get(i)), s);
3438                 }
3439             }
3440         }
3441 
3442         /**
3443          * get an array of all criterion attached to this
3444          * recursing through all sub criterion
3445          */
3446         public Criterion[] getAttachedCriterion()
3447         {
3448             ArrayList<Criterion> crits = new ArrayList<Criterion>();
3449             traverseCriterion(this, crits);
3450             Criterion[] crita = new Criterion[crits.size()];
3451             for (int i = 0; i < crits.size(); i++)
3452             {
3453                 crita[i] = crits.get(i);
3454             }
3455 
3456             return crita;
3457         }
3458 
3459         /**
3460          * method supporting recursion through all criterions to give
3461          * us an ArrayList of them
3462          */
3463         private void traverseCriterion(Criterion c, List<Criterion> a)
3464         {
3465             if (c != null)
3466             {
3467                 a.add(c);
3468                 for (int i = 0; i < c.getClauses().size(); i++)
3469                 {
3470                     traverseCriterion(c.getClauses().get(i), a);
3471                 }
3472             }
3473         }
3474     } // end of inner class Criterion
3475 }