From 01a9f8845d38cd32694d91b35d7a844c3646e3c3 Mon Sep 17 00:00:00 2001 From: Mark Slee Date: Fri, 31 Aug 2007 00:55:28 +0000 Subject: [PATCH] Add -javabean option to Thrift Summary: In case you want getters and setters and iterators and magic. Submitted by Dave Engberg Reviewed By: dreiss git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665239 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/cpp/src/generate/t_java_generator.cc | 129 +++++++++++++++++- compiler/cpp/src/generate/t_java_generator.h | 10 +- compiler/cpp/src/main.cc | 15 +- 3 files changed, 143 insertions(+), 11 deletions(-) diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc index c138df35..90b93282 100644 --- a/compiler/cpp/src/generate/t_java_generator.cc +++ b/compiler/cpp/src/generate/t_java_generator.cc @@ -18,11 +18,12 @@ using namespace std; */ void t_java_generator::init_generator() { // Make output directory - mkdir(T_JAVA_DIR, S_IREAD | S_IWRITE | S_IEXEC); + const char* java_dir = bean_style_ ? T_JAVABEAN_DIR : T_JAVA_DIR; + mkdir(java_dir, S_IREAD | S_IWRITE | S_IEXEC); package_name_ = program_->get_java_package(); string dir = package_name_; - string subdir = T_JAVA_DIR; + string subdir = java_dir; string::size_type loc; while ((loc = dir.find(".")) != string::npos) { subdir = subdir + "/" + dir.substr(0, loc); @@ -362,12 +363,16 @@ void t_java_generator::generate_java_struct_definition(ofstream &out, scope_up(out); - // Members are public + // Members are public for -java, private for -javabean const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - indent(out) << - "public " << declare_field(*m_iter, false) << endl; + if (bean_style_) { + indent(out) << "private "; + } else { + indent(out) << "public "; + } + out << declare_field(*m_iter, false) << endl; } // Inner Isset class @@ -400,7 +405,7 @@ void t_java_generator::generate_java_struct_definition(ofstream &out, indent_down(); indent(out) << "}" << endl << endl; - + // Full constructor for all fields if (!members.empty()) { indent(out) << @@ -422,12 +427,15 @@ void t_java_generator::generate_java_struct_definition(ofstream &out, for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "this." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << ";" << endl; + indent(out) << "this.__isset." << (*m_iter)->get_name() << " = true;" << endl; } indent_down(); indent(out) << "}" << endl << endl; } - + if (bean_style_) { + generate_java_bean_boilerplate(out, tstruct); + } generate_java_struct_reader(out, tstruct); if (is_result) { generate_java_struct_result_writer(out, tstruct); @@ -663,6 +671,113 @@ void t_java_generator::generate_java_struct_result_writer(ofstream& out, endl; } +/** + * Generates a set of Java Bean boilerplate functions (setters, getters, etc.) + * for the given struct. + * + * @param tstruct The struct definition + */ +void t_java_generator::generate_java_bean_boilerplate(ofstream& out, + t_struct* tstruct) { + const vector& fields = tstruct->get_members(); + vector::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; + cap_name[0] = toupper(cap_name[0]); + + if (type->is_set() || type->is_list()) { + + t_type* element_type; + if (type->is_set()) { + element_type = ((t_set*)type)->get_elem_type(); + } else { + element_type = ((t_list*)type)->get_elem_type(); + } + + // Iterator getter for sets and lists + indent(out) << "public java.util.Iterator get" << cap_name << "() {" << + endl; + indent_up(); + indent(out) << "return (this." << field_name << " == null) ? null : " << + "this." << field_name << ".iterator();" << endl; + indent_down(); + indent(out) << "}" << endl << endl; + + // Add to set or list, create if the set/list is null + indent(out) << "public void addTo" << cap_name << "(" << + type_name(element_type) << + " elem) {" << endl; + indent_up(); + indent(out) << "if (this." << field_name << " == null) {" << endl; + indent_up(); + indent(out) << "this." << field_name << " = new " << type_name(type) << + "();" << endl; + indent_down(); + indent(out) << "}" << endl; + indent(out) << "this." << field_name << ".add(elem);" << endl; + indent(out) << "this.__isset." << field_name << " = true;" << endl; + indent_down(); + indent(out) << "}" << endl << endl; + + } else if (type->is_map()) { + // Put to map + t_type* key_type = ((t_map*)type)->get_key_type(); + t_type* val_type = ((t_map*)type)->get_val_type(); + indent(out) << "public void putTo" << cap_name << "(" << + type_name(key_type) << " key, " << + type_name(val_type) << " val) {" << endl; + indent_up(); + indent(out) << "if (this." << field_name << " == null) {" << endl; + indent_up(); + indent(out) << "this." << field_name << " = new " << + type_name(type, false, true) << "();" << endl; + indent_down(); + indent(out) << "}" << endl; + indent(out) << "this." << field_name << ".put(key, val);" << endl; + indent(out) << "this.__isset." << field_name << " = true;" << endl; + indent_down(); + indent(out) << "}" << endl << endl; + } + + // Simple getter + indent(out) << "public " << type_name(type); + if (type->is_base_type() && + ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) { + out << " is"; + } else { + out << " get"; + } + out << cap_name << "() {" << endl; + indent_up(); + indent(out) << "return this." << field_name << ";" << endl; + indent_down(); + indent(out) << "}" << endl << endl; + + // Simple setter + indent(out) << "public void set" << cap_name << "(" << type_name(type) << + " " << field_name << ") {" << endl; + indent_up(); + indent(out) << "this." << field_name << " = " << field_name << ";" << + endl; + indent(out) << "this.__isset." << field_name << " = true;" << endl; + indent_down(); + indent(out) << "}" << endl << endl; + + // Unsetter + indent(out) << "public void unset" << cap_name << "() {" << endl; + indent_up(); + if (type->is_container() || type->is_struct() || type->is_xception()) { + indent(out) << "this." << field_name << " = null;" << endl; + } + indent(out) << "this.__isset." << field_name << " = false;" << endl; + indent_down(); + indent(out) << "}" << endl << endl; + } +} + /** * Generates a toString() method for the given struct * diff --git a/compiler/cpp/src/generate/t_java_generator.h b/compiler/cpp/src/generate/t_java_generator.h index 9509d09d..db085156 100644 --- a/compiler/cpp/src/generate/t_java_generator.h +++ b/compiler/cpp/src/generate/t_java_generator.h @@ -16,6 +16,7 @@ // TODO(mcslee: Paramaterize the output dir #define T_JAVA_DIR "gen-java" +#define T_JAVABEAN_DIR "gen-javabean" /** * Java code generator. @@ -24,8 +25,9 @@ */ class t_java_generator : public t_oop_generator { public: - t_java_generator(t_program* program) : - t_oop_generator(program) {} + t_java_generator(t_program* program, bool bean_style=false) : + t_oop_generator(program), + bean_style_(bean_style) {} /** * Init and close methods @@ -60,6 +62,7 @@ class t_java_generator : public t_oop_generator { 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_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct); void generate_function_helpers(t_function* tfunction); @@ -156,6 +159,9 @@ class t_java_generator : public t_oop_generator { std::string package_name_; std::ofstream f_service_; std::string package_dir_; + + bool bean_style_; + }; #endif diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc index b070b3b9..e46fceab 100644 --- a/compiler/cpp/src/main.cc +++ b/compiler/cpp/src/main.cc @@ -131,6 +131,7 @@ int g_doctext_lineno; */ bool gen_cpp = false; bool gen_java = false; +bool gen_javabean = false; bool gen_rb = false; bool gen_py = false; bool gen_xsd = false; @@ -542,6 +543,7 @@ void usage() { fprintf(stderr, "Options:\n"); fprintf(stderr, " -cpp Generate C++ output files\n"); fprintf(stderr, " -java Generate Java output files\n"); + fprintf(stderr, " -javabean Generate Java bean-style output files\n"); fprintf(stderr, " -php Generate PHP output files\n"); fprintf(stderr, " -phpi Generate PHP inlined files\n"); fprintf(stderr, " -py Generate Python output files\n"); @@ -773,7 +775,14 @@ void generate(t_program* program) { if (gen_java) { pverbose("Generating Java\n"); - t_java_generator* java = new t_java_generator(program); + t_java_generator* java = new t_java_generator(program, false); + java->generate_program(); + delete java; + } + + if (gen_javabean) { + pverbose("Generating Java Beans\n"); + t_java_generator* java = new t_java_generator(program, true); java->generate_program(); delete java; } @@ -891,6 +900,8 @@ int main(int argc, char** argv) { gen_recurse = true; } else if (strcmp(arg, "-cpp") == 0) { gen_cpp = true; + } else if (strcmp(arg, "-javabean") == 0) { + gen_javabean = true; } else if (strcmp(arg, "-java") == 0) { gen_java = true; } else if (strcmp(arg, "-php") == 0) { @@ -933,7 +944,7 @@ int main(int argc, char** argv) { } // You gotta generate something! - if (!gen_cpp && !gen_java && !gen_php && !gen_phpi && !gen_py && !gen_rb && !gen_xsd && !gen_perl && !gen_ocaml && !gen_erl && !gen_hs) { + if (!gen_cpp && !gen_java && !gen_javabean && !gen_php && !gen_phpi && !gen_py && !gen_rb && !gen_xsd && !gen_perl && !gen_ocaml && !gen_erl && !gen_hs) { fprintf(stderr, "!!! No output language(s) specified\n\n"); usage(); } -- 2.17.1