PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/thrift-0.8.0/compiler/cpp/src/generate/t_xsd_generator.cc

https://gitlab.com/sudarsunkannan/mapkeeper
C++ | 359 lines | 262 code | 48 blank | 49 comment | 46 complexity | d4dc4a71a49abc7b965f60c9d3ddf84c MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. #include <fstream>
  20. #include <iostream>
  21. #include <sstream>
  22. #include <stdlib.h>
  23. #include <sys/stat.h>
  24. #include <sstream>
  25. #include "t_generator.h"
  26. #include "platform.h"
  27. using namespace std;
  28. /**
  29. * XSD generator, creates an XSD for the base types etc.
  30. *
  31. */
  32. class t_xsd_generator : public t_generator {
  33. public:
  34. t_xsd_generator(
  35. t_program* program,
  36. const std::map<std::string, std::string>& parsed_options,
  37. const std::string& option_string)
  38. : t_generator(program)
  39. {
  40. (void) parsed_options;
  41. (void) option_string;
  42. out_dir_base_ = "gen-xsd";
  43. }
  44. virtual ~t_xsd_generator() {}
  45. /**
  46. * Init and close methods
  47. */
  48. void init_generator();
  49. void close_generator();
  50. /**
  51. * Program-level generation functions
  52. */
  53. void generate_typedef(t_typedef* ttypedef);
  54. void generate_enum(t_enum* tenum) {
  55. (void) tenum;
  56. }
  57. void generate_service(t_service* tservice);
  58. void generate_struct(t_struct* tstruct);
  59. private:
  60. void generate_element(std::ostream& out, std::string name, t_type* ttype, t_struct* attrs=NULL, bool optional=false, bool nillable=false, bool list_element=false);
  61. std::string ns(std::string in, std::string ns) {
  62. return ns + ":" + in;
  63. }
  64. std::string xsd(std::string in) {
  65. return ns(in, "xsd");
  66. }
  67. std::string type_name(t_type* ttype);
  68. std::string base_type_name(t_base_type::t_base tbase);
  69. /**
  70. * Output xsd/php file
  71. */
  72. std::ofstream f_xsd_;
  73. std::ofstream f_php_;
  74. /**
  75. * Output string stream
  76. */
  77. std::ostringstream s_xsd_types_;
  78. };
  79. void t_xsd_generator::init_generator() {
  80. // Make output directory
  81. MKDIR(get_out_dir().c_str());
  82. // Make output file
  83. string f_php_name = get_out_dir()+program_->get_name()+"_xsd.php";
  84. f_php_.open(f_php_name.c_str());
  85. f_php_ <<
  86. "<?php" << endl;
  87. }
  88. void t_xsd_generator::close_generator() {
  89. f_php_ << "?>" << endl;
  90. f_php_.close();
  91. }
  92. void t_xsd_generator::generate_typedef(t_typedef* ttypedef) {
  93. indent(s_xsd_types_) <<
  94. "<xsd:simpleType name=\"" << ttypedef->get_name() << "\">" << endl;
  95. indent_up();
  96. if (ttypedef->get_type()->is_string() && ((t_base_type*)ttypedef->get_type())->is_string_enum()) {
  97. indent(s_xsd_types_) <<
  98. "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\">" << endl;
  99. indent_up();
  100. const vector<string>& values = ((t_base_type*)ttypedef->get_type())->get_string_enum_vals();
  101. vector<string>::const_iterator v_iter;
  102. for (v_iter = values.begin(); v_iter != values.end(); ++v_iter) {
  103. indent(s_xsd_types_) <<
  104. "<xsd:enumeration value=\"" << (*v_iter) << "\" />" << endl;
  105. }
  106. indent_down();
  107. indent(s_xsd_types_) <<
  108. "</xsd:restriction>" << endl;
  109. } else {
  110. indent(s_xsd_types_) <<
  111. "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\" />" << endl;
  112. }
  113. indent_down();
  114. indent(s_xsd_types_) <<
  115. "</xsd:simpleType>" << endl << endl;
  116. }
  117. void t_xsd_generator::generate_struct(t_struct* tstruct) {
  118. vector<t_field*>::const_iterator m_iter;
  119. const vector<t_field*>& members = tstruct->get_members();
  120. bool xsd_all = tstruct->get_xsd_all();
  121. indent(s_xsd_types_) << "<xsd:complexType name=\"" << tstruct->get_name() << "\">" << endl;
  122. indent_up();
  123. if (xsd_all) {
  124. indent(s_xsd_types_) << "<xsd:all>" << endl;
  125. } else {
  126. indent(s_xsd_types_) << "<xsd:sequence>" << endl;
  127. }
  128. indent_up();
  129. for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
  130. 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());
  131. }
  132. indent_down();
  133. if (xsd_all) {
  134. indent(s_xsd_types_) << "</xsd:all>" << endl;
  135. } else {
  136. indent(s_xsd_types_) << "</xsd:sequence>" << endl;
  137. }
  138. indent_down();
  139. indent(s_xsd_types_) <<
  140. "</xsd:complexType>" << endl <<
  141. endl;
  142. }
  143. void t_xsd_generator::generate_element(ostream& out,
  144. string name,
  145. t_type* ttype,
  146. t_struct* attrs,
  147. bool optional,
  148. bool nillable,
  149. bool list_element) {
  150. string sminOccurs = (optional || list_element) ? " minOccurs=\"0\"" : "";
  151. string smaxOccurs = list_element ? " maxOccurs=\"unbounded\"" : "";
  152. string soptional = sminOccurs + smaxOccurs;
  153. string snillable = nillable ? " nillable=\"true\"" : "";
  154. if (ttype->is_void() || ttype->is_list()) {
  155. indent(out) <<
  156. "<xsd:element name=\"" << name << "\"" << soptional << snillable << ">" << endl;
  157. indent_up();
  158. if (attrs == NULL && ttype->is_void()) {
  159. indent(out) <<
  160. "<xsd:complexType />" << endl;
  161. } else {
  162. indent(out) <<
  163. "<xsd:complexType>" << endl;
  164. indent_up();
  165. if (ttype->is_list()) {
  166. indent(out) << "<xsd:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">" << endl;
  167. indent_up();
  168. string subname;
  169. t_type* subtype = ((t_list*)ttype)->get_elem_type();
  170. if (subtype->is_base_type() || subtype->is_container()) {
  171. subname = name + "_elt";
  172. } else {
  173. subname = type_name(subtype);
  174. }
  175. f_php_ << "$GLOBALS['" << program_->get_name() << "_xsd_elt_" << name << "'] = '" << subname << "';" << endl;
  176. generate_element(out, subname, subtype, NULL, false, false, true);
  177. indent_down();
  178. indent(out) << "</xsd:sequence>" << endl;
  179. indent(out) << "<xsd:attribute name=\"list\" type=\"xsd:boolean\" />" << endl;
  180. }
  181. if (attrs != NULL) {
  182. const vector<t_field*>& members = attrs->get_members();
  183. vector<t_field*>::const_iterator a_iter;
  184. for (a_iter = members.begin(); a_iter != members.end(); ++a_iter) {
  185. indent(out) << "<xsd:attribute name=\"" << (*a_iter)->get_name() << "\" type=\"" << type_name((*a_iter)->get_type()) << "\" />" << endl;
  186. }
  187. }
  188. indent_down();
  189. indent(out) <<
  190. "</xsd:complexType>" << endl;
  191. }
  192. indent_down();
  193. indent(out) <<
  194. "</xsd:element>" << endl;
  195. } else {
  196. if (attrs == NULL) {
  197. indent(out) <<
  198. "<xsd:element name=\"" << name << "\"" << " type=\"" << type_name(ttype) << "\"" << soptional << snillable << " />" << endl;
  199. } else {
  200. // Wow, all this work for a SIMPLE TYPE with attributes?!?!?!
  201. indent(out) << "<xsd:element name=\"" << name << "\"" << soptional << snillable << ">" << endl;
  202. indent_up();
  203. indent(out) << "<xsd:complexType>" << endl;
  204. indent_up();
  205. indent(out) << "<xsd:complexContent>" << endl;
  206. indent_up();
  207. indent(out) << "<xsd:extension base=\"" << type_name(ttype) << "\">" << endl;
  208. indent_up();
  209. const vector<t_field*>& members = attrs->get_members();
  210. vector<t_field*>::const_iterator a_iter;
  211. for (a_iter = members.begin(); a_iter != members.end(); ++a_iter) {
  212. indent(out) << "<xsd:attribute name=\"" << (*a_iter)->get_name() << "\" type=\"" << type_name((*a_iter)->get_type()) << "\" />" << endl;
  213. }
  214. indent_down();
  215. indent(out) << "</xsd:extension>" << endl;
  216. indent_down();
  217. indent(out) << "</xsd:complexContent>" << endl;
  218. indent_down();
  219. indent(out) << "</xsd:complexType>" << endl;
  220. indent_down();
  221. indent(out) << "</xsd:element>" << endl;
  222. }
  223. }
  224. }
  225. void t_xsd_generator::generate_service(t_service* tservice) {
  226. // Make output file
  227. string f_xsd_name = get_out_dir()+tservice->get_name()+".xsd";
  228. f_xsd_.open(f_xsd_name.c_str());
  229. string ns = program_->get_namespace("xsd");
  230. if (ns.size() > 0) {
  231. ns = " targetNamespace=\"" + ns + "\" xmlns=\"" + ns + "\" " +
  232. "elementFormDefault=\"qualified\"";
  233. }
  234. // Print the XSD header
  235. f_xsd_ <<
  236. "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" << endl <<
  237. "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" << ns << ">" << endl <<
  238. endl <<
  239. "<!-- Yo yo yo, this XSD woz be generated by Thrift. -->" << endl <<
  240. endl;
  241. // Print out the type definitions
  242. indent(f_xsd_) << s_xsd_types_.str();
  243. // Keep a list of all the possible exceptions that might get thrown
  244. map<string, t_struct*> all_xceptions;
  245. // List the elements that you might actually get
  246. vector<t_function*> functions = tservice->get_functions();
  247. vector<t_function*>::iterator f_iter;
  248. for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
  249. string elemname = (*f_iter)->get_name() + "_response";
  250. t_type* returntype = (*f_iter)->get_returntype();
  251. generate_element(f_xsd_, elemname, returntype);
  252. f_xsd_ << endl;
  253. t_struct* xs = (*f_iter)->get_xceptions();
  254. const std::vector<t_field*>& xceptions = xs->get_members();
  255. vector<t_field*>::const_iterator x_iter;
  256. for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
  257. all_xceptions[(*x_iter)->get_name()] = (t_struct*)((*x_iter)->get_type());
  258. }
  259. }
  260. map<string, t_struct*>::iterator ax_iter;
  261. for (ax_iter = all_xceptions.begin(); ax_iter != all_xceptions.end(); ++ax_iter) {
  262. generate_element(f_xsd_, ax_iter->first, ax_iter->second);
  263. }
  264. // Close the XSD document
  265. f_xsd_ << endl << "</xsd:schema>" << endl;
  266. f_xsd_.close();
  267. }
  268. string t_xsd_generator::type_name(t_type* ttype) {
  269. if (ttype->is_typedef()) {
  270. return ttype->get_name();
  271. }
  272. if (ttype->is_base_type()) {
  273. return xsd(base_type_name(((t_base_type*)ttype)->get_base()));
  274. }
  275. if (ttype->is_enum()) {
  276. return xsd("int");
  277. }
  278. if (ttype->is_struct() || ttype->is_xception()) {
  279. return ttype->get_name();
  280. }
  281. return "container";
  282. }
  283. /**
  284. * Returns the XSD type that corresponds to the thrift type.
  285. *
  286. * @param tbase The base type
  287. * @return Explicit XSD type, i.e. xsd:string
  288. */
  289. string t_xsd_generator::base_type_name(t_base_type::t_base tbase) {
  290. switch (tbase) {
  291. case t_base_type::TYPE_VOID:
  292. return "void";
  293. case t_base_type::TYPE_STRING:
  294. return "string";
  295. case t_base_type::TYPE_BOOL:
  296. return "boolean";
  297. case t_base_type::TYPE_BYTE:
  298. return "byte";
  299. case t_base_type::TYPE_I16:
  300. return "short";
  301. case t_base_type::TYPE_I32:
  302. return "int";
  303. case t_base_type::TYPE_I64:
  304. return "long";
  305. case t_base_type::TYPE_DOUBLE:
  306. return "decimal";
  307. default:
  308. throw "compiler error: no C++ base type name for base type " + t_base_type::t_base_name(tbase);
  309. }
  310. }
  311. THRIFT_REGISTER_GENERATOR(xsd, "XSD", "")