From: Mark Slee Date: Thu, 18 Jan 2007 22:59:59 +0000 (+0000) Subject: Thrift now generates XSD files X-Git-Tag: 0.2.0~1544 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=0e0ff7e00353fc4a9a1b5a6f49069d05b64604f2;p=common%2Fthrift.git Thrift now generates XSD files Summary: Are you fucking kidding me? This shit is robust. Reviewed By: fetter-tbr-d00d git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664928 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/compiler/cpp/Makefile b/compiler/cpp/Makefile index 3d405a1b..3b9be48c 100644 --- a/compiler/cpp/Makefile +++ b/compiler/cpp/Makefile @@ -35,6 +35,7 @@ BIN_DIR = bin/ # Source files SRC_FILES = main.cc \ generate/t_generator.cc \ + generate/t_xsd_generator.cc \ generate/t_py_generator.cc \ generate/t_java_generator.cc \ generate/t_php_generator.cc \ diff --git a/compiler/cpp/src/generate/t_generator.h b/compiler/cpp/src/generate/t_generator.h index 50f7bf6d..5e835a28 100644 --- a/compiler/cpp/src/generate/t_generator.h +++ b/compiler/cpp/src/generate/t_generator.h @@ -5,6 +5,7 @@ #include #include #include "parse/t_program.h" +#include "globals.h" /** * Base class for a thrift code generator. This class defines the basic diff --git a/compiler/cpp/src/generate/t_xsd_generator.cc b/compiler/cpp/src/generate/t_xsd_generator.cc new file mode 100644 index 00000000..cb184a3d --- /dev/null +++ b/compiler/cpp/src/generate/t_xsd_generator.cc @@ -0,0 +1,178 @@ +#include +#include +#include +#include "t_xsd_generator.h" +using namespace std; + +void t_xsd_generator::init_generator() { + // Make output directory + mkdir(T_XSD_DIR, S_IREAD | S_IWRITE | S_IEXEC); +} + +void t_xsd_generator::close_generator() { +} + +void t_xsd_generator::generate_typedef(t_typedef* ttypedef) { + indent(s_xsd_types_) << + "get_name() << "\">" << endl; + indent_up(); + indent(s_xsd_types_) << + "get_type()) << "\" />" << endl; + indent_down(); + indent(s_xsd_types_) << + "" << endl << endl; +} + +void t_xsd_generator::generate_struct(t_struct* tstruct) { + vector::const_iterator m_iter; + const vector& members = tstruct->get_members(); + + indent(s_xsd_types_) << "get_name() << "\">" << endl; + indent_up(); + indent(s_xsd_types_) << "" << endl; + indent_up(); + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + generate_element(s_xsd_types_, (*m_iter)->get_name(), (*m_iter)->get_type()); + } + + indent_down(); + indent(s_xsd_types_) << "" << endl; + indent_down(); + indent(s_xsd_types_) << + "" << endl << + endl; +} + +void t_xsd_generator::generate_element(ostream& out, + string name, + t_type* ttype) { + if (ttype->is_void() || ttype->is_list()) { + indent(out) << + "" << endl; + indent_up(); + if (ttype->is_void()) { + indent(out) << + "" << endl; + } else if (ttype->is_list()) { + indent(out) << "" << endl; + indent_up(); + indent(out) << "" << endl; + indent_up(); + string subname; + t_type* subtype = ((t_list*)ttype)->get_elem_type(); + if (subtype->is_base_type() || subtype->is_container()) { + subname = name + "_elt"; + } else { + subname = type_name(subtype); + } + generate_element(out, subname, subtype); + indent_down(); + indent(out) << "" << endl; + indent(out) << "" << endl; + indent_down(); + indent(out) << "" << endl; + } + indent_down(); + indent(out) << + "" << endl; + } else { + indent(out) << + "" << endl; + } +} + +void t_xsd_generator::generate_service(t_service* tservice) { + // Make output file + string f_xsd_name = string(T_XSD_DIR)+"/"+tservice->get_name()+".xsd"; + f_xsd_.open(f_xsd_name.c_str()); + + // Print the XSD header + f_xsd_ << + "" << endl << + "" << endl << + endl << + "" << endl << + endl; + + // Print out the type definitions + indent(f_xsd_) << s_xsd_types_.str(); + + // Keep a list of all the possible exceptions that might get thrown + set all_xceptions; + + // List the elements that you might actually get + vector functions = tservice->get_functions(); + vector::iterator f_iter; + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + string elemname = (*f_iter)->get_name() + "_result"; + t_type* returntype = (*f_iter)->get_returntype(); + generate_element(f_xsd_, elemname, returntype); + f_xsd_ << endl; + + t_struct* xs = (*f_iter)->get_xceptions(); + const std::vector& xceptions = xs->get_members(); + vector::const_iterator x_iter; + for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { + all_xceptions.insert((t_struct*)((*x_iter)->get_type())); + } + } + + set::iterator ax_iter; + for (ax_iter = all_xceptions.begin(); ax_iter != all_xceptions.end(); ++ax_iter) { + generate_element(f_xsd_, (*ax_iter)->get_name(), *ax_iter); + } + + // Close the XSD document + f_xsd_ << endl << "" << endl; + f_xsd_.close(); +} + +string t_xsd_generator::type_name(t_type* ttype) { + if (ttype->is_typedef()) { + return ttype->get_name(); + } + + if (ttype->is_base_type()) { + return xsd(base_type_name(((t_base_type*)ttype)->get_base())); + } + + if (ttype->is_enum()) { + return xsd("int"); + } + + if (ttype->is_struct() || ttype->is_xception()) { + return ttype->get_name(); + } + + return "container"; +} + +/** + * Returns the XSD type that corresponds to the thrift type. + * + * @param tbase The base type + * @return Explicit XSD type, i.e. xsd:string + */ +string t_xsd_generator::base_type_name(t_base_type::t_base tbase) { + switch (tbase) { + case t_base_type::TYPE_VOID: + return "void"; + case t_base_type::TYPE_STRING: + return "string"; + case t_base_type::TYPE_BOOL: + return "boolean"; + case t_base_type::TYPE_BYTE: + return "byte"; + case t_base_type::TYPE_I16: + return "short"; + case t_base_type::TYPE_I32: + return "int"; + case t_base_type::TYPE_I64: + return "long"; + case t_base_type::TYPE_DOUBLE: + return "decimal"; + default: + throw "compiler error: no C++ base type name for base type " + tbase; + } +} diff --git a/compiler/cpp/src/generate/t_xsd_generator.h b/compiler/cpp/src/generate/t_xsd_generator.h new file mode 100644 index 00000000..fc39765b --- /dev/null +++ b/compiler/cpp/src/generate/t_xsd_generator.h @@ -0,0 +1,68 @@ +#ifndef T_XSD_GENERATOR_H +#define T_XSD_GENERATOR_H + +#include +#include +#include +#include "t_generator.h" + +// TODO(mcslee): Paramaterize the output dir +#define T_XSD_DIR "gen-xsd" + +/** + * XSD generator, creates an XSD for the base types etc. + * + * @author Mark Slee + */ +class t_xsd_generator : public t_generator { + public: + t_xsd_generator(t_program* program) : + t_generator(program) {} + + virtual ~t_xsd_generator() {} + + /** + * Init and close methods + */ + + void init_generator(); + void close_generator(); + + /** + * Program-level generation functions + */ + + void generate_typedef(t_typedef* ttypedef); + void generate_enum(t_enum* tenum) {} + + void generate_service(t_service* tservice); + void generate_struct(t_struct* tstruct); + + private: + + void generate_element(std::ostream& out, std::string name, t_type* ttype); + + std::string ns(std::string in, std::string ns) { + return ns + ":" + in; + } + + std::string xsd(std::string in) { + return ns(in, "xsd"); + } + + std::string type_name(t_type* ttype); + std::string base_type_name(t_base_type::t_base tbase); + + /** + * Output xsd file + */ + std::ofstream f_xsd_; + + /** + * Output string stream + */ + std::ostringstream s_xsd_types_; + +}; + +#endif diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc index 7280a379..065c95f6 100644 --- a/compiler/cpp/src/main.cc +++ b/compiler/cpp/src/main.cc @@ -26,6 +26,7 @@ #include "generate/t_java_generator.h" #include "generate/t_php_generator.h" #include "generate/t_py_generator.h" +#include "generate/t_xsd_generator.h" using namespace std; @@ -108,6 +109,7 @@ char* g_time_str; bool gen_cpp = false; bool gen_java = false; bool gen_py = false; +bool gen_xsd = false; bool gen_php = false; bool gen_phpi = false; bool gen_recurse = false; @@ -515,6 +517,14 @@ void generate(t_program* program) { py->generate_program(); delete py; } + + if (gen_xsd) { + pverbose("Generating XSD\n"); + t_xsd_generator* xsd = new t_xsd_generator(program); + xsd->generate_program(); + delete xsd; + } + } catch (string s) { printf("Error: %s\n", s.c_str()); } catch (const char* exc) { @@ -571,6 +581,8 @@ int main(int argc, char** argv) { gen_phpi = true; } else if (strcmp(arg, "-py") == 0) { gen_py = true; + } else if (strcmp(arg, "-xsd") == 0) { + gen_xsd = true; } else if (strcmp(arg, "-I") == 0) { // An argument of "-I\ asdf" is invalid and has unknown results arg = argv[++i]; @@ -591,7 +603,7 @@ int main(int argc, char** argv) { } // You gotta generate something! - if (!gen_cpp && !gen_java && !gen_php && !gen_phpi && !gen_py) { + if (!gen_cpp && !gen_java && !gen_php && !gen_phpi && !gen_py && !gen_xsd) { fprintf(stderr, "!!! No output language(s) specified\n\n"); usage(); }