View Javadoc

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