1 // Copyright (c) 2006- Facebook
2 // Distributed under the Thrift Software License
4 // See accompanying file LICENSE or visit the Thrift site at:
5 // http://developers.facebook.com/thrift/
10 #include "t_xsd_generator.h"
13 void t_xsd_generator::init_generator() {
14 // Make output directory
15 mkdir(get_out_dir().c_str(), S_IRWXU
| S_IRWXG
| S_IRWXO
);
18 string f_php_name
= get_out_dir()+program_
->get_name()+"_xsd.php";
19 f_php_
.open(f_php_name
.c_str());
26 void t_xsd_generator::close_generator() {
27 f_php_
<< "?>" << endl
;
31 void t_xsd_generator::generate_typedef(t_typedef
* ttypedef
) {
32 indent(s_xsd_types_
) <<
33 "<xsd:simpleType name=\"" << ttypedef
->get_name() << "\">" << endl
;
35 if (ttypedef
->get_type()->is_string() && ((t_base_type
*)ttypedef
->get_type())->is_string_enum()) {
36 indent(s_xsd_types_
) <<
37 "<xsd:restriction base=\"" << type_name(ttypedef
->get_type()) << "\">" << endl
;
39 const vector
<string
>& values
= ((t_base_type
*)ttypedef
->get_type())->get_string_enum_vals();
40 vector
<string
>::const_iterator v_iter
;
41 for (v_iter
= values
.begin(); v_iter
!= values
.end(); ++v_iter
) {
42 indent(s_xsd_types_
) <<
43 "<xsd:enumeration value=\"" << (*v_iter
) << "\" />" << endl
;
46 indent(s_xsd_types_
) <<
47 "</xsd:restriction>" << endl
;
49 indent(s_xsd_types_
) <<
50 "<xsd:restriction base=\"" << type_name(ttypedef
->get_type()) << "\" />" << endl
;
53 indent(s_xsd_types_
) <<
54 "</xsd:simpleType>" << endl
<< endl
;
57 void t_xsd_generator::generate_struct(t_struct
* tstruct
) {
58 vector
<t_field
*>::const_iterator m_iter
;
59 const vector
<t_field
*>& members
= tstruct
->get_members();
60 bool xsd_all
= tstruct
->get_xsd_all();
62 indent(s_xsd_types_
) << "<xsd:complexType name=\"" << tstruct
->get_name() << "\">" << endl
;
65 indent(s_xsd_types_
) << "<xsd:all>" << endl
;
67 indent(s_xsd_types_
) << "<xsd:sequence>" << endl
;
71 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
72 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
, (*m_iter
)->get_xsd_nillable());
77 indent(s_xsd_types_
) << "</xsd:all>" << endl
;
79 indent(s_xsd_types_
) << "</xsd:sequence>" << endl
;
82 indent(s_xsd_types_
) <<
83 "</xsd:complexType>" << endl
<<
87 void t_xsd_generator::generate_element(ostream
& out
,
94 string sminOccurs
= (optional
|| list_element
) ? " minOccurs=\"0\"" : "";
95 string smaxOccurs
= list_element
? " maxOccurs=\"unbounded\"" : "";
96 string soptional
= sminOccurs
+ smaxOccurs
;
97 string snillable
= nillable
? " nillable=\"true\"" : "";
99 if (ttype
->is_void() || ttype
->is_list()) {
101 "<xsd:element name=\"" << name
<< "\"" << soptional
<< snillable
<< ">" << endl
;
103 if (attrs
== NULL
&& ttype
->is_void()) {
105 "<xsd:complexType />" << endl
;
108 "<xsd:complexType>" << endl
;
110 if (ttype
->is_list()) {
111 indent(out
) << "<xsd:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">" << endl
;
114 t_type
* subtype
= ((t_list
*)ttype
)->get_elem_type();
115 if (subtype
->is_base_type() || subtype
->is_container()) {
116 subname
= name
+ "_elt";
118 subname
= type_name(subtype
);
120 f_php_
<< "$GLOBALS['" << program_
->get_name() << "_xsd_elt_" << name
<< "'] = '" << subname
<< "';" << endl
;
121 generate_element(out
, subname
, subtype
, NULL
, false, false, true);
123 indent(out
) << "</xsd:sequence>" << endl
;
124 indent(out
) << "<xsd:attribute name=\"list\" type=\"xsd:boolean\" />" << endl
;
127 const vector
<t_field
*>& members
= attrs
->get_members();
128 vector
<t_field
*>::const_iterator a_iter
;
129 for (a_iter
= members
.begin(); a_iter
!= members
.end(); ++a_iter
) {
130 indent(out
) << "<xsd:attribute name=\"" << (*a_iter
)->get_name() << "\" type=\"" << type_name((*a_iter
)->get_type()) << "\" />" << endl
;
135 "</xsd:complexType>" << endl
;
139 "</xsd:element>" << endl
;
143 "<xsd:element name=\"" << name
<< "\"" << " type=\"" << type_name(ttype
) << "\"" << soptional
<< snillable
<< " />" << endl
;
145 // Wow, all this work for a SIMPLE TYPE with attributes?!?!?!
146 indent(out
) << "<xsd:element name=\"" << name
<< "\"" << soptional
<< snillable
<< ">" << endl
;
148 indent(out
) << "<xsd:complexType>" << endl
;
150 indent(out
) << "<xsd:complexContent>" << endl
;
152 indent(out
) << "<xsd:extension base=\"" << type_name(ttype
) << "\">" << endl
;
154 const vector
<t_field
*>& members
= attrs
->get_members();
155 vector
<t_field
*>::const_iterator a_iter
;
156 for (a_iter
= members
.begin(); a_iter
!= members
.end(); ++a_iter
) {
157 indent(out
) << "<xsd:attribute name=\"" << (*a_iter
)->get_name() << "\" type=\"" << type_name((*a_iter
)->get_type()) << "\" />" << endl
;
160 indent(out
) << "</xsd:extension>" << endl
;
162 indent(out
) << "</xsd:complexContent>" << endl
;
164 indent(out
) << "</xsd:complexType>" << endl
;
166 indent(out
) << "</xsd:element>" << endl
;
171 void t_xsd_generator::generate_service(t_service
* tservice
) {
173 string f_xsd_name
= get_out_dir()+tservice
->get_name()+".xsd";
174 f_xsd_
.open(f_xsd_name
.c_str());
176 string ns
= program_
->get_xsd_namespace();
178 ns
= " targetNamespace=\"" + ns
+ "\" xmlns=\"" + ns
+ "\" " +
179 "elementFormDefault=\"qualified\"";
182 // Print the XSD header
184 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" << endl
<<
185 "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" << ns
<< ">" << endl
<<
187 "<!-- Yo yo yo, this XSD woz be generated by Thrift. -->" << endl
<<
190 // Print out the type definitions
191 indent(f_xsd_
) << s_xsd_types_
.str();
193 // Keep a list of all the possible exceptions that might get thrown
194 map
<string
, t_struct
*> all_xceptions
;
196 // List the elements that you might actually get
197 vector
<t_function
*> functions
= tservice
->get_functions();
198 vector
<t_function
*>::iterator f_iter
;
199 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
200 string elemname
= (*f_iter
)->get_name() + "_response";
201 t_type
* returntype
= (*f_iter
)->get_returntype();
202 generate_element(f_xsd_
, elemname
, returntype
);
205 t_struct
* xs
= (*f_iter
)->get_xceptions();
206 const std::vector
<t_field
*>& xceptions
= xs
->get_members();
207 vector
<t_field
*>::const_iterator x_iter
;
208 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
209 all_xceptions
[(*x_iter
)->get_name()] = (t_struct
*)((*x_iter
)->get_type());
213 map
<string
, t_struct
*>::iterator ax_iter
;
214 for (ax_iter
= all_xceptions
.begin(); ax_iter
!= all_xceptions
.end(); ++ax_iter
) {
215 generate_element(f_xsd_
, ax_iter
->first
, ax_iter
->second
);
218 // Close the XSD document
219 f_xsd_
<< endl
<< "</xsd:schema>" << endl
;
223 string
t_xsd_generator::type_name(t_type
* ttype
) {
224 if (ttype
->is_typedef()) {
225 return ttype
->get_name();
228 if (ttype
->is_base_type()) {
229 return xsd(base_type_name(((t_base_type
*)ttype
)->get_base()));
232 if (ttype
->is_enum()) {
236 if (ttype
->is_struct() || ttype
->is_xception()) {
237 return ttype
->get_name();
244 * Returns the XSD type that corresponds to the thrift type.
246 * @param tbase The base type
247 * @return Explicit XSD type, i.e. xsd:string
249 string
t_xsd_generator::base_type_name(t_base_type::t_base tbase
) {
251 case t_base_type::TYPE_VOID
:
253 case t_base_type::TYPE_STRING
:
255 case t_base_type::TYPE_BOOL
:
257 case t_base_type::TYPE_BYTE
:
259 case t_base_type::TYPE_I16
:
261 case t_base_type::TYPE_I32
:
263 case t_base_type::TYPE_I64
:
265 case t_base_type::TYPE_DOUBLE
:
268 throw "compiler error: no C++ base type name for base type " + t_base_type::t_base_name(tbase
);