Generate quality overrides of hashCode for Thrift structs (in Java).
This feature is turned off by default because it adds a new dependency:
Apache Commons Lang. This package seems enough like Boost that
I would be open to turning this feature on by default.
Also updated test/java/build.xml to use this new option.
ant test still passes.
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665542 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index 4b255b1..8d478ce 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -36,6 +36,9 @@
iter = parsed_options.find("beans");
bean_style_ = (iter != parsed_options.end());
+ iter = parsed_options.find("hashcode");
+ gen_hash_code_ = (iter != parsed_options.end());
+
out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java");
}
@@ -177,6 +180,7 @@
std::string package_dir_;
bool bean_style_;
+ bool gen_hash_code_;
};
@@ -226,6 +230,11 @@
* @return List of imports for Java types that are used in here
*/
string t_java_generator::java_type_imports() {
+ string hash_builder;
+ if (gen_hash_code_) {
+ hash_builder = "import org.apache.commons.lang.builder.HashCodeBuilder;\n";
+ }
+
return
string() +
"import java.util.List;\n" +
@@ -234,6 +243,7 @@
"import java.util.HashMap;\n" +
"import java.util.Set;\n" +
"import java.util.HashSet;\n" +
+ hash_builder +
"import com.facebook.thrift.*;\n\n";
}
@@ -708,13 +718,54 @@
scope_down(out);
out << endl;
- out <<
- indent() << "public int hashCode() {" << endl;
- indent_up();
- out <<
- indent() << "return 0;" << endl;
- scope_down(out);
- out << endl;
+ if (gen_hash_code_) {
+ out <<
+ indent() << "public int hashCode() {" << endl;
+ indent_up();
+
+ out <<
+ indent() << "HashCodeBuilder builder = new HashCodeBuilder();" << endl;
+
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ out << endl;
+
+ t_type* t = get_true_type((*m_iter)->get_type());
+ bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
+ bool can_be_null = type_can_be_null(t);
+ string name = (*m_iter)->get_name();
+
+ string present = "true";
+
+ if (is_optional) {
+ present += " && (__isset." + name + ")";
+ }
+ if (can_be_null) {
+ present += " && (" + name + " != null)";
+ }
+
+ out <<
+ indent() << "boolean present_" << name << " = "
+ << present << ";" << endl <<
+ indent() << "builder.append(present_" << name << ");" << endl <<
+ indent() << "if (present_" << name << ")" << endl <<
+ indent() << " builder.append(" << name << ");" << endl;
+ }
+
+ out << endl;
+ out <<
+ indent() << "return builder.toHashCode();" << endl;
+ scope_down(out);
+ out << endl;
+
+ } else {
+ out <<
+ indent() << "public int hashCode() {" << endl;
+ indent_up();
+ out <<
+ indent() << "return 0;" << endl;
+ scope_down(out);
+ out << endl;
+ }
}
/**
@@ -2291,4 +2342,5 @@
THRIFT_REGISTER_GENERATOR(java, "Java",
" beans: Generate bean-style output files.\n"
+" hashcode: Generate quality hashCode methods.\n"
);
diff --git a/test/java/build.xml b/test/java/build.xml
index 68d7b98..7eed8c3 100644
--- a/test/java/build.xml
+++ b/test/java/build.xml
@@ -5,7 +5,7 @@
<property name="src" location="src" />
<property name="gen" location="gen-java" />
<property name="build" location="build" />
- <property name="cpath" location="../../lib/java/libthrift.jar" />
+ <property name="cpath" location="../../lib/java/libthrift.jar:/usr/share/java/commons-lang-2.3.jar" />
<target name="init">
<tstamp />
@@ -14,13 +14,13 @@
<target name="generate">
<exec executable="../../compiler/cpp/thrift">
- <arg line="--gen java ../ThriftTest.thrift" />
+ <arg line="--gen java:hashcode ../ThriftTest.thrift" />
</exec>
<exec executable="../../compiler/cpp/thrift">
- <arg line="--gen java ../DebugProtoTest.thrift" />
+ <arg line="--gen java:hashcode ../DebugProtoTest.thrift" />
</exec>
<exec executable="../../compiler/cpp/thrift">
- <arg line="--gen java ../OptionalRequiredTest.thrift" />
+ <arg line="--gen java:hashcode ../OptionalRequiredTest.thrift" />
</exec>
</target>