1 // Copyright (c) 2006- Facebook
2 // Distributed under the Thrift Software License
4 // See accompanying file LICENSE or visit the Thrift site at:
5 // http://developers.facebook.com/thrift/
10 #include "t_java_generator.h"
15 * Prepares for file generation by opening up the necessary file output
18 * @param tprogram The program to generate
20 void t_java_generator::init_generator() {
21 // Make output directory
22 MKDIR(get_out_dir().c_str());
23 package_name_
= program_
->get_java_package();
25 string dir
= package_name_
;
26 string subdir
= get_out_dir();
27 string::size_type loc
;
28 while ((loc
= dir
.find(".")) != string::npos
) {
29 subdir
= subdir
+ "/" + dir
.substr(0, loc
);
30 MKDIR(subdir
.c_str());
31 dir
= dir
.substr(loc
+1);
34 subdir
= subdir
+ "/" + dir
;
35 MKDIR(subdir
.c_str());
38 package_dir_
= subdir
;
42 * Packages the generated file
44 * @return String of the package, i.e. "package com.facebook.thriftdemo;"
46 string
t_java_generator::java_package() {
47 if (!package_name_
.empty()) {
48 return string("package ") + package_name_
+ ";\n\n";
54 * Prints standard java imports
56 * @return List of imports for Java types that are used in here
58 string
t_java_generator::java_type_imports() {
61 "import java.util.ArrayList;\n" +
62 "import java.util.AbstractMap;\n" +
63 "import java.util.HashMap;\n" +
64 "import java.util.HashSet;\n" +
65 "import com.facebook.thrift.*;\n\n";
69 * Prints standard java imports
71 * @return List of imports necessary for thrift
73 string
t_java_generator::java_thrift_imports() {
76 "import com.facebook.thrift.protocol.*;\n" +
77 "import com.facebook.thrift.transport.*;\n\n";
83 void t_java_generator::close_generator() {}
86 * Generates a typedef. This is not done in Java, since it does
87 * not support arbitrary name replacements, and it'd be a wacky waste
88 * of overhead to make wrapper classes.
90 * @param ttypedef The type definition
92 void t_java_generator::generate_typedef(t_typedef
* ttypedef
) {}
95 * Enums are a class with a set of static constants.
97 * @param tenum The enumeration
99 void t_java_generator::generate_enum(t_enum
* tenum
) {
101 string f_enum_name
= package_dir_
+"/"+(tenum
->get_name())+".java";
103 f_enum
.open(f_enum_name
.c_str());
105 // Comment and package it
108 java_package() << endl
;
111 "public class " << tenum
->get_name() << " ";
114 vector
<t_enum_value
*> constants
= tenum
->get_constants();
115 vector
<t_enum_value
*>::iterator c_iter
;
117 for (c_iter
= constants
.begin(); c_iter
!= constants
.end(); ++c_iter
) {
118 if ((*c_iter
)->has_value()) {
119 value
= (*c_iter
)->get_value();
125 "public static final int " << (*c_iter
)->get_name() <<
126 " = " << value
<< ";" << endl
;
134 * Generates a class that holds all the constants.
136 void t_java_generator::generate_consts(std::vector
<t_const
*> consts
) {
137 string f_consts_name
= package_dir_
+"/Constants.java";
139 f_consts
.open(f_consts_name
.c_str());
148 "public class Constants {" << endl
<<
151 vector
<t_const
*>::iterator c_iter
;
152 for (c_iter
= consts
.begin(); c_iter
!= consts
.end(); ++c_iter
) {
153 print_const_value(f_consts
,
154 (*c_iter
)->get_name(),
155 (*c_iter
)->get_type(),
156 (*c_iter
)->get_value(),
167 * Prints the value of a constant with the given type. Note that type checking
168 * is NOT performed in this function as it is always run beforehand using the
169 * validate_types method in main.cc
171 void t_java_generator::print_const_value(std::ofstream
& out
, string name
, t_type
* type
, t_const_value
* value
, bool in_static
, bool defval
) {
176 (in_static
? "" : "public static final ") <<
177 type_name(type
) << " ";
179 if (type
->is_base_type()) {
180 string v2
= render_const_value(out
, name
, type
, value
);
181 out
<< name
<< " = " << v2
<< ";" << endl
<< endl
;
182 } else if (type
->is_enum()) {
183 out
<< name
<< " = " << value
->get_integer() << ";" << endl
<< endl
;
184 } else if (type
->is_struct() || type
->is_xception()) {
185 const vector
<t_field
*>& fields
= ((t_struct
*)type
)->get_members();
186 vector
<t_field
*>::const_iterator f_iter
;
187 const map
<t_const_value
*, t_const_value
*>& val
= value
->get_map();
188 map
<t_const_value
*, t_const_value
*>::const_iterator v_iter
;
189 out
<< name
<< " = new " << type_name(type
) << "();" << endl
;
191 indent(out
) << "static {" << endl
;
194 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
195 t_type
* field_type
= NULL
;
196 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
197 if ((*f_iter
)->get_name() == v_iter
->first
->get_string()) {
198 field_type
= (*f_iter
)->get_type();
201 if (field_type
== NULL
) {
202 throw "type error: " + type
->get_name() + " has no field " + v_iter
->first
->get_string();
204 string val
= render_const_value(out
, name
, field_type
, v_iter
->second
);
205 indent(out
) << name
<< "." << v_iter
->first
->get_string() << " = " << val
<< ";" << endl
;
206 indent(out
) << name
<< ".__isset." << v_iter
->first
->get_string() << " = true;" << endl
;
210 indent(out
) << "}" << endl
;
213 } else if (type
->is_map()) {
214 out
<< name
<< " = new " << type_name(type
, true, true) << "();" << endl
;
216 indent(out
) << "static {" << endl
;
219 t_type
* ktype
= ((t_map
*)type
)->get_key_type();
220 t_type
* vtype
= ((t_map
*)type
)->get_val_type();
221 const map
<t_const_value
*, t_const_value
*>& val
= value
->get_map();
222 map
<t_const_value
*, t_const_value
*>::const_iterator v_iter
;
223 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
224 string key
= render_const_value(out
, name
, ktype
, v_iter
->first
);
225 string val
= render_const_value(out
, name
, vtype
, v_iter
->second
);
226 indent(out
) << name
<< ".put(" << key
<< ", " << val
<< ");" << endl
;
230 indent(out
) << "}" << endl
;
233 } else if (type
->is_list() || type
->is_set()) {
234 out
<< name
<< " = new " << type_name(type
) << "();" << endl
;
236 indent(out
) << "static {" << endl
;
240 if (type
->is_list()) {
241 etype
= ((t_list
*)type
)->get_elem_type();
243 etype
= ((t_set
*)type
)->get_elem_type();
245 const vector
<t_const_value
*>& val
= value
->get_list();
246 vector
<t_const_value
*>::const_iterator v_iter
;
247 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
248 string val
= render_const_value(out
, name
, etype
, *v_iter
);
249 indent(out
) << name
<< ".add(" << val
<< ");" << endl
;
253 indent(out
) << "}" << endl
;
259 string
t_java_generator::render_const_value(ofstream
& out
, string name
, t_type
* type
, t_const_value
* value
) {
260 std::ostringstream render
;
262 if (type
->is_base_type()) {
263 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
265 case t_base_type::TYPE_STRING
:
266 render
<< "\"" + value
->get_string() + "\"";
268 case t_base_type::TYPE_BOOL
:
269 render
<< ((value
->get_integer() > 0) ? "true" : "false");
271 case t_base_type::TYPE_BYTE
:
272 case t_base_type::TYPE_I16
:
273 case t_base_type::TYPE_I32
:
274 case t_base_type::TYPE_I64
:
275 render
<< value
->get_integer();
277 case t_base_type::TYPE_DOUBLE
:
278 if (value
->get_type() == t_const_value::CV_INTEGER
) {
279 render
<< value
->get_integer();
281 render
<< value
->get_double();
285 throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase
);
287 } else if (type
->is_enum()) {
288 render
<< value
->get_integer();
290 string t
= tmp("tmp");
291 print_const_value(out
, t
, type
, value
, true);
299 * Generates a struct definition for a thrift data type. This is a class
300 * with data members, read(), write(), and an inner Isset class.
302 * @param tstruct The struct definition
304 void t_java_generator::generate_struct(t_struct
* tstruct
) {
305 generate_java_struct(tstruct
, false);
309 * Exceptions are structs, but they inherit from Exception
311 * @param tstruct The struct definition
313 void t_java_generator::generate_xception(t_struct
* txception
) {
314 generate_java_struct(txception
, true);
319 * Java struct definition.
321 * @param tstruct The struct definition
323 void t_java_generator::generate_java_struct(t_struct
* tstruct
,
326 string f_struct_name
= package_dir_
+"/"+(tstruct
->get_name())+".java";
328 f_struct
.open(f_struct_name
.c_str());
333 java_type_imports() <<
334 java_thrift_imports();
336 generate_java_struct_definition(f_struct
,
343 * Java struct definition. This has various parameters, as it could be
344 * generated standalone or inside another class as a helper. If it
345 * is a helper than it is a static class.
347 * @param tstruct The struct definition
348 * @param is_exception Is this an exception?
349 * @param in_class If inside a class, needs to be static class
350 * @param is_result If this is a result it needs a different writer
352 void t_java_generator::generate_java_struct_definition(ofstream
&out
,
357 generate_java_doc(out
, tstruct
);
360 "public " << (in_class
? "static " : "") << "class " << tstruct
->get_name() << " ";
363 out
<< "extends Exception ";
365 out
<< "implements TBase, java.io.Serializable ";
369 // Members are public for -java, private for -javabean
370 const vector
<t_field
*>& members
= tstruct
->get_members();
371 vector
<t_field
*>::const_iterator m_iter
;
372 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
374 indent(out
) << "private ";
376 indent(out
) << "public ";
378 out
<< declare_field(*m_iter
, false) << endl
;
382 if (members
.size() > 0) {
385 indent() << "public final Isset __isset = new Isset();" << endl
<<
386 indent() << "public static final class Isset {" << endl
;
388 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
390 "public boolean " << (*m_iter
)->get_name() << " = false;" << endl
;
394 indent() << "}" << endl
<<
398 // Default constructor
400 "public " << tstruct
->get_name() << "() {" << endl
;
402 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
403 t_type
* t
= get_true_type((*m_iter
)->get_type());
404 if ((*m_iter
)->get_value() != NULL
) {
405 print_const_value(out
, "this." + (*m_iter
)->get_name(), t
, (*m_iter
)->get_value(), true, true);
409 indent(out
) << "}" << endl
<< endl
;
412 // Full constructor for all fields
413 if (!members
.empty()) {
415 "public " << tstruct
->get_name() << "(" << endl
;
417 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ) {
418 indent(out
) << type_name((*m_iter
)->get_type()) << " " <<
419 (*m_iter
)->get_name();
421 if (m_iter
!= members
.end()) {
427 indent(out
) << "{" << endl
;
429 indent(out
) << "this();" << endl
;
430 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
431 indent(out
) << "this." << (*m_iter
)->get_name() << " = " <<
432 (*m_iter
)->get_name() << ";" << endl
;
433 indent(out
) << "this.__isset." << (*m_iter
)->get_name() << " = true;" << endl
;
436 indent(out
) << "}" << endl
<< endl
;
440 generate_java_bean_boilerplate(out
, tstruct
);
442 generate_java_struct_reader(out
, tstruct
);
444 generate_java_struct_result_writer(out
, tstruct
);
446 generate_java_struct_writer(out
, tstruct
);
448 generate_java_struct_tostring(out
, tstruct
);
454 * Generates a function to read all the fields of the struct.
456 * @param tstruct The struct definition
458 void t_java_generator::generate_java_struct_reader(ofstream
& out
,
461 indent() << "public void read(TProtocol iprot) throws TException {" << endl
;
464 const vector
<t_field
*>& fields
= tstruct
->get_members();
465 vector
<t_field
*>::const_iterator f_iter
;
467 // Declare stack tmp variables and read struct header
469 indent() << "TField field;" << endl
<<
470 indent() << "iprot.readStructBegin();" << endl
;
472 // Loop over reading in fields
474 "while (true)" << endl
;
477 // Read beginning field marker
479 "field = iprot.readFieldBegin();" << endl
;
481 // Check for field STOP marker and break
483 "if (field.type == TType.STOP) { " << endl
;
491 // Switch statement on the field we are reading
493 "switch (field.id)" << endl
;
497 // Generate deserialization code for known cases
498 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
500 "case " << (*f_iter
)->get_key() << ":" << endl
;
503 "if (field.type == " << type_to_enum((*f_iter
)->get_type()) << ") {" << endl
;
506 generate_deserialize_field(out
, *f_iter
, "this.");
508 indent() << "this.__isset." << (*f_iter
)->get_name() << " = true;" << endl
;
511 indent() << "} else { " << endl
<<
512 indent() << " TProtocolUtil.skip(iprot, field.type);" << endl
<<
513 indent() << "}" << endl
<<
514 indent() << "break;" << endl
;
518 // In the default case we skip the field
520 indent() << "default:" << endl
<<
521 indent() << " TProtocolUtil.skip(iprot, field.type);" << endl
<<
522 indent() << " break;" << endl
;
526 // Read field end marker
528 "iprot.readFieldEnd();" << endl
;
533 indent() << "iprot.readStructEnd();" << endl
;
537 indent() << "}" << endl
<<
542 * Generates a function to write all the fields of the struct
544 * @param tstruct The struct definition
546 void t_java_generator::generate_java_struct_writer(ofstream
& out
,
549 indent() << "public void write(TProtocol oprot) throws TException {" << endl
;
552 string name
= tstruct
->get_name();
553 const vector
<t_field
*>& fields
= tstruct
->get_members();
554 vector
<t_field
*>::const_iterator f_iter
;
556 indent(out
) << "TStruct struct = new TStruct(\"" << name
<< "\");" << endl
;
557 indent(out
) << "oprot.writeStructBegin(struct);" << endl
;
559 if (!fields
.empty()) {
560 indent(out
) << "TField field = new TField();" << endl
;
562 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
563 bool null_allowed
= type_can_be_null((*f_iter
)->get_type());
566 indent() << "if (this." << (*f_iter
)->get_name() << " != null) {" << endl
;
569 bool optional
= bean_style_
&& (*f_iter
)->get_req() == t_field::T_OPTIONAL
;
572 indent() << "if (this.__isset." << (*f_iter
)->get_name() << ") {" << endl
;
576 indent() << "field.name = \"" << (*f_iter
)->get_name() << "\";" << endl
<<
577 indent() << "field.type = " << type_to_enum((*f_iter
)->get_type()) << ";" << endl
<<
578 indent() << "field.id = " << (*f_iter
)->get_key() << ";" << endl
<<
579 indent() << "oprot.writeFieldBegin(field);" << endl
;
581 // Write field contents
582 generate_serialize_field(out
, *f_iter
, "this.");
584 // Write field closer
586 "oprot.writeFieldEnd();" << endl
;
590 indent(out
) << "}" << endl
;
594 indent(out
) << "}" << endl
;
597 // Write the struct map
599 indent() << "oprot.writeFieldStop();" << endl
<<
600 indent() << "oprot.writeStructEnd();" << endl
;
604 indent() << "}" << endl
<<
609 * Generates a function to write all the fields of the struct,
610 * which is a function result. These fields are only written
611 * if they are set in the Isset array, and only one of them
612 * can be set at a time.
614 * @param tstruct The struct definition
616 void t_java_generator::generate_java_struct_result_writer(ofstream
& out
,
619 indent() << "public void write(TProtocol oprot) throws TException {" << endl
;
622 string name
= tstruct
->get_name();
623 const vector
<t_field
*>& fields
= tstruct
->get_members();
624 vector
<t_field
*>::const_iterator f_iter
;
626 indent(out
) << "TStruct struct = new TStruct(\"" << name
<< "\");" << endl
;
627 indent(out
) << "oprot.writeStructBegin(struct);" << endl
;
629 if (!fields
.empty()) {
630 indent(out
) << "TField field = new TField();" << endl
;
633 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
645 "(this.__isset." << (*f_iter
)->get_name() << ") {" << endl
;
648 bool null_allowed
= type_can_be_null((*f_iter
)->get_type());
651 indent() << "if (this." << (*f_iter
)->get_name() << " != null) {" << endl
;
656 indent() << "field.name = \"" << (*f_iter
)->get_name() << "\";" << endl
<<
657 indent() << "field.type = " << type_to_enum((*f_iter
)->get_type()) << ";" << endl
<<
658 indent() << "field.id = " << (*f_iter
)->get_key() << ";" << endl
<<
659 indent() << "oprot.writeFieldBegin(field);" << endl
;
661 // Write field contents
662 generate_serialize_field(out
, *f_iter
, "this.");
664 // Write field closer
666 "oprot.writeFieldEnd();" << endl
;
670 indent(out
) << "}" << endl
;
676 // Write the struct map
679 indent() << "oprot.writeFieldStop();" << endl
<<
680 indent() << "oprot.writeStructEnd();" << endl
;
684 indent() << "}" << endl
<<
689 * Generates a set of Java Bean boilerplate functions (setters, getters, etc.)
690 * for the given struct.
692 * @param tstruct The struct definition
694 void t_java_generator::generate_java_bean_boilerplate(ofstream
& out
,
696 const vector
<t_field
*>& fields
= tstruct
->get_members();
697 vector
<t_field
*>::const_iterator f_iter
;
698 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
699 t_field
* field
= *f_iter
;
700 t_type
* type
= get_true_type(field
->get_type());
701 std::string field_name
= field
->get_name();
702 std::string cap_name
= field_name
;
703 cap_name
[0] = toupper(cap_name
[0]);
705 if (type
->is_container()) {
706 // Method to return the size of the collection
707 indent(out
) << "public int get" << cap_name
<< "Size() {" << endl
;
709 indent(out
) << "return (this." << field_name
<< " == null) ? 0 : " <<
710 "this." << field_name
<< ".size();" << endl
;
712 indent(out
) << "}" << endl
<< endl
;
715 if (type
->is_set() || type
->is_list()) {
717 t_type
* element_type
;
718 if (type
->is_set()) {
719 element_type
= ((t_set
*)type
)->get_elem_type();
721 element_type
= ((t_list
*)type
)->get_elem_type();
724 // Iterator getter for sets and lists
725 indent(out
) << "public java.util.Iterator<" <<
726 type_name(element_type
) << "> get" << cap_name
<< "Iterator() {" << endl
;
728 indent(out
) << "return (this." << field_name
<< " == null) ? null : " <<
729 "this." << field_name
<< ".iterator();" << endl
;
731 indent(out
) << "}" << endl
<< endl
;
733 // Add to set or list, create if the set/list is null
734 indent(out
) << "public void addTo" << cap_name
<< "(" <<
735 type_name(element_type
) <<
738 indent(out
) << "if (this." << field_name
<< " == null) {" << endl
;
740 indent(out
) << "this." << field_name
<< " = new " << type_name(type
) <<
743 indent(out
) << "}" << endl
;
744 indent(out
) << "this." << field_name
<< ".add(elem);" << endl
;
745 indent(out
) << "this.__isset." << field_name
<< " = true;" << endl
;
747 indent(out
) << "}" << endl
<< endl
;
749 } else if (type
->is_map()) {
751 t_type
* key_type
= ((t_map
*)type
)->get_key_type();
752 t_type
* val_type
= ((t_map
*)type
)->get_val_type();
753 indent(out
) << "public void putTo" << cap_name
<< "(" <<
754 type_name(key_type
) << " key, " <<
755 type_name(val_type
) << " val) {" << endl
;
757 indent(out
) << "if (this." << field_name
<< " == null) {" << endl
;
759 indent(out
) << "this." << field_name
<< " = new " <<
760 type_name(type
, false, true) << "();" << endl
;
762 indent(out
) << "}" << endl
;
763 indent(out
) << "this." << field_name
<< ".put(key, val);" << endl
;
764 indent(out
) << "this.__isset." << field_name
<< " = true;" << endl
;
766 indent(out
) << "}" << endl
<< endl
;
770 indent(out
) << "public " << type_name(type
);
771 if (type
->is_base_type() &&
772 ((t_base_type
*)type
)->get_base() == t_base_type::TYPE_BOOL
) {
777 out
<< cap_name
<< "() {" << endl
;
779 indent(out
) << "return this." << field_name
<< ";" << endl
;
781 indent(out
) << "}" << endl
<< endl
;
784 indent(out
) << "public void set" << cap_name
<< "(" << type_name(type
) <<
785 " " << field_name
<< ") {" << endl
;
787 indent(out
) << "this." << field_name
<< " = " << field_name
<< ";" <<
789 indent(out
) << "this.__isset." << field_name
<< " = true;" << endl
;
791 indent(out
) << "}" << endl
<< endl
;
794 indent(out
) << "public void unset" << cap_name
<< "() {" << endl
;
796 if (type
->is_container() || type
->is_struct() || type
->is_xception()) {
797 indent(out
) << "this." << field_name
<< " = null;" << endl
;
799 indent(out
) << "this.__isset." << field_name
<< " = false;" << endl
;
801 indent(out
) << "}" << endl
<< endl
;
806 * Generates a toString() method for the given struct
808 * @param tstruct The struct definition
810 void t_java_generator::generate_java_struct_tostring(ofstream
& out
,
813 indent() << "public String toString() {" << endl
;
817 indent() << "StringBuilder sb = new StringBuilder(\"" << tstruct
->get_name() << "(\");" << endl
;
819 const vector
<t_field
*>& fields
= tstruct
->get_members();
820 vector
<t_field
*>::const_iterator f_iter
;
822 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
825 indent(out
) << "sb.append(\"" << (*f_iter
)->get_name() << ":\");" << endl
;
827 indent(out
) << "sb.append(\"," << (*f_iter
)->get_name() << ":\");" << endl
;
829 t_type
* ttype
= (*f_iter
)->get_type();
830 if (ttype
->is_xception() || ttype
->is_struct()) {
831 indent(out
) << "sb.append(this." << (*f_iter
)->get_name() << ".toString());" << endl
;
833 indent(out
) << "sb.append(this." << (*f_iter
)->get_name() << ");" << endl
;
837 indent() << "sb.append(\")\");" << endl
<<
838 indent() << "return sb.toString();" << endl
;
841 indent(out
) << "}" << endl
<<
847 * Generates a thrift service. In C++, this comprises an entirely separate
848 * header and source file. The header file defines the methods and includes
849 * the data types defined in the main header file, and the implementation
850 * file contains implementations of the basic printer and default interfaces.
852 * @param tservice The service definition
854 void t_java_generator::generate_service(t_service
* tservice
) {
856 string f_service_name
= package_dir_
+"/"+service_name_
+".java";
857 f_service_
.open(f_service_name
.c_str());
862 java_type_imports() <<
863 java_thrift_imports();
866 "public class " << service_name_
<< " {" << endl
<<
870 // Generate the three main parts of the service
871 generate_service_interface(tservice
);
872 generate_service_client(tservice
);
873 generate_service_server(tservice
);
874 generate_service_helpers(tservice
);
883 * Generates a service interface definition.
885 * @param tservice The service to generate a header definition for
887 void t_java_generator::generate_service_interface(t_service
* tservice
) {
889 string extends_iface
= "";
890 if (tservice
->get_extends() != NULL
) {
891 extends
= type_name(tservice
->get_extends());
892 extends_iface
= " extends " + extends
+ ".Iface";
895 generate_java_doc(f_service_
, tservice
);
896 f_service_
<< indent() << "public interface Iface" << extends_iface
<<
897 " {" << endl
<< endl
;
899 vector
<t_function
*> functions
= tservice
->get_functions();
900 vector
<t_function
*>::iterator f_iter
;
901 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
902 generate_java_doc(f_service_
, *f_iter
);
903 indent(f_service_
) << "public " << function_signature(*f_iter
) << ";" <<
908 indent() << "}" << endl
<<
913 * Generates structs for all the service args and return types
915 * @param tservice The service
917 void t_java_generator::generate_service_helpers(t_service
* tservice
) {
918 vector
<t_function
*> functions
= tservice
->get_functions();
919 vector
<t_function
*>::iterator f_iter
;
920 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
921 t_struct
* ts
= (*f_iter
)->get_arglist();
922 generate_java_struct_definition(f_service_
, ts
, false, true);
923 generate_function_helpers(*f_iter
);
928 * Generates a service client definition.
930 * @param tservice The service to generate a server for.
932 void t_java_generator::generate_service_client(t_service
* tservice
) {
934 string extends_client
= "";
935 if (tservice
->get_extends() != NULL
) {
936 extends
= type_name(tservice
->get_extends());
937 extends_client
= " extends " + extends
+ ".Client";
940 indent(f_service_
) <<
941 "public static class Client" << extends_client
<< " implements Iface {" << endl
;
944 indent(f_service_
) <<
945 "public Client(TProtocol prot)" << endl
;
946 scope_up(f_service_
);
947 indent(f_service_
) <<
948 "this(prot, prot);" << endl
;
949 scope_down(f_service_
);
952 indent(f_service_
) <<
953 "public Client(TProtocol iprot, TProtocol oprot)" << endl
;
954 scope_up(f_service_
);
955 if (extends
.empty()) {
957 indent() << "iprot_ = iprot;" << endl
<<
958 indent() << "oprot_ = oprot;" << endl
;
961 indent() << "super(iprot, oprot);" << endl
;
963 scope_down(f_service_
);
966 if (extends
.empty()) {
968 indent() << "protected TProtocol iprot_;" << endl
<<
969 indent() << "protected TProtocol oprot_;" << endl
<<
971 indent() << "protected int seqid_;" << endl
<<
975 // Generate client method implementations
976 vector
<t_function
*> functions
= tservice
->get_functions();
977 vector
<t_function
*>::const_iterator f_iter
;
978 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
979 string funname
= (*f_iter
)->get_name();
982 indent(f_service_
) <<
983 "public " << function_signature(*f_iter
) << endl
;
984 scope_up(f_service_
);
985 indent(f_service_
) <<
986 "send_" << funname
<< "(";
988 // Get the struct of function call params
989 t_struct
* arg_struct
= (*f_iter
)->get_arglist();
991 // Declare the function arguments
992 const vector
<t_field
*>& fields
= arg_struct
->get_members();
993 vector
<t_field
*>::const_iterator fld_iter
;
995 for (fld_iter
= fields
.begin(); fld_iter
!= fields
.end(); ++fld_iter
) {
1001 f_service_
<< (*fld_iter
)->get_name();
1003 f_service_
<< ");" << endl
;
1005 if (!(*f_iter
)->is_async()) {
1006 f_service_
<< indent();
1007 if (!(*f_iter
)->get_returntype()->is_void()) {
1008 f_service_
<< "return ";
1011 "recv_" << funname
<< "();" << endl
;
1013 scope_down(f_service_
);
1016 t_function
send_function(g_type_void
,
1017 string("send_") + (*f_iter
)->get_name(),
1018 (*f_iter
)->get_arglist());
1020 string argsname
= (*f_iter
)->get_name() + "_args";
1023 indent(f_service_
) <<
1024 "public " << function_signature(&send_function
) << endl
;
1025 scope_up(f_service_
);
1027 // Serialize the request
1029 indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname
<< "\", TMessageType.CALL, seqid_));" << endl
<<
1030 indent() << argsname
<< " args = new " << argsname
<< "();" << endl
;
1032 for (fld_iter
= fields
.begin(); fld_iter
!= fields
.end(); ++fld_iter
) {
1034 indent() << "args." << (*fld_iter
)->get_name() << " = " << (*fld_iter
)->get_name() << ";" << endl
;
1038 indent() << "args.write(oprot_);" << endl
<<
1039 indent() << "oprot_.writeMessageEnd();" << endl
<<
1040 indent() << "oprot_.getTransport().flush();" << endl
;
1042 scope_down(f_service_
);
1045 if (!(*f_iter
)->is_async()) {
1046 string resultname
= (*f_iter
)->get_name() + "_result";
1048 t_struct
noargs(program_
);
1049 t_function
recv_function((*f_iter
)->get_returntype(),
1050 string("recv_") + (*f_iter
)->get_name(),
1052 (*f_iter
)->get_xceptions());
1054 indent(f_service_
) <<
1055 "public " << function_signature(&recv_function
) << endl
;
1056 scope_up(f_service_
);
1058 // TODO(mcslee): Message validation here, was the seqid etc ok?
1061 indent() << "TMessage msg = iprot_.readMessageBegin();" << endl
<<
1062 indent() << "if (msg.type == TMessageType.EXCEPTION) {" << endl
<<
1063 indent() << " TApplicationException x = TApplicationException.read(iprot_);" << endl
<<
1064 indent() << " iprot_.readMessageEnd();" << endl
<<
1065 indent() << " throw x;" << endl
<<
1066 indent() << "}" << endl
<<
1067 indent() << resultname
<< " result = new " << resultname
<< "();" << endl
<<
1068 indent() << "result.read(iprot_);" << endl
<<
1069 indent() << "iprot_.readMessageEnd();" << endl
;
1071 // Careful, only return _result if not a void function
1072 if (!(*f_iter
)->get_returntype()->is_void()) {
1074 indent() << "if (result.__isset.success) {" << endl
<<
1075 indent() << " return result.success;" << endl
<<
1076 indent() << "}" << endl
;
1079 t_struct
* xs
= (*f_iter
)->get_xceptions();
1080 const std::vector
<t_field
*>& xceptions
= xs
->get_members();
1081 vector
<t_field
*>::const_iterator x_iter
;
1082 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1084 indent() << "if (result.__isset." << (*x_iter
)->get_name() << ") {" << endl
<<
1085 indent() << " throw result." << (*x_iter
)->get_name() << ";" << endl
<<
1086 indent() << "}" << endl
;
1089 // If you get here it's an exception, unless a void function
1090 if ((*f_iter
)->get_returntype()->is_void()) {
1091 indent(f_service_
) <<
1095 indent() << "throw new TApplicationException(TApplicationException.MISSING_RESULT, \"" << (*f_iter
)->get_name() << " failed: unknown result\");" << endl
;
1099 scope_down(f_service_
);
1105 indent(f_service_
) <<
1110 * Generates a service server definition.
1112 * @param tservice The service to generate a server for.
1114 void t_java_generator::generate_service_server(t_service
* tservice
) {
1115 // Generate the dispatch methods
1116 vector
<t_function
*> functions
= tservice
->get_functions();
1117 vector
<t_function
*>::iterator f_iter
;
1120 string extends
= "";
1121 string extends_processor
= "";
1122 if (tservice
->get_extends() != NULL
) {
1123 extends
= type_name(tservice
->get_extends());
1124 extends_processor
= " extends " + extends
+ ".Processor";
1127 // Generate the header portion
1128 indent(f_service_
) <<
1129 "public static class Processor" << extends_processor
<< " implements TProcessor {" << endl
;
1132 indent(f_service_
) <<
1133 "public Processor(Iface iface)" << endl
;
1134 scope_up(f_service_
);
1135 if (!extends
.empty()) {
1137 indent() << "super(iface);" << endl
;
1140 indent() << "iface_ = iface;" << endl
;
1142 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1144 indent() << "processMap_.put(\"" << (*f_iter
)->get_name() << "\", new " << (*f_iter
)->get_name() << "());" << endl
;
1147 scope_down(f_service_
);
1150 if (extends
.empty()) {
1152 indent() << "protected static interface ProcessFunction {" << endl
<<
1153 indent() << " public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException;" << endl
<<
1154 indent() << "}" << endl
<<
1159 indent() << "private Iface iface_;" << endl
;
1161 if (extends
.empty()) {
1163 indent() << "protected final HashMap<String,ProcessFunction> processMap_ = new HashMap<String,ProcessFunction>();" << endl
;
1168 // Generate the server implementation
1169 indent(f_service_
) <<
1170 "public boolean process(TProtocol iprot, TProtocol oprot) throws TException" << endl
;
1171 scope_up(f_service_
);
1174 indent() << "TMessage msg = iprot.readMessageBegin();" << endl
;
1176 // TODO(mcslee): validate message, was the seqid etc. legit?
1179 indent() << "ProcessFunction fn = processMap_.get(msg.name);" << endl
<<
1180 indent() << "if (fn == null) {" << endl
<<
1181 indent() << " TProtocolUtil.skip(iprot, TType.STRUCT);" << endl
<<
1182 indent() << " iprot.readMessageEnd();" << endl
<<
1183 indent() << " TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, \"Invalid method name: '\"+msg.name+\"'\");" << endl
<<
1184 indent() << " oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" << endl
<<
1185 indent() << " x.write(oprot);" << endl
<<
1186 indent() << " oprot.writeMessageEnd();" << endl
<<
1187 indent() << " oprot.getTransport().flush();" << endl
<<
1188 indent() << " return true;" << endl
<<
1189 indent() << "}" << endl
<<
1190 indent() << "fn.process(msg.seqid, iprot, oprot);" << endl
;
1193 indent() << "return true;" << endl
;
1195 scope_down(f_service_
);
1198 // Generate the process subfunctions
1199 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1200 generate_process_function(tservice
, *f_iter
);
1204 indent(f_service_
) <<
1210 * Generates a struct and helpers for a function.
1212 * @param tfunction The function
1214 void t_java_generator::generate_function_helpers(t_function
* tfunction
) {
1215 if (tfunction
->is_async()) {
1219 t_struct
result(program_
, tfunction
->get_name() + "_result");
1220 t_field
success(tfunction
->get_returntype(), "success", 0);
1221 if (!tfunction
->get_returntype()->is_void()) {
1222 result
.append(&success
);
1225 t_struct
* xs
= tfunction
->get_xceptions();
1226 const vector
<t_field
*>& fields
= xs
->get_members();
1227 vector
<t_field
*>::const_iterator f_iter
;
1228 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1229 result
.append(*f_iter
);
1232 generate_java_struct_definition(f_service_
, &result
, false, true, true);
1236 * Generates a process function definition.
1238 * @param tfunction The function to write a dispatcher for
1240 void t_java_generator::generate_process_function(t_service
* tservice
,
1241 t_function
* tfunction
) {
1243 indent(f_service_
) <<
1244 "private class " << tfunction
->get_name() << " implements ProcessFunction {" << endl
;
1248 indent(f_service_
) <<
1249 "public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException" << endl
;
1250 scope_up(f_service_
);
1252 string argsname
= tfunction
->get_name() + "_args";
1253 string resultname
= tfunction
->get_name() + "_result";
1256 indent() << argsname
<< " args = new " << argsname
<< "();" << endl
<<
1257 indent() << "args.read(iprot);" << endl
<<
1258 indent() << "iprot.readMessageEnd();" << endl
;
1260 t_struct
* xs
= tfunction
->get_xceptions();
1261 const std::vector
<t_field
*>& xceptions
= xs
->get_members();
1262 vector
<t_field
*>::const_iterator x_iter
;
1264 // Declare result for non async function
1265 if (!tfunction
->is_async()) {
1267 indent() << resultname
<< " result = new " << resultname
<< "();" << endl
;
1270 // Try block for a function with exceptions
1271 if (xceptions
.size() > 0) {
1273 indent() << "try {" << endl
;
1277 // Generate the function call
1278 t_struct
* arg_struct
= tfunction
->get_arglist();
1279 const std::vector
<t_field
*>& fields
= arg_struct
->get_members();
1280 vector
<t_field
*>::const_iterator f_iter
;
1282 f_service_
<< indent();
1283 if (!tfunction
->is_async() && !tfunction
->get_returntype()->is_void()) {
1284 f_service_
<< "result.success = ";
1287 "iface_." << tfunction
->get_name() << "(";
1289 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1295 f_service_
<< "args." << (*f_iter
)->get_name();
1297 f_service_
<< ");" << endl
;
1299 // Set isset on success field
1300 if (!tfunction
->is_async() && !tfunction
->get_returntype()->is_void()) {
1302 indent() << "result.__isset.success = true;" << endl
;
1305 if (!tfunction
->is_async() && xceptions
.size() > 0) {
1307 f_service_
<< indent() << "}";
1308 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1309 f_service_
<< " catch (" << type_name((*x_iter
)->get_type(), false, false) << " " << (*x_iter
)->get_name() << ") {" << endl
;
1310 if (!tfunction
->is_async()) {
1313 indent() << "result." << (*x_iter
)->get_name() << " = " << (*x_iter
)->get_name() << ";" << endl
<<
1314 indent() << "result.__isset." << (*x_iter
)->get_name() << " = true;" << endl
;
1316 f_service_
<< indent() << "}";
1324 // Shortcut out here for async functions
1325 if (tfunction
->is_async()) {
1327 indent() << "return;" << endl
;
1328 scope_down(f_service_
);
1333 indent() << "}" << endl
<<
1339 indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction
->get_name() << "\", TMessageType.REPLY, seqid));" << endl
<<
1340 indent() << "result.write(oprot);" << endl
<<
1341 indent() << "oprot.writeMessageEnd();" << endl
<<
1342 indent() << "oprot.getTransport().flush();" << endl
;
1345 scope_down(f_service_
);
1351 indent() << "}" << endl
<<
1356 * Deserializes a field of any type.
1358 * @param tfield The field
1359 * @param prefix The variable name or container for this field
1361 void t_java_generator::generate_deserialize_field(ofstream
& out
,
1364 t_type
* type
= get_true_type(tfield
->get_type());
1366 if (type
->is_void()) {
1367 throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " +
1368 prefix
+ tfield
->get_name();
1371 string name
= prefix
+ tfield
->get_name();
1373 if (type
->is_struct() || type
->is_xception()) {
1374 generate_deserialize_struct(out
,
1377 } else if (type
->is_container()) {
1378 generate_deserialize_container(out
, type
, name
);
1379 } else if (type
->is_base_type() || type
->is_enum()) {
1382 name
<< " = iprot.";
1384 if (type
->is_base_type()) {
1385 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1387 case t_base_type::TYPE_VOID
:
1388 throw "compiler error: cannot serialize void field in a struct: " +
1391 case t_base_type::TYPE_STRING
:
1392 if (((t_base_type
*)type
)->is_binary()) {
1393 out
<< "readBinary();";
1395 out
<< "readString();";
1398 case t_base_type::TYPE_BOOL
:
1399 out
<< "readBool();";
1401 case t_base_type::TYPE_BYTE
:
1402 out
<< "readByte();";
1404 case t_base_type::TYPE_I16
:
1405 out
<< "readI16();";
1407 case t_base_type::TYPE_I32
:
1408 out
<< "readI32();";
1410 case t_base_type::TYPE_I64
:
1411 out
<< "readI64();";
1413 case t_base_type::TYPE_DOUBLE
:
1414 out
<< "readDouble();";
1417 throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase
);
1419 } else if (type
->is_enum()) {
1420 out
<< "readI32();";
1425 printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
1426 tfield
->get_name().c_str(), type_name(type
).c_str());
1431 * Generates an unserializer for a struct, invokes read()
1433 void t_java_generator::generate_deserialize_struct(ofstream
& out
,
1437 indent() << prefix
<< " = new " << type_name(tstruct
) << "();" << endl
<<
1438 indent() << prefix
<< ".read(iprot);" << endl
;
1442 * Deserializes a container by reading its size and then iterating
1444 void t_java_generator::generate_deserialize_container(ofstream
& out
,
1451 if (ttype
->is_map()) {
1453 } else if (ttype
->is_set()) {
1455 } else if (ttype
->is_list()) {
1459 // Declare variables, read header
1460 if (ttype
->is_map()) {
1461 indent(out
) << "TMap " << obj
<< " = iprot.readMapBegin();" << endl
;
1462 } else if (ttype
->is_set()) {
1463 indent(out
) << "TSet " << obj
<< " = iprot.readSetBegin();" << endl
;
1464 } else if (ttype
->is_list()) {
1465 indent(out
) << "TList " << obj
<< " = iprot.readListBegin();" << endl
;
1469 << prefix
<< " = new " << type_name(ttype
, false, true)
1470 // size the collection correctly
1472 << (ttype
->is_list() ? "" : "2*" )
1476 // For loop iterates over elements
1477 string i
= tmp("_i");
1479 "for (int " << i
<< " = 0; " <<
1480 i
<< " < " << obj
<< ".size" << "; " <<
1481 "++" << i
<< ")" << endl
;
1485 if (ttype
->is_map()) {
1486 generate_deserialize_map_element(out
, (t_map
*)ttype
, prefix
);
1487 } else if (ttype
->is_set()) {
1488 generate_deserialize_set_element(out
, (t_set
*)ttype
, prefix
);
1489 } else if (ttype
->is_list()) {
1490 generate_deserialize_list_element(out
, (t_list
*)ttype
, prefix
);
1495 // Read container end
1496 if (ttype
->is_map()) {
1497 indent(out
) << "iprot.readMapEnd();" << endl
;
1498 } else if (ttype
->is_set()) {
1499 indent(out
) << "iprot.readSetEnd();" << endl
;
1500 } else if (ttype
->is_list()) {
1501 indent(out
) << "iprot.readListEnd();" << endl
;
1509 * Generates code to deserialize a map
1511 void t_java_generator::generate_deserialize_map_element(ofstream
& out
,
1514 string key
= tmp("_key");
1515 string val
= tmp("_val");
1516 t_field
fkey(tmap
->get_key_type(), key
);
1517 t_field
fval(tmap
->get_val_type(), val
);
1520 declare_field(&fkey
) << endl
;
1522 declare_field(&fval
) << endl
;
1524 generate_deserialize_field(out
, &fkey
);
1525 generate_deserialize_field(out
, &fval
);
1528 prefix
<< ".put(" << key
<< ", " << val
<< ");" << endl
;
1532 * Deserializes a set element
1534 void t_java_generator::generate_deserialize_set_element(ofstream
& out
,
1537 string elem
= tmp("_elem");
1538 t_field
felem(tset
->get_elem_type(), elem
);
1541 declare_field(&felem
) << endl
;
1543 generate_deserialize_field(out
, &felem
);
1546 prefix
<< ".add(" << elem
<< ");" << endl
;
1550 * Deserializes a list element
1552 void t_java_generator::generate_deserialize_list_element(ofstream
& out
,
1555 string elem
= tmp("_elem");
1556 t_field
felem(tlist
->get_elem_type(), elem
);
1559 declare_field(&felem
, true) << endl
;
1561 generate_deserialize_field(out
, &felem
);
1564 prefix
<< ".add(" << elem
<< ");" << endl
;
1569 * Serializes a field of any type.
1571 * @param tfield The field to serialize
1572 * @param prefix Name to prepend to field name
1574 void t_java_generator::generate_serialize_field(ofstream
& out
,
1577 t_type
* type
= get_true_type(tfield
->get_type());
1579 // Do nothing for void types
1580 if (type
->is_void()) {
1581 throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " +
1582 prefix
+ tfield
->get_name();
1585 if (type
->is_struct() || type
->is_xception()) {
1586 generate_serialize_struct(out
,
1588 prefix
+ tfield
->get_name());
1589 } else if (type
->is_container()) {
1590 generate_serialize_container(out
,
1592 prefix
+ tfield
->get_name());
1593 } else if (type
->is_base_type() || type
->is_enum()) {
1595 string name
= prefix
+ tfield
->get_name();
1599 if (type
->is_base_type()) {
1600 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1602 case t_base_type::TYPE_VOID
:
1604 "compiler error: cannot serialize void field in a struct: " + name
;
1606 case t_base_type::TYPE_STRING
:
1607 if (((t_base_type
*)type
)->is_binary()) {
1608 out
<< "writeBinary(" << name
<< ");";
1610 out
<< "writeString(" << name
<< ");";
1613 case t_base_type::TYPE_BOOL
:
1614 out
<< "writeBool(" << name
<< ");";
1616 case t_base_type::TYPE_BYTE
:
1617 out
<< "writeByte(" << name
<< ");";
1619 case t_base_type::TYPE_I16
:
1620 out
<< "writeI16(" << name
<< ");";
1622 case t_base_type::TYPE_I32
:
1623 out
<< "writeI32(" << name
<< ");";
1625 case t_base_type::TYPE_I64
:
1626 out
<< "writeI64(" << name
<< ");";
1628 case t_base_type::TYPE_DOUBLE
:
1629 out
<< "writeDouble(" << name
<< ");";
1632 throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase
);
1634 } else if (type
->is_enum()) {
1635 out
<< "writeI32(" << name
<< ");";
1639 printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
1641 tfield
->get_name().c_str(),
1642 type_name(type
).c_str());
1647 * Serializes all the members of a struct.
1649 * @param tstruct The struct to serialize
1650 * @param prefix String prefix to attach to all fields
1652 void t_java_generator::generate_serialize_struct(ofstream
& out
,
1656 indent() << prefix
<< ".write(oprot);" << endl
;
1660 * Serializes a container by writing its size then the elements.
1662 * @param ttype The type of container
1663 * @param prefix String prefix for fields
1665 void t_java_generator::generate_serialize_container(ofstream
& out
,
1670 if (ttype
->is_map()) {
1672 "oprot.writeMapBegin(new TMap(" <<
1673 type_to_enum(((t_map
*)ttype
)->get_key_type()) << ", " <<
1674 type_to_enum(((t_map
*)ttype
)->get_val_type()) << ", " <<
1675 prefix
<< ".size()));" << endl
;
1676 } else if (ttype
->is_set()) {
1678 "oprot.writeSetBegin(new TSet(" <<
1679 type_to_enum(((t_set
*)ttype
)->get_elem_type()) << ", " <<
1680 prefix
<< ".size()));" << endl
;
1681 } else if (ttype
->is_list()) {
1683 "oprot.writeListBegin(new TList(" <<
1684 type_to_enum(((t_list
*)ttype
)->get_elem_type()) << ", " <<
1685 prefix
<< ".size()));" << endl
;
1688 string iter
= tmp("_iter");
1689 if (ttype
->is_map()) {
1692 type_name(((t_map
*)ttype
)->get_key_type()) << " " << iter
<<
1694 prefix
<< ".keySet())";
1695 } else if (ttype
->is_set()) {
1698 type_name(((t_set
*)ttype
)->get_elem_type()) << " " << iter
<<
1701 } else if (ttype
->is_list()) {
1704 type_name(((t_list
*)ttype
)->get_elem_type()) << " " << iter
<<
1711 if (ttype
->is_map()) {
1712 generate_serialize_map_element(out
, (t_map
*)ttype
, iter
, prefix
);
1713 } else if (ttype
->is_set()) {
1714 generate_serialize_set_element(out
, (t_set
*)ttype
, iter
);
1715 } else if (ttype
->is_list()) {
1716 generate_serialize_list_element(out
, (t_list
*)ttype
, iter
);
1721 if (ttype
->is_map()) {
1723 "oprot.writeMapEnd();" << endl
;
1724 } else if (ttype
->is_set()) {
1726 "oprot.writeSetEnd();" << endl
;
1727 } else if (ttype
->is_list()) {
1729 "oprot.writeListEnd();" << endl
;
1736 * Serializes the members of a map.
1738 void t_java_generator::generate_serialize_map_element(ofstream
& out
,
1742 t_field
kfield(tmap
->get_key_type(), iter
);
1743 generate_serialize_field(out
, &kfield
, "");
1744 t_field
vfield(tmap
->get_val_type(), map
+ ".get(" + iter
+ ")");
1745 generate_serialize_field(out
, &vfield
, "");
1749 * Serializes the members of a set.
1751 void t_java_generator::generate_serialize_set_element(ofstream
& out
,
1754 t_field
efield(tset
->get_elem_type(), iter
);
1755 generate_serialize_field(out
, &efield
, "");
1759 * Serializes the members of a list.
1761 void t_java_generator::generate_serialize_list_element(ofstream
& out
,
1764 t_field
efield(tlist
->get_elem_type(), iter
);
1765 generate_serialize_field(out
, &efield
, "");
1769 * Returns a Java type name
1771 * @param ttype The type
1772 * @param container Is the type going inside a container?
1773 * @return Java type name, i.e. HashMap<Key,Value>
1775 string
t_java_generator::type_name(t_type
* ttype
, bool in_container
, bool in_init
) {
1776 // In Java typedefs are just resolved to their real type
1777 ttype
= get_true_type(ttype
);
1779 if (ttype
->is_base_type()) {
1780 return base_type_name((t_base_type
*)ttype
, in_container
);
1781 } else if (ttype
->is_enum()) {
1782 return (in_container
? "Integer" : "int");
1783 } else if (ttype
->is_map()) {
1784 t_map
* tmap
= (t_map
*) ttype
;
1789 prefix
= "AbstractMap";
1791 return prefix
+ "<" +
1792 type_name(tmap
->get_key_type(), true) + "," +
1793 type_name(tmap
->get_val_type(), true) + ">";
1794 } else if (ttype
->is_set()) {
1795 t_set
* tset
= (t_set
*) ttype
;
1796 return "HashSet<" + type_name(tset
->get_elem_type(), true) + ">";
1797 } else if (ttype
->is_list()) {
1798 t_list
* tlist
= (t_list
*) ttype
;
1799 return "ArrayList<" + type_name(tlist
->get_elem_type(), true) + ">";
1802 // Check for namespacing
1803 t_program
* program
= ttype
->get_program();
1804 if (program
!= NULL
&& program
!= program_
) {
1805 string package
= program
->get_java_package();
1806 if (!package
.empty()) {
1807 return package
+ "." + ttype
->get_name();
1811 return ttype
->get_name();
1815 * Returns the C++ type that corresponds to the thrift type.
1817 * @param tbase The base type
1818 * @param container Is it going in a Java container?
1820 string
t_java_generator::base_type_name(t_base_type
* type
,
1821 bool in_container
) {
1822 t_base_type::t_base tbase
= type
->get_base();
1825 case t_base_type::TYPE_VOID
:
1827 case t_base_type::TYPE_STRING
:
1828 if (type
->is_binary()) {
1833 case t_base_type::TYPE_BOOL
:
1834 return (in_container
? "Boolean" : "boolean");
1835 case t_base_type::TYPE_BYTE
:
1836 return (in_container
? "Byte" : "byte");
1837 case t_base_type::TYPE_I16
:
1838 return (in_container
? "Short" : "short");
1839 case t_base_type::TYPE_I32
:
1840 return (in_container
? "Integer" : "int");
1841 case t_base_type::TYPE_I64
:
1842 return (in_container
? "Long" : "long");
1843 case t_base_type::TYPE_DOUBLE
:
1844 return (in_container
? "Double" : "double");
1846 throw "compiler error: no C++ name for base type " + t_base_type::t_base_name(tbase
);
1851 * Declares a field, which may include initialization as necessary.
1853 * @param ttype The type
1855 string
t_java_generator::declare_field(t_field
* tfield
, bool init
) {
1856 // TODO(mcslee): do we ever need to initialize the field?
1857 string result
= type_name(tfield
->get_type()) + " " + tfield
->get_name();
1859 t_type
* ttype
= get_true_type(tfield
->get_type());
1860 if (ttype
->is_base_type() && tfield
->get_value() != NULL
) {
1862 result
+= " = " + render_const_value(dummy
, tfield
->get_name(), ttype
, tfield
->get_value());
1863 } else if (ttype
->is_base_type()) {
1864 t_base_type::t_base tbase
= ((t_base_type
*)ttype
)->get_base();
1866 case t_base_type::TYPE_VOID
:
1867 throw "NO T_VOID CONSTRUCT";
1868 case t_base_type::TYPE_STRING
:
1869 result
+= " = null";
1871 case t_base_type::TYPE_BOOL
:
1872 result
+= " = false";
1874 case t_base_type::TYPE_BYTE
:
1875 case t_base_type::TYPE_I16
:
1876 case t_base_type::TYPE_I32
:
1877 case t_base_type::TYPE_I64
:
1880 case t_base_type::TYPE_DOUBLE
:
1881 result
+= " = (double)0";
1885 } else if (ttype
->is_enum()) {
1887 } else if (ttype
->is_container()) {
1888 result
+= " = new " + type_name(ttype
, false, true) + "()";
1890 result
+= " = new " + type_name(ttype
, false, true) + "()";;
1893 return result
+ ";";
1897 * Renders a function signature of the form 'type name(args)'
1899 * @param tfunction Function definition
1900 * @return String of rendered function definition
1902 string
t_java_generator::function_signature(t_function
* tfunction
,
1904 t_type
* ttype
= tfunction
->get_returntype();
1905 std::string result
=
1906 type_name(ttype
) + " " + prefix
+ tfunction
->get_name() + "(" + argument_list(tfunction
->get_arglist()) + ") throws ";
1907 t_struct
* xs
= tfunction
->get_xceptions();
1908 const std::vector
<t_field
*>& xceptions
= xs
->get_members();
1909 vector
<t_field
*>::const_iterator x_iter
;
1910 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1911 result
+= type_name((*x_iter
)->get_type(), false, false) + ", ";
1913 result
+= "TException";
1918 * Renders a comma separated field list, with type names
1920 string
t_java_generator::argument_list(t_struct
* tstruct
) {
1923 const vector
<t_field
*>& fields
= tstruct
->get_members();
1924 vector
<t_field
*>::const_iterator f_iter
;
1926 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1932 result
+= type_name((*f_iter
)->get_type()) + " " + (*f_iter
)->get_name();
1938 * Converts the parse type to a C++ enum string for the given type.
1940 string
t_java_generator::type_to_enum(t_type
* type
) {
1941 type
= get_true_type(type
);
1943 if (type
->is_base_type()) {
1944 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1946 case t_base_type::TYPE_VOID
:
1947 throw "NO T_VOID CONSTRUCT";
1948 case t_base_type::TYPE_STRING
:
1949 return "TType.STRING";
1950 case t_base_type::TYPE_BOOL
:
1951 return "TType.BOOL";
1952 case t_base_type::TYPE_BYTE
:
1953 return "TType.BYTE";
1954 case t_base_type::TYPE_I16
:
1956 case t_base_type::TYPE_I32
:
1958 case t_base_type::TYPE_I64
:
1960 case t_base_type::TYPE_DOUBLE
:
1961 return "TType.DOUBLE";
1963 } else if (type
->is_enum()) {
1965 } else if (type
->is_struct() || type
->is_xception()) {
1966 return "TType.STRUCT";
1967 } else if (type
->is_map()) {
1969 } else if (type
->is_set()) {
1971 } else if (type
->is_list()) {
1972 return "TType.LIST";
1975 throw "INVALID TYPE IN type_to_enum: " + type
->get_name();
1979 * Emits a JavaDoc comment if the provided object has a doc in Thrift
1981 void t_java_generator::generate_java_doc(ofstream
&out
,
1983 if (tdoc
->has_doc()) {
1984 indent(out
) << "/**" << endl
;
1985 stringstream
docs(tdoc
->get_doc(), ios_base::in
);
1986 while (!docs
.eof()) {
1988 docs
.getline(line
, 1024);
1989 if (strlen(line
) > 0 || !docs
.eof()) { // skip the empty last line
1990 indent(out
) << " * " << line
<< endl
;
1993 indent(out
) << " */" << endl
;