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