blob: 9ddc752990fafcde55c93d16ba287005995ac534 [file] [log] [blame]
Mark Sleee9ce01c2007-05-16 02:29:53 +00001// Copyright (c) 2006- Facebook
2// Distributed under the Thrift Software License
3//
4// See accompanying file LICENSE or visit the Thrift site at:
5// http://developers.facebook.com/thrift/
6
Mark Sleeb15a68b2006-06-07 06:46:24 +00007#include <sstream>
David Reissdc61be92008-02-27 01:55:09 +00008#include <string>
9#include <fstream>
10#include <iostream>
11#include <vector>
12
13#include <sys/stat.h>
14
David Reiss204420f2008-01-11 20:59:03 +000015#include "platform.h"
David Reissdc61be92008-02-27 01:55:09 +000016#include "t_oop_generator.h"
Mark Sleeb15a68b2006-06-07 06:46:24 +000017using namespace std;
18
David Reissdc61be92008-02-27 01:55:09 +000019
20
21/**
22 * Java code generator.
23 *
24 * @author Mark Slee <mcslee@facebook.com>
25 */
26class t_java_generator : public t_oop_generator {
27 public:
28 t_java_generator(
29 t_program* program,
30 const std::map<std::string, std::string>& parsed_options,
31 const std::string& option_string)
32 : t_oop_generator(program)
33 {
34 std::map<std::string, std::string>::const_iterator iter;
35
36 iter = parsed_options.find("beans");
37 bean_style_ = (iter != parsed_options.end());
38
David Reiss14feb412008-03-02 06:29:23 +000039 iter = parsed_options.find("hashcode");
40 gen_hash_code_ = (iter != parsed_options.end());
41
David Reissdc61be92008-02-27 01:55:09 +000042 out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java");
43 }
44
45
46 /**
47 * Init and close methods
48 */
49
50 void init_generator();
51 void close_generator();
52
53 void generate_consts(std::vector<t_const*> consts);
54
55 /**
56 * Program-level generation functions
57 */
58
59 void generate_typedef (t_typedef* ttypedef);
60 void generate_enum (t_enum* tenum);
61 void generate_struct (t_struct* tstruct);
62 void generate_xception(t_struct* txception);
63 void generate_service (t_service* tservice);
64
65 void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value, bool in_static, bool defval=false);
66 std::string render_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value);
67
68 /**
69 * Service-level generation functions
70 */
71
72 void generate_java_struct(t_struct* tstruct, bool is_exception);
73
74 void generate_java_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception=false, bool in_class=false, bool is_result=false);
David Reiss3b15ebc2008-03-02 06:29:19 +000075 void generate_java_struct_equality(std::ofstream& out, t_struct* tstruct);
David Reissdc61be92008-02-27 01:55:09 +000076 void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
77 void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
78 void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
79 void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct);
80 void generate_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
81
82 void generate_function_helpers(t_function* tfunction);
83
84 void generate_service_interface (t_service* tservice);
85 void generate_service_helpers (t_service* tservice);
86 void generate_service_client (t_service* tservice);
87 void generate_service_server (t_service* tservice);
88 void generate_process_function (t_service* tservice, t_function* tfunction);
89
90 /**
91 * Serialization constructs
92 */
93
94 void generate_deserialize_field (std::ofstream& out,
95 t_field* tfield,
96 std::string prefix="");
97
98 void generate_deserialize_struct (std::ofstream& out,
99 t_struct* tstruct,
100 std::string prefix="");
101
102 void generate_deserialize_container (std::ofstream& out,
103 t_type* ttype,
104 std::string prefix="");
105
106 void generate_deserialize_set_element (std::ofstream& out,
107 t_set* tset,
108 std::string prefix="");
109
110 void generate_deserialize_map_element (std::ofstream& out,
111 t_map* tmap,
112 std::string prefix="");
113
114 void generate_deserialize_list_element (std::ofstream& out,
115 t_list* tlist,
116 std::string prefix="");
117
118 void generate_serialize_field (std::ofstream& out,
119 t_field* tfield,
120 std::string prefix="");
121
122 void generate_serialize_struct (std::ofstream& out,
123 t_struct* tstruct,
124 std::string prefix="");
125
126 void generate_serialize_container (std::ofstream& out,
127 t_type* ttype,
128 std::string prefix="");
129
130 void generate_serialize_map_element (std::ofstream& out,
131 t_map* tmap,
132 std::string iter,
133 std::string map);
134
135 void generate_serialize_set_element (std::ofstream& out,
136 t_set* tmap,
137 std::string iter);
138
139 void generate_serialize_list_element (std::ofstream& out,
140 t_list* tlist,
141 std::string iter);
142
143 void generate_java_doc (std::ofstream& out,
144 t_doc* tdoc);
145
146
147 /**
148 * Helper rendering functions
149 */
150
151 std::string java_package();
152 std::string java_type_imports();
153 std::string java_thrift_imports();
154 std::string type_name(t_type* ttype, bool in_container=false, bool in_init=false);
155 std::string base_type_name(t_base_type* tbase, bool in_container=false);
156 std::string declare_field(t_field* tfield, bool init=false);
157 std::string function_signature(t_function* tfunction, std::string prefix="");
158 std::string argument_list(t_struct* tstruct);
159 std::string type_to_enum(t_type* ttype);
160
161 bool type_can_be_null(t_type* ttype) {
162 ttype = get_true_type(ttype);
163
164 return
165 ttype->is_container() ||
166 ttype->is_struct() ||
167 ttype->is_xception() ||
168 ttype->is_string();
169 }
170
171
172 private:
173
174 /**
175 * File streams
176 */
177
178 std::string package_name_;
179 std::ofstream f_service_;
180 std::string package_dir_;
181
182 bool bean_style_;
David Reiss14feb412008-03-02 06:29:23 +0000183 bool gen_hash_code_;
David Reissdc61be92008-02-27 01:55:09 +0000184
185};
186
187
Mark Sleeb15a68b2006-06-07 06:46:24 +0000188/**
189 * Prepares for file generation by opening up the necessary file output
190 * streams.
191 *
192 * @param tprogram The program to generate
193 */
Mark Sleef0712dc2006-10-25 19:03:57 +0000194void t_java_generator::init_generator() {
Mark Sleeb15a68b2006-06-07 06:46:24 +0000195 // Make output directory
David Reiss204420f2008-01-11 20:59:03 +0000196 MKDIR(get_out_dir().c_str());
David Reiss771f8c72008-02-27 01:55:25 +0000197 package_name_ = program_->get_namespace("java");
Mark Slee98e962b2007-02-20 18:44:05 +0000198
199 string dir = package_name_;
dweatherford65b70752007-10-31 02:18:14 +0000200 string subdir = get_out_dir();
Mark Slee98e962b2007-02-20 18:44:05 +0000201 string::size_type loc;
202 while ((loc = dir.find(".")) != string::npos) {
203 subdir = subdir + "/" + dir.substr(0, loc);
David Reiss204420f2008-01-11 20:59:03 +0000204 MKDIR(subdir.c_str());
Mark Slee98e962b2007-02-20 18:44:05 +0000205 dir = dir.substr(loc+1);
206 }
207 if (dir.size() > 0) {
208 subdir = subdir + "/" + dir;
David Reiss204420f2008-01-11 20:59:03 +0000209 MKDIR(subdir.c_str());
Mark Slee98e962b2007-02-20 18:44:05 +0000210 }
211
212 package_dir_ = subdir;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000213}
214
215/**
216 * Packages the generated file
Mark Sleef5377b32006-10-10 01:42:59 +0000217 *
218 * @return String of the package, i.e. "package com.facebook.thriftdemo;"
Mark Sleeb15a68b2006-06-07 06:46:24 +0000219 */
220string t_java_generator::java_package() {
Mark Sleef0712dc2006-10-25 19:03:57 +0000221 if (!package_name_.empty()) {
222 return string("package ") + package_name_ + ";\n\n";
223 }
224 return "";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000225}
226
227/**
228 * Prints standard java imports
Mark Sleef5377b32006-10-10 01:42:59 +0000229 *
230 * @return List of imports for Java types that are used in here
Mark Sleeb15a68b2006-06-07 06:46:24 +0000231 */
232string t_java_generator::java_type_imports() {
David Reiss14feb412008-03-02 06:29:23 +0000233 string hash_builder;
234 if (gen_hash_code_) {
235 hash_builder = "import org.apache.commons.lang.builder.HashCodeBuilder;\n";
236 }
237
Mark Sleeb15a68b2006-06-07 06:46:24 +0000238 return
239 string() +
Mark Slee22360b22008-02-09 00:18:32 +0000240 "import java.util.List;\n" +
Mark Sleeb15a68b2006-06-07 06:46:24 +0000241 "import java.util.ArrayList;\n" +
Mark Slee22360b22008-02-09 00:18:32 +0000242 "import java.util.Map;\n" +
Mark Sleeb15a68b2006-06-07 06:46:24 +0000243 "import java.util.HashMap;\n" +
Mark Slee22360b22008-02-09 00:18:32 +0000244 "import java.util.Set;\n" +
Mark Sleeb15a68b2006-06-07 06:46:24 +0000245 "import java.util.HashSet;\n" +
David Reiss14feb412008-03-02 06:29:23 +0000246 hash_builder +
Mark Slee78f58e22006-09-02 04:17:07 +0000247 "import com.facebook.thrift.*;\n\n";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000248}
249
250/**
251 * Prints standard java imports
Mark Sleef5377b32006-10-10 01:42:59 +0000252 *
253 * @return List of imports necessary for thrift
Mark Sleeb15a68b2006-06-07 06:46:24 +0000254 */
255string t_java_generator::java_thrift_imports() {
256 return
257 string() +
258 "import com.facebook.thrift.protocol.*;\n" +
259 "import com.facebook.thrift.transport.*;\n\n";
260}
261
262/**
Mark Sleef5377b32006-10-10 01:42:59 +0000263 * Nothing in Java
Mark Sleeb15a68b2006-06-07 06:46:24 +0000264 */
Mark Sleef0712dc2006-10-25 19:03:57 +0000265void t_java_generator::close_generator() {}
Mark Sleeb15a68b2006-06-07 06:46:24 +0000266
267/**
Mark Sleef5377b32006-10-10 01:42:59 +0000268 * Generates a typedef. This is not done in Java, since it does
269 * not support arbitrary name replacements, and it'd be a wacky waste
270 * of overhead to make wrapper classes.
Mark Sleeb15a68b2006-06-07 06:46:24 +0000271 *
272 * @param ttypedef The type definition
273 */
274void t_java_generator::generate_typedef(t_typedef* ttypedef) {}
275
276/**
Mark Slee5ab57052007-11-27 08:38:16 +0000277 * Enums are a class with a set of static constants.
Mark Sleeb15a68b2006-06-07 06:46:24 +0000278 *
279 * @param tenum The enumeration
280 */
281void t_java_generator::generate_enum(t_enum* tenum) {
282 // Make output file
Mark Slee98e962b2007-02-20 18:44:05 +0000283 string f_enum_name = package_dir_+"/"+(tenum->get_name())+".java";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000284 ofstream f_enum;
285 f_enum.open(f_enum_name.c_str());
286
Mark Sleef5377b32006-10-10 01:42:59 +0000287 // Comment and package it
Mark Sleeb15a68b2006-06-07 06:46:24 +0000288 f_enum <<
289 autogen_comment() <<
Mark Slee52f643d2006-08-09 00:03:43 +0000290 java_package() << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000291
292 f_enum <<
293 "public class " << tenum->get_name() << " ";
294 scope_up(f_enum);
295
Mark Slee30152872006-11-28 01:24:07 +0000296 vector<t_enum_value*> constants = tenum->get_constants();
297 vector<t_enum_value*>::iterator c_iter;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000298 int value = -1;
299 for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
300 if ((*c_iter)->has_value()) {
301 value = (*c_iter)->get_value();
302 } else {
303 ++value;
304 }
305
306 indent(f_enum) <<
Mark Slee52f643d2006-08-09 00:03:43 +0000307 "public static final int " << (*c_iter)->get_name() <<
308 " = " << value << ";" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000309 }
310
311 scope_down(f_enum);
Mark Sleef5377b32006-10-10 01:42:59 +0000312 f_enum.close();
Mark Sleeb15a68b2006-06-07 06:46:24 +0000313}
314
315/**
Mark Sleeaa7671d2006-11-29 03:19:31 +0000316 * Generates a class that holds all the constants.
317 */
318void t_java_generator::generate_consts(std::vector<t_const*> consts) {
Mark Slee98e962b2007-02-20 18:44:05 +0000319 string f_consts_name = package_dir_+"/Constants.java";
Mark Sleeaa7671d2006-11-29 03:19:31 +0000320 ofstream f_consts;
321 f_consts.open(f_consts_name.c_str());
322
323 // Print header
324 f_consts <<
325 autogen_comment() <<
Mark Slee5ab57052007-11-27 08:38:16 +0000326 java_package() <<
Mark Sleeaa7671d2006-11-29 03:19:31 +0000327 java_type_imports();
328
329 f_consts <<
330 "public class Constants {" << endl <<
331 endl;
332 indent_up();
333 vector<t_const*>::iterator c_iter;
334 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
335 print_const_value(f_consts,
336 (*c_iter)->get_name(),
337 (*c_iter)->get_type(),
338 (*c_iter)->get_value(),
339 false);
340 }
341 indent_down();
342 indent(f_consts) <<
343 "}" << endl;
344 f_consts.close();
345}
346
347
348/**
349 * Prints the value of a constant with the given type. Note that type checking
350 * is NOT performed in this function as it is always run beforehand using the
351 * validate_types method in main.cc
352 */
Mark Slee7ff32452007-02-01 05:26:18 +0000353void t_java_generator::print_const_value(std::ofstream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval) {
354
355 indent(out);
356 if (!defval) {
357 out <<
358 (in_static ? "" : "public static final ") <<
359 type_name(type) << " ";
360 }
Mark Sleeaa7671d2006-11-29 03:19:31 +0000361 if (type->is_base_type()) {
362 string v2 = render_const_value(out, name, type, value);
Mark Slee7ff32452007-02-01 05:26:18 +0000363 out << name << " = " << v2 << ";" << endl << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000364 } else if (type->is_enum()) {
Mark Slee7ff32452007-02-01 05:26:18 +0000365 out << name << " = " << value->get_integer() << ";" << endl << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000366 } else if (type->is_struct() || type->is_xception()) {
367 const vector<t_field*>& fields = ((t_struct*)type)->get_members();
368 vector<t_field*>::const_iterator f_iter;
369 const map<t_const_value*, t_const_value*>& val = value->get_map();
370 map<t_const_value*, t_const_value*>::const_iterator v_iter;
Mark Sleedd43eb82008-02-13 22:03:15 +0000371 out << name << " = new " << type_name(type, false, true) << "();" << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000372 if (!in_static) {
373 indent(out) << "static {" << endl;
374 indent_up();
375 }
376 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
377 t_type* field_type = NULL;
378 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
379 if ((*f_iter)->get_name() == v_iter->first->get_string()) {
380 field_type = (*f_iter)->get_type();
381 }
382 }
383 if (field_type == NULL) {
384 throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
385 }
386 string val = render_const_value(out, name, field_type, v_iter->second);
387 indent(out) << name << "." << v_iter->first->get_string() << " = " << val << ";" << endl;
388 indent(out) << name << ".__isset." << v_iter->first->get_string() << " = true;" << endl;
389 }
390 if (!in_static) {
391 indent_down();
392 indent(out) << "}" << endl;
393 }
394 out << endl;
395 } else if (type->is_map()) {
Mark Sleedd43eb82008-02-13 22:03:15 +0000396 out << name << " = new " << type_name(type, false, true) << "();" << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000397 if (!in_static) {
398 indent(out) << "static {" << endl;
399 indent_up();
400 }
401 t_type* ktype = ((t_map*)type)->get_key_type();
402 t_type* vtype = ((t_map*)type)->get_val_type();
403 const map<t_const_value*, t_const_value*>& val = value->get_map();
404 map<t_const_value*, t_const_value*>::const_iterator v_iter;
405 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
406 string key = render_const_value(out, name, ktype, v_iter->first);
407 string val = render_const_value(out, name, vtype, v_iter->second);
408 indent(out) << name << ".put(" << key << ", " << val << ");" << endl;
409 }
410 if (!in_static) {
411 indent_down();
412 indent(out) << "}" << endl;
413 }
414 out << endl;
415 } else if (type->is_list() || type->is_set()) {
Mark Sleedd43eb82008-02-13 22:03:15 +0000416 out << name << " = new " << type_name(type, false, true) << "();" << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000417 if (!in_static) {
418 indent(out) << "static {" << endl;
419 indent_up();
420 }
421 t_type* etype;
422 if (type->is_list()) {
423 etype = ((t_list*)type)->get_elem_type();
424 } else {
425 etype = ((t_set*)type)->get_elem_type();
426 }
427 const vector<t_const_value*>& val = value->get_list();
428 vector<t_const_value*>::const_iterator v_iter;
429 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
430 string val = render_const_value(out, name, etype, *v_iter);
431 indent(out) << name << ".add(" << val << ");" << endl;
432 }
433 if (!in_static) {
434 indent_down();
435 indent(out) << "}" << endl;
436 }
437 out << endl;
438 }
439}
440
441string t_java_generator::render_const_value(ofstream& out, string name, t_type* type, t_const_value* value) {
442 std::ostringstream render;
443
444 if (type->is_base_type()) {
445 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
446 switch (tbase) {
447 case t_base_type::TYPE_STRING:
448 render << "\"" + value->get_string() + "\"";
449 break;
450 case t_base_type::TYPE_BOOL:
Mark Slee6632e0b2007-03-14 09:08:38 +0000451 render << ((value->get_integer() > 0) ? "true" : "false");
Mark Sleeaa7671d2006-11-29 03:19:31 +0000452 break;
453 case t_base_type::TYPE_BYTE:
454 case t_base_type::TYPE_I16:
455 case t_base_type::TYPE_I32:
456 case t_base_type::TYPE_I64:
457 render << value->get_integer();
458 break;
459 case t_base_type::TYPE_DOUBLE:
460 if (value->get_type() == t_const_value::CV_INTEGER) {
461 render << value->get_integer();
462 } else {
463 render << value->get_double();
464 }
465 break;
466 default:
David Reissdd7796f2007-08-28 21:09:06 +0000467 throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
Mark Sleeaa7671d2006-11-29 03:19:31 +0000468 }
469 } else if (type->is_enum()) {
470 render << value->get_integer();
471 } else {
472 string t = tmp("tmp");
473 print_const_value(out, t, type, value, true);
474 render << t;
475 }
476
477 return render.str();
478}
479
480/**
Mark Sleef5377b32006-10-10 01:42:59 +0000481 * Generates a struct definition for a thrift data type. This is a class
482 * with data members, read(), write(), and an inner Isset class.
Mark Sleeb15a68b2006-06-07 06:46:24 +0000483 *
484 * @param tstruct The struct definition
485 */
486void t_java_generator::generate_struct(t_struct* tstruct) {
Mark Slee78f58e22006-09-02 04:17:07 +0000487 generate_java_struct(tstruct, false);
488}
489
Mark Sleef5377b32006-10-10 01:42:59 +0000490/**
491 * Exceptions are structs, but they inherit from Exception
492 *
493 * @param tstruct The struct definition
494 */
Mark Slee78f58e22006-09-02 04:17:07 +0000495void t_java_generator::generate_xception(t_struct* txception) {
496 generate_java_struct(txception, true);
497}
498
Mark Sleef5377b32006-10-10 01:42:59 +0000499
500/**
501 * Java struct definition.
502 *
503 * @param tstruct The struct definition
504 */
Mark Slee78f58e22006-09-02 04:17:07 +0000505void t_java_generator::generate_java_struct(t_struct* tstruct,
506 bool is_exception) {
Mark Sleeb15a68b2006-06-07 06:46:24 +0000507 // Make output file
Mark Slee98e962b2007-02-20 18:44:05 +0000508 string f_struct_name = package_dir_+"/"+(tstruct->get_name())+".java";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000509 ofstream f_struct;
510 f_struct.open(f_struct_name.c_str());
511
512 f_struct <<
513 autogen_comment() <<
514 java_package() <<
Mark Slee78f58e22006-09-02 04:17:07 +0000515 java_type_imports() <<
516 java_thrift_imports();
Mark Sleeb15a68b2006-06-07 06:46:24 +0000517
Mark Slee78f58e22006-09-02 04:17:07 +0000518 generate_java_struct_definition(f_struct,
519 tstruct,
520 is_exception);
521 f_struct.close();
522}
523
Mark Sleef5377b32006-10-10 01:42:59 +0000524/**
525 * Java struct definition. This has various parameters, as it could be
526 * generated standalone or inside another class as a helper. If it
527 * is a helper than it is a static class.
528 *
529 * @param tstruct The struct definition
530 * @param is_exception Is this an exception?
531 * @param in_class If inside a class, needs to be static class
532 * @param is_result If this is a result it needs a different writer
533 */
Mark Slee78f58e22006-09-02 04:17:07 +0000534void t_java_generator::generate_java_struct_definition(ofstream &out,
535 t_struct* tstruct,
536 bool is_exception,
537 bool in_class,
538 bool is_result) {
Mark Slee8775c732007-09-10 22:33:05 +0000539 generate_java_doc(out, tstruct);
540
Mark Sleef0712dc2006-10-25 19:03:57 +0000541 indent(out) <<
Mark Slee78f58e22006-09-02 04:17:07 +0000542 "public " << (in_class ? "static " : "") << "class " << tstruct->get_name() << " ";
Mark Slee5ab57052007-11-27 08:38:16 +0000543
Mark Slee78f58e22006-09-02 04:17:07 +0000544 if (is_exception) {
545 out << "extends Exception ";
546 }
Mark Slee34b29262007-10-09 20:55:10 +0000547 out << "implements TBase, java.io.Serializable ";
Mark Slee5ab57052007-11-27 08:38:16 +0000548
Mark Slee78f58e22006-09-02 04:17:07 +0000549 scope_up(out);
Mark Sleeb15a68b2006-06-07 06:46:24 +0000550
Mark Slee01a9f882007-08-31 00:55:28 +0000551 // Members are public for -java, private for -javabean
Mark Sleeb15a68b2006-06-07 06:46:24 +0000552 const vector<t_field*>& members = tstruct->get_members();
Mark Slee5ab57052007-11-27 08:38:16 +0000553 vector<t_field*>::const_iterator m_iter;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000554 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Mark Slee01a9f882007-08-31 00:55:28 +0000555 if (bean_style_) {
556 indent(out) << "private ";
557 } else {
558 indent(out) << "public ";
559 }
560 out << declare_field(*m_iter, false) << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000561 }
Mark Slee78f58e22006-09-02 04:17:07 +0000562
Mark Sleef5377b32006-10-10 01:42:59 +0000563 // Inner Isset class
Mark Slee78f58e22006-09-02 04:17:07 +0000564 if (members.size() > 0) {
565 out <<
566 endl <<
Mark Sleee9a1edc2007-05-03 01:30:18 +0000567 indent() << "public final Isset __isset = new Isset();" << endl <<
Mark Sleeadb5cad2008-02-04 21:34:22 +0000568 indent() << "public static final class Isset implements java.io.Serializable {" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000569 indent_up();
570 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
571 indent(out) <<
572 "public boolean " << (*m_iter)->get_name() << " = false;" << endl;
573 }
574 indent_down();
575 out <<
576 indent() << "}" << endl <<
577 endl;
578 }
Mark Slee5ab57052007-11-27 08:38:16 +0000579
Mark Slee7ff32452007-02-01 05:26:18 +0000580 // Default constructor
581 indent(out) <<
582 "public " << tstruct->get_name() << "() {" << endl;
583 indent_up();
584 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
David Reisse087a302007-08-23 21:43:25 +0000585 t_type* t = get_true_type((*m_iter)->get_type());
David Reiss80a702f2007-12-18 02:54:06 +0000586 if ((*m_iter)->get_value() != NULL) {
Mark Slee7ff32452007-02-01 05:26:18 +0000587 print_const_value(out, "this." + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true);
588 }
589 }
590 indent_down();
591 indent(out) << "}" << endl << endl;
592
Mark Slee01a9f882007-08-31 00:55:28 +0000593
Mark Sleea0f8bdc2007-08-29 04:36:28 +0000594 // Full constructor for all fields
595 if (!members.empty()) {
596 indent(out) <<
597 "public " << tstruct->get_name() << "(" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +0000598 indent_up();
Mark Sleea0f8bdc2007-08-29 04:36:28 +0000599 for (m_iter = members.begin(); m_iter != members.end(); ) {
600 indent(out) << type_name((*m_iter)->get_type()) << " " <<
601 (*m_iter)->get_name();
602 ++m_iter;
603 if (m_iter != members.end()) {
604 out << "," << endl;
605 }
606 }
607 out << ")" << endl;
608 indent_down();
609 indent(out) << "{" << endl;
610 indent_up();
611 indent(out) << "this();" << endl;
612 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
613 indent(out) << "this." << (*m_iter)->get_name() << " = " <<
614 (*m_iter)->get_name() << ";" << endl;
Mark Slee01a9f882007-08-31 00:55:28 +0000615 indent(out) << "this.__isset." << (*m_iter)->get_name() << " = true;" << endl;
Mark Sleea0f8bdc2007-08-29 04:36:28 +0000616 }
617 indent_down();
618 indent(out) << "}" << endl << endl;
619 }
620
Mark Slee01a9f882007-08-31 00:55:28 +0000621 if (bean_style_) {
622 generate_java_bean_boilerplate(out, tstruct);
623 }
David Reiss3b15ebc2008-03-02 06:29:19 +0000624
625 generate_java_struct_equality(out, tstruct);
626
Mark Slee78f58e22006-09-02 04:17:07 +0000627 generate_java_struct_reader(out, tstruct);
628 if (is_result) {
629 generate_java_struct_result_writer(out, tstruct);
630 } else {
631 generate_java_struct_writer(out, tstruct);
632 }
Mark Slee81097572007-03-14 03:07:00 +0000633 generate_java_struct_tostring(out, tstruct);
Mark Slee78f58e22006-09-02 04:17:07 +0000634 scope_down(out);
Mark Sleeb7f58ff2006-09-02 21:59:28 +0000635 out << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000636}
637
Mark Sleef5377b32006-10-10 01:42:59 +0000638/**
David Reiss3b15ebc2008-03-02 06:29:19 +0000639 * Generates equals methods and a hashCode method for a structure.
640 *
641 * @param tstruct The struct definition
642 */
643void t_java_generator::generate_java_struct_equality(ofstream& out,
644 t_struct* tstruct) {
645 out <<
646 indent() << "public boolean equals(Object that) {" << endl;
647 indent_up();
648 out <<
649 indent() << "if (that == null)" << endl <<
650 indent() << " return false;" << endl <<
651 indent() << "if (that instanceof " << tstruct->get_name() << ")" << endl <<
652 indent() << " return this.equals((" << tstruct->get_name() << ")that);" << endl <<
653 indent() << "return false;" << endl;
654 scope_down(out);
655 out << endl;
656
657 out <<
658 indent() << "public boolean equals(" << tstruct->get_name() << " that) {" << endl;
659 indent_up();
660 out <<
661 indent() << "if (that == null)" << endl <<
662 indent() << " return false;" << endl;
663
664 const vector<t_field*>& members = tstruct->get_members();
665 vector<t_field*>::const_iterator m_iter;
666 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
667 out << endl;
668
669 t_type* t = get_true_type((*m_iter)->get_type());
670 // Most existing Thrift code does not use isset or optional/required,
671 // so we treat "default" fields as required.
672 bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
673 bool can_be_null = type_can_be_null(t);
674 string name = (*m_iter)->get_name();
675
676 string this_present = "true";
677 string that_present = "true";
678 string unequal;
679
680 if (is_optional) {
681 this_present += " && (this.__isset." + name + ")";
682 that_present += " && (that.__isset." + name + ")";
683 }
684 if (can_be_null) {
685 this_present += " && (this." + name + " != null)";
686 that_present += " && (that." + name + " != null)";
687 }
688
689 out <<
690 indent() << "boolean this_present_" << name << " = "
691 << this_present << ";" << endl <<
692 indent() << "boolean that_present_" << name << " = "
693 << that_present << ";" << endl <<
694 indent() << "if (" << "this_present_" << name
695 << " || that_present_" << name << ") {" << endl;
696 indent_up();
697 out <<
698 indent() << "if (!(" << "this_present_" << name
699 << " && that_present_" << name << "))" << endl <<
700 indent() << " return false;" << endl;
701
702 if (t->is_base_type() && ((t_base_type*)t)->is_binary()) {
703 unequal = "!java.util.Arrays.equals(this." + name + ", that." + name + ")";
704 } else if (can_be_null) {
705 unequal = "!this." + name + ".equals(that." + name + ")";
706 } else {
707 unequal = "this." + name + " != that." + name;
708 }
709
710 out <<
711 indent() << "if (" << unequal << ")" << endl <<
712 indent() << " return false;" << endl;
713
714 scope_down(out);
715 }
716 out << endl;
717 indent(out) << "return true;" << endl;
718 scope_down(out);
719 out << endl;
720
David Reiss14feb412008-03-02 06:29:23 +0000721 if (gen_hash_code_) {
722 out <<
723 indent() << "public int hashCode() {" << endl;
724 indent_up();
725
726 out <<
727 indent() << "HashCodeBuilder builder = new HashCodeBuilder();" << endl;
728
729 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
730 out << endl;
731
732 t_type* t = get_true_type((*m_iter)->get_type());
733 bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
734 bool can_be_null = type_can_be_null(t);
735 string name = (*m_iter)->get_name();
736
737 string present = "true";
738
739 if (is_optional) {
740 present += " && (__isset." + name + ")";
741 }
742 if (can_be_null) {
743 present += " && (" + name + " != null)";
744 }
745
746 out <<
747 indent() << "boolean present_" << name << " = "
748 << present << ";" << endl <<
749 indent() << "builder.append(present_" << name << ");" << endl <<
750 indent() << "if (present_" << name << ")" << endl <<
751 indent() << " builder.append(" << name << ");" << endl;
752 }
753
754 out << endl;
755 out <<
756 indent() << "return builder.toHashCode();" << endl;
757 scope_down(out);
758 out << endl;
759
760 } else {
761 out <<
762 indent() << "public int hashCode() {" << endl;
763 indent_up();
764 out <<
765 indent() << "return 0;" << endl;
766 scope_down(out);
767 out << endl;
768 }
David Reiss3b15ebc2008-03-02 06:29:19 +0000769}
770
771/**
Mark Sleef5377b32006-10-10 01:42:59 +0000772 * Generates a function to read all the fields of the struct.
773 *
774 * @param tstruct The struct definition
775 */
Mark Slee78f58e22006-09-02 04:17:07 +0000776void t_java_generator::generate_java_struct_reader(ofstream& out,
777 t_struct* tstruct) {
778 out <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000779 indent() << "public void read(TProtocol iprot) throws TException {" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000780 indent_up();
781
782 const vector<t_field*>& fields = tstruct->get_members();
783 vector<t_field*>::const_iterator f_iter;
784
Mark Slee5de75dd2007-08-31 20:06:36 +0000785 // Declare stack tmp variables and read struct header
Mark Slee78f58e22006-09-02 04:17:07 +0000786 out <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000787 indent() << "TField field;" << endl <<
Mark Slee5de75dd2007-08-31 20:06:36 +0000788 indent() << "iprot.readStructBegin();" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +0000789
Mark Slee78f58e22006-09-02 04:17:07 +0000790 // Loop over reading in fields
791 indent(out) <<
792 "while (true)" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000793 scope_up(out);
Mark Slee5ab57052007-11-27 08:38:16 +0000794
Mark Slee78f58e22006-09-02 04:17:07 +0000795 // Read beginning field marker
796 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000797 "field = iprot.readFieldBegin();" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +0000798
Mark Slee78f58e22006-09-02 04:17:07 +0000799 // Check for field STOP marker and break
800 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000801 "if (field.type == TType.STOP) { " << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000802 indent_up();
803 indent(out) <<
804 "break;" << endl;
805 indent_down();
806 indent(out) <<
807 "}" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +0000808
Mark Slee78f58e22006-09-02 04:17:07 +0000809 // Switch statement on the field we are reading
810 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000811 "switch (field.id)" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000812
813 scope_up(out);
Mark Slee5ab57052007-11-27 08:38:16 +0000814
Mark Slee78f58e22006-09-02 04:17:07 +0000815 // Generate deserialization code for known cases
816 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
817 indent(out) <<
818 "case " << (*f_iter)->get_key() << ":" << endl;
819 indent_up();
Mark Slee2006d992007-01-29 17:58:54 +0000820 indent(out) <<
821 "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
822 indent_up();
823
Mark Sleeb7f58ff2006-09-02 21:59:28 +0000824 generate_deserialize_field(out, *f_iter, "this.");
Mark Slee78f58e22006-09-02 04:17:07 +0000825 out <<
Mark Sleeb7f58ff2006-09-02 21:59:28 +0000826 indent() << "this.__isset." << (*f_iter)->get_name() << " = true;" << endl;
Mark Slee2006d992007-01-29 17:58:54 +0000827 indent_down();
828 out <<
829 indent() << "} else { " << endl <<
830 indent() << " TProtocolUtil.skip(iprot, field.type);" << endl <<
831 indent() << "}" << endl <<
832 indent() << "break;" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000833 indent_down();
834 }
Mark Slee5ab57052007-11-27 08:38:16 +0000835
Mark Slee78f58e22006-09-02 04:17:07 +0000836 // In the default case we skip the field
837 out <<
838 indent() << "default:" << endl <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000839 indent() << " TProtocolUtil.skip(iprot, field.type);" << endl <<
Mark Slee78f58e22006-09-02 04:17:07 +0000840 indent() << " break;" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +0000841
Mark Slee78f58e22006-09-02 04:17:07 +0000842 scope_down(out);
843
844 // Read field end marker
845 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000846 "iprot.readFieldEnd();" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +0000847
Mark Slee78f58e22006-09-02 04:17:07 +0000848 scope_down(out);
Mark Slee5ab57052007-11-27 08:38:16 +0000849
Mark Slee78f58e22006-09-02 04:17:07 +0000850 out <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000851 indent() << "iprot.readStructEnd();" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000852
853 indent_down();
854 out <<
855 indent() << "}" << endl <<
856 endl;
857}
858
Mark Sleef5377b32006-10-10 01:42:59 +0000859/**
860 * Generates a function to write all the fields of the struct
861 *
862 * @param tstruct The struct definition
863 */
Mark Slee78f58e22006-09-02 04:17:07 +0000864void t_java_generator::generate_java_struct_writer(ofstream& out,
865 t_struct* tstruct) {
866 out <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000867 indent() << "public void write(TProtocol oprot) throws TException {" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000868 indent_up();
869
870 string name = tstruct->get_name();
871 const vector<t_field*>& fields = tstruct->get_members();
872 vector<t_field*>::const_iterator f_iter;
873
Mark Slee5de75dd2007-08-31 20:06:36 +0000874 indent(out) << "TStruct struct = new TStruct(\"" << name << "\");" << endl;
875 indent(out) << "oprot.writeStructBegin(struct);" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000876
Mark Slee5de75dd2007-08-31 20:06:36 +0000877 if (!fields.empty()) {
878 indent(out) << "TField field = new TField();" << endl;
879 }
Mark Slee78f58e22006-09-02 04:17:07 +0000880 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
Mark Sleef3763a12007-01-18 02:35:27 +0000881 bool null_allowed = type_can_be_null((*f_iter)->get_type());
882 if (null_allowed) {
883 out <<
884 indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
885 indent_up();
886 }
David Reiss204420f2008-01-11 20:59:03 +0000887 bool optional = bean_style_ && (*f_iter)->get_req() == t_field::T_OPTIONAL;
Mark Slee2e7801d2007-10-24 02:56:24 +0000888 if (optional) {
889 out <<
890 indent() << "if (this.__isset." << (*f_iter)->get_name() << ") {" << endl;
891 }
Mark Sleef3763a12007-01-18 02:35:27 +0000892
Mark Slee78f58e22006-09-02 04:17:07 +0000893 out <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000894 indent() << "field.name = \"" << (*f_iter)->get_name() << "\";" << endl <<
895 indent() << "field.type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl <<
896 indent() << "field.id = " << (*f_iter)->get_key() << ";" << endl <<
897 indent() << "oprot.writeFieldBegin(field);" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000898
899 // Write field contents
900 generate_serialize_field(out, *f_iter, "this.");
901
902 // Write field closer
903 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000904 "oprot.writeFieldEnd();" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +0000905
Mark Slee2e7801d2007-10-24 02:56:24 +0000906 if (optional) {
907 indent_down();
908 indent(out) << "}" << endl;
909 }
Mark Sleef3763a12007-01-18 02:35:27 +0000910 if (null_allowed) {
911 indent_down();
912 indent(out) << "}" << endl;
913 }
Mark Slee78f58e22006-09-02 04:17:07 +0000914 }
915 // Write the struct map
916 out <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000917 indent() << "oprot.writeFieldStop();" << endl <<
918 indent() << "oprot.writeStructEnd();" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000919
920 indent_down();
921 out <<
Mark Slee81097572007-03-14 03:07:00 +0000922 indent() << "}" << endl <<
923 endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000924}
925
Mark Sleef5377b32006-10-10 01:42:59 +0000926/**
927 * Generates a function to write all the fields of the struct,
928 * which is a function result. These fields are only written
929 * if they are set in the Isset array, and only one of them
930 * can be set at a time.
931 *
932 * @param tstruct The struct definition
933 */
Mark Slee78f58e22006-09-02 04:17:07 +0000934void t_java_generator::generate_java_struct_result_writer(ofstream& out,
935 t_struct* tstruct) {
936 out <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000937 indent() << "public void write(TProtocol oprot) throws TException {" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000938 indent_up();
939
940 string name = tstruct->get_name();
941 const vector<t_field*>& fields = tstruct->get_members();
942 vector<t_field*>::const_iterator f_iter;
943
Mark Slee5de75dd2007-08-31 20:06:36 +0000944 indent(out) << "TStruct struct = new TStruct(\"" << name << "\");" << endl;
945 indent(out) << "oprot.writeStructBegin(struct);" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000946
Mark Slee5de75dd2007-08-31 20:06:36 +0000947 if (!fields.empty()) {
948 indent(out) << "TField field = new TField();" << endl;
949 }
Mark Slee78f58e22006-09-02 04:17:07 +0000950 bool first = true;
951 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
952 if (first) {
953 first = false;
954 out <<
955 endl <<
956 indent() << "if ";
957 } else {
958 out <<
959 " else if ";
960 }
961
962 out <<
963 "(this.__isset." << (*f_iter)->get_name() << ") {" << endl;
964 indent_up();
965
Mark Sleef3763a12007-01-18 02:35:27 +0000966 bool null_allowed = type_can_be_null((*f_iter)->get_type());
967 if (null_allowed) {
968 out <<
969 indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl;
970 indent_up();
971 }
972
Mark Slee78f58e22006-09-02 04:17:07 +0000973 out <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000974 indent() << "field.name = \"" << (*f_iter)->get_name() << "\";" << endl <<
975 indent() << "field.type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl <<
976 indent() << "field.id = " << (*f_iter)->get_key() << ";" << endl <<
977 indent() << "oprot.writeFieldBegin(field);" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000978
979 // Write field contents
980 generate_serialize_field(out, *f_iter, "this.");
981
982 // Write field closer
983 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000984 "oprot.writeFieldEnd();" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000985
Mark Sleef3763a12007-01-18 02:35:27 +0000986 if (null_allowed) {
987 indent_down();
988 indent(out) << "}" << endl;
989 }
990
Mark Slee78f58e22006-09-02 04:17:07 +0000991 indent_down();
992 indent(out) << "}";
993 }
994 // Write the struct map
995 out <<
996 endl <<
Mark Slee575fa9a2006-10-25 20:54:10 +0000997 indent() << "oprot.writeFieldStop();" << endl <<
998 indent() << "oprot.writeStructEnd();" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +0000999
1000 indent_down();
1001 out <<
1002 indent() << "}" << endl <<
1003 endl;
1004}
1005
Mark Slee81097572007-03-14 03:07:00 +00001006/**
Mark Slee01a9f882007-08-31 00:55:28 +00001007 * Generates a set of Java Bean boilerplate functions (setters, getters, etc.)
1008 * for the given struct.
1009 *
1010 * @param tstruct The struct definition
1011 */
1012void t_java_generator::generate_java_bean_boilerplate(ofstream& out,
1013 t_struct* tstruct) {
1014 const vector<t_field*>& fields = tstruct->get_members();
1015 vector<t_field*>::const_iterator f_iter;
1016 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1017 t_field* field = *f_iter;
1018 t_type* type = get_true_type(field->get_type());
1019 std::string field_name = field->get_name();
1020 std::string cap_name = field_name;
1021 cap_name[0] = toupper(cap_name[0]);
1022
Mark Slee979ff952007-09-10 20:53:23 +00001023 if (type->is_container()) {
1024 // Method to return the size of the collection
1025 indent(out) << "public int get" << cap_name << "Size() {" << endl;
1026 indent_up();
Mark Slee5ab57052007-11-27 08:38:16 +00001027 indent(out) << "return (this." << field_name << " == null) ? 0 : " <<
Mark Slee979ff952007-09-10 20:53:23 +00001028 "this." << field_name << ".size();" << endl;
1029 indent_down();
1030 indent(out) << "}" << endl << endl;
1031 }
1032
Mark Slee01a9f882007-08-31 00:55:28 +00001033 if (type->is_set() || type->is_list()) {
1034
1035 t_type* element_type;
1036 if (type->is_set()) {
1037 element_type = ((t_set*)type)->get_elem_type();
1038 } else {
1039 element_type = ((t_list*)type)->get_elem_type();
1040 }
1041
1042 // Iterator getter for sets and lists
Mark Slee979ff952007-09-10 20:53:23 +00001043 indent(out) << "public java.util.Iterator<" <<
1044 type_name(element_type) << "> get" << cap_name << "Iterator() {" << endl;
Mark Slee01a9f882007-08-31 00:55:28 +00001045 indent_up();
Mark Slee5ab57052007-11-27 08:38:16 +00001046 indent(out) << "return (this." << field_name << " == null) ? null : " <<
Mark Slee01a9f882007-08-31 00:55:28 +00001047 "this." << field_name << ".iterator();" << endl;
1048 indent_down();
1049 indent(out) << "}" << endl << endl;
1050
1051 // Add to set or list, create if the set/list is null
1052 indent(out) << "public void addTo" << cap_name << "(" <<
1053 type_name(element_type) <<
1054 " elem) {" << endl;
1055 indent_up();
1056 indent(out) << "if (this." << field_name << " == null) {" << endl;
1057 indent_up();
Mark Sleedd43eb82008-02-13 22:03:15 +00001058 indent(out) << "this." << field_name << " = new " << type_name(type, false, true) <<
Mark Slee01a9f882007-08-31 00:55:28 +00001059 "();" << endl;
1060 indent_down();
1061 indent(out) << "}" << endl;
1062 indent(out) << "this." << field_name << ".add(elem);" << endl;
1063 indent(out) << "this.__isset." << field_name << " = true;" << endl;
1064 indent_down();
1065 indent(out) << "}" << endl << endl;
1066
1067 } else if (type->is_map()) {
1068 // Put to map
1069 t_type* key_type = ((t_map*)type)->get_key_type();
1070 t_type* val_type = ((t_map*)type)->get_val_type();
1071 indent(out) << "public void putTo" << cap_name << "(" <<
1072 type_name(key_type) << " key, " <<
1073 type_name(val_type) << " val) {" << endl;
1074 indent_up();
1075 indent(out) << "if (this." << field_name << " == null) {" << endl;
1076 indent_up();
1077 indent(out) << "this." << field_name << " = new " <<
1078 type_name(type, false, true) << "();" << endl;
1079 indent_down();
1080 indent(out) << "}" << endl;
1081 indent(out) << "this." << field_name << ".put(key, val);" << endl;
1082 indent(out) << "this.__isset." << field_name << " = true;" << endl;
1083 indent_down();
1084 indent(out) << "}" << endl << endl;
1085 }
1086
1087 // Simple getter
1088 indent(out) << "public " << type_name(type);
1089 if (type->is_base_type() &&
1090 ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) {
1091 out << " is";
1092 } else {
1093 out << " get";
1094 }
1095 out << cap_name << "() {" << endl;
1096 indent_up();
1097 indent(out) << "return this." << field_name << ";" << endl;
1098 indent_down();
1099 indent(out) << "}" << endl << endl;
1100
1101 // Simple setter
1102 indent(out) << "public void set" << cap_name << "(" << type_name(type) <<
1103 " " << field_name << ") {" << endl;
1104 indent_up();
1105 indent(out) << "this." << field_name << " = " << field_name << ";" <<
1106 endl;
1107 indent(out) << "this.__isset." << field_name << " = true;" << endl;
1108 indent_down();
1109 indent(out) << "}" << endl << endl;
1110
1111 // Unsetter
1112 indent(out) << "public void unset" << cap_name << "() {" << endl;
1113 indent_up();
1114 if (type->is_container() || type->is_struct() || type->is_xception()) {
1115 indent(out) << "this." << field_name << " = null;" << endl;
1116 }
1117 indent(out) << "this.__isset." << field_name << " = false;" << endl;
1118 indent_down();
1119 indent(out) << "}" << endl << endl;
1120 }
1121}
1122
1123/**
Mark Slee81097572007-03-14 03:07:00 +00001124 * Generates a toString() method for the given struct
1125 *
1126 * @param tstruct The struct definition
1127 */
1128void t_java_generator::generate_java_struct_tostring(ofstream& out,
1129 t_struct* tstruct) {
1130 out <<
1131 indent() << "public String toString() {" << endl;
1132 indent_up();
1133
1134 out <<
eletuchy447d7d232007-06-13 04:24:11 +00001135 indent() << "StringBuilder sb = new StringBuilder(\"" << tstruct->get_name() << "(\");" << endl;
Mark Slee81097572007-03-14 03:07:00 +00001136
1137 const vector<t_field*>& fields = tstruct->get_members();
1138 vector<t_field*>::const_iterator f_iter;
1139 bool first = true;
1140 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1141 if (first) {
1142 first = false;
1143 indent(out) << "sb.append(\"" << (*f_iter)->get_name() << ":\");" << endl;
1144 } else {
1145 indent(out) << "sb.append(\"," << (*f_iter)->get_name() << ":\");" << endl;
1146 }
1147 t_type* ttype = (*f_iter)->get_type();
1148 if (ttype->is_xception() || ttype->is_struct()) {
1149 indent(out) << "sb.append(this." << (*f_iter)->get_name() << ".toString());" << endl;
1150 } else {
1151 indent(out) << "sb.append(this." << (*f_iter)->get_name() << ");" << endl;
1152 }
1153 }
1154 out <<
1155 indent() << "sb.append(\")\");" << endl <<
1156 indent() << "return sb.toString();" << endl;
1157
1158 indent_down();
1159 indent(out) << "}" << endl <<
1160 endl;
1161}
1162
Mark Slee78f58e22006-09-02 04:17:07 +00001163
Mark Sleeb15a68b2006-06-07 06:46:24 +00001164/**
1165 * Generates a thrift service. In C++, this comprises an entirely separate
1166 * header and source file. The header file defines the methods and includes
1167 * the data types defined in the main header file, and the implementation
1168 * file contains implementations of the basic printer and default interfaces.
1169 *
1170 * @param tservice The service definition
1171 */
1172void t_java_generator::generate_service(t_service* tservice) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00001173 // Make output file
Mark Slee98e962b2007-02-20 18:44:05 +00001174 string f_service_name = package_dir_+"/"+service_name_+".java";
Mark Slee78f58e22006-09-02 04:17:07 +00001175 f_service_.open(f_service_name.c_str());
Mark Sleeb15a68b2006-06-07 06:46:24 +00001176
1177 f_service_ <<
1178 autogen_comment() <<
1179 java_package() <<
1180 java_type_imports() <<
1181 java_thrift_imports();
1182
1183 f_service_ <<
Mark Slee78f58e22006-09-02 04:17:07 +00001184 "public class " << service_name_ << " {" << endl <<
1185 endl;
Mark Sleedafa3cf2006-09-02 23:56:49 +00001186 indent_up();
Mark Slee78f58e22006-09-02 04:17:07 +00001187
1188 // Generate the three main parts of the service
1189 generate_service_interface(tservice);
1190 generate_service_client(tservice);
1191 generate_service_server(tservice);
1192 generate_service_helpers(tservice);
1193
Mark Sleedafa3cf2006-09-02 23:56:49 +00001194 indent_down();
Mark Slee78f58e22006-09-02 04:17:07 +00001195 f_service_ <<
1196 "}" << endl;
1197 f_service_.close();
1198}
1199
1200/**
1201 * Generates a service interface definition.
1202 *
1203 * @param tservice The service to generate a header definition for
1204 */
1205void t_java_generator::generate_service_interface(t_service* tservice) {
Mark Sleef0712dc2006-10-25 19:03:57 +00001206 string extends = "";
1207 string extends_iface = "";
1208 if (tservice->get_extends() != NULL) {
1209 extends = type_name(tservice->get_extends());
1210 extends_iface = " extends " + extends + ".Iface";
1211 }
1212
Mark Slee8775c732007-09-10 22:33:05 +00001213 generate_java_doc(f_service_, tservice);
1214 f_service_ << indent() << "public interface Iface" << extends_iface <<
1215 " {" << endl << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001216 indent_up();
1217 vector<t_function*> functions = tservice->get_functions();
Mark Slee5ab57052007-11-27 08:38:16 +00001218 vector<t_function*>::iterator f_iter;
Mark Slee78f58e22006-09-02 04:17:07 +00001219 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
Mark Slee8775c732007-09-10 22:33:05 +00001220 generate_java_doc(f_service_, *f_iter);
1221 indent(f_service_) << "public " << function_signature(*f_iter) << ";" <<
1222 endl << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001223 }
1224 indent_down();
1225 f_service_ <<
1226 indent() << "}" << endl <<
1227 endl;
1228}
1229
Mark Sleef5377b32006-10-10 01:42:59 +00001230/**
1231 * Generates structs for all the service args and return types
1232 *
1233 * @param tservice The service
1234 */
Mark Slee78f58e22006-09-02 04:17:07 +00001235void t_java_generator::generate_service_helpers(t_service* tservice) {
1236 vector<t_function*> functions = tservice->get_functions();
Mark Slee5ab57052007-11-27 08:38:16 +00001237 vector<t_function*>::iterator f_iter;
Mark Slee78f58e22006-09-02 04:17:07 +00001238 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1239 t_struct* ts = (*f_iter)->get_arglist();
1240 generate_java_struct_definition(f_service_, ts, false, true);
1241 generate_function_helpers(*f_iter);
1242 }
1243}
1244
1245/**
1246 * Generates a service client definition.
1247 *
1248 * @param tservice The service to generate a server for.
1249 */
1250void t_java_generator::generate_service_client(t_service* tservice) {
Mark Sleef0712dc2006-10-25 19:03:57 +00001251 string extends = "";
1252 string extends_client = "";
1253 if (tservice->get_extends() != NULL) {
1254 extends = type_name(tservice->get_extends());
1255 extends_client = " extends " + extends + ".Client";
1256 }
1257
1258 indent(f_service_) <<
1259 "public static class Client" << extends_client << " implements Iface {" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001260 indent_up();
1261
1262 indent(f_service_) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001263 "public Client(TProtocol prot)" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001264 scope_up(f_service_);
Mark Slee5ab57052007-11-27 08:38:16 +00001265 indent(f_service_) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001266 "this(prot, prot);" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001267 scope_down(f_service_);
1268 f_service_ << endl;
1269
1270 indent(f_service_) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001271 "public Client(TProtocol iprot, TProtocol oprot)" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001272 scope_up(f_service_);
Mark Sleef0712dc2006-10-25 19:03:57 +00001273 if (extends.empty()) {
1274 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001275 indent() << "iprot_ = iprot;" << endl <<
1276 indent() << "oprot_ = oprot;" << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00001277 } else {
1278 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001279 indent() << "super(iprot, oprot);" << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00001280 }
Mark Sleeb15a68b2006-06-07 06:46:24 +00001281 scope_down(f_service_);
1282 f_service_ << endl;
Mark Slee5ab57052007-11-27 08:38:16 +00001283
Mark Sleef0712dc2006-10-25 19:03:57 +00001284 if (extends.empty()) {
1285 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001286 indent() << "protected TProtocol iprot_;" << endl <<
1287 indent() << "protected TProtocol oprot_;" << endl <<
Mark Sleef0712dc2006-10-25 19:03:57 +00001288 endl <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001289 indent() << "protected int seqid_;" << endl <<
Mark Sleef0712dc2006-10-25 19:03:57 +00001290 endl;
Mark Slee6756f132008-02-09 00:26:29 +00001291
1292 indent(f_service_) <<
1293 "public TProtocol getInputProtocol()" << endl;
1294 scope_up(f_service_);
1295 indent(f_service_) <<
1296 "return this.iprot_;" << endl;
1297 scope_down(f_service_);
1298 f_service_ << endl;
1299
1300 indent(f_service_) <<
1301 "public TProtocol getOutputProtocol()" << endl;
1302 scope_up(f_service_);
1303 indent(f_service_) <<
1304 "return this.oprot_;" << endl;
1305 scope_down(f_service_);
1306 f_service_ << endl;
1307
Mark Sleef0712dc2006-10-25 19:03:57 +00001308 }
Mark Sleeb15a68b2006-06-07 06:46:24 +00001309
1310 // Generate client method implementations
1311 vector<t_function*> functions = tservice->get_functions();
Mark Slee5ab57052007-11-27 08:38:16 +00001312 vector<t_function*>::const_iterator f_iter;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001313 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1314 string funname = (*f_iter)->get_name();
1315
1316 // Open function
1317 indent(f_service_) <<
Mark Slee78f58e22006-09-02 04:17:07 +00001318 "public " << function_signature(*f_iter) << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001319 scope_up(f_service_);
Mark Slee52f643d2006-08-09 00:03:43 +00001320 indent(f_service_) <<
1321 "send_" << funname << "(";
1322
1323 // Get the struct of function call params
1324 t_struct* arg_struct = (*f_iter)->get_arglist();
Mark Slee5ab57052007-11-27 08:38:16 +00001325
Mark Slee52f643d2006-08-09 00:03:43 +00001326 // Declare the function arguments
1327 const vector<t_field*>& fields = arg_struct->get_members();
1328 vector<t_field*>::const_iterator fld_iter;
1329 bool first = true;
1330 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
1331 if (first) {
1332 first = false;
1333 } else {
1334 f_service_ << ", ";
1335 }
1336 f_service_ << (*fld_iter)->get_name();
1337 }
1338 f_service_ << ");" << endl;
1339
1340 if (!(*f_iter)->is_async()) {
1341 f_service_ << indent();
1342 if (!(*f_iter)->get_returntype()->is_void()) {
1343 f_service_ << "return ";
1344 }
1345 f_service_ <<
1346 "recv_" << funname << "();" << endl;
1347 }
1348 scope_down(f_service_);
1349 f_service_ << endl;
Mark Slee5ab57052007-11-27 08:38:16 +00001350
Mark Sleef0712dc2006-10-25 19:03:57 +00001351 t_function send_function(g_type_void,
Mark Slee52f643d2006-08-09 00:03:43 +00001352 string("send_") + (*f_iter)->get_name(),
1353 (*f_iter)->get_arglist());
1354
Mark Slee78f58e22006-09-02 04:17:07 +00001355 string argsname = (*f_iter)->get_name() + "_args";
1356
Mark Slee52f643d2006-08-09 00:03:43 +00001357 // Open function
1358 indent(f_service_) <<
Mark Slee78f58e22006-09-02 04:17:07 +00001359 "public " << function_signature(&send_function) << endl;
Mark Slee52f643d2006-08-09 00:03:43 +00001360 scope_up(f_service_);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001361
1362 // Serialize the request
1363 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001364 indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname << "\", TMessageType.CALL, seqid_));" << endl <<
1365 indent() << argsname << " args = new " << argsname << "();" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001366
1367 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
1368 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001369 indent() << "args." << (*fld_iter)->get_name() << " = " << (*fld_iter)->get_name() << ";" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001370 }
1371
Mark Sleeb15a68b2006-06-07 06:46:24 +00001372 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001373 indent() << "args.write(oprot_);" << endl <<
1374 indent() << "oprot_.writeMessageEnd();" << endl <<
Mark Slee9f8361f2007-02-09 02:14:43 +00001375 indent() << "oprot_.getTransport().flush();" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001376
Mark Sleeb15a68b2006-06-07 06:46:24 +00001377 scope_down(f_service_);
1378 f_service_ << endl;
Mark Slee52f643d2006-08-09 00:03:43 +00001379
1380 if (!(*f_iter)->is_async()) {
Mark Slee78f58e22006-09-02 04:17:07 +00001381 string resultname = (*f_iter)->get_name() + "_result";
1382
Mark Sleef0712dc2006-10-25 19:03:57 +00001383 t_struct noargs(program_);
Mark Slee52f643d2006-08-09 00:03:43 +00001384 t_function recv_function((*f_iter)->get_returntype(),
1385 string("recv_") + (*f_iter)->get_name(),
Mark Slee78f58e22006-09-02 04:17:07 +00001386 &noargs,
1387 (*f_iter)->get_xceptions());
Mark Slee52f643d2006-08-09 00:03:43 +00001388 // Open function
1389 indent(f_service_) <<
Mark Slee78f58e22006-09-02 04:17:07 +00001390 "public " << function_signature(&recv_function) << endl;
Mark Slee52f643d2006-08-09 00:03:43 +00001391 scope_up(f_service_);
Mark Slee5ab57052007-11-27 08:38:16 +00001392
Mark Slee5e046572007-02-21 04:17:55 +00001393 // TODO(mcslee): Message validation here, was the seqid etc ok?
1394
Mark Slee78f58e22006-09-02 04:17:07 +00001395 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001396 indent() << "TMessage msg = iprot_.readMessageBegin();" << endl <<
Mark Slee5e046572007-02-21 04:17:55 +00001397 indent() << "if (msg.type == TMessageType.EXCEPTION) {" << endl <<
1398 indent() << " TApplicationException x = TApplicationException.read(iprot_);" << endl <<
1399 indent() << " iprot_.readMessageEnd();" << endl <<
1400 indent() << " throw x;" << endl <<
1401 indent() << "}" << endl <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001402 indent() << resultname << " result = new " << resultname << "();" << endl <<
1403 indent() << "result.read(iprot_);" << endl <<
1404 indent() << "iprot_.readMessageEnd();" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001405
Mark Slee52f643d2006-08-09 00:03:43 +00001406 // Careful, only return _result if not a void function
1407 if (!(*f_iter)->get_returntype()->is_void()) {
Mark Slee78f58e22006-09-02 04:17:07 +00001408 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001409 indent() << "if (result.__isset.success) {" << endl <<
1410 indent() << " return result.success;" << endl <<
Mark Slee78f58e22006-09-02 04:17:07 +00001411 indent() << "}" << endl;
1412 }
1413
1414 t_struct* xs = (*f_iter)->get_xceptions();
1415 const std::vector<t_field*>& xceptions = xs->get_members();
1416 vector<t_field*>::const_iterator x_iter;
1417 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
1418 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001419 indent() << "if (result.__isset." << (*x_iter)->get_name() << ") {" << endl <<
1420 indent() << " throw result." << (*x_iter)->get_name() << ";" << endl <<
Mark Slee78f58e22006-09-02 04:17:07 +00001421 indent() << "}" << endl;
1422 }
1423
Mark Sleef5377b32006-10-10 01:42:59 +00001424 // If you get here it's an exception, unless a void function
Mark Slee78f58e22006-09-02 04:17:07 +00001425 if ((*f_iter)->get_returntype()->is_void()) {
Mark Slee52f643d2006-08-09 00:03:43 +00001426 indent(f_service_) <<
1427 "return;" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001428 } else {
1429 f_service_ <<
Mark Slee5e046572007-02-21 04:17:55 +00001430 indent() << "throw new TApplicationException(TApplicationException.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
Mark Slee52f643d2006-08-09 00:03:43 +00001431 }
Mark Slee5ab57052007-11-27 08:38:16 +00001432
Mark Slee52f643d2006-08-09 00:03:43 +00001433 // Close function
1434 scope_down(f_service_);
1435 f_service_ << endl;
1436 }
Mark Sleeb15a68b2006-06-07 06:46:24 +00001437 }
1438
1439 indent_down();
Mark Sleef0712dc2006-10-25 19:03:57 +00001440 indent(f_service_) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00001441 "}" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001442}
1443
1444/**
1445 * Generates a service server definition.
1446 *
1447 * @param tservice The service to generate a server for.
1448 */
1449void t_java_generator::generate_service_server(t_service* tservice) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00001450 // Generate the dispatch methods
1451 vector<t_function*> functions = tservice->get_functions();
Mark Slee5ab57052007-11-27 08:38:16 +00001452 vector<t_function*>::iterator f_iter;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001453
Mark Sleef0712dc2006-10-25 19:03:57 +00001454 // Extends stuff
1455 string extends = "";
1456 string extends_processor = "";
1457 if (tservice->get_extends() != NULL) {
1458 extends = type_name(tservice->get_extends());
1459 extends_processor = " extends " + extends + ".Processor";
1460 }
1461
Mark Sleeb15a68b2006-06-07 06:46:24 +00001462 // Generate the header portion
Mark Sleef0712dc2006-10-25 19:03:57 +00001463 indent(f_service_) <<
1464 "public static class Processor" << extends_processor << " implements TProcessor {" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001465 indent_up();
1466
1467 indent(f_service_) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001468 "public Processor(Iface iface)" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001469 scope_up(f_service_);
Mark Slee575fa9a2006-10-25 20:54:10 +00001470 if (!extends.empty()) {
Mark Sleef0712dc2006-10-25 19:03:57 +00001471 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001472 indent() << "super(iface);" << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00001473 }
Mark Sleeb15a68b2006-06-07 06:46:24 +00001474 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001475 indent() << "iface_ = iface;" << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00001476
1477 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1478 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001479 indent() << "processMap_.put(\"" << (*f_iter)->get_name() << "\", new " << (*f_iter)->get_name() << "());" << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00001480 }
Mark Slee5ab57052007-11-27 08:38:16 +00001481
Mark Sleeb15a68b2006-06-07 06:46:24 +00001482 scope_down(f_service_);
1483 f_service_ << endl;
Mark Slee5ab57052007-11-27 08:38:16 +00001484
Mark Sleef0712dc2006-10-25 19:03:57 +00001485 if (extends.empty()) {
1486 f_service_ <<
Mark Slee725f9e62006-10-31 05:08:33 +00001487 indent() << "protected static interface ProcessFunction {" << endl <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001488 indent() << " public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException;" << endl <<
Mark Sleef0712dc2006-10-25 19:03:57 +00001489 indent() << "}" << endl <<
1490 endl;
1491 }
1492
Mark Sleeb15a68b2006-06-07 06:46:24 +00001493 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001494 indent() << "private Iface iface_;" << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00001495
1496 if (extends.empty()) {
1497 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001498 indent() << "protected final HashMap<String,ProcessFunction> processMap_ = new HashMap<String,ProcessFunction>();" << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00001499 }
Mark Slee5ab57052007-11-27 08:38:16 +00001500
Mark Sleef0712dc2006-10-25 19:03:57 +00001501 f_service_ << endl;
Mark Slee5ab57052007-11-27 08:38:16 +00001502
Mark Sleeb15a68b2006-06-07 06:46:24 +00001503 // Generate the server implementation
1504 indent(f_service_) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001505 "public boolean process(TProtocol iprot, TProtocol oprot) throws TException" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001506 scope_up(f_service_);
1507
1508 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001509 indent() << "TMessage msg = iprot.readMessageBegin();" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001510
Mark Sleef5377b32006-10-10 01:42:59 +00001511 // TODO(mcslee): validate message, was the seqid etc. legit?
Mark Sleeb15a68b2006-06-07 06:46:24 +00001512
Mark Sleeb15a68b2006-06-07 06:46:24 +00001513 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001514 indent() << "ProcessFunction fn = processMap_.get(msg.name);" << endl <<
Mark Sleef0712dc2006-10-25 19:03:57 +00001515 indent() << "if (fn == null) {" << endl <<
Mark Slee5e046572007-02-21 04:17:55 +00001516 indent() << " TProtocolUtil.skip(iprot, TType.STRUCT);" << endl <<
1517 indent() << " iprot.readMessageEnd();" << endl <<
1518 indent() << " TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, \"Invalid method name: '\"+msg.name+\"'\");" << endl <<
1519 indent() << " oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" << endl <<
1520 indent() << " x.write(oprot);" << endl <<
1521 indent() << " oprot.writeMessageEnd();" << endl <<
1522 indent() << " oprot.getTransport().flush();" << endl <<
1523 indent() << " return true;" << endl <<
1524 indent() << "}" << endl <<
1525 indent() << "fn.process(msg.seqid, iprot, oprot);" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +00001526
Mark Sleeb15a68b2006-06-07 06:46:24 +00001527 f_service_ <<
Mark Slee78f58e22006-09-02 04:17:07 +00001528 indent() << "return true;" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001529
1530 scope_down(f_service_);
1531 f_service_ << endl;
1532
1533 // Generate the process subfunctions
1534 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1535 generate_process_function(tservice, *f_iter);
1536 }
1537
1538 indent_down();
Mark Sleef0712dc2006-10-25 19:03:57 +00001539 indent(f_service_) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00001540 "}" << endl <<
1541 endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001542}
Mark Sleeb15a68b2006-06-07 06:46:24 +00001543
Mark Slee78f58e22006-09-02 04:17:07 +00001544/**
1545 * Generates a struct and helpers for a function.
1546 *
1547 * @param tfunction The function
1548 */
1549void t_java_generator::generate_function_helpers(t_function* tfunction) {
1550 if (tfunction->is_async()) {
1551 return;
1552 }
1553
Mark Sleef0712dc2006-10-25 19:03:57 +00001554 t_struct result(program_, tfunction->get_name() + "_result");
Mark Slee78f58e22006-09-02 04:17:07 +00001555 t_field success(tfunction->get_returntype(), "success", 0);
1556 if (!tfunction->get_returntype()->is_void()) {
1557 result.append(&success);
1558 }
1559
1560 t_struct* xs = tfunction->get_xceptions();
1561 const vector<t_field*>& fields = xs->get_members();
1562 vector<t_field*>::const_iterator f_iter;
1563 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1564 result.append(*f_iter);
1565 }
1566
1567 generate_java_struct_definition(f_service_, &result, false, true, true);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001568}
1569
1570/**
1571 * Generates a process function definition.
1572 *
1573 * @param tfunction The function to write a dispatcher for
1574 */
1575void t_java_generator::generate_process_function(t_service* tservice,
1576 t_function* tfunction) {
Mark Sleef0712dc2006-10-25 19:03:57 +00001577 // Open class
1578 indent(f_service_) <<
1579 "private class " << tfunction->get_name() << " implements ProcessFunction {" << endl;
1580 indent_up();
1581
Mark Sleeb15a68b2006-06-07 06:46:24 +00001582 // Open function
1583 indent(f_service_) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001584 "public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001585 scope_up(f_service_);
1586
Mark Slee78f58e22006-09-02 04:17:07 +00001587 string argsname = tfunction->get_name() + "_args";
1588 string resultname = tfunction->get_name() + "_result";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001589
Mark Slee78f58e22006-09-02 04:17:07 +00001590 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001591 indent() << argsname << " args = new " << argsname << "();" << endl <<
1592 indent() << "args.read(iprot);" << endl <<
1593 indent() << "iprot.readMessageEnd();" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001594
1595 t_struct* xs = tfunction->get_xceptions();
1596 const std::vector<t_field*>& xceptions = xs->get_members();
1597 vector<t_field*>::const_iterator x_iter;
1598
1599 // Declare result for non async function
1600 if (!tfunction->is_async()) {
1601 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001602 indent() << resultname << " result = new " << resultname << "();" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001603 }
1604
Mark Slee78f58e22006-09-02 04:17:07 +00001605 // Try block for a function with exceptions
1606 if (xceptions.size() > 0) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00001607 f_service_ <<
Mark Slee78f58e22006-09-02 04:17:07 +00001608 indent() << "try {" << endl;
1609 indent_up();
1610 }
Mark Slee5ab57052007-11-27 08:38:16 +00001611
Mark Slee78f58e22006-09-02 04:17:07 +00001612 // Generate the function call
1613 t_struct* arg_struct = tfunction->get_arglist();
1614 const std::vector<t_field*>& fields = arg_struct->get_members();
1615 vector<t_field*>::const_iterator f_iter;
1616
1617 f_service_ << indent();
1618 if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) {
Mark Slee575fa9a2006-10-25 20:54:10 +00001619 f_service_ << "result.success = ";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001620 }
1621 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001622 "iface_." << tfunction->get_name() << "(";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001623 bool first = true;
1624 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1625 if (first) {
1626 first = false;
1627 } else {
1628 f_service_ << ", ";
1629 }
Mark Slee575fa9a2006-10-25 20:54:10 +00001630 f_service_ << "args." << (*f_iter)->get_name();
Mark Sleeb15a68b2006-06-07 06:46:24 +00001631 }
1632 f_service_ << ");" << endl;
1633
Mark Slee78f58e22006-09-02 04:17:07 +00001634 // Set isset on success field
1635 if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) {
1636 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001637 indent() << "result.__isset.success = true;" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001638 }
Mark Slee78f58e22006-09-02 04:17:07 +00001639
1640 if (!tfunction->is_async() && xceptions.size() > 0) {
1641 indent_down();
1642 f_service_ << indent() << "}";
1643 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
Mark Sleea0f8bdc2007-08-29 04:36:28 +00001644 f_service_ << " catch (" << type_name((*x_iter)->get_type(), false, false) << " " << (*x_iter)->get_name() << ") {" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001645 if (!tfunction->is_async()) {
1646 indent_up();
1647 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001648 indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl <<
1649 indent() << "result.__isset." << (*x_iter)->get_name() << " = true;" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001650 indent_down();
1651 f_service_ << indent() << "}";
1652 } else {
1653 f_service_ << "}";
1654 }
1655 }
1656 f_service_ << endl;
1657 }
1658
1659 // Shortcut out here for async functions
1660 if (tfunction->is_async()) {
1661 f_service_ <<
1662 indent() << "return;" << endl;
Mark Sleea3f39722006-10-26 02:52:47 +00001663 scope_down(f_service_);
1664
1665 // Close class
Mark Slee78f58e22006-09-02 04:17:07 +00001666 indent_down();
Mark Sleea3f39722006-10-26 02:52:47 +00001667 f_service_ <<
1668 indent() << "}" << endl <<
Mark Slee78f58e22006-09-02 04:17:07 +00001669 endl;
1670 return;
1671 }
1672
1673 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001674 indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.REPLY, seqid));" << endl <<
1675 indent() << "result.write(oprot);" << endl <<
1676 indent() << "oprot.writeMessageEnd();" << endl <<
Mark Slee9f8361f2007-02-09 02:14:43 +00001677 indent() << "oprot.getTransport().flush();" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001678
1679 // Close function
1680 scope_down(f_service_);
1681 f_service_ << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00001682
1683 // Close class
1684 indent_down();
1685 f_service_ <<
1686 indent() << "}" << endl <<
1687 endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001688}
1689
1690/**
1691 * Deserializes a field of any type.
Mark Sleef5377b32006-10-10 01:42:59 +00001692 *
1693 * @param tfield The field
1694 * @param prefix The variable name or container for this field
Mark Sleeb15a68b2006-06-07 06:46:24 +00001695 */
Mark Slee78f58e22006-09-02 04:17:07 +00001696void t_java_generator::generate_deserialize_field(ofstream& out,
1697 t_field* tfield,
1698 string prefix) {
David Reisse087a302007-08-23 21:43:25 +00001699 t_type* type = get_true_type(tfield->get_type());
Mark Sleeb15a68b2006-06-07 06:46:24 +00001700
1701 if (type->is_void()) {
1702 throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " +
1703 prefix + tfield->get_name();
1704 }
1705
1706 string name = prefix + tfield->get_name();
1707
Mark Slee78f58e22006-09-02 04:17:07 +00001708 if (type->is_struct() || type->is_xception()) {
1709 generate_deserialize_struct(out,
Mark Slee216e7d62006-11-21 00:44:23 +00001710 (t_struct*)type,
Mark Slee78f58e22006-09-02 04:17:07 +00001711 name);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001712 } else if (type->is_container()) {
Mark Slee216e7d62006-11-21 00:44:23 +00001713 generate_deserialize_container(out, type, name);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001714 } else if (type->is_base_type() || type->is_enum()) {
1715
Mark Slee78f58e22006-09-02 04:17:07 +00001716 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001717 name << " = iprot.";
Mark Slee5ab57052007-11-27 08:38:16 +00001718
Mark Sleeb15a68b2006-06-07 06:46:24 +00001719 if (type->is_base_type()) {
1720 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
1721 switch (tbase) {
1722 case t_base_type::TYPE_VOID:
1723 throw "compiler error: cannot serialize void field in a struct: " +
1724 name;
1725 break;
Mark Slee5ab57052007-11-27 08:38:16 +00001726 case t_base_type::TYPE_STRING:
Mark Slee8d725a22007-04-13 01:57:12 +00001727 if (((t_base_type*)type)->is_binary()) {
1728 out << "readBinary();";
1729 } else {
1730 out << "readString();";
1731 }
Mark Slee78f58e22006-09-02 04:17:07 +00001732 break;
1733 case t_base_type::TYPE_BOOL:
Mark Slee575fa9a2006-10-25 20:54:10 +00001734 out << "readBool();";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001735 break;
1736 case t_base_type::TYPE_BYTE:
Mark Slee575fa9a2006-10-25 20:54:10 +00001737 out << "readByte();";
Mark Slee78f58e22006-09-02 04:17:07 +00001738 break;
1739 case t_base_type::TYPE_I16:
Mark Slee575fa9a2006-10-25 20:54:10 +00001740 out << "readI16();";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001741 break;
1742 case t_base_type::TYPE_I32:
Mark Slee575fa9a2006-10-25 20:54:10 +00001743 out << "readI32();";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001744 break;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001745 case t_base_type::TYPE_I64:
Mark Slee575fa9a2006-10-25 20:54:10 +00001746 out << "readI64();";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001747 break;
Mark Sleec98d0502006-09-06 02:42:25 +00001748 case t_base_type::TYPE_DOUBLE:
Mark Slee575fa9a2006-10-25 20:54:10 +00001749 out << "readDouble();";
Mark Sleec98d0502006-09-06 02:42:25 +00001750 break;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001751 default:
David Reissdd7796f2007-08-28 21:09:06 +00001752 throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001753 }
1754 } else if (type->is_enum()) {
Mark Slee575fa9a2006-10-25 20:54:10 +00001755 out << "readI32();";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001756 }
Mark Slee78f58e22006-09-02 04:17:07 +00001757 out <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00001758 endl;
1759 } else {
1760 printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
1761 tfield->get_name().c_str(), type_name(type).c_str());
1762 }
1763}
1764
1765/**
Mark Sleef5377b32006-10-10 01:42:59 +00001766 * Generates an unserializer for a struct, invokes read()
Mark Sleeb15a68b2006-06-07 06:46:24 +00001767 */
Mark Slee78f58e22006-09-02 04:17:07 +00001768void t_java_generator::generate_deserialize_struct(ofstream& out,
1769 t_struct* tstruct,
1770 string prefix) {
1771 out <<
Mark Sleef0712dc2006-10-25 19:03:57 +00001772 indent() << prefix << " = new " << type_name(tstruct) << "();" << endl <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001773 indent() << prefix << ".read(iprot);" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001774}
1775
Mark Sleef5377b32006-10-10 01:42:59 +00001776/**
1777 * Deserializes a container by reading its size and then iterating
1778 */
Mark Slee78f58e22006-09-02 04:17:07 +00001779void t_java_generator::generate_deserialize_container(ofstream& out,
1780 t_type* ttype,
1781 string prefix) {
1782 scope_up(out);
Mark Slee5ab57052007-11-27 08:38:16 +00001783
Mark Sleeb15a68b2006-06-07 06:46:24 +00001784 string obj;
1785
1786 if (ttype->is_map()) {
1787 obj = tmp("_map");
1788 } else if (ttype->is_set()) {
1789 obj = tmp("_set");
1790 } else if (ttype->is_list()) {
1791 obj = tmp("_list");
1792 }
1793
1794 // Declare variables, read header
1795 if (ttype->is_map()) {
eletuchy447d7d232007-06-13 04:24:11 +00001796 indent(out) << "TMap " << obj << " = iprot.readMapBegin();" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001797 } else if (ttype->is_set()) {
eletuchy447d7d232007-06-13 04:24:11 +00001798 indent(out) << "TSet " << obj << " = iprot.readSetBegin();" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001799 } else if (ttype->is_list()) {
eletuchy447d7d232007-06-13 04:24:11 +00001800 indent(out) << "TList " << obj << " = iprot.readListBegin();" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001801 }
1802
eletuchy447d7d232007-06-13 04:24:11 +00001803 indent(out)
Mark Slee5ab57052007-11-27 08:38:16 +00001804 << prefix << " = new " << type_name(ttype, false, true)
eletuchy447d7d232007-06-13 04:24:11 +00001805 // size the collection correctly
Mark Slee5ab57052007-11-27 08:38:16 +00001806 << "("
eletuchy447d7d232007-06-13 04:24:11 +00001807 << (ttype->is_list() ? "" : "2*" )
1808 << obj << ".size"
1809 << ");" << endl;
1810
Mark Sleeb15a68b2006-06-07 06:46:24 +00001811 // For loop iterates over elements
1812 string i = tmp("_i");
Mark Slee78f58e22006-09-02 04:17:07 +00001813 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00001814 "for (int " << i << " = 0; " <<
Mark Slee52f643d2006-08-09 00:03:43 +00001815 i << " < " << obj << ".size" << "; " <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00001816 "++" << i << ")" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +00001817
Mark Slee78f58e22006-09-02 04:17:07 +00001818 scope_up(out);
Mark Slee5ab57052007-11-27 08:38:16 +00001819
Mark Sleeb15a68b2006-06-07 06:46:24 +00001820 if (ttype->is_map()) {
Mark Slee78f58e22006-09-02 04:17:07 +00001821 generate_deserialize_map_element(out, (t_map*)ttype, prefix);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001822 } else if (ttype->is_set()) {
Mark Slee78f58e22006-09-02 04:17:07 +00001823 generate_deserialize_set_element(out, (t_set*)ttype, prefix);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001824 } else if (ttype->is_list()) {
Mark Slee78f58e22006-09-02 04:17:07 +00001825 generate_deserialize_list_element(out, (t_list*)ttype, prefix);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001826 }
Mark Slee5ab57052007-11-27 08:38:16 +00001827
Mark Slee78f58e22006-09-02 04:17:07 +00001828 scope_down(out);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001829
1830 // Read container end
1831 if (ttype->is_map()) {
Mark Slee575fa9a2006-10-25 20:54:10 +00001832 indent(out) << "iprot.readMapEnd();" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001833 } else if (ttype->is_set()) {
Mark Slee575fa9a2006-10-25 20:54:10 +00001834 indent(out) << "iprot.readSetEnd();" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001835 } else if (ttype->is_list()) {
Mark Slee575fa9a2006-10-25 20:54:10 +00001836 indent(out) << "iprot.readListEnd();" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001837 }
1838
Mark Slee78f58e22006-09-02 04:17:07 +00001839 scope_down(out);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001840}
1841
1842
1843/**
1844 * Generates code to deserialize a map
1845 */
Mark Slee78f58e22006-09-02 04:17:07 +00001846void t_java_generator::generate_deserialize_map_element(ofstream& out,
1847 t_map* tmap,
Mark Sleeb15a68b2006-06-07 06:46:24 +00001848 string prefix) {
1849 string key = tmp("_key");
1850 string val = tmp("_val");
1851 t_field fkey(tmap->get_key_type(), key);
1852 t_field fval(tmap->get_val_type(), val);
1853
Mark Slee78f58e22006-09-02 04:17:07 +00001854 indent(out) <<
Mark Slee7ff32452007-02-01 05:26:18 +00001855 declare_field(&fkey) << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001856 indent(out) <<
Mark Slee7ff32452007-02-01 05:26:18 +00001857 declare_field(&fval) << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001858
Mark Slee78f58e22006-09-02 04:17:07 +00001859 generate_deserialize_field(out, &fkey);
1860 generate_deserialize_field(out, &fval);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001861
Mark Slee78f58e22006-09-02 04:17:07 +00001862 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00001863 prefix << ".put(" << key << ", " << val << ");" << endl;
1864}
1865
Mark Sleef5377b32006-10-10 01:42:59 +00001866/**
1867 * Deserializes a set element
1868 */
Mark Slee78f58e22006-09-02 04:17:07 +00001869void t_java_generator::generate_deserialize_set_element(ofstream& out,
1870 t_set* tset,
Mark Sleeb15a68b2006-06-07 06:46:24 +00001871 string prefix) {
1872 string elem = tmp("_elem");
1873 t_field felem(tset->get_elem_type(), elem);
1874
Mark Slee78f58e22006-09-02 04:17:07 +00001875 indent(out) <<
Mark Slee9860ee22007-11-30 01:43:36 +00001876 declare_field(&felem) << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001877
Mark Slee78f58e22006-09-02 04:17:07 +00001878 generate_deserialize_field(out, &felem);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001879
Mark Slee78f58e22006-09-02 04:17:07 +00001880 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00001881 prefix << ".add(" << elem << ");" << endl;
1882}
1883
Mark Sleef5377b32006-10-10 01:42:59 +00001884/**
1885 * Deserializes a list element
1886 */
Mark Slee78f58e22006-09-02 04:17:07 +00001887void t_java_generator::generate_deserialize_list_element(ofstream& out,
1888 t_list* tlist,
Mark Sleeb15a68b2006-06-07 06:46:24 +00001889 string prefix) {
1890 string elem = tmp("_elem");
1891 t_field felem(tlist->get_elem_type(), elem);
1892
Mark Slee78f58e22006-09-02 04:17:07 +00001893 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00001894 declare_field(&felem, true) << endl;
1895
Mark Slee78f58e22006-09-02 04:17:07 +00001896 generate_deserialize_field(out, &felem);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001897
Mark Slee78f58e22006-09-02 04:17:07 +00001898 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00001899 prefix << ".add(" << elem << ");" << endl;
1900}
1901
1902
1903/**
1904 * Serializes a field of any type.
1905 *
1906 * @param tfield The field to serialize
1907 * @param prefix Name to prepend to field name
1908 */
Mark Slee78f58e22006-09-02 04:17:07 +00001909void t_java_generator::generate_serialize_field(ofstream& out,
1910 t_field* tfield,
1911 string prefix) {
David Reisse087a302007-08-23 21:43:25 +00001912 t_type* type = get_true_type(tfield->get_type());
Mark Sleeb15a68b2006-06-07 06:46:24 +00001913
1914 // Do nothing for void types
1915 if (type->is_void()) {
1916 throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " +
1917 prefix + tfield->get_name();
1918 }
Mark Slee5ab57052007-11-27 08:38:16 +00001919
Mark Slee78f58e22006-09-02 04:17:07 +00001920 if (type->is_struct() || type->is_xception()) {
1921 generate_serialize_struct(out,
Mark Slee216e7d62006-11-21 00:44:23 +00001922 (t_struct*)type,
Mark Slee78f58e22006-09-02 04:17:07 +00001923 prefix + tfield->get_name());
Mark Sleeb15a68b2006-06-07 06:46:24 +00001924 } else if (type->is_container()) {
Mark Slee78f58e22006-09-02 04:17:07 +00001925 generate_serialize_container(out,
Mark Slee216e7d62006-11-21 00:44:23 +00001926 type,
Mark Sleeb15a68b2006-06-07 06:46:24 +00001927 prefix + tfield->get_name());
1928 } else if (type->is_base_type() || type->is_enum()) {
1929
1930 string name = prefix + tfield->get_name();
Mark Slee78f58e22006-09-02 04:17:07 +00001931 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001932 "oprot.";
Mark Slee5ab57052007-11-27 08:38:16 +00001933
Mark Sleeb15a68b2006-06-07 06:46:24 +00001934 if (type->is_base_type()) {
1935 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
1936 switch (tbase) {
1937 case t_base_type::TYPE_VOID:
1938 throw
1939 "compiler error: cannot serialize void field in a struct: " + name;
1940 break;
1941 case t_base_type::TYPE_STRING:
Mark Slee8d725a22007-04-13 01:57:12 +00001942 if (((t_base_type*)type)->is_binary()) {
1943 out << "writeBinary(" << name << ");";
1944 } else {
1945 out << "writeString(" << name << ");";
1946 }
Mark Slee78f58e22006-09-02 04:17:07 +00001947 break;
1948 case t_base_type::TYPE_BOOL:
Mark Slee575fa9a2006-10-25 20:54:10 +00001949 out << "writeBool(" << name << ");";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001950 break;
1951 case t_base_type::TYPE_BYTE:
Mark Slee575fa9a2006-10-25 20:54:10 +00001952 out << "writeByte(" << name << ");";
Mark Slee78f58e22006-09-02 04:17:07 +00001953 break;
1954 case t_base_type::TYPE_I16:
Mark Slee575fa9a2006-10-25 20:54:10 +00001955 out << "writeI16(" << name << ");";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001956 break;
1957 case t_base_type::TYPE_I32:
Mark Slee575fa9a2006-10-25 20:54:10 +00001958 out << "writeI32(" << name << ");";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001959 break;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001960 case t_base_type::TYPE_I64:
Mark Slee575fa9a2006-10-25 20:54:10 +00001961 out << "writeI64(" << name << ");";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001962 break;
Mark Sleec98d0502006-09-06 02:42:25 +00001963 case t_base_type::TYPE_DOUBLE:
Mark Slee575fa9a2006-10-25 20:54:10 +00001964 out << "writeDouble(" << name << ");";
Mark Sleec98d0502006-09-06 02:42:25 +00001965 break;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001966 default:
David Reissdd7796f2007-08-28 21:09:06 +00001967 throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001968 }
1969 } else if (type->is_enum()) {
Mark Slee575fa9a2006-10-25 20:54:10 +00001970 out << "writeI32(" << name << ");";
Mark Sleeb15a68b2006-06-07 06:46:24 +00001971 }
Mark Slee78f58e22006-09-02 04:17:07 +00001972 out << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001973 } else {
1974 printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
1975 prefix.c_str(),
1976 tfield->get_name().c_str(),
1977 type_name(type).c_str());
1978 }
1979}
1980
1981/**
1982 * Serializes all the members of a struct.
1983 *
1984 * @param tstruct The struct to serialize
1985 * @param prefix String prefix to attach to all fields
1986 */
Mark Slee78f58e22006-09-02 04:17:07 +00001987void t_java_generator::generate_serialize_struct(ofstream& out,
1988 t_struct* tstruct,
Mark Sleeb15a68b2006-06-07 06:46:24 +00001989 string prefix) {
Mark Slee78f58e22006-09-02 04:17:07 +00001990 out <<
Mark Slee575fa9a2006-10-25 20:54:10 +00001991 indent() << prefix << ".write(oprot);" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001992}
1993
Mark Sleef5377b32006-10-10 01:42:59 +00001994/**
1995 * Serializes a container by writing its size then the elements.
1996 *
1997 * @param ttype The type of container
1998 * @param prefix String prefix for fields
1999 */
Mark Slee78f58e22006-09-02 04:17:07 +00002000void t_java_generator::generate_serialize_container(ofstream& out,
2001 t_type* ttype,
Mark Sleeb15a68b2006-06-07 06:46:24 +00002002 string prefix) {
Mark Slee78f58e22006-09-02 04:17:07 +00002003 scope_up(out);
Mark Slee5ab57052007-11-27 08:38:16 +00002004
Mark Sleeb15a68b2006-06-07 06:46:24 +00002005 if (ttype->is_map()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002006 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00002007 "oprot.writeMapBegin(new TMap(" <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00002008 type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
2009 type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
2010 prefix << ".size()));" << endl;
2011 } else if (ttype->is_set()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002012 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00002013 "oprot.writeSetBegin(new TSet(" <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00002014 type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
2015 prefix << ".size()));" << endl;
2016 } else if (ttype->is_list()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002017 indent(out) <<
Mark Slee575fa9a2006-10-25 20:54:10 +00002018 "oprot.writeListBegin(new TList(" <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00002019 type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
2020 prefix << ".size()));" << endl;
2021 }
2022
2023 string iter = tmp("_iter");
2024 if (ttype->is_map()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002025 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00002026 "for (" <<
2027 type_name(((t_map*)ttype)->get_key_type()) << " " << iter <<
2028 " : " <<
2029 prefix << ".keySet())";
2030 } else if (ttype->is_set()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002031 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00002032 "for (" <<
2033 type_name(((t_set*)ttype)->get_elem_type()) << " " << iter <<
2034 " : " <<
2035 prefix << ")";
2036 } else if (ttype->is_list()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002037 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00002038 "for (" <<
2039 type_name(((t_list*)ttype)->get_elem_type()) << " " << iter <<
2040 " : " <<
2041 prefix << ")";
2042 }
2043
Mark Slee78f58e22006-09-02 04:17:07 +00002044 scope_up(out);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002045
2046 if (ttype->is_map()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002047 generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002048 } else if (ttype->is_set()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002049 generate_serialize_set_element(out, (t_set*)ttype, iter);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002050 } else if (ttype->is_list()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002051 generate_serialize_list_element(out, (t_list*)ttype, iter);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002052 }
Mark Slee5ab57052007-11-27 08:38:16 +00002053
Mark Slee78f58e22006-09-02 04:17:07 +00002054 scope_down(out);
Mark Slee5ab57052007-11-27 08:38:16 +00002055
2056 if (ttype->is_map()) {
2057 indent(out) <<
2058 "oprot.writeMapEnd();" << endl;
2059 } else if (ttype->is_set()) {
2060 indent(out) <<
2061 "oprot.writeSetEnd();" << endl;
2062 } else if (ttype->is_list()) {
2063 indent(out) <<
2064 "oprot.writeListEnd();" << endl;
2065 }
2066
2067 scope_down(out);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002068}
2069
2070/**
2071 * Serializes the members of a map.
Mark Slee5ab57052007-11-27 08:38:16 +00002072 */
Mark Slee78f58e22006-09-02 04:17:07 +00002073void t_java_generator::generate_serialize_map_element(ofstream& out,
2074 t_map* tmap,
Mark Sleeb15a68b2006-06-07 06:46:24 +00002075 string iter,
2076 string map) {
2077 t_field kfield(tmap->get_key_type(), iter);
Mark Slee78f58e22006-09-02 04:17:07 +00002078 generate_serialize_field(out, &kfield, "");
Mark Sleeb15a68b2006-06-07 06:46:24 +00002079 t_field vfield(tmap->get_val_type(), map + ".get(" + iter + ")");
Mark Slee78f58e22006-09-02 04:17:07 +00002080 generate_serialize_field(out, &vfield, "");
Mark Sleeb15a68b2006-06-07 06:46:24 +00002081}
2082
2083/**
2084 * Serializes the members of a set.
2085 */
Mark Slee78f58e22006-09-02 04:17:07 +00002086void t_java_generator::generate_serialize_set_element(ofstream& out,
2087 t_set* tset,
Mark Sleeb15a68b2006-06-07 06:46:24 +00002088 string iter) {
2089 t_field efield(tset->get_elem_type(), iter);
Mark Slee78f58e22006-09-02 04:17:07 +00002090 generate_serialize_field(out, &efield, "");
Mark Sleeb15a68b2006-06-07 06:46:24 +00002091}
2092
2093/**
2094 * Serializes the members of a list.
2095 */
Mark Slee78f58e22006-09-02 04:17:07 +00002096void t_java_generator::generate_serialize_list_element(ofstream& out,
2097 t_list* tlist,
2098 string iter) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002099 t_field efield(tlist->get_elem_type(), iter);
Mark Slee78f58e22006-09-02 04:17:07 +00002100 generate_serialize_field(out, &efield, "");
Mark Sleeb15a68b2006-06-07 06:46:24 +00002101}
2102
2103/**
2104 * Returns a Java type name
2105 *
2106 * @param ttype The type
Mark Slee52f643d2006-08-09 00:03:43 +00002107 * @param container Is the type going inside a container?
Mark Sleef5377b32006-10-10 01:42:59 +00002108 * @return Java type name, i.e. HashMap<Key,Value>
Mark Sleeb15a68b2006-06-07 06:46:24 +00002109 */
Mark Slee725f9e62006-10-31 05:08:33 +00002110string t_java_generator::type_name(t_type* ttype, bool in_container, bool in_init) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002111 // In Java typedefs are just resolved to their real type
David Reisse087a302007-08-23 21:43:25 +00002112 ttype = get_true_type(ttype);
Mark Slee22360b22008-02-09 00:18:32 +00002113 string prefix;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002114
2115 if (ttype->is_base_type()) {
Mark Slee8d725a22007-04-13 01:57:12 +00002116 return base_type_name((t_base_type*)ttype, in_container);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002117 } else if (ttype->is_enum()) {
Mark Slee52f643d2006-08-09 00:03:43 +00002118 return (in_container ? "Integer" : "int");
Mark Sleeb15a68b2006-06-07 06:46:24 +00002119 } else if (ttype->is_map()) {
2120 t_map* tmap = (t_map*) ttype;
Mark Slee725f9e62006-10-31 05:08:33 +00002121 if (in_init) {
2122 prefix = "HashMap";
2123 } else {
Mark Slee22360b22008-02-09 00:18:32 +00002124 prefix = "Map";
Mark Slee725f9e62006-10-31 05:08:33 +00002125 }
2126 return prefix + "<" +
Mark Slee52f643d2006-08-09 00:03:43 +00002127 type_name(tmap->get_key_type(), true) + "," +
2128 type_name(tmap->get_val_type(), true) + ">";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002129 } else if (ttype->is_set()) {
2130 t_set* tset = (t_set*) ttype;
Mark Slee22360b22008-02-09 00:18:32 +00002131 if (in_init) {
2132 prefix = "HashSet<";
2133 } else {
2134 prefix = "Set<";
2135 }
2136 return prefix + type_name(tset->get_elem_type(), true) + ">";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002137 } else if (ttype->is_list()) {
2138 t_list* tlist = (t_list*) ttype;
Mark Slee22360b22008-02-09 00:18:32 +00002139 if (in_init) {
2140 prefix = "ArrayList<";
2141 } else {
2142 prefix = "List<";
2143 }
2144 return prefix + type_name(tlist->get_elem_type(), true) + ">";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002145 }
Mark Sleef0712dc2006-10-25 19:03:57 +00002146
2147 // Check for namespacing
2148 t_program* program = ttype->get_program();
2149 if (program != NULL && program != program_) {
David Reiss771f8c72008-02-27 01:55:25 +00002150 string package = program->get_namespace("java");
Mark Sleef0712dc2006-10-25 19:03:57 +00002151 if (!package.empty()) {
2152 return package + "." + ttype->get_name();
2153 }
2154 }
2155
2156 return ttype->get_name();
Mark Sleeb15a68b2006-06-07 06:46:24 +00002157}
2158
2159/**
2160 * Returns the C++ type that corresponds to the thrift type.
2161 *
2162 * @param tbase The base type
Mark Slee52f643d2006-08-09 00:03:43 +00002163 * @param container Is it going in a Java container?
Mark Sleeb15a68b2006-06-07 06:46:24 +00002164 */
Mark Slee8d725a22007-04-13 01:57:12 +00002165string t_java_generator::base_type_name(t_base_type* type,
Mark Slee52f643d2006-08-09 00:03:43 +00002166 bool in_container) {
Mark Slee8d725a22007-04-13 01:57:12 +00002167 t_base_type::t_base tbase = type->get_base();
2168
Mark Sleeb15a68b2006-06-07 06:46:24 +00002169 switch (tbase) {
2170 case t_base_type::TYPE_VOID:
2171 return "void";
2172 case t_base_type::TYPE_STRING:
Mark Slee8d725a22007-04-13 01:57:12 +00002173 if (type->is_binary()) {
2174 return "byte[]";
2175 } else {
2176 return "String";
2177 }
Mark Slee78f58e22006-09-02 04:17:07 +00002178 case t_base_type::TYPE_BOOL:
David Reissa65a79e2008-01-09 19:20:20 +00002179 return (in_container ? "Boolean" : "boolean");
Mark Sleeb15a68b2006-06-07 06:46:24 +00002180 case t_base_type::TYPE_BYTE:
Mark Slee8c46b1a2008-01-09 19:51:24 +00002181 return (in_container ? "Byte" : "byte");
Mark Slee78f58e22006-09-02 04:17:07 +00002182 case t_base_type::TYPE_I16:
2183 return (in_container ? "Short" : "short");
Mark Sleeb15a68b2006-06-07 06:46:24 +00002184 case t_base_type::TYPE_I32:
Mark Slee52f643d2006-08-09 00:03:43 +00002185 return (in_container ? "Integer" : "int");
Mark Sleeb15a68b2006-06-07 06:46:24 +00002186 case t_base_type::TYPE_I64:
Mark Slee52f643d2006-08-09 00:03:43 +00002187 return (in_container ? "Long" : "long");
Mark Sleec98d0502006-09-06 02:42:25 +00002188 case t_base_type::TYPE_DOUBLE:
2189 return (in_container ? "Double" : "double");
Mark Sleeb15a68b2006-06-07 06:46:24 +00002190 default:
David Reissdd7796f2007-08-28 21:09:06 +00002191 throw "compiler error: no C++ name for base type " + t_base_type::t_base_name(tbase);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002192 }
2193}
2194
2195/**
2196 * Declares a field, which may include initialization as necessary.
2197 *
2198 * @param ttype The type
2199 */
2200string t_java_generator::declare_field(t_field* tfield, bool init) {
2201 // TODO(mcslee): do we ever need to initialize the field?
2202 string result = type_name(tfield->get_type()) + " " + tfield->get_name();
2203 if (init) {
David Reisse087a302007-08-23 21:43:25 +00002204 t_type* ttype = get_true_type(tfield->get_type());
Mark Slee7ff32452007-02-01 05:26:18 +00002205 if (ttype->is_base_type() && tfield->get_value() != NULL) {
2206 ofstream dummy;
2207 result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value());
2208 } else if (ttype->is_base_type()) {
Mark Slee52f643d2006-08-09 00:03:43 +00002209 t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
2210 switch (tbase) {
2211 case t_base_type::TYPE_VOID:
2212 throw "NO T_VOID CONSTRUCT";
2213 case t_base_type::TYPE_STRING:
Mark Slee78f58e22006-09-02 04:17:07 +00002214 result += " = null";
2215 break;
2216 case t_base_type::TYPE_BOOL:
2217 result += " = false";
Mark Slee52f643d2006-08-09 00:03:43 +00002218 break;
2219 case t_base_type::TYPE_BYTE:
Mark Slee78f58e22006-09-02 04:17:07 +00002220 case t_base_type::TYPE_I16:
Mark Slee52f643d2006-08-09 00:03:43 +00002221 case t_base_type::TYPE_I32:
Mark Slee52f643d2006-08-09 00:03:43 +00002222 case t_base_type::TYPE_I64:
Mark Slee52f643d2006-08-09 00:03:43 +00002223 result += " = 0";
2224 break;
Mark Sleec98d0502006-09-06 02:42:25 +00002225 case t_base_type::TYPE_DOUBLE:
2226 result += " = (double)0";
2227 break;
Mark Slee52f643d2006-08-09 00:03:43 +00002228 }
2229
Mark Sleeb7f58ff2006-09-02 21:59:28 +00002230 } else if (ttype->is_enum()) {
Mark Slee52f643d2006-08-09 00:03:43 +00002231 result += " = 0";
Mark Sleeb7f58ff2006-09-02 21:59:28 +00002232 } else if (ttype->is_container()) {
Mark Slee725f9e62006-10-31 05:08:33 +00002233 result += " = new " + type_name(ttype, false, true) + "()";
Mark Slee52f643d2006-08-09 00:03:43 +00002234 } else {
Mark Slee7ff32452007-02-01 05:26:18 +00002235 result += " = new " + type_name(ttype, false, true) + "()";;
Mark Slee52f643d2006-08-09 00:03:43 +00002236 }
Mark Sleeb15a68b2006-06-07 06:46:24 +00002237 }
2238 return result + ";";
2239}
2240
2241/**
2242 * Renders a function signature of the form 'type name(args)'
2243 *
2244 * @param tfunction Function definition
2245 * @return String of rendered function definition
2246 */
2247string t_java_generator::function_signature(t_function* tfunction,
Mark Slee78f58e22006-09-02 04:17:07 +00002248 string prefix) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002249 t_type* ttype = tfunction->get_returntype();
Mark Slee78f58e22006-09-02 04:17:07 +00002250 std::string result =
Mark Sleef5377b32006-10-10 01:42:59 +00002251 type_name(ttype) + " " + prefix + tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ") throws ";
Mark Slee78f58e22006-09-02 04:17:07 +00002252 t_struct* xs = tfunction->get_xceptions();
2253 const std::vector<t_field*>& xceptions = xs->get_members();
2254 vector<t_field*>::const_iterator x_iter;
2255 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
Mark Sleea0f8bdc2007-08-29 04:36:28 +00002256 result += type_name((*x_iter)->get_type(), false, false) + ", ";
Mark Slee78f58e22006-09-02 04:17:07 +00002257 }
2258 result += "TException";
2259 return result;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002260}
2261
2262/**
Mark Sleef5377b32006-10-10 01:42:59 +00002263 * Renders a comma separated field list, with type names
Mark Sleeb15a68b2006-06-07 06:46:24 +00002264 */
2265string t_java_generator::argument_list(t_struct* tstruct) {
2266 string result = "";
2267
2268 const vector<t_field*>& fields = tstruct->get_members();
2269 vector<t_field*>::const_iterator f_iter;
2270 bool first = true;
2271 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2272 if (first) {
2273 first = false;
2274 } else {
2275 result += ", ";
2276 }
2277 result += type_name((*f_iter)->get_type()) + " " + (*f_iter)->get_name();
2278 }
2279 return result;
2280}
2281
2282/**
2283 * Converts the parse type to a C++ enum string for the given type.
2284 */
2285string t_java_generator::type_to_enum(t_type* type) {
David Reisse087a302007-08-23 21:43:25 +00002286 type = get_true_type(type);
Mark Slee5ab57052007-11-27 08:38:16 +00002287
Mark Sleeb15a68b2006-06-07 06:46:24 +00002288 if (type->is_base_type()) {
2289 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2290 switch (tbase) {
2291 case t_base_type::TYPE_VOID:
2292 throw "NO T_VOID CONSTRUCT";
2293 case t_base_type::TYPE_STRING:
2294 return "TType.STRING";
Mark Slee78f58e22006-09-02 04:17:07 +00002295 case t_base_type::TYPE_BOOL:
2296 return "TType.BOOL";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002297 case t_base_type::TYPE_BYTE:
2298 return "TType.BYTE";
Mark Slee78f58e22006-09-02 04:17:07 +00002299 case t_base_type::TYPE_I16:
2300 return "TType.I16";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002301 case t_base_type::TYPE_I32:
2302 return "TType.I32";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002303 case t_base_type::TYPE_I64:
2304 return "TType.I64";
Mark Sleec98d0502006-09-06 02:42:25 +00002305 case t_base_type::TYPE_DOUBLE:
2306 return "TType.DOUBLE";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002307 }
2308 } else if (type->is_enum()) {
2309 return "TType.I32";
Mark Slee78f58e22006-09-02 04:17:07 +00002310 } else if (type->is_struct() || type->is_xception()) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002311 return "TType.STRUCT";
2312 } else if (type->is_map()) {
2313 return "TType.MAP";
2314 } else if (type->is_set()) {
2315 return "TType.SET";
2316 } else if (type->is_list()) {
2317 return "TType.LIST";
2318 }
2319
2320 throw "INVALID TYPE IN type_to_enum: " + type->get_name();
2321}
Mark Slee8775c732007-09-10 22:33:05 +00002322
2323/**
2324 * Emits a JavaDoc comment if the provided object has a doc in Thrift
2325 */
2326void t_java_generator::generate_java_doc(ofstream &out,
2327 t_doc* tdoc) {
2328 if (tdoc->has_doc()) {
2329 indent(out) << "/**" << endl;
2330 stringstream docs(tdoc->get_doc(), ios_base::in);
2331 while (!docs.eof()) {
2332 char line[1024];
2333 docs.getline(line, 1024);
2334 if (strlen(line) > 0 || !docs.eof()) { // skip the empty last line
2335 indent(out) << " * " << line << endl;
2336 }
2337 }
2338 indent(out) << " */" << endl;
2339 }
2340}
David Reisse1404d22008-02-27 01:55:05 +00002341
2342
2343THRIFT_REGISTER_GENERATOR(java, "Java",
2344" beans: Generate bean-style output files.\n"
David Reiss69875352008-03-04 21:10:41 +00002345" hashcode: Generate quality hashCode methods.\n"
David Reisse1404d22008-02-27 01:55:05 +00002346);