You are viewing a plain text version of this content. The canonical link for it is here.
Posted to torque-dev@db.apache.org by tf...@apache.org on 2005/11/12 12:15:30 UTC

svn commit: r332758 - in /db/torque/runtime/trunk: src/java/org/apache/torque/util/Criteria.java src/test/org/apache/torque/util/CriteriaTest.java xdocs/changes.xml

Author: tfischer
Date: Sat Nov 12 03:15:21 2005
New Revision: 332758

URL: http://svn.apache.org/viewcvs?rev=332758&view=rev
Log:
Scott's fix for TRQS321. 
Criteria is now serializable, and has an improved equals() method and a 
hashCode() method.
Thanks to Martin Goulet for an early version of the patch.

Modified:
    db/torque/runtime/trunk/src/java/org/apache/torque/util/Criteria.java
    db/torque/runtime/trunk/src/test/org/apache/torque/util/CriteriaTest.java
    db/torque/runtime/trunk/xdocs/changes.xml

Modified: db/torque/runtime/trunk/src/java/org/apache/torque/util/Criteria.java
URL: http://svn.apache.org/viewcvs/db/torque/runtime/trunk/src/java/org/apache/torque/util/Criteria.java?rev=332758&r1=332757&r2=332758&view=diff
==============================================================================
--- db/torque/runtime/trunk/src/java/org/apache/torque/util/Criteria.java (original)
+++ db/torque/runtime/trunk/src/java/org/apache/torque/util/Criteria.java Sat Nov 12 03:15:21 2005
@@ -16,6 +16,9 @@
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.lang.reflect.Array;
 import java.math.BigDecimal;
@@ -30,6 +33,7 @@
 
 import org.apache.commons.collections.OrderedMap;
 import org.apache.commons.collections.map.ListOrderedMap;
+import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -54,10 +58,13 @@
  * @author <a href="mailto:sam@neurogrid.com">Sam Joseph</a>
  * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
  * @author <a href="mailto:fischer@seitenbau.de">Thomas Fischer</a>
+ * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
  * @version $Id$
  */
 public class Criteria extends Hashtable
 {
+    /** Serial version. */
+    private static final long serialVersionUID = -9001666575933085601L;
 
     /** Comparison type. */
     public static final SqlEnum EQUAL = SqlEnum.EQUAL;
@@ -148,7 +155,7 @@
     private UniqueList groupByColumns = new UniqueList();
     private Criterion having = null;
     private OrderedMap asColumns = ListOrderedMap.decorate(new HashMap());
-    private List joins = null;
+    private transient List joins = null;
 
     /** The name of the database. */
     private String dbName;
@@ -275,6 +282,16 @@
     }
 
     /**
+     * Get the table aliases.
+     *
+     * @return A Map which maps the table alias names to the actual table names.
+     */
+    public Map getAliases()
+    {
+        return aliases;
+    }
+
+    /**
      * Allows one to specify an alias for a table that can
      * be used in various parts of the SQL.
      *
@@ -1818,6 +1835,9 @@
                     && selectModifiers.equals(criteria.getSelectModifiers())
                     && selectColumns.equals(criteria.getSelectColumns())
                     && orderByColumns.equals(criteria.getOrderByColumns())
+                    && ObjectUtils.equals(aliases, criteria.getAliases())
+                    && asColumns.equals(criteria.getAsColumns())
+                    && joins.equals(criteria.getJoins())
                 )
             {
                 isEquiv = true;
@@ -1845,6 +1865,30 @@
         return isEquiv;
     }
 
+    /**
+     * Returns the hash code value for this Join.
+     *
+     * @return a hash code value for this object.
+     */
+    public int hashCode()
+    {
+        int result = 16;
+        result = 37 * result + offset;
+        result = 37 * result + limit;
+        result = 37 * result + (ignoreCase ? 0 : 1);
+        result = 37 * result + (singleRecord ? 0 : 1);
+        result = 37 * result + (cascade ? 0 : 1);
+        result = 37 * result + dbName.hashCode();
+        result = 37 * result + selectModifiers.hashCode();
+        result = 37 * result + selectColumns.hashCode();
+        result = 37 * result + orderByColumns.hashCode();
+        result = 37 * result + (aliases == null ? 0 : aliases.hashCode());
+        result = 37 * result + asColumns.hashCode();
+        result = 37 * result + joins.hashCode();
+        result = 37 * result + super.hashCode();
+        return result;
+    }
+
     /*
      * ------------------------------------------------------------------------
      *
@@ -3000,11 +3044,90 @@
     }
 
     /**
-     * This is an inner class that describes an object in the
-     * criteria.
+     * Serializes this Criteria.
+     *
+     * @param s The output stream.
+     * @throws IOException if an IO error occurs.
+     */
+    private void writeObject(ObjectOutputStream s) throws IOException
+    {
+        s.defaultWriteObject();
+
+        // Joins need to be serialized manually.
+        ArrayList serializableJoins = null;
+        if (joins != null && joins.size() > 0)
+        {
+            serializableJoins = new ArrayList(joins.size());
+
+            for (Iterator jonisIter = joins.iterator(); jonisIter.hasNext();)
+            {
+                Join join = (Join) jonisIter.next();
+
+                ArrayList joinContent = new ArrayList(3);
+                joinContent.add(join.getLeftColumn());
+                joinContent.add(join.getRightColumn());
+                joinContent.add(join.getJoinType());
+
+                serializableJoins.add(joinContent);
+            }
+        }
+
+        s.writeObject(serializableJoins);
+    }
+
+    /**
+     * Deserialize a Criteria.
+     *
+     * @param s The input stream.
+     * @throws IOException if an IO error occurs.
+     * @throws ClassNotFoundException if the class cannot be located.
+     */
+    private void readObject(ObjectInputStream s)
+            throws IOException, ClassNotFoundException
+    {
+        s.defaultReadObject();
+
+        // Criteria.put() differs somewhat from Hashtable.put().
+        // This necessitates some corrective behavior upon deserialization.
+        for (Iterator iter = keySet().iterator(); iter.hasNext();)
+        {
+            Object key = iter.next();
+            Object value = get(key);
+            if (value instanceof Criteria.Criterion)
+            {
+                super.put(key, value);
+            }
+        }
+
+        // Joins need to be deserialized manually.
+        ArrayList joins = (ArrayList) s.readObject();
+        if (joins != null)
+        {
+            for (int i = 0; i < joins.size(); i++)
+            {
+                ArrayList joinContent = (ArrayList) joins.get(i);
+
+                String leftColumn = (String) joinContent.get(0);
+                String rightColumn = (String) joinContent.get(1);
+                SqlEnum joinType = null;
+                Object joinTypeObj = joinContent.get(2);
+                if (joinTypeObj != null)
+                {
+                    joinType = (SqlEnum) joinTypeObj;
+                }
+                addJoin(leftColumn, rightColumn, joinType);
+            }
+        }
+    }
+
+    /**
+     * This is an inner class that describes an object in the criteria.
      */
     public final class Criterion implements Serializable
     {
+        /** Serial version. */
+        private static final long serialVersionUID = 7157097965404611710L;
+
         public static final String AND = " AND ";
         public static final String OR = " OR ";
 
@@ -3449,7 +3572,7 @@
         }
 
         /**
-         * This method checks another Criteria to see if they contain
+         * This method checks another Criteria.Criterion to see if they contain
          * the same attributes and hashtable entries.
          */
         public boolean equals(Object obj)
@@ -3589,7 +3712,7 @@
                 }
             }
         }
-    }
+    } // end of inner class Criterion
 
     /**
      * Data object to describe a join between two tables, for example
@@ -3675,5 +3798,43 @@
 
             return result.toString();
         }
+
+        /**
+         * This method checks another Criteria.Join to see if they contain the
+         * same attributes.
+         */
+        public boolean equals(Object obj)
+        {
+            if (this == obj)
+            {
+                return true;
+            }
+
+            if ((obj == null) || !(obj instanceof Join))
+            {
+                return false;
+            }
+
+            Join join = (Join) obj;
+
+            return ObjectUtils.equals(leftColumn, join.getLeftColumn())
+                    && ObjectUtils.equals(rightColumn, join.getRightColumn())
+                    && ObjectUtils.equals(joinType, join.getJoinType());
+        }
+
+        /**
+         * Returns the hash code value for this Join.
+         *
+         * @return a hash code value for this object.
+         */
+        public int hashCode()
+        {
+            int result = 13;
+            result = 37 * result + leftColumn.hashCode();
+            result = 37 * result + rightColumn.hashCode();
+            result = 37 * result + (null == joinType ? 0 : joinType.hashCode());
+            return result;
+        }
+
     } // end of inner class Join
 }

Modified: db/torque/runtime/trunk/src/test/org/apache/torque/util/CriteriaTest.java
URL: http://svn.apache.org/viewcvs/db/torque/runtime/trunk/src/test/org/apache/torque/util/CriteriaTest.java?rev=332758&r1=332757&r2=332758&view=diff
==============================================================================
--- db/torque/runtime/trunk/src/test/org/apache/torque/util/CriteriaTest.java (original)
+++ db/torque/runtime/trunk/src/test/org/apache/torque/util/CriteriaTest.java Sat Nov 12 03:15:21 2005
@@ -19,19 +19,23 @@
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.configuration.BaseConfiguration;
 import org.apache.commons.configuration.Configuration;
-
+import org.apache.commons.lang.SerializationUtils;
 import org.apache.torque.BaseTestCase;
 import org.apache.torque.TorqueException;
 import org.apache.torque.adapter.DBFactory;
+import org.apache.torque.util.Criteria.Criterion;
+import org.apache.torque.util.Criteria.Join;
 
 /**
  * Test class for Criteria.
  *
  * @author <a href="mailto:celkins@scardini.com">Christopher Elkins</a>
  * @author <a href="mailto:sam@neurogrid.com">Sam Joseph</a>
+ * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
  * @version $Id$
  */
 public class CriteriaTest extends BaseTestCase
@@ -483,29 +487,94 @@
         assertTrue(result.equals(firstExpect) || result.equals(secondExpect));
     }
 
-//    /**
-//     * Very basic test that serialization works.
-//     */
-//    public void testSerialization()
-//    {
-//        // Hashtable works:
-//        Hashtable h = new Hashtable();
-//        h.put("Author.NAME", "author");
-//        Hashtable hClone = (Hashtable) SerializationUtils.clone(h);
-//        assertEquals(h, hClone);
-//
-//        // Criterion works (even though Bloch strongly recommends against inner
-//        // classes implementing Serializable):
-//        Criterion cn = c.new Criterion("Author.NAME", "author");
-//        Criterion cnClone = (Criterion) SerializationUtils.clone(cn);
-//        assertEquals(cn, cnClone);
-//
-//        // Criteria DOES NOT WORK - i.e. it isn't actually Serializable at present.
-//        // http://mail-archives.apache.org/mod_mbox/db-torque-dev/200404.mbox/%3CF4DFE8EDB932F641A9407CFB5CA599C3F17DF1@e2kmtl1.internal.sungard.corp%3E
-//        c.add("Author.NAME", "author");
-//        Criteria cClone = (Criteria) SerializationUtils.clone(c);
-//        assertEquals(c, cClone);
-//    }
+    /**
+     * Test that serialization works.
+     */
+    public void testSerialization()
+    {
+        c.setOffset(10);
+        c.setLimit(11);
+        c.setIgnoreCase(true);
+        c.setSingleRecord(true);
+        c.setCascade(true);
+        c.setDbName("myDB");
+        c.setAll();
+        c.setDistinct();
+        c.addSelectColumn("Author.NAME");
+        c.addSelectColumn("Author.AUTHOR_ID");
+        c.addDescendingOrderByColumn("Author.NAME");
+        c.addAscendingOrderByColumn("Author.AUTHOR_ID");
+        c.addAlias("Writer", "Author");
+        c.addAsColumn("AUTHOR_NAME", "Author.NAME");
+        c.addJoin("Author.AUTHOR_ID", "Book.AUTHOR_ID", Criteria.INNER_JOIN);
+        c.add("Author.NAME", (Object) "author%", Criteria.LIKE);
+
+        // Some direct Criterion checks
+        Criterion cn = c.getCriterion("Author.NAME");
+        cn.setIgnoreCase(true);
+        assertEquals("author%", cn.getValue());
+        assertEquals(Criteria.LIKE, cn.getComparison());
+        Criterion cnDirectClone = (Criterion) SerializationUtils.clone(cn);
+        assertEquals(cn, cnDirectClone);
+
+        // Clone the object
+        Criteria cClone = (Criteria) SerializationUtils.clone(c);
+
+        // Check the clone
+        assertEquals(c.size(), cClone.size());
+        assertEquals(10, cClone.getOffset());
+        assertEquals(c.getOffset(), cClone.getOffset());
+        assertEquals(11, cClone.getLimit());
+        assertEquals(c.getLimit(), cClone.getLimit());
+        assertEquals(true, cClone.isIgnoreCase());
+        assertEquals(c.isIgnoreCase(), cClone.isIgnoreCase());
+        assertEquals(true, cClone.isSingleRecord());
+        assertEquals(c.isSingleRecord(), cClone.isSingleRecord());
+        assertEquals(true, cClone.isCascade());
+        assertEquals(c.isCascade(), cClone.isCascade());
+        assertEquals("myDB", cClone.getDbName());
+        assertEquals(c.getDbName(), cClone.getDbName());
+        List selectModifiersClone = cClone.getSelectModifiers();
+        assertTrue(selectModifiersClone.contains(Criteria.ALL.toString()));
+        assertTrue(selectModifiersClone.contains(Criteria.DISTINCT.toString()));
+        assertEquals(c.getSelectModifiers(), cClone.getSelectModifiers());
+        List selectColumnsClone = cClone.getSelectColumns();
+        assertTrue(selectColumnsClone.contains("Author.NAME"));
+        assertTrue(selectColumnsClone.contains("Author.AUTHOR_ID"));
+        assertEquals(c.getSelectColumns(), cClone.getSelectColumns());
+        List orderByColumnsClone = cClone.getOrderByColumns();
+        assertTrue(orderByColumnsClone.contains("Author.NAME DESC"));
+        assertTrue(orderByColumnsClone.contains("Author.AUTHOR_ID ASC"));
+        assertEquals(c.getOrderByColumns(), cClone.getOrderByColumns());
+        Map aliasesClone = cClone.getAliases();
+        assertTrue(aliasesClone.containsKey("Writer"));
+        assertEquals("Author", aliasesClone.get("Writer"));
+        assertEquals(c.getAliases(), cClone.getAliases());
+        Map asColumnsClone = cClone.getAsColumns();
+        assertTrue(asColumnsClone.containsKey("AUTHOR_NAME"));
+        assertEquals("Author.NAME", asColumnsClone.get("AUTHOR_NAME"));
+        assertEquals(c.getAsColumns(), cClone.getAsColumns());
+
+        // Check Joins
+        List joinsClone = cClone.getJoins();
+        Join joinClone = (Join) joinsClone.get(0);
+        assertEquals("Author.AUTHOR_ID", joinClone.getLeftColumn());
+        assertEquals("Book.AUTHOR_ID", joinClone.getRightColumn());
+        assertEquals(Criteria.INNER_JOIN, joinClone.getJoinType());
+        assertEquals(c.getJoins(), cClone.getJoins());
+
+        // Some Criterion checks
+        Criterion cnClone = cClone.getCriterion("Author.NAME");
+        assertEquals("author%", cnClone.getValue());
+        assertEquals(Criteria.LIKE, cnClone.getComparison());
+        assertEquals(cn.isIgnoreCase(), cnClone.isIgnoreCase());
+
+        // Confirm that equals() checks all of the above.
+        assertEquals(c, cClone);
+
+        // Check hashCode() too.
+        assertEquals(c.hashCode(), cClone.hashCode());
+    }
 
     /**
      * test for TRQS25

Modified: db/torque/runtime/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewcvs/db/torque/runtime/trunk/xdocs/changes.xml?rev=332758&r1=332757&r2=332758&view=diff
==============================================================================
--- db/torque/runtime/trunk/xdocs/changes.xml (original)
+++ db/torque/runtime/trunk/xdocs/changes.xml Sat Nov 12 03:15:21 2005
@@ -26,6 +26,11 @@
   <body>
 
   <release version="3.2-rc3-dev" date="in SVN">
+    <action type="fix" dev="seade">
+      Corrected serialization of Criteria objects.  While there also fixed
+      equals() and added hashCode().
+      Thanks to Martin Goulet for a very early version of the serialization fix.
+    </action>
     <action type="add" dev="tfischer">
       Added scale (i.e number of digits after the decimal point) support 
       for the sql data types NUMERIC and DECIMAL in the JDBCTransformTask



---------------------------------------------------------------------
To unsubscribe, e-mail: torque-dev-unsubscribe@db.apache.org
For additional commands, e-mail: torque-dev-help@db.apache.org