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 <table></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);
}