Package org.apache.torque.util

Source Code of org.apache.torque.util.Criteria$Criterion

package org.apache.torque.util;

/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.io.Serializable;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.torque.Torque;
import org.apache.torque.adapter.DB;
import org.apache.torque.om.DateKey;
import org.apache.torque.om.ObjectKey;

/**
* This is a utility class that is used for retrieving different types
* of values from a hashtable based on a simple name string.  This
* class is meant to minimize the amount of casting that needs to be
* done when working with Hashtables.
*
* NOTE: other methods will be added as needed and as time permits.
*
* @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
* @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
* @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
* @author <a href="mailto:eric@dobbse.net">Eric Dobbs</a>
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
* @author <a href="mailto:sam@neurogrid.com">Sam Joseph</a>
* @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
* @version $Id: Criteria.java,v 1.42.2.3 2004/05/20 04:36:06 seade Exp $
*/
public class Criteria extends Hashtable
{

    /** Comparison type. */
    public static final SqlEnum EQUAL = SqlEnum.EQUAL;

    /** Comparison type. */
    public static final SqlEnum NOT_EQUAL = SqlEnum.NOT_EQUAL;

    /** Comparison type. */
    public static final SqlEnum ALT_NOT_EQUAL = SqlEnum.ALT_NOT_EQUAL;

    /** Comparison type. */
    public static final SqlEnum GREATER_THAN = SqlEnum.GREATER_THAN;

    /** Comparison type. */
    public static final SqlEnum LESS_THAN = SqlEnum.LESS_THAN;

    /** Comparison type. */
    public static final SqlEnum GREATER_EQUAL = SqlEnum.GREATER_EQUAL;

    /** Comparison type. */
    public static final SqlEnum LESS_EQUAL = SqlEnum.LESS_EQUAL;

    /** Comparison type. */
    public static final SqlEnum LIKE = SqlEnum.LIKE;

    /** Comparison type. */
    public static final SqlEnum NOT_LIKE = SqlEnum.NOT_LIKE;

    /** Comparison type. */
    public static final SqlEnum ILIKE = SqlEnum.ILIKE;

    /** Comparison type. */
    public static final SqlEnum NOT_ILIKE = SqlEnum.NOT_ILIKE;

    /** Comparison type. */
    public static final SqlEnum CUSTOM = SqlEnum.CUSTOM;

    /** Comparison type. */
    public static final SqlEnum DISTINCT = SqlEnum.DISTINCT;

    /** Comparison type. */
    public static final SqlEnum IN = SqlEnum.IN;

    /** Comparison type. */
    public static final SqlEnum NOT_IN = SqlEnum.NOT_IN;

    /** Comparison type. */
    public static final SqlEnum ALL = SqlEnum.ALL;

    /** Comparison type. */
    public static final SqlEnum JOIN = SqlEnum.JOIN;

    /** "Order by" qualifier - ascending */
    private static final SqlEnum ASC = SqlEnum.ASC;

    /** "Order by" qualifier - descending */
    private static final SqlEnum DESC = SqlEnum.DESC;

    /** "IS NULL" null comparison */
    public static final SqlEnum ISNULL = SqlEnum.ISNULL;

    /** "IS NOT NULL" null comparison */
    public static final SqlEnum ISNOTNULL = SqlEnum.ISNOTNULL;

    /** "CURRENT_DATE" ANSI SQL function */
    public static final SqlEnum CURRENT_DATE = SqlEnum.CURRENT_DATE;

    /** "CURRENT_TIME" ANSI SQL function */
    public static final SqlEnum CURRENT_TIME = SqlEnum.CURRENT_TIME;

    private static final int DEFAULT_CAPACITY = 10;

    private boolean ignoreCase = false;
    private boolean singleRecord = false;
    private boolean cascade = false;
    private UniqueList selectModifiers = new UniqueList();
    private UniqueList selectColumns = new UniqueList();
    private UniqueList orderByColumns = new UniqueList();
    private UniqueList groupByColumns = new UniqueList();
    private Criterion having = null;
    private Hashtable asColumns = new Hashtable(8);
    private ArrayList joinL = null;
    private ArrayList joinR = null;

    /** The name of the database. */
    private String dbName;

    /** The name of the database as given in the contructor. */
    private String originalDbName;

    /**
     * To limit the number of rows to return.  <code>-1</code> means return all
     * rows.
     */
    private int limit = -1;

    /** To start the results at a row other than the first one. */
    private int offset = 0;

    private HashMap aliases = null;

    private boolean useTransaction = false;

    /** the log. */
    private static Log log = LogFactory.getLog(Criteria.class);

    /**
     * Creates a new instance with the default capacity.
     */
    public Criteria()
    {
        this(DEFAULT_CAPACITY);
    }

    /**
     * Creates a new instance with the specified capacity.
     *
     * @param initialCapacity An int.
     */
    public Criteria(int initialCapacity)
    {
        this(Torque.getDefaultDB(), initialCapacity);
    }

    /**
     * Creates a new instance with the default capacity which corresponds to
     * the specified database.
     *
     * @param dbName The dabase name.
     */
    public Criteria(String dbName)
    {
        this(dbName, DEFAULT_CAPACITY);
    }

    /**
     * Creates a new instance with the specified capacity which corresponds to
     * the specified database.
     *
     * @param dbName          The dabase name.
     * @param initialCapacity The initial capacity.
     */
    public Criteria(String dbName, int initialCapacity)
    {
        super(initialCapacity);
        this.dbName = dbName;
        this.originalDbName = dbName;
    }

    /**
     * Brings this criteria back to its initial state, so that it
     * can be reused as if it was new. Except if the criteria has grown in
     * capacity, it is left at the current capacity.
     */
    public void clear()
    {
        super.clear();
        ignoreCase = false;
        singleRecord = false;
        cascade = false;
        selectModifiers.clear();
        selectColumns.clear();
        orderByColumns.clear();
        groupByColumns.clear();
        having = null;
        asColumns.clear();
        joinL = null;
        joinR = null;
        dbName = originalDbName;
        offset = 0;
        limit = -1;
        aliases = null;
        useTransaction = false;
    }

    /**
     * Add an AS clause to the select columns. Usage:
     * <p>
     * <code>
     *
     * Criteria myCrit = new Criteria();
     * myCrit.addAsColumn("alias", "ALIAS("+MyPeer.ID+")");
     *
     * </code>
     *
     * @param name  wanted Name of the column
     * @param clause SQL clause to select from the table
     *
     * If the name already exists, it is replaced by the new clause.
     *
     * @return A modified Criteria object.
     */
    public Criteria addAsColumn(String name, String clause)
    {
        asColumns.put(name, clause);
        return this;
    }

    /**
     * Get the column aliases.
     *
     * @return A Hashtable which map the column alias names
     * to the alias clauses.
     */
    public Hashtable getAsColumns()
    {
        return asColumns;
    }

    /**
     * Allows one to specify an alias for a table that can
     * be used in various parts of the SQL.
     *
     * @param alias a <code>String</code> value
     * @param table a <code>String</code> value
     */
    public void addAlias(String alias, String table)
    {
        if (aliases == null)
        {
            aliases = new HashMap(8);
        }
        aliases.put(alias, table);
    }

    /**
     * Returns the table name associated with an alias.
     *
     * @param alias a <code>String</code> value
     * @return a <code>String</code> value
     */
    public String getTableForAlias(String alias)
    {
        if (aliases == null)
        {
            return null;
        }
        return (String) aliases.get(alias);
    }

    /**
     * Does this Criteria Object contain the specified key?
     *
     * @param table The name of the table.
     * @param column The name of the column.
     * @return True if this Criteria Object contain the specified key.
     */
    public boolean containsKey(String table, String column)
    {
        return containsKey(table + '.' + column);
    }

    /**
     * Convenience method to return value as a boolean.
     *
     * @param column String name of column.
     * @return A boolean.
     */
    public boolean getBoolean(String column)
    {
        return ((Boolean) getCriterion(column).getValue()).booleanValue();
    }

    /**
     * Convenience method to return value as a boolean.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A boolean.
     */
    public boolean getBoolean(String table, String column)
    {
        return getBoolean(new StringBuffer(table.length() + column.length() + 1)
                .append(table).append('.').append(column)
                .toString());
    }

    /**
     * Will force the sql represented by this criteria to be executed within
     * a transaction.  This is here primarily to support the oid type in
     * postgresql.  Though it can be used to require any single sql statement
     * to use a transaction.
     */
    public void setUseTransaction(boolean v)
    {
        useTransaction = v;
    }

    /**
     * called by BasePeer to determine whether the sql command specified by
     * this criteria must be wrapped in a transaction.
     *
     * @return a <code>boolean</code> value
     */
    protected boolean isUseTransaction()
    {
        return useTransaction;
    }

    /**
     * Method to return criteria related to columns in a table.
     *
     * @param column String name of column.
     * @return A Criterion.
     */
    public Criterion getCriterion(String column)
    {
        return (Criterion) super.get(column);
    }

    /**
     * Method to return criteria related to a column in a table.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A Criterion.
     */
    public Criterion getCriterion(String table, String column)
    {
        return getCriterion(
                new StringBuffer(table.length() + column.length() + 1)
                .append(table).append('.').append(column)
                .toString());
    }

    /**
     * Method to return criterion that is not added automatically
     * to this Criteria.  This can be used to chain the
     * Criterions to form a more complex where clause.
     *
     * @param column String full name of column (for example TABLE.COLUMN).
     * @return A Criterion.
     */
    public Criterion getNewCriterion(String column, Object value,
            SqlEnum comparison)
    {
        return new Criterion(column, value, comparison);
    }

    /**
     * Method to return criterion that is not added automatically
     * to this Criteria.  This can be used to chain the
     * Criterions to form a more complex where clause.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A Criterion.
     */
    public Criterion getNewCriterion(String table, String column,
                                     Object value, SqlEnum comparison)
    {
        return new Criterion(table, column, value, comparison);
    }

    /**
     * This method adds a prepared Criterion object to the Criteria.
     * You can get a new, empty Criterion object with the
     * getNewCriterion() method. If a criterion for the requested column
     * already exists, it is replaced. This is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria();
     * Criteria.Criterion c = crit
     * .getNewCriterion(BasePeer.ID, new Integer(5), Criteria.LESS_THAN);
     * crit.add(c);
     * </code>
     *
     * @param c A Criterion object
     *
     * @return A modified Criteria object.
     */
    public Criteria add(Criterion c)
    {
        StringBuffer sb = new StringBuffer(c.getTable().length()
                + c.getColumn().length() + 1);
        sb.append(c.getTable());
        sb.append('.');
        sb.append(c.getColumn());
        super.put(sb.toString(), c);
        return this;
    }

    /**
     * Method to return a String table name.
     *
     * @param name A String with the name of the key.
     * @return A String with the value of the object at key.
     */
    public String getColumnName(String name)
    {
        return getCriterion(name).getColumn();
    }

    /**
     * Method to return a comparison String.
     *
     * @param key String name of the key.
     * @return A String with the value of the object at key.
     */
    public SqlEnum getComparison(String key)
    {
        return getCriterion(key).getComparison();
    }

    /**
     * Method to return a comparison String.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A String with the value of the object at key.
     */
    public SqlEnum getComparison(String table, String column)
    {
        return getComparison(
                new StringBuffer(table.length() + column.length() + 1)
                .append(table).append('.').append(column)
                .toString());
    }

    /**
     * Convenience method to return a Date.
     *
     * @param name column name (TABLE.COLUMN)
     * @return A java.util.Date with the value of object at key.
     */
    public java.util.Date getDate(String name)
    {
        return (java.util.Date) getCriterion(name).getValue();
    }

    /**
     * Convenience method to return a Date.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A java.util.Date with the value of object at key.
     */
    public java.util.Date getDate(String table, String column)
    {
        return getDate(
                new StringBuffer(table.length() + column.length() + 1)
                .append(table).append('.').append(column)
                .toString());
    }

    /**
     * Get the Database(Map) name.
     *
     * @return A String with the Database(Map) name.  By default, this
     * is PoolBrokerService.DEFAULT.
     */
    public String getDbName()
    {
        return dbName;
    }

    /**
     * Set the DatabaseMap name.  If <code>null</code> is supplied, uses value
     * provided by <code>Torque.getDefaultDB()</code>.
     *
     * @param dbName A String with the Database(Map) name.
     */
    public void setDbName(String dbName)
    {
        this.dbName = (dbName == null ? Torque.getDefaultDB() : dbName.trim());
    }

    /**
     * Convenience method to return a double.
     *
     * @param name A String with the name of the key.
     * @return A double with the value of object at key.
     */
    public double getDouble(String name)
    {
        Object obj = getCriterion(name).getValue();
        if (obj instanceof String)
        {
            return new Double((String) obj).doubleValue();
        }
        return ((Double) obj).doubleValue();
    }

    /**
     * Convenience method to return a double.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A double with the value of object at key.
     */
    public double getDouble(String table, String column)
    {
        return getDouble(new StringBuffer(table.length() + column.length() + 1)
                .append(table).append('.').append(column)
                .toString());
    }

    /**
     * Convenience method to return a float.
     *
     * @param name A String with the name of the key.
     * @return A float with the value of object at key.
     */
    public float getFloat(String name)
    {
        Object obj = getCriterion(name).getValue();
        if (obj instanceof String)
        {
            return new Float((String) obj).floatValue();
        }
        return ((Float) obj).floatValue();
    }

    /**
     * Convenience method to return a float.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A float with the value of object at key.
     */
    public float getFloat(String table, String column)
    {
        return getFloat(new StringBuffer(table.length() + column.length() + 1)
                .append(table).append('.').append(column)
                .toString());
    }

    /**
     * Convenience method to return an Integer.
     *
     * @param name A String with the name of the key.
     * @return An Integer with the value of object at key.
     */
    public Integer getInteger(String name)
    {
        Object obj = getCriterion(name).getValue();
        if (obj instanceof String)
        {
            return new Integer((String) obj);
        }
        return ((Integer) obj);
    }

    /**
     * Convenience method to return an Integer.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return An Integer with the value of object at key.
     */
    public Integer getInteger(String table, String column)
    {
        return getInteger(
                new StringBuffer(table.length() + column.length() + 1)
                .append(table).append('.').append(column)
                .toString());
    }

    /**
     * Convenience method to return an int.
     *
     * @param name A String with the name of the key.
     * @return An int with the value of object at key.
     */
    public int getInt(String name)
    {
        Object obj = getCriterion(name).getValue();
        if (obj instanceof String)
        {
            return new Integer((String) obj).intValue();
        }
        return ((Integer) obj).intValue();
    }

    /**
     * Convenience method to return an int.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return An int with the value of object at key.
     */
    public int getInt(String table, String column)
    {
        return getInt(
            new StringBuffer(table.length() + column.length() + 1)
            .append(table).append('.').append(column)
            .toString());
    }

    /**
     * Convenience method to return a BigDecimal.
     *
     * @param name A String with the name of the key.
     * @return A BigDecimal with the value of object at key.
     */
    public BigDecimal getBigDecimal(String name)
    {
        Object obj = getCriterion(name).getValue();
        if (obj instanceof String)
        {
            return new BigDecimal((String) obj);
        }
        return (BigDecimal) obj;
    }

    /**
     * Convenience method to return a BigDecimal.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A BigDecimal with the value of object at key.
     */
    public BigDecimal getBigDecimal(String table, String column)
    {
        return getBigDecimal(
            new StringBuffer(table.length() + column.length() + 1)
            .append(table).append('.').append(column)
            .toString());
    }

    /**
     * Convenience method to return a long.
     *
     * @param name A String with the name of the key.
     * @return A long with the value of object at key.
     */
    public long getLong(String name)
    {
        Object obj = getCriterion(name).getValue();
        if (obj instanceof String)
        {
            return new Long((String) obj).longValue();
        }
        return ((Long) obj).longValue();
    }

    /**
     * Convenience method to return a long.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A long with the value of object at key.
     */
    public long getLong(String table, String column)
    {
        return getLong(
            new StringBuffer(table.length() + column.length() + 1)
            .append(table).append('.').append(column)
            .toString());
    }

    /**
     * Convenience method to return a String.
     *
     * @param name A String with the name of the key.
     * @return A String with the value of object at key.
     */
    public String getString(String name)
    {
        return (String) getCriterion(name).getValue();
    }

    /**
     * Convenience method to return a String.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A String with the value of object at key.
     */
    public String getString(String table, String column)
    {
        return getString(
            new StringBuffer(table.length() + column.length() + 1)
            .append(table).append('.').append(column)
            .toString());
    }

    /**
     * Method to return a String table name.
     *
     * @param name A String with the name of the key.
     * @return A String with the value of object at key.
     */
     public String getTableName(String name)
    {
        return getCriterion(name).getTable();
    }

    /**
     * Convenience method to return a List.
     *
     * @param name A String with the name of the key.
     * @return A List with the value of object at key.
     */
    public List getList(String name)
    {
        return (List) getCriterion(name).getValue();
    }

    /**
     * Convenience method to return a List.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A List with the value of object at key.
     */
    public List getList(String table, String column)
    {
        return getList(
            new StringBuffer(table.length() + column.length() + 1)
            .append(table).append('.').append(column)
            .toString());
    }

    /**
     * Method to return the value that was added to Criteria.
     *
     * @param name A String with the name of the key.
     * @return An Object with the value of object at key.
     */
    public Object getValue(String name)
    {
        return getCriterion(name).getValue();
    }

    /**
     * Method to return the value that was added to Criteria.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return An Object with the value of object at key.
     */
    public Object getValue(String table, String column)
    {
        return getValue(
            new StringBuffer(table.length() + column.length() + 1)
            .append(table).append('.').append(column)
            .toString());
    }

    /**
     * Convenience method to return an ObjectKey.
     *
     * @param name A String with the name of the key.
     * @return An ObjectKey with the value of object at key.
     */
    public ObjectKey getObjectKey(String name)
    {
        return (ObjectKey) getCriterion(name).getValue();
    }

    /**
     * Convenience method to return an ObjectKey.
     *
     * @param table String name of table.
     * @param column String name of column.
     * @return A String with the value of object at key.
     */
    public ObjectKey getObjectKey(String table, String column)
    {
        return getObjectKey(
            new StringBuffer(table.length() + column.length() + 1)
            .append(table).append('.').append(column)
            .toString());
    }

    /**
     * Overrides Hashtable get, so that the value placed in the
     * Criterion is returned instead of the Criterion.
     *
     * @param key An Object.
     * @return An Object.
     */
    public Object get(Object key)
    {
        return getValue((String) key);
    }

    /**
     * Overrides Hashtable put, so that this object is returned
     * instead of the value previously in the Criteria object.
     * The reason is so that it more closely matches the behavior
     * of the add() methods. If you want to get the previous value
     * then you should first Criteria.get() it yourself. Note, if
     * you attempt to pass in an Object that is not a String, it will
     * throw a NPE. The reason for this is that none of the add()
     * methods support adding anything other than a String as a key.
     *
     * @param key An Object. Must be instanceof String!
     * @param value An Object.
     * @throws NullPointerException if key != String or key/value is null.
     * @return Instance of self.
     */
    public Object put(Object key, Object value)
    {
        if (!(key instanceof String))
        {
            throw new NullPointerException(
                            "Criteria: Key must be a String object.");
        }
        return add((String) key, value);
    }

    /**
     * Copies all of the mappings from the specified Map to this Criteria
     * These mappings will replace any mappings that this Criteria had for any
     * of the keys currently in the specified Map.
     *
     * if the map was another Criteria, its attributes are copied to this
     * Criteria, overwriting previous settings.
     *
     * @param t Mappings to be stored in this map.
     */
    public synchronized void putAll(Map t)
    {
        Iterator i = t.entrySet().iterator();
        while (i.hasNext())
        {
            Map.Entry e = (Map.Entry) i.next();
            Object val = e.getValue();
            if (val instanceof Criteria.Criterion)
            {
                super.put(e.getKey(), val);
            }
            else
            {
                put(e.getKey(), val);
            }
        }
        if (t instanceof Criteria)
        {
            Criteria c = (Criteria) t;
            this.joinL = c.joinL;
            this.joinR = c.joinR;
        }
        /* this would make a copy, not included
           but might want to use some of it.
        if (t instanceof Criteria)
        {
            Criteria c = (Criteria)t;
            this.ignoreCase = c.ignoreCase;
            this.singleRecord = c.singleRecord;
            this.cascade = c.cascade;
            this.selectModifiers = c.selectModifiers;
            this.selectColumns = c.selectColumns;
            this.orderByColumns = c.orderByColumns;
            this.dbName = c.dbName;
            this.limit = c.limit;
            this.offset = c.offset;
            this.aliases = c.aliases;
        }
        */
    }

    /**
     * This method adds a new criterion to the list of criterias. If a
     * criterion for the requested column already exists, it is
     * replaced. This is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().add(&quot;column&quot;,
     *                                      &quot;value&quot;);
     * </code>
     *
     * An EQUAL comparison is used for column and value.
     *
     * The name of the table must be used implicitly in the column name,
     * so the Column name must be something like 'TABLE.id'. If you
     * don't like this, you can use the add(table, column, value) method.
     *
     * @param column The column to run the comparison on
     * @param value An Object.
     *
     * @return A modified Criteria object.
     */
    public Criteria add (String column, Object value)
    {
        add(column, value, EQUAL);
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias.
     * If a criterion for the requested column already exists, it is
     * replaced. If is used as follow:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().add(&quot;column&quot;,
     *                                      &quot;value&quot;
     *                                      &quot;Criterion.GREATER_THAN&quot;);
     * </code>
     *
     * Any comparison can be used.
     *
     * The name of the table must be used implicitly in the column name,
     * so the Column name must be something like 'TABLE.id'. If you
     * don't like this, you can use the add(table, column, value) method.
     *
     * @param column The column to run the comparison on
     * @param value An Object.
     * @param comparison A String.
     *
     * @return A modified Criteria object.
     */
    public Criteria add(String column, Object value, SqlEnum comparison)
    {
        super.put(column, new Criterion(column, value, comparison));
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias.
     * If a criterion for the requested column already exists, it is
     * replaced. If is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().add(&quot;table&quot;,
     *                                      &quot;column&quot;,
     *                                      &quot;value&quot;);
     * </code>
     *
     * An EQUAL comparison is used for column and value.
     *
     * @param table Name of the table which contains the column
     * @param column The column to run the comparison on
     * @param value An Object.
     *
     * @return A modified Criteria object.
     */
    public Criteria add(String table, String column, Object value)
    {
        add(table, column, value, EQUAL);
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias.
     * If a criterion for the requested column already exists, it is
     * replaced. If is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().add(&quot;table&quot;,
     *                                      &quot;column&quot;,
     *                                      &quot;value&quot;,
     *                                      &quot;Criterion.GREATER_THAN&quot;);
     * </code>
     *
     * Any comparison can be used.
     *
     * @param table Name of table which contains the column
     * @param column The column to run the comparison on
     * @param value An Object.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria add(String table,
                        String column,
                        Object value,
                        SqlEnum comparison)
    {
        StringBuffer sb = new StringBuffer(table.length()
                + column.length() + 1);
        sb.append(table);
        sb.append('.');
        sb.append(column);
        super.put(sb.toString(),
                  new Criterion(table, column, value, comparison));
        return this;
    }

    /**
     * Convenience method to add a boolean to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Boolean(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A Boolean.
     *
     * @return A modified Criteria object.
     */
    public Criteria add(String column, boolean value)
    {
        add(column, (value ? Boolean.TRUE : Boolean.FALSE));
        return this;
    }

    /**
     * Convenience method to add a boolean to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Boolean(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A Boolean.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria add(String column, boolean value, SqlEnum comparison)
    {
        add(column, new Boolean(value), comparison);
        return this;
    }

    /**
     * Convenience method to add an int to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Integer(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value An int.
     * @return A modified Criteria object.
     */
    public Criteria add(String column, int value)
    {
        add(column, new Integer(value));
        return this;
    }

    /**
     * Convenience method to add an int to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Integer(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value An int.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria add(String column, int value, SqlEnum comparison)
    {
        add(column, new Integer(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a long to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Long(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A long.
     * @return A modified Criteria object.
     */
    public Criteria add(String column, long value)
    {
        add(column, new Long(value));
        return this;
    }

    /**
     * Convenience method to add a long to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Long(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A long.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria add(String column, long value, SqlEnum comparison)
    {
        add(column, new Long(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a float to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Float(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A float.
     * @return A modified Criteria object.
     */
    public Criteria add(String column, float value)
    {
        add(column, new Float(value));
        return this;
    }

    /**
     * Convenience method to add a float to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Float(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A float.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria add(String column, float value, SqlEnum comparison)
    {
        add(column, new Float(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a double to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Double(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A double.
     * @return A modified Criteria object.
     */
    public Criteria add(String column, double value)
    {
        add(column, new Double(value));
        return this;
    }

    /**
     * Convenience method to add a double to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new Double(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A double.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria add(String column, double value, SqlEnum comparison)
    {
        add(column, new Double(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a Date object specified by
     * year, month, and date into the Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new GregorianCalendar(year, month,date), EQUAL);
     * </code>
     *
     * @param column A String value to use as column.
     * @param year An int with the year.
     * @param month An int with the month. Month value is 0-based.
     *        e.g., 0 for January
     * @param date An int with the date.
     * @return A modified Criteria object.
     */
    public Criteria addDate(String column, int year, int month, int date)
    {
        add(column, new GregorianCalendar(year, month, date).getTime());
        return this;
    }

    /**
     * Convenience method to add a Date object specified by
     * year, month, and date into the Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * add(column, new GregorianCalendar(year, month,date), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param year An int with the year.
     * @param month An int with the month. Month value is 0-based.
     *        e.g., 0 for January
     * @param date An int with the date.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria addDate(String column, int year, int month, int date,
                            SqlEnum comparison)
    {
        add(column, new GregorianCalendar(year, month, date).getTime(),
            comparison);
        return this;
    }

    /**
     * This is the way that you should add a join of two tables.  For
     * example:
     *
     * <p>
     * AND PROJECT.PROJECT_ID=FOO.PROJECT_ID
     * <p>
     *
     * left = PROJECT.PROJECT_ID
     * right = FOO.PROJECT_ID
     *
     * @param left A String with the left side of the join.
     * @param right A String with the right side of the join.
     * @return A modified Criteria object.
     */
    public Criteria addJoin(String left, String right)
    {
        if (joinL == null)
        {
            joinL = new ArrayList(3);
            joinR = new ArrayList(3);
        }
        joinL.add(left);
        joinR.add(right);

        return this;
    }

    /**
     * get one side of the set of possible joins.  This method is meant to
     * be called by BasePeer.
     */
    public List getJoinL()
    {
        return joinL;
    }

    /**
     * get one side of the set of possible joins.  This method is meant to
     * be called by BasePeer.
     */
    public List getJoinR()
    {
        return joinR;
    }

    /**
     * Adds an 'IN' clause with the criteria supplied as an Object
     * array.  For example:
     *
     * <p>
     * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * replaced.
     *
     * @param column The column to run the comparison on
     * @param values An Object[] with the allowed values.
     * @return A modified Criteria object.
     */
    public Criteria addIn(String column, Object[] values)
    {
        add(column, (Object) values, Criteria.IN);
        return this;
    }

    /**
     * Adds an 'IN' clause with the criteria supplied as an int array.
     * For example:
     *
     * <p>
     * FOO.ID IN ('2', '3', '7')
     * <p>
     *
     * where 'values' contains those three integers.
     *
     * If a criterion for the requested column already exists, it is
     * replaced.
     *
     * @param column The column to run the comparison on
     * @param values An int[] with the allowed values.
     * @return A modified Criteria object.
     */
    public Criteria addIn(String column, int[] values)
    {
        add(column, (Object) values, Criteria.IN);
        return this;
    }

    /**
     * Adds an 'IN' clause with the criteria supplied as a List.
     * For example:
     *
     * <p>
     * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * replaced.
     *
     * @param column The column to run the comparison on
     * @param values A List with the allowed values.
     * @return A modified Criteria object.
     */
    public Criteria addIn(String column, List values)
    {
        add(column, (Object) values, Criteria.IN);
        return this;
    }

    /**
     * Adds a 'NOT IN' clause with the criteria supplied as an Object
     * array.  For example:
     *
     * <p>
     * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * replaced.
     *
     * @param column The column to run the comparison on
     * @param values An Object[] with the disallowed values.
     * @return A modified Criteria object.
     */
    public Criteria addNotIn(String column, Object[] values)
    {
        add(column, (Object) values, Criteria.NOT_IN);
        return this;
    }

    /**
     * Adds a 'NOT IN' clause with the criteria supplied as an int
     * array.  For example:
     *
     * <p>
     * FOO.ID NOT IN ('2', '3', '7')
     * <p>
     *
     * where 'values' contains those three integers.
     *
     * If a criterion for the requested column already exists, it is
     * replaced.
     *
     * @param column The column to run the comparison on
     * @param values An int[] with the disallowed values.
     * @return A modified Criteria object.
     */
    public Criteria addNotIn(String column, int[] values)
    {
        add(column, (Object) values, Criteria.NOT_IN);
        return this;
    }

    /**
     * Adds a 'NOT IN' clause with the criteria supplied as a List.
     * For example:
     *
     * <p>
     * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * replaced.
     *
     * @param column The column to run the comparison on
     * @param values A List with the disallowed values.
     * @return A modified Criteria object.
     */
    public Criteria addNotIn(String column, List values)
    {
        add(column, (Object) values, Criteria.NOT_IN);
        return this;
    }

    /**
     * Adds "ALL " to the SQL statement.
     */
    public void setAll()
    {
        selectModifiers.add(ALL.toString());
    }

    /**
     * Adds "DISTINCT " to the SQL statement.
     */
    public void setDistinct()
    {
        selectModifiers.add(DISTINCT.toString());
    }

    /**
     * Sets ignore case.
     *
     * @param b True if case should be ignored.
     * @return A modified Criteria object.
     */
    public Criteria setIgnoreCase(boolean b)
    {
        ignoreCase = b;
        return this;
    }

    /**
     * Is ignore case on or off?
     *
     * @return True if case is ignored.
     */
    public boolean isIgnoreCase()
    {
        return ignoreCase;
    }

    /**
     * Set single record?  Set this to <code>true</code> if you expect the query
     * to result in only a single result record (the default behaviour is to
     * throw a TorqueException if multiple records are returned when the query
     * is executed).  This should be used in situations where returning multiple
     * rows would indicate an error of some sort.  If your query might return
     * multiple records but you are only interested in the first one then you
     * should be using setLimit(1).
     *
     * @param b set to <code>true</code> if you expect the query to select just
     * one record.
     * @return A modified Criteria object.
     */
    public Criteria setSingleRecord(boolean b)
    {
        singleRecord = b;
        return this;
    }

    /**
     * Is single record?
     *
     * @return True if a single record is being returned.
     */
    public boolean isSingleRecord()
    {
        return singleRecord;
    }

    /**
     * Set cascade.
     *
     * @param b True if cascade is set.
     * @return A modified Criteria object.
     */
    public Criteria setCascade(boolean b)
    {
        cascade = b;
        return this;
    }

    /**
     * Is cascade set?
     *
     * @return True if cascade is set.
     */
    public boolean isCascade()
    {
        return cascade;
    }

    /**
     * Set limit.
     *
     * @param limit An int with the value for limit.
     * @return A modified Criteria object.
     */
    public Criteria setLimit(int limit)
    {
        this.limit = limit;
        return this;
    }

    /**
     * Get limit.
     *
     * @return An int with the value for limit.
     */
    public int getLimit()
    {
        return limit;
    }

    /**
     * Set offset.
     *
     * @param offset An int with the value for offset.
     * @return A modified Criteria object.
     */
    public Criteria setOffset(int offset)
    {
        this.offset = offset;
        return this;
    }

    /**
     * Get offset.
     *
     * @return An int with the value for offset.
     */
    public int getOffset()
    {
        return offset;
    }

    /**
     * Add select column.
     *
     * @param name A String with the name of the select column.
     * @return A modified Criteria object.
     */
    public Criteria addSelectColumn(String name)
    {
        selectColumns.add(name);
        return this;
    }

    /**
     * Get select columns.
     *
     * @return An StringStack with the name of the select
     * columns.
     */
    public UniqueList getSelectColumns()
    {
        return selectColumns;
    }

    /**
     * Get select modifiers.
     *
     * @return An UniqueList with the select modifiers.
     */
    public UniqueList getSelectModifiers()
    {
        return selectModifiers;
    }

    /**
     * Add group by column name.
     *
     * @param groupBy The name of the column to group by.
     * @return A modified Criteria object.
     */
    public Criteria addGroupByColumn(String groupBy)
    {
        groupByColumns.add(groupBy);
        return this;
    }

    /**
     * Add order by column name, explicitly specifying ascending.
     *
     * @param name The name of the column to order by.
     * @return A modified Criteria object.
     */
    public Criteria addAscendingOrderByColumn(String name)
    {
        orderByColumns.add(name + ' ' + ASC);
        return this;
    }

    /**
     * Add order by column name, explicitly specifying descending.
     *
     * @param name The name of the column to order by.
     * @return A modified Criteria object.
     */
    public Criteria addDescendingOrderByColumn(String name)
    {
        orderByColumns.add(name + ' ' + DESC);
        return this;
    }

    /**
     * Get order by columns.
     *
     * @return An UniqueList with the name of the order columns.
     */
    public UniqueList getOrderByColumns()
    {
        return orderByColumns;
    }

    /**
     * Get group by columns.
     *
     * @return An UniqueList with the name of the groupBy clause.
     */
    public UniqueList getGroupByColumns()
    {
        return groupByColumns;
    }

    /**
     * Get Having Criterion.
     *
     * @return A Criterion that is the having clause.
     */
    public Criterion getHaving()
    {
        return having;
    }

    /**
     * Remove an object from the criteria.
     *
     * @param key A String with the key to be removed.
     * @return The removed object.
     */
    public Object remove(String key)
    {
        Object foo = super.remove(key);
        if (foo instanceof Criterion)
        {
            return ((Criterion) foo).getValue();
        }
        return foo;
    }

    /**
     * Build a string representation of the Criteria.
     *
     * @return A String with the representation of the Criteria.
     */
    public String toString()
    {
        StringBuffer sb = new StringBuffer("Criteria:: ");
        Iterator it = keySet().iterator();
        while (it.hasNext())
        {
            String key = (String) it.next();
            sb.append(key).append("<=>")
                .append(super.get(key).toString()).append(":  ");
        }

        try
        {
            sb.append("\nCurrent Query SQL (may not be complete or applicable): ")
              .append(BasePeer.createQueryDisplayString(this));
        }
        catch (Exception exc)
        {
        }

        return sb.toString();
    }

    /**
     * This method checks another Criteria to see if they contain
     * the same attributes and hashtable entries.
     */
    public boolean equals(Object crit)
    {
        boolean isEquiv = false;
        if (crit == null || !(crit instanceof Criteria))
        {
            isEquiv = false;
        }
        else if (this == crit)
        {
            isEquiv = true;
        }
        else if (this.size() == ((Criteria) crit).size())
        {
            Criteria criteria = (Criteria) crit;
            if (this.offset == criteria.getOffset()
                && this.limit == criteria.getLimit()
                && ignoreCase == criteria.isIgnoreCase()
                && singleRecord == criteria.isSingleRecord()
                && cascade == criteria.isCascade()
                && dbName.equals(criteria.getDbName())
                && selectModifiers.equals(criteria.getSelectModifiers())
                && selectColumns.equals(criteria.getSelectColumns())
                && orderByColumns.equals(criteria.getOrderByColumns())
               )
            {
                isEquiv = true;
                for (Iterator it = criteria.keySet().iterator(); it.hasNext();)
                {
                    String key = (String) it.next();
                    if (this.containsKey(key))
                    {
                        Criterion a = this.getCriterion(key);
                        Criterion b = criteria.getCriterion(key);
                        if (!a.equals(b))
                        {
                            isEquiv = false;
                            break;
                        }
                    }
                    else
                    {
                        isEquiv = false;
                        break;
                    }
                }
            }
        }
        return isEquiv;
    }

    /*
     *------------------------------------------------------------------------
     *
     * Start of the "and" methods
     *
     *------------------------------------------------------------------------
     */

    /**
     * This method adds a prepared Criterion object to the Criteria as a having
     * clause. You can get a new, empty Criterion object with the
     * getNewCriterion() method.
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria();
     * Criteria.Criterion c = crit.getNewCriterion(BasePeer.ID, new Integer(5),
     *         Criteria.LESS_THAN);
     * crit.addHaving(c);
     * </code>
     *
     * @param having A Criterion object
     * @return A modified Criteria object.
     */
    public Criteria addHaving(Criterion having)
    {
        this.having = having;
        return this;
    }

    /**
     * This method adds a prepared Criterion object to the Criteria.
     * You can get a new, empty Criterion object with the
     * getNewCriterion() method. If a criterion for the requested column
     * already exists, it is "AND"ed to the existing criterion.
     * This is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria();
     * Criteria.Criterion c = crit.getNewCriterion(BasePeer.ID, new Integer(5),
     *         Criteria.LESS_THAN);
     * crit.and(c);
     * </code>
     *
     * @param c A Criterion object
     * @return A modified Criteria object.
     */
    public Criteria and(Criterion c)
    {
        Criterion oc = getCriterion(c.getTable() + '.' + c.getColumn());

        if (oc == null)
        {
            add(c);
        }
        else
        {
            oc.and(c);
        }
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias. If a
     * criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion. This is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().and(&quot;column&quot;,
     *                                      &quot;value&quot;);
     * </code>
     *
     * An EQUAL comparison is used for column and value.
     *
     * The name of the table must be used implicitly in the column name,
     * so the Column name must be something like 'TABLE.id'. If you
     * don't like this, you can use the and(table, column, value) method.
     *
     * @param column The column to run the comparison on
     * @param value An Object.
     *
     * @return A modified Criteria object.
     */
    public Criteria and(String column, Object value)
    {
        and(column, value, EQUAL);
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias.
     * If a criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion. If is used as follow:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().and(&quot;column&quot;,
     *                                      &quot;value&quot;
     *                                      &quot;Criterion.GREATER_THAN&quot;);
     * </code>
     *
     * Any comparison can be used.
     *
     * The name of the table must be used implicitly in the column name,
     * so the Column name must be something like 'TABLE.id'. If you
     * don't like this, you can use the and(table, column, value) method.
     *
     * @param column The column to run the comparison on
     * @param value An Object.
     * @param comparison A String.
     *
     * @return A modified Criteria object.
     */
    public Criteria and(String column, Object value, SqlEnum comparison)
    {
        Criterion oc = getCriterion(column);
        Criterion nc = new Criterion(column, value, comparison);

        if (oc == null)
        {
            super.put(column, nc);
        }
        else
        {
            oc.and(nc);
        }
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias.
     * If a criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion. If is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().and(&quot;table&quot;,
     *                                      &quot;column&quot;,
     *                                      &quot;value&quot;);
     * </code>
     *
     * An EQUAL comparison is used for column and value.
     *
     * @param table Name of the table which contains the column
     * @param column The column to run the comparison on
     * @param value An Object.
     * @return A modified Criteria object.
     */
    public Criteria and(String table, String column, Object value)
    {
        and(table, column, value, EQUAL);
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias.
     * If a criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion. If is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().and(&quot;table&quot;,
     *                                      &quot;column&quot;,
     *                                      &quot;value&quot;,
     *                                      &quot;Criterion.GREATER_THAN&quot;);
     * </code>
     *
     * Any comparison can be used.
     *
     * @param table Name of table which contains the column
     * @param column The column to run the comparison on
     * @param value An Object.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria and(String table, String column, Object value,
                        SqlEnum comparison)
    {
        StringBuffer sb = new StringBuffer(table.length()
                + column.length() + 1);
        sb.append(table);
        sb.append('.');
        sb.append(column);

        Criterion oc = getCriterion(table, column);
        Criterion nc = new Criterion(table, column, value, comparison);

        if (oc == null)
        {
            super.put(sb.toString(), nc);
        }
        else
        {
            oc.and(nc);
        }
        return this;
    }

    /**
     * Convenience method to add a boolean to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Boolean(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A Boolean.
     * @return A modified Criteria object.
     */
    public Criteria and(String column, boolean value)
    {
        and(column, new Boolean(value));
        return this;
    }

    /**
     * Convenience method to add a boolean to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Boolean(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A Boolean.
     * @param comparison String describing how to compare the column
     * with the value
     * @return A modified Criteria object.
     */
    public Criteria and(String column, boolean value, SqlEnum comparison)
    {
        and(column, new Boolean(value), comparison);
        return this;
    }

    /**
     * Convenience method to add an int to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Integer(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value An int.
     * @return A modified Criteria object.
     */
    public Criteria and(String column, int value)
    {
        and(column, new Integer(value));
        return this;
    }

    /**
     * Convenience method to add an int to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Integer(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value An int.
     * @param comparison String describing how to compare the column with the value
     * @return A modified Criteria object.
     */
    public Criteria and(String column, int value, SqlEnum comparison)
    {
        and(column, new Integer(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a long to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Long(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A long.
     * @return A modified Criteria object.
     */
    public Criteria and(String column, long value)
    {
        and(column, new Long(value));
        return this;
    }

    /**
     * Convenience method to add a long to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Long(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A long.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria and(String column, long value, SqlEnum comparison)
    {
        and(column, new Long(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a float to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Float(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A float.
     * @return A modified Criteria object.
     */
    public Criteria and(String column, float value)
    {
        and(column, new Float(value));
        return this;
    }

    /**
     * Convenience method to add a float to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Float(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A float.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria and(String column, float value, SqlEnum comparison)
    {
        and(column, new Float(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a double to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Double(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A double.
     * @return A modified Criteria object.
     */
    public Criteria and(String column, double value)
    {
        and(column, new Double(value));
        return this;
    }

    /**
     * Convenience method to add a double to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new Double(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A double.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria and(String column, double value, SqlEnum comparison)
    {
        and(column, new Double(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a Date object specified by
     * year, month, and date into the Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new GregorianCalendar(year, month,date), EQUAL);
     * </code>
     *
     * @param column A String value to use as column.
     * @param year An int with the year.
     * @param month An int with the month.
     * @param date An int with the date.
     * @return A modified Criteria object.
     */
    public Criteria andDate(String column, int year, int month, int date)
    {
        and(column, new GregorianCalendar(year, month, date));
        return this;
    }

    /**
     * Convenience method to add a Date object specified by
     * year, month, and date into the Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * and(column, new GregorianCalendar(year, month,date), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param year An int with the year.
     * @param month An int with the month.
     * @param date An int with the date.
     * @param comparison String describing how to compare the column with
     *        the value
     * @return A modified Criteria object.
     */
    public Criteria andDate(String column, int year, int month, int date,
                            SqlEnum comparison)
    {
        and(column, new GregorianCalendar(year, month, date), comparison);
        return this;
    }

    /**
     * Adds an 'IN' clause with the criteria supplied as an Object array.
     * For example:
     *
     * <p>
     * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values An Object[] with the allowed values.
     * @return A modified Criteria object.
     */
    public Criteria andIn(String column, Object[] values)
    {
        and(column, (Object) values, Criteria.IN);
        return this;
    }

    /**
     * Adds an 'IN' clause with the criteria supplied as an int array.
     * For example:
     *
     * <p>
     * FOO.ID IN ('2', '3', '7')
     * <p>
     *
     * where 'values' contains those three integers.
     *
     * If a criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values An int[] with the allowed values.
     * @return A modified Criteria object.
     */
    public Criteria andIn(String column, int[] values)
    {
        and(column, (Object) values, Criteria.IN);
        return this;
    }

    /**
     * Adds an 'IN' clause with the criteria supplied as a List.
     * For example:
     *
     * <p>
     * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values A List with the allowed values.
     * @return A modified Criteria object.
     */
    public Criteria andIn(String column, List values)
    {
        and(column, (Object) values, Criteria.IN);
        return this;
    }

    /**
     * Adds a 'NOT IN' clause with the criteria supplied as an Object
     * array.  For example:
     *
     * <p>
     * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values An Object[] with the disallowed values.
     * @return A modified Criteria object.
     */
    public Criteria andNotIn(String column, Object[] values)
    {
        and(column, (Object) values, Criteria.NOT_IN);
        return this;
    }

    /**
     * Adds a 'NOT IN' clause with the criteria supplied as an int
     * array.  For example:
     *
     * <p>
     * FOO.ID NOT IN ('2', '3', '7')
     * <p>
     *
     * where 'values' contains those three integers.
     *
     * If a criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values An int[] with the disallowed values.
     * @return A modified Criteria object.
     */
     public Criteria andNotIn(String column, int[] values)
    {
        and(column, (Object) values, Criteria.NOT_IN);
        return this;
    }

    /**
     * Adds a 'NOT IN' clause with the criteria supplied as a List.
     * For example:
     *
     * <p>
     * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * "AND"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values A List with the disallowed values.
     * @return A modified Criteria object.
     */
    public Criteria andNotIn(String column, List values)
    {
        and(column, (Object) values, Criteria.NOT_IN);
        return this;
    }

    /*
     *------------------------------------------------------------------------
     *
     * Start of the "or" methods
     *
     *------------------------------------------------------------------------
     */

    /**
     * This method adds a prepared Criterion object to the Criteria.
     * You can get a new, empty Criterion object with the
     * getNewCriterion() method. If a criterion for the requested column
     * already exists, it is "OR"ed to the existing criterion.
     * This is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria();
     * Criteria.Criterion c = crit.getNewCriterion(BasePeer.ID, new Integer(5), Criteria.LESS_THAN);
     * crit.or(c);
     * </code>
     *
     * @param c A Criterion object
     * @return A modified Criteria object.
     */
    public Criteria or(Criterion c)
    {
        Criterion oc = getCriterion(c.getTable() + '.' + c.getColumn());

        if (oc == null)
        {
            add(c);
        }
        else
        {
            oc.or(c);
        }
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias. If a
     * criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion. This is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().or(&quot;column&quot;,
     *                                      &quot;value&quot;);
     * </code>
     *
     * An EQUAL comparison is used for column and value.
     *
     * The name of the table must be used implicitly in the column name,
     * so the Column name must be something like 'TABLE.id'. If you
     * don't like this, you can use the or(table, column, value) method.
     *
     * @param column The column to run the comparison on
     * @param value An Object.
     *
     * @return A modified Criteria object.
     */
    public Criteria or(String column, Object value)
    {
        or(column, value, EQUAL);
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias.
     * If a criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion. If is used as follow:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().or(&quot;column&quot;,
     *                                      &quot;value&quot;
     *                                      &quot;Criterion.GREATER_THAN&quot;);
     * </code>
     *
     * Any comparison can be used.
     *
     * The name of the table must be used implicitly in the column name,
     * so the Column name must be something like 'TABLE.id'. If you
     * don't like this, you can use the or(table, column, value) method.
     *
     * @param column The column to run the comparison on
     * @param value An Object.
     * @param comparison A String.
     * @return A modified Criteria object.
     */
    public Criteria or(String column, Object value, SqlEnum comparison)
    {
        Criterion oc = getCriterion(column);
        Criterion nc = new Criterion(column, value, comparison);

        if (oc == null)
        {
            super.put(column, nc);
        }
        else
        {
            oc.or(nc);
        }
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias.
     * If a criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion. If is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().or(&quot;table&quot;,
     *                                      &quot;column&quot;,
     *                                      &quot;value&quot;);
     * </code>
     *
     * An EQUAL comparison is used for column and value.
     *
     * @param table Name of the table which contains the column
     * @param column The column to run the comparison on
     * @param value An Object.
     * @return A modified Criteria object.
     */
    public Criteria or(String table, String column, Object value)
    {
        or(table, column, value, EQUAL);
        return this;
    }

    /**
     * This method adds a new criterion to the list of criterias.
     * If a criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion. If is used as follows:
     *
     * <p>
     * <code>
     * Criteria crit = new Criteria().or(&quot;table&quot;,
     *                                      &quot;column&quot;,
     *                                      &quot;value&quot;,
     *                                      &quot;Criterion.GREATER_THAN&quot;);
     * </code>
     *
     * Any comparison can be used.
     *
     * @param table Name of table which contains the column
     * @param column The column to run the comparison on
     * @param value An Object.
     * @param comparison String describing how to compare the column with the value
     * @return A modified Criteria object.
     */
    public Criteria or(String table, String column, Object value,
                       SqlEnum comparison)
    {
        StringBuffer sb = new StringBuffer(table.length() + column.length() + 1);
        sb.append(table);
        sb.append('.');
        sb.append(column);

        Criterion oc = getCriterion(table, column);
        Criterion nc = new Criterion(table, column, value, comparison);
        if (oc == null)
        {
            super.put(sb.toString(), nc);
        }
        else
        {
            oc.or(nc);
        }
        return this;
    }

    /**
     * Convenience method to add a boolean to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Boolean(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A Boolean.
     * @return A modified Criteria object.
     */
    public Criteria or(String column, boolean value)
    {
        or(column, new Boolean(value));
        return this;
    }

    /**
     * Convenience method to add a boolean to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Boolean(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A Boolean.
     * @param comparison String describing how to compare the column
     * with the value
     * @return A modified Criteria object.
     */
    public Criteria or(String column, boolean value, SqlEnum comparison)
    {
        or(column, new Boolean(value), comparison);
        return this;
    }

    /**
     * Convenience method to add an int to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Integer(value), EQUAL);
     * </code>
     *
     *
     * @param column The column to run the comparison on
     * @param value An int.
     * @return A modified Criteria object.
     */
    public Criteria or(String column, int value)
    {
        or(column, new Integer(value));
        return this;
    }

    /**
     * Convenience method to add an int to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Integer(value), comparison);
     * </code>
     *
     *
     * @param column The column to run the comparison on
     * @param value An int.
     * @param comparison String describing how to compare the column
     * with the value
     * @return A modified Criteria object.
     */
    public Criteria or(String column, int value, SqlEnum comparison)
    {
        or(column, new Integer(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a long to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Long(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A long.
     * @return A modified Criteria object.
     */
    public Criteria or(String column, long value)
    {
        or(column, new Long(value));
        return this;
    }

    /**
     * Convenience method to add a long to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Long(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A long.
     * @param comparison String describing how to compare the column
     * with the value
     * @return A modified Criteria object.
     */
    public Criteria or(String column, long value, SqlEnum comparison)
    {
        or(column, new Long(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a float to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Float(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A float.
     * @return A modified Criteria object.
     */
    public Criteria or(String column, float value)
    {
        or(column, new Float(value));
        return this;
    }

    /**
     * Convenience method to add a float to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Float(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A float.
     * @param comparison String describing how to compare the column
     * with the value
     * @return A modified Criteria object.
     */
    public Criteria or(String column, float value, SqlEnum comparison)
    {
        or(column, new Float(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a double to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Double(value), EQUAL);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A double.
     * @return A modified Criteria object.
     */
    public Criteria or(String column, double value)
    {
        or(column, new Double(value));
        return this;
    }

    /**
     * Convenience method to add a double to Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new Double(value), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param value A double.
     * @param comparison String describing how to compare the column
     * with the value
     * @return A modified Criteria object.
     */
    public Criteria or(String column, double value, SqlEnum comparison)
    {
        or(column, new Double(value), comparison);
        return this;
    }

    /**
     * Convenience method to add a Date object specified by
     * year, month, and date into the Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new GregorianCalendar(year, month,date), EQUAL);
     * </code>
     *
     * @param column A String value to use as column.
     * @param year An int with the year.
     * @param month An int with the month.
     * @param date An int with the date.
     * @return A modified Criteria object.
     */
    public Criteria orDate(String column, int year, int month, int date)
    {
        or(column, new GregorianCalendar(year, month, date));
        return this;
    }

    /**
     * Convenience method to add a Date object specified by
     * year, month, and date into the Criteria.
     * Equal to
     *
     * <p>
     * <code>
     * or(column, new GregorianCalendar(year, month,date), comparison);
     * </code>
     *
     * @param column The column to run the comparison on
     * @param year An int with the year.
     * @param month An int with the month.
     * @param date An int with the date.
     * @param comparison String describing how to compare the column
     * with the value
     * @return A modified Criteria object.
     */
    public Criteria orDate(String column, int year, int month, int date,
                           SqlEnum comparison)
    {
        or(column, new GregorianCalendar(year, month, date), comparison);
        return this;
    }

    /**
     * Adds an 'IN' clause with the criteria supplied as an Object
     * array.  For example:
     *
     * <p>
     * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values An Object[] with the allowed values.
     * @return A modified Criteria object.
     */
    public Criteria orIn(String column, Object[] values)
    {
        or(column, (Object) values, Criteria.IN);
        return this;
    }

    /**
     * Adds an 'IN' clause with the criteria supplied as an int array.
     * For example:
     *
     * <p>
     * FOO.ID IN ('2', '3', '7')
     * <p>
     *
     * where 'values' contains those three integers.
     *
     * If a criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values An int[] with the allowed values.
     * @return A modified Criteria object.
     */
    public Criteria orIn(String column, int[] values)
    {
        or(column, (Object) values, Criteria.IN);
        return this;
    }

    /**
     * Adds an 'IN' clause with the criteria supplied as a List.
     * For example:
     *
     * <p>
     * FOO.NAME IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values A List with the allowed values.
     * @return A modified Criteria object.
     */
    public Criteria orIn(String column, List values)
    {
        or(column, (Object) values, Criteria.IN);
        return this;
    }

    /**
     * Adds a 'NOT IN' clause with the criteria supplied as an Object
     * array.  For example:
     *
     * <p>
     * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values An Object[] with the disallowed values.
     * @return A modified Criteria object.
     */
    public Criteria orNotIn(String column, Object[] values)
    {
        or(column, (Object) values, Criteria.NOT_IN);
        return this;
    }

    /**
     * Adds a 'NOT IN' clause with the criteria supplied as an int
     * array.  For example:
     *
     * <p>
     * FOO.ID NOT IN ('2', '3', '7')
     * <p>
     *
     * where 'values' contains those three integers.
     *
     * If a criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values An int[] with the disallowed values.
     * @return A modified Criteria object.
     */
    public Criteria orNotIn(String column, int[] values)
    {
        or(column, (Object) values, Criteria.NOT_IN);
        return this;
    }

    /**
     * Adds a 'NOT IN' clause with the criteria supplied as a List.
     * For example:
     *
     * <p>
     * FOO.NAME NOT IN ('FOO', 'BAR', 'ZOW')
     * <p>
     *
     * where 'values' contains three objects that evaluate to the
     * respective strings above when .toString() is called.
     *
     * If a criterion for the requested column already exists, it is
     * "OR"ed to the existing criterion.
     *
     * @param column The column to run the comparison on
     * @param values A List with the disallowed values.
     * @return A modified Criteria object.
     */
    public Criteria orNotIn(String column, List values)
    {
        or(column, (Object) values, Criteria.NOT_IN);
        return this;
    }

    /**
     * Peers can set this flag to notify BasePeer that the table(s) involved
     * in the Criteria contain Blobs, so that the operation can be placed
     * in a transaction if the db requires it.
     * This is primarily to support Postgresql.
     *
     * @deprecated this flag is not used any longer
     */
    public void setBlobFlag(boolean b)
    {
        // do nothing as we don't use the flag any longer
    }

    /**
     * This is an inner class that describes an object in the
     * criteria.
     */
    public final class Criterion implements Serializable
    {
        public static final String AND = " AND ";
        public static final String OR = " OR ";

        /** Value of the CO. */
        private Object value;

        /** Comparison value. */
        private SqlEnum comparison;

        /** Table name. */
        private String table;

        /** Column name. */
        private String column;

        /** flag to ignore case in comparision */
        private boolean ignoreStringCase = false;

        /**
         * The DB adaptor which might be used to get db specific
         * variations of sql.
         */
        private DB db;

        /**
         * other connected criteria and their conjunctions.
         */
        private List clauses = new ArrayList();
        private List conjunctions = new ArrayList();

        /**
         * Creates a new instance, initializing a couple members.
         */
        private Criterion(Object val, SqlEnum comp)
        {
            this.value = val;
            this.comparison = comp;
        }

        /**
         * Create a new instance.
         *
         * @param table A String with the name of the table.
         * @param column A String with the name of the column.
         * @param val An Object with the value for the Criteria.
         * @param comp A String with the comparison value.
         */
        Criterion(String table, String column, Object val, SqlEnum comp)
        {
            this(val, comp);
            this.table = (table == null ? "" : table);
            this.column = (column == null ? "" : column);
        }

        /**
         * Create a new instance.
         *
         * @param tableColumn A String with the full name of the
         * column.
         * @param val An Object with the value for the Criteria.
         * @param comp A String with the comparison value.
         */
        Criterion(String tableColumn, Object val, SqlEnum comp)
        {
            this(val, comp);
            int dot = tableColumn.indexOf('.');
            if (dot == -1)
            {
                table = "";
                column = tableColumn;
            }
            else
            {
                table = tableColumn.substring(0, dot);
                column = tableColumn.substring(dot + 1);
            }
        }

        /**
         * Create a new instance.
         *
         * @param table A String with the name of the table.
         * @param column A String with the name of the column.
         * @param val An Object with the value for the Criteria.
         */
        Criterion(String table, String column, Object val)
        {
            this(table, column, val, EQUAL);
        }

        /**
         * Create a new instance.
         *
         * @param tableColumn A String with the full name of the
         * column.
         * @param val An Object with the value for the Criteria.
         */
        Criterion(String tableColumn, Object val)
        {
            this(tableColumn, val, EQUAL);
        }

        /**
         * Get the column name.
         *
         * @return A String with the column name.
         */
        public String getColumn()
        {
            return this.column;
        }

        /**
         * Set the table name.
         *
         * @param name A String with the table name.
         */
        public void setTable(String name)
        {
            this.table = name;
        }

        /**
         * Get the table name.
         *
         * @return A String with the table name.
         */
        public String getTable()
        {
            return this.table;
        }

        /**
         * Get the comparison.
         *
         * @return A String with the comparison.
         */
        public SqlEnum getComparison()
        {
            return this.comparison;
        }

        /**
         * Get the value.
         *
         * @return An Object with the value.
         */
        public Object getValue()
        {
            return this.value;
        }

        /**
         * Get the value of db.
         * The DB adaptor which might be used to get db specific
         * variations of sql.
         * @return value of db.
         */
        public DB getDb()
        {
            DB db = null;
            if (this.db == null)
            {
                // db may not be set if generating preliminary sql for
                // debugging.
                try
                {
                    db = Torque.getDB(getDbName());
                }
                catch (Exception e)
                {
                    // we are only doing this to allow easier debugging, so
                    // no need to throw up the exception, just make note of it.
                    log.error(
                            "Could not get a DB adapter, so sql may be wrong");
                }
            }
            else
            {
                db = this.db;
            }

            return db;
        }

        /**
         * Set the value of db.
         * The DB adaptor might be used to get db specific
         * variations of sql.
         * @param v  Value to assign to db.
         */
        public void setDB(DB v)
        {
            this.db = v;

            for (int i = 0; i < this.clauses.size(); i++)
            {
                ((Criterion) (clauses.get(i))).setDB(v);
            }
        }

        /**
         * Sets ignore case.
         *
         * @param b True if case should be ignored.
         * @return A modified Criteria object.
         */
        public Criterion setIgnoreCase(boolean b)
        {
            ignoreStringCase = b;
            return this;
        }

        /**
         * Is ignore case on or off?
         *
         * @return True if case is ignored.
         */
         public boolean isIgnoreCase()
         {
             return ignoreStringCase;
         }

        /**
         *  get the list of clauses in this Criterion
         */
        private List getClauses()
        {
            return clauses;
        }

        /**
         *  get the list of conjunctions in this Criterion
         */
        private List getConjunctions()
        {
            return conjunctions;
        }

        /**
         * Append an AND Criterion onto this Criterion's list.
         */
        public Criterion and(Criterion criterion)
        {
            this.clauses.add(criterion);
            this.conjunctions.add(AND);
            return this;
        }

        /**
         * Append an OR Criterion onto this Criterion's list.
         */
        public Criterion or(Criterion criterion)
        {
            this.clauses.add(criterion);
            this.conjunctions.add(OR);
            return this;
        }

        /**
         * Appends a representation of the Criterion onto the buffer.
         */
        public void appendTo(StringBuffer sb)
        {
            //
            // it is alright if value == null
            //

            if (column == null)
            {
                return;
            }

            Criterion clause = null;
            for (int j = 0; j < this.clauses.size(); j++)
            {
                sb.append('(');
            }
            if (CUSTOM == comparison)
            {
                if (value != null && !"".equals(value))
                {
                    sb.append((String) value);
                }
            }
            else
            {
                String field = null;
                if  (table == null)
                {
                    field = column;
                }
                else
                {
                    field = new StringBuffer(
                        table.length() + 1 + column.length())
                        .append(table).append('.').append(column)
                        .toString();
                }
                SqlExpression.build(field, value, comparison,
                                    ignoreStringCase, getDb(), sb);
            }

            for (int i = 0; i < this.clauses.size(); i++)
            {
                sb.append(this.conjunctions.get(i));
                clause = (Criterion) (this.clauses.get(i));
                clause.appendTo(sb);
                sb.append(')');
            }
        }

        /**
         * Appends a Prepared Statement representation of the Criterion
         * onto the buffer.
         *
         * @param sb The stringbuffer that will receive the Prepared Statement
         * @param params A list to which Prepared Statement parameters
         * will be appended
         */
        public void appendPsTo(StringBuffer sb, List params)
        {
            if (column == null || value == null)
            {
                return;
            }

            DB db = getDb();

            for (int j = 0; j < this.clauses.size(); j++)
            {
                sb.append('(');
            }
            if (CUSTOM == comparison)
            {
                if (!"".equals(value))
                {
                    sb.append((String) value);
                }
            }
            else
            {
                String field = null;
                if (table == null)
                {
                    field = column;
                }
                else
                {
                    field = new StringBuffer(
                        table.length() + 1 + column.length())
                        .append(table).append('.').append(column)
                        .toString();
                }

                if (comparison.equals(Criteria.IN)
                     || comparison.equals(Criteria.NOT_IN))
                {
                    sb.append(field)
                      .append(comparison);

                    UniqueList inClause = new UniqueList();

                    if (value instanceof List)
                    {
                        value = ((List) value).toArray (new Object[0]);
                    }

                    for (int i = 0; i < Array.getLength(value); i++)
                    {
                        Object item = Array.get(value, i);

                        inClause.add(SqlExpression.processInValue(item,
                                                                  ignoreCase,
                                                                  db));
                    }

                    StringBuffer inString = new StringBuffer();
                    inString.append('(').append(StringUtils.join(
                            inClause.iterator(), (","))).append(')');
                    sb.append(inString.toString());
                }
                else
                {
                    if (ignoreCase)
                    {
                        sb.append(db.ignoreCase(field))
                          .append(comparison)
                          .append(db.ignoreCase("?"));
                    }
                    else
                    {
                        sb.append(field)
                          .append(comparison)
                          .append(" ? ");
                    }

                    if (value instanceof java.util.Date)
                    {
                        params.add(new java.sql.Date(
                            ((java.util.Date) value).getTime()));
                    }
                    else if (value instanceof DateKey)
                    {
                        params.add(new java.sql.Date(
                            ((DateKey) value).getDate().getTime()));
                    }
                    else
                    {
                        params.add(value.toString());
                    }
                }
            }

            for (int i = 0; i < this.clauses.size(); i++)
            {
                sb.append(this.conjunctions.get(i));
                Criterion clause = (Criterion) (this.clauses.get(i));
                clause.appendPsTo(sb, params);
                sb.append(')');
            }
        }

        /**
         * Build a string representation of the Criterion.
         *
         * @return A String with the representation of the Criterion.
         */
        public String toString()
        {
            //
            // it is alright if value == null
            //
            if (column == null)
            {
                return "";
            }

            StringBuffer expr = new StringBuffer(25);
            appendTo(expr);
            return expr.toString();
        }

        /**
         * This method checks another Criteria to see if they contain
         * the same attributes and hashtable entries.
         */
        public boolean equals(Object obj)
        {
            if (this == obj)
            {
                return true;
            }

            if ((obj == null) || !(obj instanceof Criterion))
            {
                return false;
            }

            Criterion crit = (Criterion) obj;

            boolean isEquiv = ((table == null && crit.getTable() == null)
                || (table != null && table.equals(crit.getTable()))
                              )
                && column.equals(crit.getColumn())
                && comparison.equals(crit.getComparison());

            // we need to check for value equality
            if (isEquiv)
            {
                Object b = crit.getValue();
                if (value instanceof Object[] && b instanceof Object[])
                {
                    isEquiv &= Arrays.equals((Object[]) value, (Object[]) b);
                }
                else if (value instanceof int[] && b instanceof int[])
                {
                    isEquiv &= Arrays.equals((int[]) value, (int[]) b);
                }
                else
                {
                    isEquiv &= value.equals(b);
                }
            }

            // check chained criterion

            isEquiv &= this.clauses.size() == crit.getClauses().size();
            for (int i = 0; i < this.clauses.size(); i++)
            {
              isEquiv &=  ((String) (conjunctions.get(i)))
                  .equals((String) (crit.getConjunctions().get(i)));
              isEquiv &=  ((Criterion) (clauses.get(i)))
                  .equals((Criterion) (crit.getClauses().get(i)));
            }

            return isEquiv;
        }

        /**
         * Returns a hash code value for the object.
         */
        public int hashCode()
        {
            int h = value.hashCode() ^ comparison.hashCode();

            if (table != null)
            {
                h ^= table.hashCode();
            }

            if (column != null)
            {
                h ^= column.hashCode();
            }

            for (int i = 0; i < this.clauses.size(); i++)
            {
                h ^= ((Criterion) (clauses.get(i))).hashCode();
            }

            return h;
        }

        /**
         * get all tables from nested criterion objects
         *
         * @return the list of tables
         */
        public List getAllTables()
        {
            UniqueList tables = new UniqueList();
            addCriterionTable(this, tables);
            return tables;
        }

        /**
         * method supporting recursion through all criterions to give
         * us a StringStack of tables from each criterion
         */
        private void addCriterionTable(Criterion c, UniqueList s)
        {
            if (c != null)
            {
                s.add(c.getTable());
                for (int i = 0; i < c.getClauses().size(); i++)
                {
                    addCriterionTable((Criterion) (c.getClauses().get(i)), s);
                }
            }
        }

        /**
         * get an array of all criterion attached to this
         * recursing through all sub criterion
         */
        public Criterion[] getAttachedCriterion()
        {
            ArrayList crits = new ArrayList();
            traverseCriterion(this, crits);
            Criterion[] crita = new Criterion[crits.size()];
            for (int i = 0; i < crits.size(); i++)
            {
                crita[i] = (Criterion) crits.get(i);
            }

            return crita;
        }

        /**
         * method supporting recursion through all criterions to give
         * us an ArrayList of them
         */
        private void traverseCriterion(Criterion c, ArrayList a)
        {
            if (c != null)
            {
                a.add(c);
                for (int i = 0; i < c.getClauses().size(); i++)
                {
                    traverseCriterion((Criterion) (c.getClauses().get(i)), a);
                }
            }
        }
    }
}
TOP

Related Classes of org.apache.torque.util.Criteria$Criterion

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.