THRIFT-139. java: Expose field ids in more useful ways
- Define constants in each structure class that provide access to the
field ids by name (at compile time). Use them for (de)serialization.
- For beans-mode code, generate a generic getter and setter for accessing
fields by field id.
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@703028 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 49d8594..e8d9a95 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -44,6 +44,11 @@
out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java");
}
+ string upcase_string(string original) {
+ std::transform(original.begin(), original.end(), original.begin(), (int(*)(int)) toupper);
+ return original;
+ }
+
/**
* Init and close methods
@@ -79,6 +84,9 @@
void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct);
+ void generate_reflection_setters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name);
+ void generate_reflection_getters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name);
+ void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
void generate_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
void generate_function_helpers(t_function* tfunction);
@@ -581,6 +589,8 @@
indent(out) << "public ";
}
out << declare_field(*m_iter, false) << endl;
+
+ indent(out) << "public static final int " << upcase_string((*m_iter)->get_name()) << " = " << (*m_iter)->get_key() << ";" << endl;
}
// Inner Isset class
@@ -649,6 +659,7 @@
if (bean_style_) {
generate_java_bean_boilerplate(out, tstruct);
+ generate_generic_field_getters_setters(out, tstruct);
}
generate_java_struct_equality(out, tstruct);
@@ -844,7 +855,7 @@
// Generate deserialization code for known cases
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
indent(out) <<
- "case " << (*f_iter)->get_key() << ":" << endl;
+ "case " << upcase_string((*f_iter)->get_name()) << ":" << endl;
indent_up();
indent(out) <<
"if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
@@ -922,7 +933,7 @@
out <<
indent() << "field.name = \"" << (*f_iter)->get_name() << "\";" << endl <<
indent() << "field.type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl <<
- indent() << "field.id = " << (*f_iter)->get_key() << ";" << endl <<
+ indent() << "field.id = " << upcase_string((*f_iter)->get_name()) << ";" << endl <<
indent() << "oprot.writeFieldBegin(field);" << endl;
// Write field contents
@@ -1002,7 +1013,7 @@
out <<
indent() << "field.name = \"" << (*f_iter)->get_name() << "\";" << endl <<
indent() << "field.type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl <<
- indent() << "field.id = " << (*f_iter)->get_key() << ";" << endl <<
+ indent() << "field.id = " << upcase_string((*f_iter)->get_name()) << ";" << endl <<
indent() << "oprot.writeFieldBegin(field);" << endl;
// Write field contents
@@ -1032,6 +1043,93 @@
endl;
}
+void t_java_generator::generate_reflection_getters(ostringstream& out, t_type* type, string field_name, string cap_name) {
+ indent(out) << "case " << upcase_string(field_name) << ":" << endl;
+ indent_up();
+
+ if (type->is_base_type() && !type->is_string()) {
+ t_base_type* base_type = (t_base_type*)type;
+
+ indent(out) << "return new " << type_name(type, true, false) << "(" << (base_type->is_bool() ? "is" : "get") << cap_name << "());" << endl << endl;
+ } else {
+ indent(out) << "return get" << cap_name << "();" << endl << endl;
+ }
+
+ indent_down();
+}
+
+void t_java_generator::generate_reflection_setters(ostringstream& out, t_type* type, string field_name, string cap_name) {
+ indent(out) << "case " << upcase_string(field_name) << ":" << endl;
+ indent_up();
+
+ indent(out) << "set" << cap_name << "((" << type_name(type, true, false) << ")value);" << endl;
+ indent(out) << "break;" << endl << endl;
+
+ indent_down();
+}
+
+void t_java_generator::generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct) {
+
+ std::ostringstream getter_stream;
+ std::ostringstream setter_stream;
+
+ // build up the bodies of both the getter and setter at once
+ const vector<t_field*>& fields = tstruct->get_members();
+ vector<t_field*>::const_iterator f_iter;
+ for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+ t_field* field = *f_iter;
+ t_type* type = get_true_type(field->get_type());
+ std::string field_name = field->get_name();
+ std::string cap_name = field_name;
+ if (nocamel_style_) {
+ cap_name = "_" + cap_name;
+ } else {
+ cap_name[0] = toupper(cap_name[0]);
+ }
+
+ indent_up();
+ generate_reflection_setters(setter_stream, type, field_name, cap_name);
+ generate_reflection_getters(getter_stream, type, field_name, cap_name);
+ indent_down();
+ }
+
+
+ // create the setter
+ indent(out) << "public void setFieldValue(int fieldID, Object value) {" << endl;
+ indent_up();
+
+ indent(out) << "switch (fieldID) {" << endl;
+
+ out << setter_stream.str();
+
+ indent(out) << "default:" << endl;
+ indent(out) << " throw new IllegalArgumentException(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+
+ indent(out) << "}" << endl;
+
+ indent_down();
+ indent(out) << "}" << endl << endl;
+
+ // create the getter
+ indent(out) << "public Object getFieldValue(int fieldID) {" << endl;
+ indent_up();
+
+ indent(out) << "switch (fieldID) {" << endl;
+
+ out << getter_stream.str();
+
+ indent(out) << "default:" << endl;
+ indent(out) << " throw new IllegalArgumentException(\"Field \" + fieldID + \" doesn't exist!\");" << endl;
+
+ indent(out) << "}" << endl;
+
+ indent_down();
+
+ indent(out) << "}" << endl << endl;
+}
+
+
+
/**
* Generates a set of Java Bean boilerplate functions (setters, getters, etc.)
* for the given struct.