Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
30 ashish 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
 
20
#include <fstream>
21
#include <iostream>
22
#include <sstream>
23
 
24
#include <stdlib.h>
25
#include <sys/stat.h>
26
#include <sstream>
27
#include "t_generator.h"
28
#include "platform.h"
29
using namespace std;
30
 
31
 
32
/**
33
 * XSD generator, creates an XSD for the base types etc.
34
 *
35
 */
36
class t_xsd_generator : public t_generator {
37
 public:
38
  t_xsd_generator(
39
      t_program* program,
40
      const std::map<std::string, std::string>& parsed_options,
41
      const std::string& option_string)
42
    : t_generator(program)
43
  {
44
    out_dir_base_ = "gen-xsd";
45
  }
46
 
47
  virtual ~t_xsd_generator() {}
48
 
49
  /**
50
   * Init and close methods
51
   */
52
 
53
  void init_generator();
54
  void close_generator();
55
 
56
  /**
57
   * Program-level generation functions
58
   */
59
 
60
  void generate_typedef(t_typedef* ttypedef);
61
  void generate_enum(t_enum* tenum) {}
62
 
63
  void generate_service(t_service* tservice);
64
  void generate_struct(t_struct* tstruct);
65
 
66
 private:
67
 
68
  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);
69
 
70
  std::string ns(std::string in, std::string ns) {
71
    return ns + ":" + in;
72
  }
73
 
74
  std::string xsd(std::string in) {
75
    return ns(in, "xsd");
76
  }
77
 
78
  std::string type_name(t_type* ttype);
79
  std::string base_type_name(t_base_type::t_base tbase);
80
 
81
  /**
82
   * Output xsd/php file
83
   */
84
  std::ofstream f_xsd_;
85
  std::ofstream f_php_;
86
 
87
  /**
88
   * Output string stream
89
   */
90
  std::ostringstream s_xsd_types_;
91
 
92
};
93
 
94
 
95
void t_xsd_generator::init_generator() {
96
  // Make output directory
97
  MKDIR(get_out_dir().c_str());
98
 
99
  // Make output file
100
  string f_php_name = get_out_dir()+program_->get_name()+"_xsd.php";
101
  f_php_.open(f_php_name.c_str());
102
 
103
  f_php_ <<
104
    "<?php" << endl;
105
 
106
}
107
 
108
void t_xsd_generator::close_generator() {
109
  f_php_ << "?>" << endl;
110
  f_php_.close();
111
}
112
 
113
void t_xsd_generator::generate_typedef(t_typedef* ttypedef) {
114
  indent(s_xsd_types_) <<
115
    "<xsd:simpleType name=\"" << ttypedef->get_name() << "\">" << endl;
116
  indent_up();
117
  if (ttypedef->get_type()->is_string() && ((t_base_type*)ttypedef->get_type())->is_string_enum()) {
118
    indent(s_xsd_types_) <<
119
      "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\">" << endl;
120
    indent_up();
121
    const vector<string>& values = ((t_base_type*)ttypedef->get_type())->get_string_enum_vals();
122
    vector<string>::const_iterator v_iter;
123
    for (v_iter = values.begin(); v_iter != values.end(); ++v_iter) {
124
      indent(s_xsd_types_) <<
125
        "<xsd:enumeration value=\"" << (*v_iter) << "\" />" << endl;
126
    }
127
    indent_down();
128
    indent(s_xsd_types_) <<
129
      "</xsd:restriction>" << endl;
130
  } else {
131
    indent(s_xsd_types_) <<
132
      "<xsd:restriction base=\"" << type_name(ttypedef->get_type()) << "\" />" << endl;
133
  }
134
  indent_down();
135
  indent(s_xsd_types_) <<
136
    "</xsd:simpleType>" << endl << endl;
137
}
138
 
139
void t_xsd_generator::generate_struct(t_struct* tstruct) {
140
  vector<t_field*>::const_iterator m_iter;
141
  const vector<t_field*>& members = tstruct->get_members();
142
  bool xsd_all = tstruct->get_xsd_all();
143
 
144
  indent(s_xsd_types_) << "<xsd:complexType name=\"" << tstruct->get_name() << "\">" << endl;
145
  indent_up();
146
  if (xsd_all) {
147
    indent(s_xsd_types_) << "<xsd:all>" << endl;
148
  } else {
149
    indent(s_xsd_types_) << "<xsd:sequence>" << endl;
150
  }
151
  indent_up();
152
 
153
  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
154
    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());
155
  }
156
 
157
  indent_down();
158
  if (xsd_all) {
159
    indent(s_xsd_types_) << "</xsd:all>" << endl;
160
  } else {
161
    indent(s_xsd_types_) << "</xsd:sequence>" << endl;
162
  }
163
  indent_down();
164
  indent(s_xsd_types_) <<
165
    "</xsd:complexType>" << endl <<
166
    endl;
167
}
168
 
169
void t_xsd_generator::generate_element(ostream& out,
170
                                       string name,
171
                                       t_type* ttype,
172
                                       t_struct* attrs,
173
                                       bool optional,
174
                                       bool nillable,
175
                                       bool list_element) {
176
  string sminOccurs = (optional || list_element) ? " minOccurs=\"0\"" : "";
177
  string smaxOccurs = list_element ? " maxOccurs=\"unbounded\"" : "";
178
  string soptional = sminOccurs + smaxOccurs;
179
  string snillable = nillable ? " nillable=\"true\"" : "";
180
 
181
  if (ttype->is_void() || ttype->is_list()) {
182
    indent(out) <<
183
      "<xsd:element name=\"" << name << "\"" << soptional << snillable << ">" << endl;
184
    indent_up();
185
    if (attrs == NULL && ttype->is_void()) {
186
      indent(out) <<
187
        "<xsd:complexType />" << endl;
188
    } else {
189
      indent(out) <<
190
        "<xsd:complexType>" << endl;
191
      indent_up();
192
      if (ttype->is_list()) {
193
        indent(out) << "<xsd:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">" << endl;
194
        indent_up();
195
        string subname;
196
        t_type* subtype = ((t_list*)ttype)->get_elem_type();
197
        if (subtype->is_base_type() || subtype->is_container()) {
198
          subname = name + "_elt";
199
        } else {
200
          subname = type_name(subtype);
201
        }
202
        f_php_ << "$GLOBALS['" << program_->get_name() << "_xsd_elt_" << name << "'] = '" << subname << "';" << endl;
203
        generate_element(out, subname, subtype, NULL, false, false, true);
204
        indent_down();
205
        indent(out) << "</xsd:sequence>" << endl;
206
        indent(out) << "<xsd:attribute name=\"list\" type=\"xsd:boolean\" />" << endl;
207
      }
208
      if (attrs != NULL) {
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
      }
215
      indent_down();
216
      indent(out) <<
217
        "</xsd:complexType>" << endl;
218
    }
219
    indent_down();
220
    indent(out) <<
221
      "</xsd:element>" << endl;
222
  } else {
223
    if (attrs == NULL) {
224
      indent(out) <<
225
        "<xsd:element name=\"" << name << "\"" << " type=\"" << type_name(ttype) << "\"" << soptional << snillable << " />" << endl;
226
    } else {
227
      // Wow, all this work for a SIMPLE TYPE with attributes?!?!?!
228
      indent(out) << "<xsd:element name=\"" << name << "\"" << soptional << snillable << ">" << endl;
229
      indent_up();
230
      indent(out) << "<xsd:complexType>" << endl;
231
      indent_up();
232
      indent(out) << "<xsd:complexContent>" << endl;
233
      indent_up();
234
      indent(out) << "<xsd:extension base=\"" << type_name(ttype) << "\">" << endl;
235
      indent_up();
236
      const vector<t_field*>& members = attrs->get_members();
237
      vector<t_field*>::const_iterator a_iter;
238
      for (a_iter = members.begin(); a_iter != members.end(); ++a_iter) {
239
        indent(out) << "<xsd:attribute name=\"" << (*a_iter)->get_name() << "\" type=\"" << type_name((*a_iter)->get_type()) << "\" />" << endl;
240
      }
241
      indent_down();
242
      indent(out) << "</xsd:extension>" << endl;
243
      indent_down();
244
      indent(out) << "</xsd:complexContent>" << endl;
245
      indent_down();
246
      indent(out) << "</xsd:complexType>" << endl;
247
      indent_down();
248
      indent(out) << "</xsd:element>" << endl;
249
    }
250
  }
251
}
252
 
253
void t_xsd_generator::generate_service(t_service* tservice) {
254
  // Make output file
255
  string f_xsd_name = get_out_dir()+tservice->get_name()+".xsd";
256
  f_xsd_.open(f_xsd_name.c_str());
257
 
258
  string ns = program_->get_namespace("xsd");
259
  if (ns.size() > 0) {
260
    ns = " targetNamespace=\"" + ns + "\" xmlns=\"" + ns + "\" " +
261
      "elementFormDefault=\"qualified\"";
262
  }
263
 
264
  // Print the XSD header
265
  f_xsd_ <<
266
    "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" << endl <<
267
    "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" << ns << ">" << endl <<
268
    endl <<
269
    "<!-- Yo yo yo, this XSD woz be generated by Thrift. -->" << endl <<
270
    endl;
271
 
272
  // Print out the type definitions
273
  indent(f_xsd_) << s_xsd_types_.str();
274
 
275
  // Keep a list of all the possible exceptions that might get thrown
276
  map<string, t_struct*> all_xceptions;
277
 
278
  // List the elements that you might actually get
279
  vector<t_function*> functions = tservice->get_functions();
280
  vector<t_function*>::iterator f_iter;
281
  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
282
    string elemname = (*f_iter)->get_name() + "_response";
283
    t_type* returntype = (*f_iter)->get_returntype();
284
    generate_element(f_xsd_, elemname, returntype);
285
    f_xsd_ << endl;
286
 
287
    t_struct* xs = (*f_iter)->get_xceptions();
288
    const std::vector<t_field*>& xceptions = xs->get_members();
289
    vector<t_field*>::const_iterator x_iter;
290
    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
291
      all_xceptions[(*x_iter)->get_name()] = (t_struct*)((*x_iter)->get_type());
292
    }
293
  }
294
 
295
  map<string, t_struct*>::iterator ax_iter;
296
  for (ax_iter = all_xceptions.begin(); ax_iter != all_xceptions.end(); ++ax_iter) {
297
    generate_element(f_xsd_, ax_iter->first, ax_iter->second);
298
  }
299
 
300
  // Close the XSD document
301
  f_xsd_ << endl << "</xsd:schema>" << endl;
302
  f_xsd_.close();
303
}
304
 
305
string t_xsd_generator::type_name(t_type* ttype) {
306
  if (ttype->is_typedef()) {
307
    return ttype->get_name();
308
  }
309
 
310
  if (ttype->is_base_type()) {
311
    return xsd(base_type_name(((t_base_type*)ttype)->get_base()));
312
  }
313
 
314
  if (ttype->is_enum()) {
315
    return xsd("int");
316
  }
317
 
318
  if (ttype->is_struct() || ttype->is_xception()) {
319
    return ttype->get_name();
320
  }
321
 
322
  return "container";
323
}
324
 
325
/**
326
 * Returns the XSD type that corresponds to the thrift type.
327
 *
328
 * @param tbase The base type
329
 * @return Explicit XSD type, i.e. xsd:string
330
 */
331
string t_xsd_generator::base_type_name(t_base_type::t_base tbase) {
332
  switch (tbase) {
333
  case t_base_type::TYPE_VOID:
334
    return "void";
335
  case t_base_type::TYPE_STRING:
336
    return "string";
337
  case t_base_type::TYPE_BOOL:
338
    return "boolean";
339
  case t_base_type::TYPE_BYTE:
340
    return "byte";
341
  case t_base_type::TYPE_I16:
342
    return "short";
343
  case t_base_type::TYPE_I32:
344
    return "int";
345
  case t_base_type::TYPE_I64:
346
    return "long";
347
  case t_base_type::TYPE_DOUBLE:
348
    return "decimal";
349
  default:
350
    throw "compiler error: no C++ base type name for base type " + t_base_type::t_base_name(tbase);
351
  }
352
}
353
 
354
THRIFT_REGISTER_GENERATOR(xsd, "XSD", "");