Friday, November 20, 2009

Andrew Beacock's Blog: Write simpler equals & hashCode Java methods using EqualsBuilder & HashCodeBuilder from Apache Commons

Andrew Beacock's Blog: Write simpler equals & hashCode Java methods using EqualsBuilder & HashCodeBuilder from Apache Commons

Useful post. Here is a utility class to automatically generate the equals and hashcode methods based on classname.
http://ravivenkatesan.blogspot.com/

Utility class to automatically generate equals and hashcode methods

I came across a useful tip on Andy Beacock's blog around using the Apache Commons EqualsBuilder and HashCodeBuilder. I liked the approach and the solution, but had a whole bunch of entity classes. I used MyEclipse JPA reverse engineering to generate these from the database tables. I looked around for a solution to automatically generate code for the equals and hashcode methods and eventually ended up writing custom code using reflection and regular expressions. The utility class (code provided below) takes the fully qualified class name of a class that should be in your classpath. It uses reflection to go through all the methods in the class, uses regular expressions to match the getters, generates equals and hashcode methods, and prints them to the console.


http://blog.andrewbeacock.com/2008/08/write-simpler-equals-hashcode-java.html
/**
*
*/
package utility;

import java.lang.reflect.Method;
import java.util.regex.Pattern;

/**
* @author Ravi Venkatesan
* Utility class to generate equals and hashcode methods
* Developed mainly for JPA / Hibernate generated entity classes but can be used for any class
* Looks for getter methods and uses these to generate methods
*
*/
public class EqualsAndHashcodeGenerator {

/**
* @param args
*/
private static Pattern p = Pattern.compile("get");
private static Pattern pExclude = Pattern.compile("Class");

@SuppressWarnings("finally")
private static StringBuffer generateEquals (String className)
{
StringBuffer sb = new StringBuffer("");
try {
Class c = Class.forName(className);
sb.append("@Override");
sb.append("\n");
sb.append("public boolean equals(Object obj) {");
sb.append("\n");
sb.append("if (obj instanceof ");
sb.append(c.getSimpleName());
sb.append("){");
sb.append("\n");
sb.append(c.getSimpleName());
sb.append(" other = (");
sb.append(c.getSimpleName());
sb.append(") obj;");
sb.append("\n");
sb.append("EqualsBuilder builder = new EqualsBuilder();");
Method[] m = c.getMethods();
for (int i = 0; i < m.length; i++) {

if ((p.matcher(m[i].toString()).find())&&(!pExclude.matcher(m[i].toString()).find()))
{
sb.append("\n");
sb.append("builder.append(");
sb.append(m[i].getName());
sb.append("()");
sb.append(", other.");
sb.append(m[i].getName());
sb.append("()");
sb.append(");");
}
}
sb.append("\n");
sb.append("return builder.isEquals();");
sb.append("\n");
sb.append("}");
sb.append("\n");
sb.append("return false;");
sb.append("\n");
sb.append("}");
sb.append("\n");
}
catch (Exception e) {
System.out.println("Exception generating Equals: " + e);
}
finally
{
return sb;

}

}

@SuppressWarnings("finally")
private static StringBuffer generateHashCode (String className)
{
StringBuffer sb = new StringBuffer("");

try {
Class c = Class.forName(className);
sb.append("\n");
sb.append("@Override");
sb.append("\n");
sb.append("public int hashCode() {");
sb.append("\n");
sb.append("HashCodeBuilder builder = new HashCodeBuilder ();");
Method[] m = c.getMethods();
for (int i = 0; i < m.length; i++) {

if ((p.matcher(m[i].toString()).find())&&(!pExclude.matcher(m[i].toString()).find()))
{
sb.append("\n");
sb.append("builder.append(");
sb.append(m[i].getName());
sb.append("()");
sb.append(");");
}
}
sb.append("\n");
sb.append("return builder.toHashCode();");
sb.append("\n");
sb.append("}");
return sb;
}
catch (Exception e) {
System.out.println("Exception generating Hashcode: " + e);
}
finally
{
return sb;

}

}
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("");
sb.append(generateEquals(args[0]));
sb.append(generateHashCode(args[0]));
System.out.println(sb);
}
}