Author: jgbutler
Date: Tue Apr 20 17:10:50 2010
New Revision: 935997

URL: http://svn.apache.org/viewvc?rev=935997&view=rev
Log:
[ibator] improve generated equals and hashCode methods

Modified:
    ibatis/java/ibator/trunk/core/ibator-core/doc/ReleaseNotes.txt
    ibatis/java/ibator/trunk/core/ibator-core/doc/html/whatsNew.html
    
ibatis/java/ibator/trunk/core/ibator-core/src/main/java/org/apache/ibatis/ibator/plugins/EqualsHashCodePlugin.java

Modified: ibatis/java/ibator/trunk/core/ibator-core/doc/ReleaseNotes.txt
URL: 
http://svn.apache.org/viewvc/ibatis/java/ibator/trunk/core/ibator-core/doc/ReleaseNotes.txt?rev=935997&r1=935996&r2=935997&view=diff
==============================================================================
--- ibatis/java/ibator/trunk/core/ibator-core/doc/ReleaseNotes.txt (original)
+++ ibatis/java/ibator/trunk/core/ibator-core/doc/ReleaseNotes.txt Tue Apr 20 
17:10:50 2010
@@ -46,6 +46,7 @@ Enhancements:
 19. Added new "or" method to example classes
 20. Added new "useCompoundPropertyNames" property on <table>
 21. Further improved extensibility of the example classes
+22. EqulasHashCodePlugin now generates far superior methods
 
 
 -------------------------------------------------------------------------------

Modified: ibatis/java/ibator/trunk/core/ibator-core/doc/html/whatsNew.html
URL: 
http://svn.apache.org/viewvc/ibatis/java/ibator/trunk/core/ibator-core/doc/html/whatsNew.html?rev=935997&r1=935996&r2=935997&view=diff
==============================================================================
--- ibatis/java/ibator/trunk/core/ibator-core/doc/html/whatsNew.html (original)
+++ ibatis/java/ibator/trunk/core/ibator-core/doc/html/whatsNew.html Tue Apr 20 
17:10:50 2010
@@ -130,6 +130,7 @@ to iBATIS 3.x only requires two changes 
   <li>Added new "or" method to example classes</li>
   <li>Added new "useCompoundPropertyNames" property on &lt;table&gt;</li>
   <li>Enabled a far simpler method for extending the example classes</li>
+  <li>EqualsHashCodePlugin now generates far superior methods</li>
 
 </ul>
 

Modified: 
ibatis/java/ibator/trunk/core/ibator-core/src/main/java/org/apache/ibatis/ibator/plugins/EqualsHashCodePlugin.java
URL: 
http://svn.apache.org/viewvc/ibatis/java/ibator/trunk/core/ibator-core/src/main/java/org/apache/ibatis/ibator/plugins/EqualsHashCodePlugin.java?rev=935997&r1=935996&r2=935997&view=diff
==============================================================================
--- 
ibatis/java/ibator/trunk/core/ibator-core/src/main/java/org/apache/ibatis/ibator/plugins/EqualsHashCodePlugin.java
 (original)
+++ 
ibatis/java/ibator/trunk/core/ibator-core/src/main/java/org/apache/ibatis/ibator/plugins/EqualsHashCodePlugin.java
 Tue Apr 20 17:10:50 2010
@@ -37,10 +37,9 @@ import org.apache.ibatis.ibator.internal
  * cases, but will probably NOT be correct if you have specified a rootClass -
  * because our equals method only checks the fields it knows about.
  * <p>
- * The <tt>hashCode</tt> method generated by this class is a very simplistic
- * implementation.  A better implementation would rely on the HashCodeUtil
- * from www.javapractices.com - but we do not want to introduce another
- * dependency in this simple plugin.
+ * Similarly, the <tt>hashCode</tt> method generated by this class only
+ * relies on fields it knows about.  Anything you add, or fields in a super
+ * class will not be factored into the hash code.
  * 
  * @author Jeff Butler
  * 
@@ -131,15 +130,15 @@ public class EqualsHashCodePlugin extend
         method.addBodyLine("return true;"); //$NON-NLS-1$
         method.addBodyLine("}"); //$NON-NLS-1$
 
-        StringBuilder sb = new StringBuilder();
-        sb.append("if (!(that instanceof "); //$NON-NLS-1$
-        sb.append(topLevelClass.getType().getShortName());
-        sb.append(")) {"); //$NON-NLS-1$
-        method.addBodyLine(sb.toString());
+        method.addBodyLine("if (that == null) {"); //$NON-NLS-1$
         method.addBodyLine("return false;"); //$NON-NLS-1$
         method.addBodyLine("}"); //$NON-NLS-1$
-
-        sb.setLength(0);
+        
+        method.addBodyLine("if (getClass() != that.getClass()) {"); 
//$NON-NLS-1$
+        method.addBodyLine("return false;"); //$NON-NLS-1$
+        method.addBodyLine("}"); //$NON-NLS-1$
+        
+        StringBuilder sb = new StringBuilder();
         sb.append(topLevelClass.getType().getShortName());
         sb.append(" other = ("); //$NON-NLS-1$
         sb.append(topLevelClass.getType().getShortName());
@@ -196,10 +195,10 @@ public class EqualsHashCodePlugin extend
     }
 
     /**
-     * Generates a <tt>hashCode</tt> method that multiplies the hashCodes of
-     * all fields.
+     * Generates a <tt>hashCode</tt> method that includes all fields.
      * <p>
-     * Note that this is a very simplistic implementation of hashCode.
+     * Note that this implementation is based on the eclipse foundation
+     * hashCode generator.
      * 
      * @param topLevelClass the class to which the method will be added
      * @param introspectedColumns column definitions of this class and 
@@ -221,69 +220,85 @@ public class EqualsHashCodePlugin extend
         ibatorContext.getCommentGenerator().addGeneralMethodComment(method,
                 introspectedTable);
 
-        method.addBodyLine("int hash = 23;"); //$NON-NLS-1$
+        method.addBodyLine("final int prime = 31;"); //$NON-NLS-1$
+        method.addBodyLine("int result = 1;"); //$NON-NLS-1$
 
         StringBuilder sb = new StringBuilder();
-        boolean valueDeclared = false;
-
+        boolean hasTemp = false;
         Iterator<IntrospectedColumn> iter = introspectedColumns.iterator();
         while (iter.hasNext()) {
             IntrospectedColumn introspectedColumn = iter.next();
 
-
             FullyQualifiedJavaType fqjt = introspectedColumn
                 .getFullyQualifiedJavaType();
 
             String getterMethod = JavaBeansUtil.getGetterMethodName(
                     introspectedColumn.getJavaProperty(), fqjt);
             
+            sb.setLength(0);
             if (fqjt.isPrimitive()) {
-                boolean cast = false;
                 if ("boolean".equals(fqjt.getFullyQualifiedName())) { 
//$NON-NLS-1$
-                    // no adding the booleans to the hashCode computation
-                    continue;
-                } else if ("long".equals(fqjt.getFullyQualifiedName())) { 
//$NON-NLS-1$
-                    cast = true;
+                    sb.append("result = prime * result + ("); //$NON-NLS-1$
+                    sb.append(getterMethod);
+                    sb.append("() ? 1231 : 1237);"); //$NON-NLS-1$
+                    method.addBodyLine(sb.toString());
+                } else if ("byte".equals(fqjt.getFullyQualifiedName())) { 
//$NON-NLS-1$
+                    sb.append("result = prime * result + "); //$NON-NLS-1$
+                    sb.append(getterMethod);
+                    sb.append("();"); //$NON-NLS-1$
+                    method.addBodyLine(sb.toString());
+                } else if ("char".equals(fqjt.getFullyQualifiedName())) { 
//$NON-NLS-1$
+                    sb.append("result = prime * result + "); //$NON-NLS-1$
+                    sb.append(getterMethod);
+                    sb.append("();"); //$NON-NLS-1$
+                    method.addBodyLine(sb.toString());
                 } else if ("double".equals(fqjt.getFullyQualifiedName())) { 
//$NON-NLS-1$
-                    cast = true;
+                    if (!hasTemp) {
+                        method.addBodyLine("long temp;"); //$NON-NLS-1$
+                        hasTemp = true;
+                    }
+                    sb.append("temp = Double.doubleToLongBits("); //$NON-NLS-1$
+                    sb.append(getterMethod);
+                    sb.append("());"); //$NON-NLS-1$
+                    method.addBodyLine(sb.toString());
+                    method.addBodyLine("result = prime * result + (int) (temp 
^ (temp >>> 32));"); //$NON-NLS-1$
                 } else if ("float".equals(fqjt.getFullyQualifiedName())) { 
//$NON-NLS-1$
-                    cast = true;
-                }
-                
-                sb.setLength(0);
-                if (!valueDeclared) {
-                    sb.append("int "); //$NON-NLS-1$
-                    valueDeclared = true;
-                }
-                sb.append("value = "); //$NON-NLS-1$
-                if (cast) {
-                    sb.append("(int) "); //$NON-NLS-1$
+                    sb.append("result = prime * result + 
Float.floatToIntBits("); //$NON-NLS-1$
+                    sb.append(getterMethod);
+                    sb.append("());"); //$NON-NLS-1$
+                    method.addBodyLine(sb.toString());
+                } else if ("int".equals(fqjt.getFullyQualifiedName())) { 
//$NON-NLS-1$
+                    sb.append("result = prime * result + "); //$NON-NLS-1$
+                    sb.append(getterMethod);
+                    sb.append("();"); //$NON-NLS-1$
+                    method.addBodyLine(sb.toString());
+                } else if ("long".equals(fqjt.getFullyQualifiedName())) { 
//$NON-NLS-1$
+                    sb.append("result = prime * result + (int) ("); 
//$NON-NLS-1$
+                    sb.append(getterMethod);
+                    sb.append("() ^ ("); //$NON-NLS-1$
+                    sb.append(getterMethod);
+                    sb.append("() >>> 32));"); //$NON-NLS-1$
+                    method.addBodyLine(sb.toString());
+                } else if ("short".equals(fqjt.getFullyQualifiedName())) { 
//$NON-NLS-1$
+                    sb.append("result = prime * result + "); //$NON-NLS-1$
+                    sb.append(getterMethod);
+                    sb.append("();"); //$NON-NLS-1$
+                    method.addBodyLine(sb.toString());
+                } else {
+                    // should never happen
+                    continue;
                 }
-                sb.append(getterMethod);
-                sb.append("();"); //$NON-NLS-1$
-                method.addBodyLine(sb.toString());
-                
-                method.addBodyLine("if (value != 0) {"); //$NON-NLS-1$
-                method.addBodyLine("hash *= value;"); //$NON-NLS-1$
-                method.addBodyLine("}"); //$NON-NLS-1$
             } else {
-                sb.setLength(0);
-                sb.append("if ("); //$NON-NLS-1$
+                sb.append("result = prime * result + (("); //$NON-NLS-1$
                 sb.append(getterMethod);
-                sb.append("() != null) {"); //$NON-NLS-1$
-                method.addBodyLine(sb.toString());
-                
-                sb.setLength(0);
-                sb.append("hash *= "); //$NON-NLS-1$
+                sb.append("() == null) ? 0 : "); //$NON-NLS-1$
                 sb.append(getterMethod);
-                sb.append("().hashCode();"); //$NON-NLS-1$
+                sb.append("().hashCode());"); //$NON-NLS-1$
                 method.addBodyLine(sb.toString());
-
-                method.addBodyLine("}"); //$NON-NLS-1$
             }
         }
 
-        method.addBodyLine("return hash;"); //$NON-NLS-1$
+        method.addBodyLine("return result;"); //$NON-NLS-1$
         
         topLevelClass.addMethod(method);
     }


Reply via email to