Adding XSD attribute support
Reviewed By: dave
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664974 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc
index 903aac0..936156b 100644
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ b/compiler/cpp/src/generate/t_php_generator.cc
@@ -844,9 +844,14 @@
f_service_ <<
"class " << service_name_ << "Rest" << extends_if << " {" << endl;
indent_up();
+
+ if (extends.empty()) {
+ f_service_ <<
+ indent() << "protected $impl_;" << endl <<
+ endl;
+ }
+
f_service_ <<
- indent() << "private $impl_;" << endl <<
- endl <<
indent() << "public function __construct($impl) {" << endl <<
indent() << " $this->impl_ = $impl;" << endl <<
indent() << "}" << endl <<
@@ -865,8 +870,9 @@
while (atype->is_typedef()) {
atype = ((t_typedef*)atype)->get_type();
}
+ string req = "$request['" + (*a_iter)->get_name() + "']";
f_service_ <<
- indent() << "$" << (*a_iter)->get_name() << " = $request['" << (*a_iter)->get_name() << "'];" << endl;
+ indent() << "$" << (*a_iter)->get_name() << " = isset(" << req << ") ? " << req << " : null;" << endl;
if (atype->is_string() &&
((t_base_type*)atype)->is_string_list()) {
f_service_ <<
diff --git a/compiler/cpp/src/generate/t_rb_generator.cc b/compiler/cpp/src/generate/t_rb_generator.cc
index 4636e43..d89bbb0 100644
--- a/compiler/cpp/src/generate/t_rb_generator.cc
+++ b/compiler/cpp/src/generate/t_rb_generator.cc
@@ -514,7 +514,6 @@
generate_service_client(tservice);
generate_service_server(tservice);
generate_service_helpers(tservice);
- generate_service_remote(tservice);
indent_down();
f_service_ << "end" << endl <<
@@ -750,143 +749,6 @@
}
/**
- * Generates a command line tool for making remote requests
- *
- * @param tservice The service to generate a remote for.
- */
-void t_rb_generator::generate_service_remote(t_service* tservice) {
- vector<t_function*> functions = tservice->get_functions();
- vector<t_function*>::iterator f_iter;
-
- string f_remote_name = string(T_RB_DIR)+"/"+service_name_+"-remote";
- ofstream f_remote;
- f_remote.open(f_remote_name.c_str());
-
- f_remote <<
- "#!/usr/bin/ruby" << endl <<
- rb_autogen_comment() << endl <<
- "import sys" << endl <<
- "import pprint" << endl <<
- "from thrift.transport import TTransport" << endl <<
- "from thrift.transport import TSocket" << endl <<
- "from thrift.protocol import TBinaryProtocol" << endl <<
- endl;
-
- f_remote <<
- "import " << service_name_ << endl <<
- "from " << program_name_ << "_types import *" << endl <<
- endl;
-
- f_remote <<
- "if len(sys.argv) <= 1 or sys.argv[1] == '--help':" << endl <<
- " print ''" << endl <<
- " print 'Usage: ' + sys.argv[0] + ' [-h host:port] [-f[ramed]] function [arg1,[arg2...]]'" << endl <<
- " print ''" << endl <<
- " print 'Functions:'" << endl;
- for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
- f_remote <<
- " print ' " << (*f_iter)->get_returntype()->get_name() << " " << (*f_iter)->get_name() << "(";
- t_struct* arg_struct = (*f_iter)->get_arglist();
- const std::vector<t_field*>& args = arg_struct->get_members();
- vector<t_field*>::const_iterator a_iter;
- int num_args = args.size();
- bool first = true;
- for (int i = 0; i < num_args; ++i) {
- if (first) {
- first = false;
- } else {
- f_remote << ", ";
- }
- f_remote <<
- args[i]->get_type()->get_name() << " " << args[i]->get_name();
- }
- f_remote << ")'" << endl;
- }
- f_remote <<
- " print ''" << endl <<
- " sys.exit(0)" << endl <<
- endl;
-
- f_remote <<
- "pp = pprint.PrettyPrinter(indent = 2)" << endl <<
- "host = 'localhost'" << endl <<
- "port = 9090" << endl <<
- "framed = False" << endl <<
- "argi = 1" << endl <<
- endl <<
- "if sys.argv[1] == '-h':" << endl <<
- " parts = sys.argv[2].split(':') " << endl <<
- " host = parts[0]" << endl <<
- " port = int(parts[1])" << endl <<
- " argi = 3" << endl <<
- endl <<
- "if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed':" << endl <<
- " framed = True" << endl <<
- " argi += 1" << endl <<
- endl <<
- "cmd = sys.argv[argi]" << endl <<
- "args = sys.argv[argi+1:]" << endl <<
- endl <<
- "socket = TSocket.TSocket(host, port)" << endl <<
- "if framed:" << endl <<
- " transport = TTransport.TFramedTransport(socket)" << endl <<
- "else:" << endl <<
- " transport = TTransport.TBufferedTransport(socket)" << endl <<
- "protocol = TBinaryProtocol.TBinaryProtocol(transport)" << endl <<
- "client = " << service_name_ << ".Client(protocol)" << endl <<
- "transport.open()" << endl <<
- endl;
-
- // Generate the dispatch methods
- bool first = true;
-
- for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
- if (first) {
- first = false;
- } else {
- f_remote << "el";
- }
-
- t_struct* arg_struct = (*f_iter)->get_arglist();
- const std::vector<t_field*>& args = arg_struct->get_members();
- vector<t_field*>::const_iterator a_iter;
- int num_args = args.size();
-
- f_remote <<
- "if cmd == '" << (*f_iter)->get_name() << "':" << endl <<
- " if len(args) != " << num_args << ":" << endl <<
- " print '" << (*f_iter)->get_name() << " requires " << num_args << " args'" << endl <<
- " sys.exit(1)" << endl <<
- " pp.pprint(client." << (*f_iter)->get_name() << "(";
- for (int i = 0; i < num_args; ++i) {
- if (args[i]->get_type()->is_string()) {
- f_remote << "args[" << i << "],";
- } else {
- f_remote << "eval(args[" << i << "]),";
- }
- }
- f_remote << "))" << endl;
-
- f_remote << endl;
- }
-
- f_remote << "transport.close()" << endl;
-
- // Close service file
- f_remote.close();
-
- // Make file executable, love that bitwise OR action
- chmod(f_remote_name.c_str(),
- S_IRUSR |
- S_IWUSR |
- S_IXUSR |
- S_IRGRP |
- S_IXGRP |
- S_IROTH |
- S_IXOTH);
-}
-
-/**
* Generates a service server definition.
*
* @param tservice The service to generate a server for.
diff --git a/compiler/cpp/src/generate/t_rb_generator.h b/compiler/cpp/src/generate/t_rb_generator.h
index bb74db6..97c0834 100644
--- a/compiler/cpp/src/generate/t_rb_generator.h
+++ b/compiler/cpp/src/generate/t_rb_generator.h
@@ -57,7 +57,6 @@
void generate_service_helpers (t_service* tservice);
void generate_service_interface (t_service* tservice);
void generate_service_client (t_service* tservice);
- void generate_service_remote (t_service* tservice);
void generate_service_server (t_service* tservice);
void generate_process_function (t_service* tservice, t_function* tfunction);
diff --git a/compiler/cpp/src/generate/t_xsd_generator.cc b/compiler/cpp/src/generate/t_xsd_generator.cc
index 7f53f9f..49550b1 100644
--- a/compiler/cpp/src/generate/t_xsd_generator.cc
+++ b/compiler/cpp/src/generate/t_xsd_generator.cc
@@ -48,7 +48,7 @@
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(), (*m_iter)->get_xsd_optional() || xsd_all, false);
+ generate_element(s_xsd_types_, (*m_iter)->get_name(), (*m_iter)->get_type(), (*m_iter)->get_xsd_attrs(), (*m_iter)->get_xsd_optional() || xsd_all);
}
indent_down();
@@ -66,46 +66,80 @@
void t_xsd_generator::generate_element(ostream& out,
string name,
t_type* ttype,
+ vector<string> attrs,
bool optional,
bool list_element) {
string sminOccurs = (optional || list_element) ? " minOccurs=\"0\"" : "";
string smaxOccurs = list_element ? " maxOccurs=\"unbounded\"" : "";
-
string soptional = sminOccurs + smaxOccurs;
if (ttype->is_void() || ttype->is_list()) {
indent(out) <<
"<xsd:element name=\"" << name << "\"" << soptional << ">" << endl;
indent_up();
- if (ttype->is_void()) {
+ if (attrs.size() == 0 && ttype->is_void()) {
indent(out) <<
"<xsd:complexType />" << endl;
- } else if (ttype->is_list()) {
- indent(out) << "<xsd:complexType>" << endl;
+ } else {
+ indent(out) <<
+ "<xsd:complexType>" << endl;
indent_up();
- indent(out) << "<xsd:sequence>" << 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);
+
+ vector<string>::iterator a_iter;
+ for (a_iter = attrs.begin(); a_iter != attrs.end(); ++a_iter) {
+ indent(out) << "<xsd:attribute name=\"" << (*a_iter) << "\" type=\"xsd:boolean\" />" << endl;
}
- f_php_ << "$GLOBALS['" << program_->get_name() << "_xsd_elt_" << name << "'] = '" << subname << "';" << endl;
- generate_element(out, subname, subtype, false, true);
+
+ if (ttype->is_list()) {
+ indent(out) << "<xsd:attribute name=\"list\" type=\"xsd:boolean\" />" << endl;
+ indent(out) << "<xsd:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">" << 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);
+ }
+ f_php_ << "$GLOBALS['" << program_->get_name() << "_xsd_elt_" << name << "'] = '" << subname << "';" << endl;
+ generate_element(out, subname, subtype, vector<string>(), false, true);
+ indent_down();
+ indent(out) << "</xsd:sequence>" << endl;
+ }
indent_down();
- indent(out) << "</xsd:sequence>" << endl;
- indent(out) << "<xsd:attribute name=\"list\" type=\"xsd:boolean\" />" << endl;
- indent_down();
- indent(out) << "</xsd:complexType>" << endl;
+ indent(out) <<
+ "</xsd:complexType>" << endl;
}
indent_down();
indent(out) <<
"</xsd:element>" << endl;
} else {
- indent(out) <<
- "<xsd:element name=\"" << name << "\"" << soptional << " type=\"" << type_name(ttype) << "\" />" << endl;
+ if (attrs.size() == 0) {
+ indent(out) <<
+ "<xsd:element name=\"" << name << "\"" << soptional << " type=\"" << type_name(ttype) << "\" />" << endl;
+ } else {
+ // Wow, all this work for a SIMPLE TYPE with attributes?!?!?!
+ indent(out) << "<xsd:element name=\"" << name << "\"" << soptional << ">" << endl;
+ indent_up();
+ indent(out) << "<xsd:complexType>" << endl;
+ indent_up();
+ indent(out) << "<xsd:complexContent>" << endl;
+ indent_up();
+ indent(out) << "<xsd:extension base=\"" << type_name(ttype) << "\">" << endl;
+ indent_up();
+ vector<string>::iterator a_iter;
+ for (a_iter = attrs.begin(); a_iter != attrs.end(); ++a_iter) {
+ indent(out) << "<xsd:attribute name=\"" << (*a_iter) << "\" type=\"xsd:boolean\" />" << endl;
+ }
+ indent_down();
+ indent(out) << "</xsd:extension>" << endl;
+ indent_down();
+ indent(out) << "</xsd:complexContent>" << endl;
+ indent_down();
+ indent(out) << "</xsd:complexType>" << endl;
+ indent_down();
+ indent(out) << "</xsd:element>" << endl;
+ }
}
}
@@ -140,7 +174,7 @@
for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
string elemname = (*f_iter)->get_name() + "_response";
t_type* returntype = (*f_iter)->get_returntype();
- generate_element(f_xsd_, elemname, returntype, false, false);
+ generate_element(f_xsd_, elemname, returntype);
f_xsd_ << endl;
t_struct* xs = (*f_iter)->get_xceptions();
@@ -153,7 +187,7 @@
map<string, t_struct*>::iterator ax_iter;
for (ax_iter = all_xceptions.begin(); ax_iter != all_xceptions.end(); ++ax_iter) {
- generate_element(f_xsd_, ax_iter->first, ax_iter->second, false, false);
+ generate_element(f_xsd_, ax_iter->first, ax_iter->second);
}
// Close the XSD document
diff --git a/compiler/cpp/src/generate/t_xsd_generator.h b/compiler/cpp/src/generate/t_xsd_generator.h
index 0413670..7a60283 100644
--- a/compiler/cpp/src/generate/t_xsd_generator.h
+++ b/compiler/cpp/src/generate/t_xsd_generator.h
@@ -40,7 +40,7 @@
private:
- void generate_element(std::ostream& out, std::string name, t_type* ttype, bool optional, bool list_element);
+ void generate_element(std::ostream& out, std::string name, t_type* ttype, std::vector<std::string> attrs=std::vector<std::string>(), bool optional=false, bool list_element=false);
std::string ns(std::string in, std::string ns) {
return ns + ":" + in;
diff --git a/compiler/cpp/src/parse/t_field.h b/compiler/cpp/src/parse/t_field.h
index 03d4ba7..090426a 100644
--- a/compiler/cpp/src/parse/t_field.h
+++ b/compiler/cpp/src/parse/t_field.h
@@ -39,6 +39,14 @@
return key_;
}
+ void set_value(t_const_value* value) {
+ value_ = value;
+ }
+
+ t_const_value* get_value() {
+ return value_;
+ }
+
void set_xsd_optional(bool xsd_optional) {
xsd_optional_ = xsd_optional;
}
@@ -47,12 +55,12 @@
return xsd_optional_;
}
- void set_value(t_const_value* value) {
- value_ = value;
+ void add_xsd_attr(std::string attr) {
+ xsd_attrs_.push_back(attr);
}
- t_const_value* get_value() {
- return value_;
+ const std::vector<std::string>& get_xsd_attrs() {
+ return xsd_attrs_;
}
const std::string& get_doc() const {
@@ -75,6 +83,7 @@
t_const_value* value_;
bool xsd_optional_;
+ std::vector<std::string> xsd_attrs_;
std::string doc_;
bool has_doc_;
diff --git a/compiler/cpp/src/thriftl.ll b/compiler/cpp/src/thriftl.ll
index 5450ad2..5486ada 100644
--- a/compiler/cpp/src/thriftl.ll
+++ b/compiler/cpp/src/thriftl.ll
@@ -64,6 +64,7 @@
"xsd_all" { return tok_xsd_all; }
"xsd_optional" { return tok_xsd_optional; }
"xsd_namespace" { return tok_xsd_namespace; }
+"xsd_attrs" { return tok_xsd_attrs; }
"include" { return tok_include; }
"void" { return tok_void; }
diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy
index 9c38996..a53d002 100644
--- a/compiler/cpp/src/thrifty.yy
+++ b/compiler/cpp/src/thrifty.yy
@@ -71,6 +71,7 @@
%token tok_xsd_all
%token tok_xsd_optional
%token tok_xsd_namespace
+%token tok_xsd_attrs
/**
* Base datatype keywords
@@ -154,6 +155,7 @@
%type<tbool> Async
%type<tbool> XsdAll
%type<tbool> XsdOptional
+%type<id> XsdAttributes
%type<id> CppType
%type<tdoc> DocTextOptional
@@ -515,6 +517,16 @@
$$ = false;
}
+XsdAttributes:
+ tok_xsd_attrs tok_identifier
+ {
+ $$ = $2;
+ }
+|
+ {
+ $$ = NULL;
+ }
+
Xception:
tok_xception tok_identifier '{' FieldList '}'
{
@@ -619,11 +631,11 @@
}
Field:
- DocTextOptional FieldIdentifier FieldType tok_identifier FieldValue XsdOptional CommaOrSemicolonOptional
+ DocTextOptional FieldIdentifier FieldType tok_identifier FieldValue XsdOptional XsdAttributes CommaOrSemicolonOptional
{
pdebug("tok_int_constant : Field -> FieldType tok_identifier");
if ($2 < 0) {
- pwarning(2, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", $3);
+ pwarning(2, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", $4);
}
$$ = new t_field($3, $4, $2);
if ($5 != NULL) {
@@ -634,6 +646,9 @@
if ($1 != NULL) {
$$->set_doc($1);
}
+ if ($7 != NULL) {
+ $$->add_xsd_attr($7);
+ }
}
FieldIdentifier: