View Javadoc

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