Allow field elements to be optional in thrift with xsd_optional keyword
Reviewed By: tbr-dave
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664932 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_xsd_generator.cc b/compiler/cpp/src/generate/t_xsd_generator.cc
index 57c9656..5d4cfa2 100644
--- a/compiler/cpp/src/generate/t_xsd_generator.cc
+++ b/compiler/cpp/src/generate/t_xsd_generator.cc
@@ -38,7 +38,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());
+ generate_element(s_xsd_types_, (*m_iter)->get_name(), (*m_iter)->get_type(), (*m_iter)->get_xsd_optional());
}
indent_down();
@@ -55,10 +55,13 @@
void t_xsd_generator::generate_element(ostream& out,
string name,
- t_type* ttype) {
+ t_type* ttype,
+ bool optional) {
+ string soptional = optional ? " minoccurs=\"0\" maxOccurs=\"1\"" : "";
+
if (ttype->is_void() || ttype->is_list()) {
indent(out) <<
- "<xsd:element name=\"" << name << "\">" << endl;
+ "<xsd:element name=\"" << name << "\"" << soptional << ">" << endl;
indent_up();
if (ttype->is_void()) {
indent(out) <<
@@ -87,7 +90,7 @@
"</xsd:element>" << endl;
} else {
indent(out) <<
- "<xsd:element name=\"" << name << "\" type=\"" << type_name(ttype) << "\" />" << endl;
+ "<xsd:element name=\"" << name << "\"" << soptional << " type=\"" << type_name(ttype) << "\" />" << endl;
}
}
diff --git a/compiler/cpp/src/generate/t_xsd_generator.h b/compiler/cpp/src/generate/t_xsd_generator.h
index fc39765..35bcf93 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);
+ void generate_element(std::ostream& out, std::string name, t_type* ttype, bool optional=false);
std::string ns(std::string in, std::string ns) {
return ns + ":" + in;
diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc
index 2fbf913..48552e6 100644
--- a/compiler/cpp/src/main.cc
+++ b/compiler/cpp/src/main.cc
@@ -435,6 +435,7 @@
g_program = program;
g_scope = program->scope();
try {
+ yylineno = 1;
if (yyparse() != 0) {
failure("Parser error during include pass.");
}
@@ -462,6 +463,7 @@
failure("Could not open input file: \"%s\"", path.c_str());
}
pverbose("Parsing %s for types\n", path.c_str());
+ yylineno = 1;
if (yyparse() != 0) {
failure("Parser error during types pass.");
}
diff --git a/compiler/cpp/src/parse/t_field.h b/compiler/cpp/src/parse/t_field.h
index 93e14d8..35414ef 100644
--- a/compiler/cpp/src/parse/t_field.h
+++ b/compiler/cpp/src/parse/t_field.h
@@ -14,12 +14,14 @@
t_field(t_type* type, std::string name) :
type_(type),
name_(name),
- key_(0) {}
+ key_(0),
+ xsd_optional_(false) {}
t_field(t_type* type, std::string name, int32_t key) :
type_(type),
name_(name),
- key_(key) {}
+ key_(key),
+ xsd_optional_(false) {}
~t_field() {}
@@ -35,10 +37,21 @@
return key_;
}
+ void set_xsd_optional(bool xsd_optional) {
+ xsd_optional_ = xsd_optional;
+ }
+
+ bool get_xsd_optional() const {
+ return xsd_optional_;
+ }
+
private:
t_type* type_;
std::string name_;
int32_t key_;
+
+ bool xsd_optional_;
+
};
#endif
diff --git a/compiler/cpp/src/thrift.l b/compiler/cpp/src/thrift.l
index b7008c6..80cbf87 100644
--- a/compiler/cpp/src/thrift.l
+++ b/compiler/cpp/src/thrift.l
@@ -60,6 +60,7 @@
"java_package" { return tok_java_package; }
"php_namespace" { return tok_php_namespace; }
"xsd_all" { return tok_xsd_all; }
+"xsd_optional" { return tok_xsd_optional; }
"include" { return tok_include; }
"void" { return tok_void; }
diff --git a/compiler/cpp/src/thrift.y b/compiler/cpp/src/thrift.y
index fe56dad..d8f3435 100644
--- a/compiler/cpp/src/thrift.y
+++ b/compiler/cpp/src/thrift.y
@@ -67,6 +67,7 @@
%token tok_php_namespace
%token tok_java_package
%token tok_xsd_all
+%token tok_xsd_optional
/**
* Base datatype keywords
@@ -143,11 +144,12 @@
%type<ttype> FunctionType
%type<tservice> FunctionList
-%type<tstruct> ThrowsOptional
-%type<tservice> ExtendsOptional
-%type<tbool> AsyncOptional
-%type<tbool> XsdAllOptional
-%type<id> CppTypeOptional
+%type<tstruct> Throws
+%type<tservice> Extends
+%type<tbool> Async
+%type<tbool> XsdAll
+%type<tbool> XsdOptional
+%type<id> CppType
%%
@@ -443,7 +445,7 @@
}
Struct:
- tok_struct tok_identifier XsdAllOptional '{' FieldList '}'
+ tok_struct tok_identifier XsdAll '{' FieldList '}'
{
pdebug("Struct -> tok_struct tok_identifier { FieldList }");
$5->set_name($2);
@@ -452,7 +454,7 @@
y_field_val = -1;
}
-XsdAllOptional:
+XsdAll:
tok_xsd_all
{
$$ = true;
@@ -462,6 +464,16 @@
$$ = false;
}
+XsdOptional:
+ tok_xsd_optional
+ {
+ $$ = true;
+ }
+|
+ {
+ $$ = false;
+ }
+
Xception:
tok_xception tok_identifier '{' FieldList '}'
{
@@ -473,7 +485,7 @@
}
Service:
- tok_service tok_identifier ExtendsOptional '{' FunctionList '}'
+ tok_service tok_identifier Extends '{' FunctionList '}'
{
pdebug("Service -> tok_service tok_identifier { FunctionList }");
$$ = $5;
@@ -481,10 +493,10 @@
$$->set_extends($3);
}
-ExtendsOptional:
+Extends:
tok_extends tok_identifier
{
- pdebug("ExtendsOptional -> tok_extends tok_identifier");
+ pdebug("Extends -> tok_extends tok_identifier");
$$ = NULL;
if (g_parse_mode == PROGRAM) {
$$ = g_scope->get_service($2);
@@ -513,14 +525,14 @@
}
Function:
- AsyncOptional FunctionType tok_identifier '(' FieldList ')' ThrowsOptional CommaOrSemicolonOptional
+ Async FunctionType tok_identifier '(' FieldList ')' Throws CommaOrSemicolonOptional
{
$5->set_name(std::string($3) + "_args");
$$ = new t_function($2, $3, $5, $7, $1);
y_field_val = -1;
}
-AsyncOptional:
+Async:
tok_async
{
$$ = true;
@@ -530,10 +542,10 @@
$$ = false;
}
-ThrowsOptional:
+Throws:
tok_throws '(' FieldList ')'
{
- pdebug("ThrowsOptional -> tok_throws ( FieldList )");
+ pdebug("Throws -> tok_throws ( FieldList )");
$$ = $3;
}
|
@@ -555,7 +567,7 @@
}
Field:
- tok_int_constant ':' FieldType tok_identifier CommaOrSemicolonOptional
+ tok_int_constant ':' FieldType tok_identifier XsdOptional CommaOrSemicolonOptional
{
pdebug("tok_int_constant : Field -> FieldType tok_identifier");
if ($1 <= 0) {
@@ -563,12 +575,14 @@
$1 = y_field_val--;
}
$$ = new t_field($3, $4, $1);
+ $$->set_xsd_optional($5);
}
-| FieldType tok_identifier CommaOrSemicolonOptional
+| FieldType tok_identifier XsdOptional CommaOrSemicolonOptional
{
pdebug("Field -> FieldType tok_identifier");
pwarning(2, "No field key specified for '%s', resulting protocol may have conflicts or not be backwards compatible!\n", $2);
$$ = new t_field($1, $2, y_field_val--);
+ $$->set_xsd_optional($3);
}
| FieldType tok_identifier '=' tok_int_constant CommaOrSemicolonOptional
{
@@ -692,7 +706,7 @@
}
MapType:
- tok_map CppTypeOptional '<' FieldType ',' FieldType '>'
+ tok_map CppType '<' FieldType ',' FieldType '>'
{
pdebug("MapType -> tok_map <FieldType, FieldType>");
$$ = new t_map($4, $6);
@@ -702,7 +716,7 @@
}
SetType:
- tok_set CppTypeOptional '<' FieldType '>'
+ tok_set CppType '<' FieldType '>'
{
pdebug("SetType -> tok_set<FieldType>");
$$ = new t_set($4);
@@ -712,7 +726,7 @@
}
ListType:
- tok_list '<' FieldType '>' CppTypeOptional
+ tok_list '<' FieldType '>' CppType
{
pdebug("ListType -> tok_list<FieldType>");
$$ = new t_list($3);
@@ -721,7 +735,7 @@
}
}
-CppTypeOptional:
+CppType:
'[' tok_cpp_type tok_literal ']'
{
$$ = $3;