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"
14 * Prepares for file generation by opening up the necessary file output
17 * @param tprogram The program to generate
19 void t_java_generator::init_generator() {
20 // Make output directory
21 mkdir(T_JAVA_DIR
, S_IREAD
| S_IWRITE
| S_IEXEC
);
22 package_name_
= program_
->get_java_package();
24 string dir
= package_name_
;
25 string subdir
= T_JAVA_DIR
;
26 string::size_type loc
;
27 while ((loc
= dir
.find(".")) != string::npos
) {
28 subdir
= subdir
+ "/" + dir
.substr(0, loc
);
29 mkdir(subdir
.c_str(), S_IREAD
| S_IWRITE
| S_IEXEC
);
30 dir
= dir
.substr(loc
+1);
33 subdir
= subdir
+ "/" + dir
;
34 mkdir(subdir
.c_str(), S_IREAD
| S_IWRITE
| S_IEXEC
);
37 package_dir_
= subdir
;
41 * Packages the generated file
43 * @return String of the package, i.e. "package com.facebook.thriftdemo;"
45 string
t_java_generator::java_package() {
46 if (!package_name_
.empty()) {
47 return string("package ") + package_name_
+ ";\n\n";
53 * Prints standard java imports
55 * @return List of imports for Java types that are used in here
57 string
t_java_generator::java_type_imports() {
60 "import java.util.ArrayList;\n" +
61 "import java.util.AbstractMap;\n" +
62 "import java.util.HashMap;\n" +
63 "import java.util.HashSet;\n" +
64 "import com.facebook.thrift.*;\n\n";
68 * Prints standard java imports
70 * @return List of imports necessary for thrift
72 string
t_java_generator::java_thrift_imports() {
75 "import com.facebook.thrift.protocol.*;\n" +
76 "import com.facebook.thrift.transport.*;\n\n";
82 void t_java_generator::close_generator() {}
85 * Generates a typedef. This is not done in Java, since it does
86 * not support arbitrary name replacements, and it'd be a wacky waste
87 * of overhead to make wrapper classes.
89 * @param ttypedef The type definition
91 void t_java_generator::generate_typedef(t_typedef
* ttypedef
) {}
94 * Enums are a class with a set of static constants.
96 * @param tenum The enumeration
98 void t_java_generator::generate_enum(t_enum
* tenum
) {
100 string f_enum_name
= package_dir_
+"/"+(tenum
->get_name())+".java";
102 f_enum
.open(f_enum_name
.c_str());
104 // Comment and package it
107 java_package() << endl
;
110 "public class " << tenum
->get_name() << " ";
113 vector
<t_enum_value
*> constants
= tenum
->get_constants();
114 vector
<t_enum_value
*>::iterator c_iter
;
116 for (c_iter
= constants
.begin(); c_iter
!= constants
.end(); ++c_iter
) {
117 if ((*c_iter
)->has_value()) {
118 value
= (*c_iter
)->get_value();
124 "public static final int " << (*c_iter
)->get_name() <<
125 " = " << value
<< ";" << endl
;
133 * Generates a class that holds all the constants.
135 void t_java_generator::generate_consts(std::vector
<t_const
*> consts
) {
136 string f_consts_name
= package_dir_
+"/Constants.java";
138 f_consts
.open(f_consts_name
.c_str());
147 "public class Constants {" << endl
<<
150 vector
<t_const
*>::iterator c_iter
;
151 for (c_iter
= consts
.begin(); c_iter
!= consts
.end(); ++c_iter
) {
152 print_const_value(f_consts
,
153 (*c_iter
)->get_name(),
154 (*c_iter
)->get_type(),
155 (*c_iter
)->get_value(),
166 * Prints the value of a constant with the given type. Note that type checking
167 * is NOT performed in this function as it is always run beforehand using the
168 * validate_types method in main.cc
170 void t_java_generator::print_const_value(std::ofstream
& out
, string name
, t_type
* type
, t_const_value
* value
, bool in_static
, bool defval
) {
175 (in_static
? "" : "public static final ") <<
176 type_name(type
) << " ";
178 if (type
->is_base_type()) {
179 string v2
= render_const_value(out
, name
, type
, value
);
180 out
<< name
<< " = " << v2
<< ";" << endl
<< endl
;
181 } else if (type
->is_enum()) {
182 out
<< name
<< " = " << value
->get_integer() << ";" << endl
<< endl
;
183 } else if (type
->is_struct() || type
->is_xception()) {
184 const vector
<t_field
*>& fields
= ((t_struct
*)type
)->get_members();
185 vector
<t_field
*>::const_iterator f_iter
;
186 const map
<t_const_value
*, t_const_value
*>& val
= value
->get_map();
187 map
<t_const_value
*, t_const_value
*>::const_iterator v_iter
;
188 out
<< name
<< " = new " << type_name(type
) << "();" << endl
;
190 indent(out
) << "static {" << endl
;
193 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
194 t_type
* field_type
= NULL
;
195 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
196 if ((*f_iter
)->get_name() == v_iter
->first
->get_string()) {
197 field_type
= (*f_iter
)->get_type();
200 if (field_type
== NULL
) {
201 throw "type error: " + type
->get_name() + " has no field " + v_iter
->first
->get_string();
203 string val
= render_const_value(out
, name
, field_type
, v_iter
->second
);
204 indent(out
) << name
<< "." << v_iter
->first
->get_string() << " = " << val
<< ";" << endl
;
205 indent(out
) << name
<< ".__isset." << v_iter
->first
->get_string() << " = true;" << endl
;
209 indent(out
) << "}" << endl
;
212 } else if (type
->is_map()) {
213 out
<< name
<< " = new " << type_name(type
, true, true) << "();" << endl
;
215 indent(out
) << "static {" << endl
;
218 t_type
* ktype
= ((t_map
*)type
)->get_key_type();
219 t_type
* vtype
= ((t_map
*)type
)->get_val_type();
220 const map
<t_const_value
*, t_const_value
*>& val
= value
->get_map();
221 map
<t_const_value
*, t_const_value
*>::const_iterator v_iter
;
222 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
223 string key
= render_const_value(out
, name
, ktype
, v_iter
->first
);
224 string val
= render_const_value(out
, name
, vtype
, v_iter
->second
);
225 indent(out
) << name
<< ".put(" << key
<< ", " << val
<< ");" << endl
;
229 indent(out
) << "}" << endl
;
232 } else if (type
->is_list() || type
->is_set()) {
233 out
<< name
<< " = new " << type_name(type
) << "();" << endl
;
235 indent(out
) << "static {" << endl
;
239 if (type
->is_list()) {
240 etype
= ((t_list
*)type
)->get_elem_type();
242 etype
= ((t_set
*)type
)->get_elem_type();
244 const vector
<t_const_value
*>& val
= value
->get_list();
245 vector
<t_const_value
*>::const_iterator v_iter
;
246 for (v_iter
= val
.begin(); v_iter
!= val
.end(); ++v_iter
) {
247 string val
= render_const_value(out
, name
, etype
, *v_iter
);
248 indent(out
) << name
<< ".add(" << val
<< ");" << endl
;
252 indent(out
) << "}" << endl
;
258 string
t_java_generator::render_const_value(ofstream
& out
, string name
, t_type
* type
, t_const_value
* value
) {
259 std::ostringstream render
;
261 if (type
->is_base_type()) {
262 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
264 case t_base_type::TYPE_STRING
:
265 render
<< "\"" + value
->get_string() + "\"";
267 case t_base_type::TYPE_BOOL
:
268 render
<< ((value
->get_integer() > 0) ? "true" : "false");
270 case t_base_type::TYPE_BYTE
:
271 case t_base_type::TYPE_I16
:
272 case t_base_type::TYPE_I32
:
273 case t_base_type::TYPE_I64
:
274 render
<< value
->get_integer();
276 case t_base_type::TYPE_DOUBLE
:
277 if (value
->get_type() == t_const_value::CV_INTEGER
) {
278 render
<< value
->get_integer();
280 render
<< value
->get_double();
284 throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase
);
286 } else if (type
->is_enum()) {
287 render
<< value
->get_integer();
289 string t
= tmp("tmp");
290 print_const_value(out
, t
, type
, value
, true);
298 * Generates a struct definition for a thrift data type. This is a class
299 * with data members, read(), write(), and an inner Isset class.
301 * @param tstruct The struct definition
303 void t_java_generator::generate_struct(t_struct
* tstruct
) {
304 generate_java_struct(tstruct
, false);
308 * Exceptions are structs, but they inherit from Exception
310 * @param tstruct The struct definition
312 void t_java_generator::generate_xception(t_struct
* txception
) {
313 generate_java_struct(txception
, true);
318 * Java struct definition.
320 * @param tstruct The struct definition
322 void t_java_generator::generate_java_struct(t_struct
* tstruct
,
325 string f_struct_name
= package_dir_
+"/"+(tstruct
->get_name())+".java";
327 f_struct
.open(f_struct_name
.c_str());
332 java_type_imports() <<
333 java_thrift_imports();
335 generate_java_struct_definition(f_struct
,
342 * Java struct definition. This has various parameters, as it could be
343 * generated standalone or inside another class as a helper. If it
344 * is a helper than it is a static class.
346 * @param tstruct The struct definition
347 * @param is_exception Is this an exception?
348 * @param in_class If inside a class, needs to be static class
349 * @param is_result If this is a result it needs a different writer
351 void t_java_generator::generate_java_struct_definition(ofstream
&out
,
357 "public " << (in_class
? "static " : "") << "class " << tstruct
->get_name() << " ";
360 out
<< "extends Exception ";
365 // Members are public
366 const vector
<t_field
*>& members
= tstruct
->get_members();
367 vector
<t_field
*>::const_iterator m_iter
;
368 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
370 "public " << declare_field(*m_iter
, false) << endl
;
374 if (members
.size() > 0) {
377 indent() << "public final Isset __isset = new Isset();" << endl
<<
378 indent() << "public final class Isset {" << endl
;
380 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
382 "public boolean " << (*m_iter
)->get_name() << " = false;" << endl
;
386 indent() << "}" << endl
<<
390 // Default constructor
392 "public " << tstruct
->get_name() << "() {" << endl
;
394 for (m_iter
= members
.begin(); m_iter
!= members
.end(); ++m_iter
) {
395 t_type
* t
= get_true_type((*m_iter
)->get_type());
396 if (!t
->is_base_type() && (*m_iter
)->get_value() != NULL
) {
397 print_const_value(out
, "this." + (*m_iter
)->get_name(), t
, (*m_iter
)->get_value(), true, true);
401 indent(out
) << "}" << endl
<< endl
;
403 generate_java_struct_reader(out
, tstruct
);
405 generate_java_struct_result_writer(out
, tstruct
);
407 generate_java_struct_writer(out
, tstruct
);
409 generate_java_struct_tostring(out
, tstruct
);
415 * Generates a function to read all the fields of the struct.
417 * @param tstruct The struct definition
419 void t_java_generator::generate_java_struct_reader(ofstream
& out
,
422 indent() << "public void read(TProtocol iprot) throws TException {" << endl
;
425 const vector
<t_field
*>& fields
= tstruct
->get_members();
426 vector
<t_field
*>::const_iterator f_iter
;
428 // Declare stack tmp variables
430 indent() << "TField field;" << endl
<<
431 indent() << "TStruct struct = iprot.readStructBegin();" << endl
;
433 // Loop over reading in fields
435 "while (true)" << endl
;
438 // Read beginning field marker
440 "field = iprot.readFieldBegin();" << endl
;
442 // Check for field STOP marker and break
444 "if (field.type == TType.STOP) { " << endl
;
452 // Switch statement on the field we are reading
454 "switch (field.id)" << endl
;
458 // Generate deserialization code for known cases
459 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
461 "case " << (*f_iter
)->get_key() << ":" << endl
;
464 "if (field.type == " << type_to_enum((*f_iter
)->get_type()) << ") {" << endl
;
467 generate_deserialize_field(out
, *f_iter
, "this.");
469 indent() << "this.__isset." << (*f_iter
)->get_name() << " = true;" << endl
;
472 indent() << "} else { " << endl
<<
473 indent() << " TProtocolUtil.skip(iprot, field.type);" << endl
<<
474 indent() << "}" << endl
<<
475 indent() << "break;" << endl
;
479 // In the default case we skip the field
481 indent() << "default:" << endl
<<
482 indent() << " TProtocolUtil.skip(iprot, field.type);" << endl
<<
483 indent() << " break;" << endl
;
487 // Read field end marker
489 "iprot.readFieldEnd();" << endl
;
494 indent() << "iprot.readStructEnd();" << endl
;
498 indent() << "}" << endl
<<
503 * Generates a function to write all the fields of the struct
505 * @param tstruct The struct definition
507 void t_java_generator::generate_java_struct_writer(ofstream
& out
,
510 indent() << "public void write(TProtocol oprot) throws TException {" << endl
;
513 string name
= tstruct
->get_name();
514 const vector
<t_field
*>& fields
= tstruct
->get_members();
515 vector
<t_field
*>::const_iterator f_iter
;
518 indent() << "TStruct struct = new TStruct(\"" << name
<< "\");" << endl
<<
519 indent() << "TField field = new TField();" << endl
<<
520 indent() << "oprot.writeStructBegin(struct);" << endl
;
522 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
523 bool null_allowed
= type_can_be_null((*f_iter
)->get_type());
526 indent() << "if (this." << (*f_iter
)->get_name() << " != null) {" << endl
;
531 indent() << "field.name = \"" << (*f_iter
)->get_name() << "\";" << endl
<<
532 indent() << "field.type = " << type_to_enum((*f_iter
)->get_type()) << ";" << endl
<<
533 indent() << "field.id = " << (*f_iter
)->get_key() << ";" << endl
<<
534 indent() << "oprot.writeFieldBegin(field);" << endl
;
536 // Write field contents
537 generate_serialize_field(out
, *f_iter
, "this.");
539 // Write field closer
541 "oprot.writeFieldEnd();" << endl
;
545 indent(out
) << "}" << endl
;
548 // Write the struct map
550 indent() << "oprot.writeFieldStop();" << endl
<<
551 indent() << "oprot.writeStructEnd();" << endl
;
555 indent() << "}" << endl
<<
560 * Generates a function to write all the fields of the struct,
561 * which is a function result. These fields are only written
562 * if they are set in the Isset array, and only one of them
563 * can be set at a time.
565 * @param tstruct The struct definition
567 void t_java_generator::generate_java_struct_result_writer(ofstream
& out
,
570 indent() << "public void write(TProtocol oprot) throws TException {" << endl
;
573 string name
= tstruct
->get_name();
574 const vector
<t_field
*>& fields
= tstruct
->get_members();
575 vector
<t_field
*>::const_iterator f_iter
;
578 indent() << "TStruct struct = new TStruct(\"" << name
<< "\");" << endl
<<
579 indent() << "TField field = new TField();" << endl
<<
580 indent() << "oprot.writeStructBegin(struct);" << endl
;
583 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
595 "(this.__isset." << (*f_iter
)->get_name() << ") {" << endl
;
598 bool null_allowed
= type_can_be_null((*f_iter
)->get_type());
601 indent() << "if (this." << (*f_iter
)->get_name() << " != null) {" << endl
;
606 indent() << "field.name = \"" << (*f_iter
)->get_name() << "\";" << endl
<<
607 indent() << "field.type = " << type_to_enum((*f_iter
)->get_type()) << ";" << endl
<<
608 indent() << "field.id = " << (*f_iter
)->get_key() << ";" << endl
<<
609 indent() << "oprot.writeFieldBegin(field);" << endl
;
611 // Write field contents
612 generate_serialize_field(out
, *f_iter
, "this.");
614 // Write field closer
616 "oprot.writeFieldEnd();" << endl
;
620 indent(out
) << "}" << endl
;
626 // Write the struct map
629 indent() << "oprot.writeFieldStop();" << endl
<<
630 indent() << "oprot.writeStructEnd();" << endl
;
634 indent() << "}" << endl
<<
639 * Generates a toString() method for the given struct
641 * @param tstruct The struct definition
643 void t_java_generator::generate_java_struct_tostring(ofstream
& out
,
646 indent() << "public String toString() {" << endl
;
650 indent() << "StringBuilder sb = new StringBuilder(\"" << tstruct
->get_name() << "(\");" << endl
;
652 const vector
<t_field
*>& fields
= tstruct
->get_members();
653 vector
<t_field
*>::const_iterator f_iter
;
655 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
658 indent(out
) << "sb.append(\"" << (*f_iter
)->get_name() << ":\");" << endl
;
660 indent(out
) << "sb.append(\"," << (*f_iter
)->get_name() << ":\");" << endl
;
662 t_type
* ttype
= (*f_iter
)->get_type();
663 if (ttype
->is_xception() || ttype
->is_struct()) {
664 indent(out
) << "sb.append(this." << (*f_iter
)->get_name() << ".toString());" << endl
;
666 indent(out
) << "sb.append(this." << (*f_iter
)->get_name() << ");" << endl
;
670 indent() << "sb.append(\")\");" << endl
<<
671 indent() << "return sb.toString();" << endl
;
674 indent(out
) << "}" << endl
<<
680 * Generates a thrift service. In C++, this comprises an entirely separate
681 * header and source file. The header file defines the methods and includes
682 * the data types defined in the main header file, and the implementation
683 * file contains implementations of the basic printer and default interfaces.
685 * @param tservice The service definition
687 void t_java_generator::generate_service(t_service
* tservice
) {
689 string f_service_name
= package_dir_
+"/"+service_name_
+".java";
690 f_service_
.open(f_service_name
.c_str());
695 java_type_imports() <<
696 java_thrift_imports();
699 "public class " << service_name_
<< " {" << endl
<<
703 // Generate the three main parts of the service
704 generate_service_interface(tservice
);
705 generate_service_client(tservice
);
706 generate_service_server(tservice
);
707 generate_service_helpers(tservice
);
716 * Generates a service interface definition.
718 * @param tservice The service to generate a header definition for
720 void t_java_generator::generate_service_interface(t_service
* tservice
) {
722 string extends_iface
= "";
723 if (tservice
->get_extends() != NULL
) {
724 extends
= type_name(tservice
->get_extends());
725 extends_iface
= " extends " + extends
+ ".Iface";
729 indent() << "public interface Iface" << extends_iface
<< " {" << endl
;
731 vector
<t_function
*> functions
= tservice
->get_functions();
732 vector
<t_function
*>::iterator f_iter
;
733 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
734 indent(f_service_
) <<
735 "public " << function_signature(*f_iter
) << ";" << endl
;
739 indent() << "}" << endl
<<
744 * Generates structs for all the service args and return types
746 * @param tservice The service
748 void t_java_generator::generate_service_helpers(t_service
* tservice
) {
749 vector
<t_function
*> functions
= tservice
->get_functions();
750 vector
<t_function
*>::iterator f_iter
;
751 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
752 t_struct
* ts
= (*f_iter
)->get_arglist();
753 generate_java_struct_definition(f_service_
, ts
, false, true);
754 generate_function_helpers(*f_iter
);
759 * Generates a service client definition.
761 * @param tservice The service to generate a server for.
763 void t_java_generator::generate_service_client(t_service
* tservice
) {
765 string extends_client
= "";
766 if (tservice
->get_extends() != NULL
) {
767 extends
= type_name(tservice
->get_extends());
768 extends_client
= " extends " + extends
+ ".Client";
771 indent(f_service_
) <<
772 "public static class Client" << extends_client
<< " implements Iface {" << endl
;
775 indent(f_service_
) <<
776 "public Client(TProtocol prot)" << endl
;
777 scope_up(f_service_
);
778 indent(f_service_
) <<
779 "this(prot, prot);" << endl
;
780 scope_down(f_service_
);
783 indent(f_service_
) <<
784 "public Client(TProtocol iprot, TProtocol oprot)" << endl
;
785 scope_up(f_service_
);
786 if (extends
.empty()) {
788 indent() << "iprot_ = iprot;" << endl
<<
789 indent() << "oprot_ = oprot;" << endl
;
792 indent() << "super(iprot, oprot);" << endl
;
794 scope_down(f_service_
);
797 if (extends
.empty()) {
799 indent() << "protected TProtocol iprot_;" << endl
<<
800 indent() << "protected TProtocol oprot_;" << endl
<<
802 indent() << "protected int seqid_;" << endl
<<
806 // Generate client method implementations
807 vector
<t_function
*> functions
= tservice
->get_functions();
808 vector
<t_function
*>::const_iterator f_iter
;
809 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
810 string funname
= (*f_iter
)->get_name();
813 indent(f_service_
) <<
814 "public " << function_signature(*f_iter
) << endl
;
815 scope_up(f_service_
);
816 indent(f_service_
) <<
817 "send_" << funname
<< "(";
819 // Get the struct of function call params
820 t_struct
* arg_struct
= (*f_iter
)->get_arglist();
822 // Declare the function arguments
823 const vector
<t_field
*>& fields
= arg_struct
->get_members();
824 vector
<t_field
*>::const_iterator fld_iter
;
826 for (fld_iter
= fields
.begin(); fld_iter
!= fields
.end(); ++fld_iter
) {
832 f_service_
<< (*fld_iter
)->get_name();
834 f_service_
<< ");" << endl
;
836 if (!(*f_iter
)->is_async()) {
837 f_service_
<< indent();
838 if (!(*f_iter
)->get_returntype()->is_void()) {
839 f_service_
<< "return ";
842 "recv_" << funname
<< "();" << endl
;
844 scope_down(f_service_
);
847 t_function
send_function(g_type_void
,
848 string("send_") + (*f_iter
)->get_name(),
849 (*f_iter
)->get_arglist());
851 string argsname
= (*f_iter
)->get_name() + "_args";
854 indent(f_service_
) <<
855 "public " << function_signature(&send_function
) << endl
;
856 scope_up(f_service_
);
858 // Serialize the request
860 indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname
<< "\", TMessageType.CALL, seqid_));" << endl
<<
861 indent() << argsname
<< " args = new " << argsname
<< "();" << endl
;
863 for (fld_iter
= fields
.begin(); fld_iter
!= fields
.end(); ++fld_iter
) {
865 indent() << "args." << (*fld_iter
)->get_name() << " = " << (*fld_iter
)->get_name() << ";" << endl
;
869 indent() << "args.write(oprot_);" << endl
<<
870 indent() << "oprot_.writeMessageEnd();" << endl
<<
871 indent() << "oprot_.getTransport().flush();" << endl
;
873 scope_down(f_service_
);
876 if (!(*f_iter
)->is_async()) {
877 string resultname
= (*f_iter
)->get_name() + "_result";
879 t_struct
noargs(program_
);
880 t_function
recv_function((*f_iter
)->get_returntype(),
881 string("recv_") + (*f_iter
)->get_name(),
883 (*f_iter
)->get_xceptions());
885 indent(f_service_
) <<
886 "public " << function_signature(&recv_function
) << endl
;
887 scope_up(f_service_
);
889 // TODO(mcslee): Message validation here, was the seqid etc ok?
892 indent() << "TMessage msg = iprot_.readMessageBegin();" << endl
<<
893 indent() << "if (msg.type == TMessageType.EXCEPTION) {" << endl
<<
894 indent() << " TApplicationException x = TApplicationException.read(iprot_);" << endl
<<
895 indent() << " iprot_.readMessageEnd();" << endl
<<
896 indent() << " throw x;" << endl
<<
897 indent() << "}" << endl
<<
898 indent() << resultname
<< " result = new " << resultname
<< "();" << endl
<<
899 indent() << "result.read(iprot_);" << endl
<<
900 indent() << "iprot_.readMessageEnd();" << endl
;
902 // Careful, only return _result if not a void function
903 if (!(*f_iter
)->get_returntype()->is_void()) {
905 indent() << "if (result.__isset.success) {" << endl
<<
906 indent() << " return result.success;" << endl
<<
907 indent() << "}" << endl
;
910 t_struct
* xs
= (*f_iter
)->get_xceptions();
911 const std::vector
<t_field
*>& xceptions
= xs
->get_members();
912 vector
<t_field
*>::const_iterator x_iter
;
913 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
915 indent() << "if (result.__isset." << (*x_iter
)->get_name() << ") {" << endl
<<
916 indent() << " throw result." << (*x_iter
)->get_name() << ";" << endl
<<
917 indent() << "}" << endl
;
920 // If you get here it's an exception, unless a void function
921 if ((*f_iter
)->get_returntype()->is_void()) {
922 indent(f_service_
) <<
926 indent() << "throw new TApplicationException(TApplicationException.MISSING_RESULT, \"" << (*f_iter
)->get_name() << " failed: unknown result\");" << endl
;
930 scope_down(f_service_
);
936 indent(f_service_
) <<
941 * Generates a service server definition.
943 * @param tservice The service to generate a server for.
945 void t_java_generator::generate_service_server(t_service
* tservice
) {
946 // Generate the dispatch methods
947 vector
<t_function
*> functions
= tservice
->get_functions();
948 vector
<t_function
*>::iterator f_iter
;
952 string extends_processor
= "";
953 if (tservice
->get_extends() != NULL
) {
954 extends
= type_name(tservice
->get_extends());
955 extends_processor
= " extends " + extends
+ ".Processor";
958 // Generate the header portion
959 indent(f_service_
) <<
960 "public static class Processor" << extends_processor
<< " implements TProcessor {" << endl
;
963 indent(f_service_
) <<
964 "public Processor(Iface iface)" << endl
;
965 scope_up(f_service_
);
966 if (!extends
.empty()) {
968 indent() << "super(iface);" << endl
;
971 indent() << "iface_ = iface;" << endl
;
973 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
975 indent() << "processMap_.put(\"" << (*f_iter
)->get_name() << "\", new " << (*f_iter
)->get_name() << "());" << endl
;
978 scope_down(f_service_
);
981 if (extends
.empty()) {
983 indent() << "protected static interface ProcessFunction {" << endl
<<
984 indent() << " public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException;" << endl
<<
985 indent() << "}" << endl
<<
990 indent() << "private Iface iface_;" << endl
;
992 if (extends
.empty()) {
994 indent() << "protected final HashMap<String,ProcessFunction> processMap_ = new HashMap<String,ProcessFunction>();" << endl
;
999 // Generate the server implementation
1000 indent(f_service_
) <<
1001 "public boolean process(TProtocol iprot, TProtocol oprot) throws TException" << endl
;
1002 scope_up(f_service_
);
1005 indent() << "TMessage msg = iprot.readMessageBegin();" << endl
;
1007 // TODO(mcslee): validate message, was the seqid etc. legit?
1010 indent() << "ProcessFunction fn = processMap_.get(msg.name);" << endl
<<
1011 indent() << "if (fn == null) {" << endl
<<
1012 indent() << " TProtocolUtil.skip(iprot, TType.STRUCT);" << endl
<<
1013 indent() << " iprot.readMessageEnd();" << endl
<<
1014 indent() << " TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, \"Invalid method name: '\"+msg.name+\"'\");" << endl
<<
1015 indent() << " oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" << endl
<<
1016 indent() << " x.write(oprot);" << endl
<<
1017 indent() << " oprot.writeMessageEnd();" << endl
<<
1018 indent() << " oprot.getTransport().flush();" << endl
<<
1019 indent() << " return true;" << endl
<<
1020 indent() << "}" << endl
<<
1021 indent() << "fn.process(msg.seqid, iprot, oprot);" << endl
;
1024 indent() << "return true;" << endl
;
1026 scope_down(f_service_
);
1029 // Generate the process subfunctions
1030 for (f_iter
= functions
.begin(); f_iter
!= functions
.end(); ++f_iter
) {
1031 generate_process_function(tservice
, *f_iter
);
1035 indent(f_service_
) <<
1041 * Generates a struct and helpers for a function.
1043 * @param tfunction The function
1045 void t_java_generator::generate_function_helpers(t_function
* tfunction
) {
1046 if (tfunction
->is_async()) {
1050 t_struct
result(program_
, tfunction
->get_name() + "_result");
1051 t_field
success(tfunction
->get_returntype(), "success", 0);
1052 if (!tfunction
->get_returntype()->is_void()) {
1053 result
.append(&success
);
1056 t_struct
* xs
= tfunction
->get_xceptions();
1057 const vector
<t_field
*>& fields
= xs
->get_members();
1058 vector
<t_field
*>::const_iterator f_iter
;
1059 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1060 result
.append(*f_iter
);
1063 generate_java_struct_definition(f_service_
, &result
, false, true, true);
1067 * Generates a process function definition.
1069 * @param tfunction The function to write a dispatcher for
1071 void t_java_generator::generate_process_function(t_service
* tservice
,
1072 t_function
* tfunction
) {
1074 indent(f_service_
) <<
1075 "private class " << tfunction
->get_name() << " implements ProcessFunction {" << endl
;
1079 indent(f_service_
) <<
1080 "public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException" << endl
;
1081 scope_up(f_service_
);
1083 string argsname
= tfunction
->get_name() + "_args";
1084 string resultname
= tfunction
->get_name() + "_result";
1087 indent() << argsname
<< " args = new " << argsname
<< "();" << endl
<<
1088 indent() << "args.read(iprot);" << endl
<<
1089 indent() << "iprot.readMessageEnd();" << endl
;
1091 t_struct
* xs
= tfunction
->get_xceptions();
1092 const std::vector
<t_field
*>& xceptions
= xs
->get_members();
1093 vector
<t_field
*>::const_iterator x_iter
;
1095 // Declare result for non async function
1096 if (!tfunction
->is_async()) {
1098 indent() << resultname
<< " result = new " << resultname
<< "();" << endl
;
1101 // Try block for a function with exceptions
1102 if (xceptions
.size() > 0) {
1104 indent() << "try {" << endl
;
1108 // Generate the function call
1109 t_struct
* arg_struct
= tfunction
->get_arglist();
1110 const std::vector
<t_field
*>& fields
= arg_struct
->get_members();
1111 vector
<t_field
*>::const_iterator f_iter
;
1113 f_service_
<< indent();
1114 if (!tfunction
->is_async() && !tfunction
->get_returntype()->is_void()) {
1115 f_service_
<< "result.success = ";
1118 "iface_." << tfunction
->get_name() << "(";
1120 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1126 f_service_
<< "args." << (*f_iter
)->get_name();
1128 f_service_
<< ");" << endl
;
1130 // Set isset on success field
1131 if (!tfunction
->is_async() && !tfunction
->get_returntype()->is_void()) {
1133 indent() << "result.__isset.success = true;" << endl
;
1136 if (!tfunction
->is_async() && xceptions
.size() > 0) {
1138 f_service_
<< indent() << "}";
1139 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1140 f_service_
<< " catch (" << (*x_iter
)->get_type()->get_name() << " " << (*x_iter
)->get_name() << ") {" << endl
;
1141 if (!tfunction
->is_async()) {
1144 indent() << "result." << (*x_iter
)->get_name() << " = " << (*x_iter
)->get_name() << ";" << endl
<<
1145 indent() << "result.__isset." << (*x_iter
)->get_name() << " = true;" << endl
;
1147 f_service_
<< indent() << "}";
1155 // Shortcut out here for async functions
1156 if (tfunction
->is_async()) {
1158 indent() << "return;" << endl
;
1159 scope_down(f_service_
);
1164 indent() << "}" << endl
<<
1170 indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction
->get_name() << "\", TMessageType.REPLY, seqid));" << endl
<<
1171 indent() << "result.write(oprot);" << endl
<<
1172 indent() << "oprot.writeMessageEnd();" << endl
<<
1173 indent() << "oprot.getTransport().flush();" << endl
;
1176 scope_down(f_service_
);
1182 indent() << "}" << endl
<<
1187 * Deserializes a field of any type.
1189 * @param tfield The field
1190 * @param prefix The variable name or container for this field
1192 void t_java_generator::generate_deserialize_field(ofstream
& out
,
1195 t_type
* type
= get_true_type(tfield
->get_type());
1197 if (type
->is_void()) {
1198 throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " +
1199 prefix
+ tfield
->get_name();
1202 string name
= prefix
+ tfield
->get_name();
1204 if (type
->is_struct() || type
->is_xception()) {
1205 generate_deserialize_struct(out
,
1208 } else if (type
->is_container()) {
1209 generate_deserialize_container(out
, type
, name
);
1210 } else if (type
->is_base_type() || type
->is_enum()) {
1213 name
<< " = iprot.";
1215 if (type
->is_base_type()) {
1216 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1218 case t_base_type::TYPE_VOID
:
1219 throw "compiler error: cannot serialize void field in a struct: " +
1222 case t_base_type::TYPE_STRING
:
1223 if (((t_base_type
*)type
)->is_binary()) {
1224 out
<< "readBinary();";
1226 out
<< "readString();";
1229 case t_base_type::TYPE_BOOL
:
1230 out
<< "readBool();";
1232 case t_base_type::TYPE_BYTE
:
1233 out
<< "readByte();";
1235 case t_base_type::TYPE_I16
:
1236 out
<< "readI16();";
1238 case t_base_type::TYPE_I32
:
1239 out
<< "readI32();";
1241 case t_base_type::TYPE_I64
:
1242 out
<< "readI64();";
1244 case t_base_type::TYPE_DOUBLE
:
1245 out
<< "readDouble();";
1248 throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase
);
1250 } else if (type
->is_enum()) {
1251 out
<< "readI32();";
1256 printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
1257 tfield
->get_name().c_str(), type_name(type
).c_str());
1262 * Generates an unserializer for a struct, invokes read()
1264 void t_java_generator::generate_deserialize_struct(ofstream
& out
,
1268 indent() << prefix
<< " = new " << type_name(tstruct
) << "();" << endl
<<
1269 indent() << prefix
<< ".read(iprot);" << endl
;
1273 * Deserializes a container by reading its size and then iterating
1275 void t_java_generator::generate_deserialize_container(ofstream
& out
,
1282 if (ttype
->is_map()) {
1284 } else if (ttype
->is_set()) {
1286 } else if (ttype
->is_list()) {
1290 // Declare variables, read header
1291 if (ttype
->is_map()) {
1292 indent(out
) << "TMap " << obj
<< " = iprot.readMapBegin();" << endl
;
1293 } else if (ttype
->is_set()) {
1294 indent(out
) << "TSet " << obj
<< " = iprot.readSetBegin();" << endl
;
1295 } else if (ttype
->is_list()) {
1296 indent(out
) << "TList " << obj
<< " = iprot.readListBegin();" << endl
;
1300 << prefix
<< " = new " << type_name(ttype
, false, true)
1301 // size the collection correctly
1303 << (ttype
->is_list() ? "" : "2*" )
1307 // For loop iterates over elements
1308 string i
= tmp("_i");
1310 "for (int " << i
<< " = 0; " <<
1311 i
<< " < " << obj
<< ".size" << "; " <<
1312 "++" << i
<< ")" << endl
;
1316 if (ttype
->is_map()) {
1317 generate_deserialize_map_element(out
, (t_map
*)ttype
, prefix
);
1318 } else if (ttype
->is_set()) {
1319 generate_deserialize_set_element(out
, (t_set
*)ttype
, prefix
);
1320 } else if (ttype
->is_list()) {
1321 generate_deserialize_list_element(out
, (t_list
*)ttype
, prefix
);
1326 // Read container end
1327 if (ttype
->is_map()) {
1328 indent(out
) << "iprot.readMapEnd();" << endl
;
1329 } else if (ttype
->is_set()) {
1330 indent(out
) << "iprot.readSetEnd();" << endl
;
1331 } else if (ttype
->is_list()) {
1332 indent(out
) << "iprot.readListEnd();" << endl
;
1340 * Generates code to deserialize a map
1342 void t_java_generator::generate_deserialize_map_element(ofstream
& out
,
1345 string key
= tmp("_key");
1346 string val
= tmp("_val");
1347 t_field
fkey(tmap
->get_key_type(), key
);
1348 t_field
fval(tmap
->get_val_type(), val
);
1351 declare_field(&fkey
) << endl
;
1353 declare_field(&fval
) << endl
;
1355 generate_deserialize_field(out
, &fkey
);
1356 generate_deserialize_field(out
, &fval
);
1359 prefix
<< ".put(" << key
<< ", " << val
<< ");" << endl
;
1363 * Deserializes a set element
1365 void t_java_generator::generate_deserialize_set_element(ofstream
& out
,
1368 string elem
= tmp("_elem");
1369 t_field
felem(tset
->get_elem_type(), elem
);
1372 declare_field(&felem
, true) << endl
;
1374 generate_deserialize_field(out
, &felem
);
1377 prefix
<< ".add(" << elem
<< ");" << endl
;
1381 * Deserializes a list element
1383 void t_java_generator::generate_deserialize_list_element(ofstream
& out
,
1386 string elem
= tmp("_elem");
1387 t_field
felem(tlist
->get_elem_type(), elem
);
1390 declare_field(&felem
, true) << endl
;
1392 generate_deserialize_field(out
, &felem
);
1395 prefix
<< ".add(" << elem
<< ");" << endl
;
1400 * Serializes a field of any type.
1402 * @param tfield The field to serialize
1403 * @param prefix Name to prepend to field name
1405 void t_java_generator::generate_serialize_field(ofstream
& out
,
1408 t_type
* type
= get_true_type(tfield
->get_type());
1410 // Do nothing for void types
1411 if (type
->is_void()) {
1412 throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " +
1413 prefix
+ tfield
->get_name();
1416 if (type
->is_struct() || type
->is_xception()) {
1417 generate_serialize_struct(out
,
1419 prefix
+ tfield
->get_name());
1420 } else if (type
->is_container()) {
1421 generate_serialize_container(out
,
1423 prefix
+ tfield
->get_name());
1424 } else if (type
->is_base_type() || type
->is_enum()) {
1426 string name
= prefix
+ tfield
->get_name();
1430 if (type
->is_base_type()) {
1431 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1433 case t_base_type::TYPE_VOID
:
1435 "compiler error: cannot serialize void field in a struct: " + name
;
1437 case t_base_type::TYPE_STRING
:
1438 if (((t_base_type
*)type
)->is_binary()) {
1439 out
<< "writeBinary(" << name
<< ");";
1441 out
<< "writeString(" << name
<< ");";
1444 case t_base_type::TYPE_BOOL
:
1445 out
<< "writeBool(" << name
<< ");";
1447 case t_base_type::TYPE_BYTE
:
1448 out
<< "writeByte(" << name
<< ");";
1450 case t_base_type::TYPE_I16
:
1451 out
<< "writeI16(" << name
<< ");";
1453 case t_base_type::TYPE_I32
:
1454 out
<< "writeI32(" << name
<< ");";
1456 case t_base_type::TYPE_I64
:
1457 out
<< "writeI64(" << name
<< ");";
1459 case t_base_type::TYPE_DOUBLE
:
1460 out
<< "writeDouble(" << name
<< ");";
1463 throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase
);
1465 } else if (type
->is_enum()) {
1466 out
<< "writeI32(" << name
<< ");";
1470 printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
1472 tfield
->get_name().c_str(),
1473 type_name(type
).c_str());
1478 * Serializes all the members of a struct.
1480 * @param tstruct The struct to serialize
1481 * @param prefix String prefix to attach to all fields
1483 void t_java_generator::generate_serialize_struct(ofstream
& out
,
1487 indent() << prefix
<< ".write(oprot);" << endl
;
1491 * Serializes a container by writing its size then the elements.
1493 * @param ttype The type of container
1494 * @param prefix String prefix for fields
1496 void t_java_generator::generate_serialize_container(ofstream
& out
,
1501 if (ttype
->is_map()) {
1503 "oprot.writeMapBegin(new TMap(" <<
1504 type_to_enum(((t_map
*)ttype
)->get_key_type()) << ", " <<
1505 type_to_enum(((t_map
*)ttype
)->get_val_type()) << ", " <<
1506 prefix
<< ".size()));" << endl
;
1507 } else if (ttype
->is_set()) {
1509 "oprot.writeSetBegin(new TSet(" <<
1510 type_to_enum(((t_set
*)ttype
)->get_elem_type()) << ", " <<
1511 prefix
<< ".size()));" << endl
;
1512 } else if (ttype
->is_list()) {
1514 "oprot.writeListBegin(new TList(" <<
1515 type_to_enum(((t_list
*)ttype
)->get_elem_type()) << ", " <<
1516 prefix
<< ".size()));" << endl
;
1519 string iter
= tmp("_iter");
1520 if (ttype
->is_map()) {
1523 type_name(((t_map
*)ttype
)->get_key_type()) << " " << iter
<<
1525 prefix
<< ".keySet())";
1526 } else if (ttype
->is_set()) {
1529 type_name(((t_set
*)ttype
)->get_elem_type()) << " " << iter
<<
1532 } else if (ttype
->is_list()) {
1535 type_name(((t_list
*)ttype
)->get_elem_type()) << " " << iter
<<
1542 if (ttype
->is_map()) {
1543 generate_serialize_map_element(out
, (t_map
*)ttype
, iter
, prefix
);
1544 } else if (ttype
->is_set()) {
1545 generate_serialize_set_element(out
, (t_set
*)ttype
, iter
);
1546 } else if (ttype
->is_list()) {
1547 generate_serialize_list_element(out
, (t_list
*)ttype
, iter
);
1550 if (ttype
->is_map()) {
1552 "oprot.writeMapEnd();" << endl
;
1553 } else if (ttype
->is_set()) {
1555 "oprot.writeSetEnd();" << endl
;
1556 } else if (ttype
->is_list()) {
1558 "oprot.writeListEnd();" << endl
;
1567 * Serializes the members of a map.
1569 void t_java_generator::generate_serialize_map_element(ofstream
& out
,
1573 t_field
kfield(tmap
->get_key_type(), iter
);
1574 generate_serialize_field(out
, &kfield
, "");
1575 t_field
vfield(tmap
->get_val_type(), map
+ ".get(" + iter
+ ")");
1576 generate_serialize_field(out
, &vfield
, "");
1580 * Serializes the members of a set.
1582 void t_java_generator::generate_serialize_set_element(ofstream
& out
,
1585 t_field
efield(tset
->get_elem_type(), iter
);
1586 generate_serialize_field(out
, &efield
, "");
1590 * Serializes the members of a list.
1592 void t_java_generator::generate_serialize_list_element(ofstream
& out
,
1595 t_field
efield(tlist
->get_elem_type(), iter
);
1596 generate_serialize_field(out
, &efield
, "");
1600 * Returns a Java type name
1602 * @param ttype The type
1603 * @param container Is the type going inside a container?
1604 * @return Java type name, i.e. HashMap<Key,Value>
1606 string
t_java_generator::type_name(t_type
* ttype
, bool in_container
, bool in_init
) {
1607 // In Java typedefs are just resolved to their real type
1608 ttype
= get_true_type(ttype
);
1610 if (ttype
->is_base_type()) {
1611 return base_type_name((t_base_type
*)ttype
, in_container
);
1612 } else if (ttype
->is_enum()) {
1613 return (in_container
? "Integer" : "int");
1614 } else if (ttype
->is_map()) {
1615 t_map
* tmap
= (t_map
*) ttype
;
1620 prefix
= "AbstractMap";
1622 return prefix
+ "<" +
1623 type_name(tmap
->get_key_type(), true) + "," +
1624 type_name(tmap
->get_val_type(), true) + ">";
1625 } else if (ttype
->is_set()) {
1626 t_set
* tset
= (t_set
*) ttype
;
1627 return "HashSet<" + type_name(tset
->get_elem_type(), true) + ">";
1628 } else if (ttype
->is_list()) {
1629 t_list
* tlist
= (t_list
*) ttype
;
1630 return "ArrayList<" + type_name(tlist
->get_elem_type(), true) + ">";
1633 // Check for namespacing
1634 t_program
* program
= ttype
->get_program();
1635 if (program
!= NULL
&& program
!= program_
) {
1636 string package
= program
->get_java_package();
1637 if (!package
.empty()) {
1638 return package
+ "." + ttype
->get_name();
1642 return ttype
->get_name();
1646 * Returns the C++ type that corresponds to the thrift type.
1648 * @param tbase The base type
1649 * @param container Is it going in a Java container?
1651 string
t_java_generator::base_type_name(t_base_type
* type
,
1652 bool in_container
) {
1653 t_base_type::t_base tbase
= type
->get_base();
1656 case t_base_type::TYPE_VOID
:
1658 case t_base_type::TYPE_STRING
:
1659 if (type
->is_binary()) {
1664 case t_base_type::TYPE_BOOL
:
1666 case t_base_type::TYPE_BYTE
:
1668 case t_base_type::TYPE_I16
:
1669 return (in_container
? "Short" : "short");
1670 case t_base_type::TYPE_I32
:
1671 return (in_container
? "Integer" : "int");
1672 case t_base_type::TYPE_I64
:
1673 return (in_container
? "Long" : "long");
1674 case t_base_type::TYPE_DOUBLE
:
1675 return (in_container
? "Double" : "double");
1677 throw "compiler error: no C++ name for base type " + t_base_type::t_base_name(tbase
);
1682 * Declares a field, which may include initialization as necessary.
1684 * @param ttype The type
1686 string
t_java_generator::declare_field(t_field
* tfield
, bool init
) {
1687 // TODO(mcslee): do we ever need to initialize the field?
1688 string result
= type_name(tfield
->get_type()) + " " + tfield
->get_name();
1690 t_type
* ttype
= get_true_type(tfield
->get_type());
1691 if (ttype
->is_base_type() && tfield
->get_value() != NULL
) {
1693 result
+= " = " + render_const_value(dummy
, tfield
->get_name(), ttype
, tfield
->get_value());
1694 } else if (ttype
->is_base_type()) {
1695 t_base_type::t_base tbase
= ((t_base_type
*)ttype
)->get_base();
1697 case t_base_type::TYPE_VOID
:
1698 throw "NO T_VOID CONSTRUCT";
1699 case t_base_type::TYPE_STRING
:
1700 result
+= " = null";
1702 case t_base_type::TYPE_BOOL
:
1703 result
+= " = false";
1705 case t_base_type::TYPE_BYTE
:
1706 case t_base_type::TYPE_I16
:
1707 case t_base_type::TYPE_I32
:
1708 case t_base_type::TYPE_I64
:
1711 case t_base_type::TYPE_DOUBLE
:
1712 result
+= " = (double)0";
1716 } else if (ttype
->is_enum()) {
1718 } else if (ttype
->is_container()) {
1719 result
+= " = new " + type_name(ttype
, false, true) + "()";
1721 result
+= " = new " + type_name(ttype
, false, true) + "()";;
1724 return result
+ ";";
1728 * Renders a function signature of the form 'type name(args)'
1730 * @param tfunction Function definition
1731 * @return String of rendered function definition
1733 string
t_java_generator::function_signature(t_function
* tfunction
,
1735 t_type
* ttype
= tfunction
->get_returntype();
1736 std::string result
=
1737 type_name(ttype
) + " " + prefix
+ tfunction
->get_name() + "(" + argument_list(tfunction
->get_arglist()) + ") throws ";
1738 t_struct
* xs
= tfunction
->get_xceptions();
1739 const std::vector
<t_field
*>& xceptions
= xs
->get_members();
1740 vector
<t_field
*>::const_iterator x_iter
;
1741 for (x_iter
= xceptions
.begin(); x_iter
!= xceptions
.end(); ++x_iter
) {
1742 result
+= (*x_iter
)->get_type()->get_name() + ", ";
1744 result
+= "TException";
1749 * Renders a comma separated field list, with type names
1751 string
t_java_generator::argument_list(t_struct
* tstruct
) {
1754 const vector
<t_field
*>& fields
= tstruct
->get_members();
1755 vector
<t_field
*>::const_iterator f_iter
;
1757 for (f_iter
= fields
.begin(); f_iter
!= fields
.end(); ++f_iter
) {
1763 result
+= type_name((*f_iter
)->get_type()) + " " + (*f_iter
)->get_name();
1769 * Converts the parse type to a C++ enum string for the given type.
1771 string
t_java_generator::type_to_enum(t_type
* type
) {
1772 type
= get_true_type(type
);
1774 if (type
->is_base_type()) {
1775 t_base_type::t_base tbase
= ((t_base_type
*)type
)->get_base();
1777 case t_base_type::TYPE_VOID
:
1778 throw "NO T_VOID CONSTRUCT";
1779 case t_base_type::TYPE_STRING
:
1780 return "TType.STRING";
1781 case t_base_type::TYPE_BOOL
:
1782 return "TType.BOOL";
1783 case t_base_type::TYPE_BYTE
:
1784 return "TType.BYTE";
1785 case t_base_type::TYPE_I16
:
1787 case t_base_type::TYPE_I32
:
1789 case t_base_type::TYPE_I64
:
1791 case t_base_type::TYPE_DOUBLE
:
1792 return "TType.DOUBLE";
1794 } else if (type
->is_enum()) {
1796 } else if (type
->is_struct() || type
->is_xception()) {
1797 return "TType.STRUCT";
1798 } else if (type
->is_map()) {
1800 } else if (type
->is_set()) {
1802 } else if (type
->is_list()) {
1803 return "TType.LIST";
1806 throw "INVALID TYPE IN type_to_enum: " + type
->get_name();