blob: fa87d094c46d8c326d87b2f1c81177ba99d7a52f [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Mark Sleee9ce01c2007-05-16 02:29:53 +000019
Mark Sleeb15a68b2006-06-07 06:46:24 +000020#include <sstream>
David Reissdc61be92008-02-27 01:55:09 +000021#include <string>
22#include <fstream>
23#include <iostream>
24#include <vector>
Bryan Duxburybb7826d2009-02-08 00:12:38 +000025#include <cctype>
David Reissdc61be92008-02-27 01:55:09 +000026
27#include <sys/stat.h>
Bryan Duxbury986d7052009-01-29 01:51:08 +000028#include <stdexcept>
David Reissdc61be92008-02-27 01:55:09 +000029
David Reiss204420f2008-01-11 20:59:03 +000030#include "platform.h"
David Reissdc61be92008-02-27 01:55:09 +000031#include "t_oop_generator.h"
Mark Sleeb15a68b2006-06-07 06:46:24 +000032using namespace std;
33
David Reissdc61be92008-02-27 01:55:09 +000034
David Reissdc61be92008-02-27 01:55:09 +000035/**
36 * Java code generator.
37 *
David Reissdc61be92008-02-27 01:55:09 +000038 */
39class t_java_generator : public t_oop_generator {
Bryan Duxbury1121b472011-08-11 18:50:58 +000040public:
David Reissdc61be92008-02-27 01:55:09 +000041 t_java_generator(
Bryan Duxbury1121b472011-08-11 18:50:58 +000042 t_program* program,
43 const std::map<std::string, std::string>& parsed_options,
44 const std::string& option_string)
45 : t_oop_generator(program)
David Reissdc61be92008-02-27 01:55:09 +000046 {
Roger Meier3b771a12010-11-17 22:11:26 +000047 (void) option_string;
David Reissdc61be92008-02-27 01:55:09 +000048 std::map<std::string, std::string>::const_iterator iter;
49
50 iter = parsed_options.find("beans");
51 bean_style_ = (iter != parsed_options.end());
52
Bryan Duxburyea7910f2010-04-03 05:04:48 +000053 iter = parsed_options.find("private-members");
54 private_members_ = (iter != parsed_options.end());
55
David Reiss70e329f2008-07-14 19:35:50 +000056 iter = parsed_options.find("nocamel");
57 nocamel_style_ = (iter != parsed_options.end());
58
David Reiss14feb412008-03-02 06:29:23 +000059 iter = parsed_options.find("hashcode");
60 gen_hash_code_ = (iter != parsed_options.end());
61
Roger Meier6b38cf62011-04-16 20:05:51 +000062 iter = parsed_options.find("android_legacy");
63 android_legacy_ = (iter != parsed_options.end());
64
Bryan Duxbury9a422392011-05-23 21:41:02 +000065 iter = parsed_options.find("java5");
66 java5_ = (iter != parsed_options.end());
67 if (java5_) {
Bryan Duxbury1121b472011-08-11 18:50:58 +000068 android_legacy_ = true;
Bryan Duxbury9a422392011-05-23 21:41:02 +000069 }
70
David Reissdc61be92008-02-27 01:55:09 +000071 out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java");
72 }
73
David Reissdc61be92008-02-27 01:55:09 +000074 /**
75 * Init and close methods
76 */
77
78 void init_generator();
79 void close_generator();
80
81 void generate_consts(std::vector<t_const*> consts);
82
83 /**
84 * Program-level generation functions
85 */
86
87 void generate_typedef (t_typedef* ttypedef);
88 void generate_enum (t_enum* tenum);
89 void generate_struct (t_struct* tstruct);
Bryan Duxburyab3666e2009-09-01 23:03:47 +000090 void generate_union (t_struct* tunion);
David Reissdc61be92008-02-27 01:55:09 +000091 void generate_xception(t_struct* txception);
92 void generate_service (t_service* tservice);
93
94 void print_const_value(std::ofstream& out, std::string name, t_type* type, t_const_value* value, bool in_static, bool defval=false);
Roger Meiere0cac982010-12-16 13:15:49 +000095 std::string render_const_value(std::ofstream& out, t_type* type, t_const_value* value);
David Reissdc61be92008-02-27 01:55:09 +000096
97 /**
98 * Service-level generation functions
99 */
100
101 void generate_java_struct(t_struct* tstruct, bool is_exception);
102
103 void generate_java_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception=false, bool in_class=false, bool is_result=false);
David Reiss3b15ebc2008-03-02 06:29:19 +0000104 void generate_java_struct_equality(std::ofstream& out, t_struct* tstruct);
Bryan Duxbury684b4f92009-07-31 00:12:21 +0000105 void generate_java_struct_compare_to(std::ofstream& out, t_struct* tstruct);
David Reissdc61be92008-02-27 01:55:09 +0000106 void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
Bryan Duxbury8bbd8442009-01-20 01:54:14 +0000107 void generate_java_validator(std::ofstream& out, t_struct* tstruct);
David Reissdc61be92008-02-27 01:55:09 +0000108 void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
109 void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
110 void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct);
Bryan Duxbury5226eea2010-08-05 20:44:53 +0000111 void generate_java_struct_clear(std::ofstream& out, t_struct* tstruct);
Bryan Duxburyc8d533b2011-01-26 22:42:02 +0000112 void generate_java_struct_write_object(std::ofstream& out, t_struct* tstruct);
113 void generate_java_struct_read_object(std::ofstream& out, t_struct* tstruct);
David Reissb936ffd2009-01-05 21:02:52 +0000114 void generate_java_meta_data_map(std::ofstream& out, t_struct* tstruct);
Bryan Duxbury986d7052009-01-29 01:51:08 +0000115 void generate_field_value_meta_data(std::ofstream& out, t_type* type);
116 std::string get_java_type_string(t_type* type);
Bryan Duxbury66467a72010-08-21 17:48:18 +0000117 void generate_java_struct_field_by_id(ofstream& out, t_struct* tstruct);
David Reiss31997ca2008-10-09 00:08:46 +0000118 void generate_reflection_setters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name);
119 void generate_reflection_getters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name);
120 void generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct);
David Reiss25be92b2009-01-05 21:02:58 +0000121 void generate_generic_isset_method(std::ofstream& out, t_struct* tstruct);
David Reissdc61be92008-02-27 01:55:09 +0000122 void generate_java_bean_boilerplate(std::ofstream& out, t_struct* tstruct);
123
124 void generate_function_helpers(t_function* tfunction);
David Reiss2db737d2009-01-05 21:02:55 +0000125 std::string get_cap_name(std::string name);
Bryan Duxburyd11f2412009-02-19 21:21:44 +0000126 std::string generate_isset_check(t_field* field);
Bryan Duxburye3c3d192009-03-07 03:08:37 +0000127 std::string generate_isset_check(std::string field);
Bryan Duxbury1121b472011-08-11 18:50:58 +0000128 void generate_isset_set(ofstream& out, t_field* field, std::string prefix);
Bryan Duxbury3efce232009-08-03 19:37:26 +0000129 std::string isset_field_id(t_field* field);
130
David Reissdc61be92008-02-27 01:55:09 +0000131 void generate_service_interface (t_service* tservice);
Bryan Duxburyd58ccec2010-05-26 16:34:48 +0000132 void generate_service_async_interface(t_service* tservice);
David Reissdc61be92008-02-27 01:55:09 +0000133 void generate_service_helpers (t_service* tservice);
134 void generate_service_client (t_service* tservice);
Bryan Duxburyd58ccec2010-05-26 16:34:48 +0000135 void generate_service_async_client(t_service* tservice);
David Reissdc61be92008-02-27 01:55:09 +0000136 void generate_service_server (t_service* tservice);
137 void generate_process_function (t_service* tservice, t_function* tfunction);
138
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000139 void generate_java_union(t_struct* tstruct);
140 void generate_union_constructor(ofstream& out, t_struct* tstruct);
141 void generate_union_getters_and_setters(ofstream& out, t_struct* tstruct);
Bryan Duxbury63c2d372011-06-08 17:46:55 +0000142 void generate_union_is_set_methods(ofstream& out, t_struct* tstruct);
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000143 void generate_union_abstract_methods(ofstream& out, t_struct* tstruct);
144 void generate_check_type(ofstream& out, t_struct* tstruct);
Bryan Duxbury18784d72011-09-20 22:53:31 +0000145 void generate_standard_scheme_read_value(ofstream& out, t_struct* tstruct);
146 void generate_standard_scheme_write_value(ofstream& out, t_struct* tstruct);
147 void generate_tuple_scheme_read_value(ofstream& out, t_struct* tstruct);
148 void generate_tuple_scheme_write_value(ofstream& out, t_struct* tstruct);
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000149 void generate_get_field_desc(ofstream& out, t_struct* tstruct);
150 void generate_get_struct_desc(ofstream& out, t_struct* tstruct);
151 void generate_get_field_name(ofstream& out, t_struct* tstruct);
152
153 void generate_union_comparisons(ofstream& out, t_struct* tstruct);
154 void generate_union_hashcode(ofstream& out, t_struct* tstruct);
155
Bryan Duxbury1121b472011-08-11 18:50:58 +0000156 void generate_scheme_map(ofstream& out, t_struct* tstruct);
157 void generate_standard_writer(ofstream& out, t_struct* tstruct);
158 void generate_standard_reader(ofstream& out, t_struct* tstruct);
159 void generate_java_struct_standard_scheme(ofstream& out, t_struct* tstruct);
160
161 void generate_java_struct_tuple_scheme(ofstream& out, t_struct* tstruct);
162 void generate_java_struct_tuple_reader(ofstream& out, t_struct* tstruct);
163 void generate_java_struct_tuple_writer(ofstream& out, t_struct* tstruct);
164
David Reissdc61be92008-02-27 01:55:09 +0000165 /**
166 * Serialization constructs
167 */
168
169 void generate_deserialize_field (std::ofstream& out,
170 t_field* tfield,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000171 std::string prefix="",
172 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000173
174 void generate_deserialize_struct (std::ofstream& out,
175 t_struct* tstruct,
176 std::string prefix="");
177
178 void generate_deserialize_container (std::ofstream& out,
179 t_type* ttype,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000180 std::string prefix="",
181 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000182
183 void generate_deserialize_set_element (std::ofstream& out,
184 t_set* tset,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000185 std::string prefix="",
186 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000187
188 void generate_deserialize_map_element (std::ofstream& out,
189 t_map* tmap,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000190 std::string prefix="",
191 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000192
193 void generate_deserialize_list_element (std::ofstream& out,
194 t_list* tlist,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000195 std::string prefix="",
196 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000197
198 void generate_serialize_field (std::ofstream& out,
199 t_field* tfield,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000200 std::string prefix="",
201 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000202
203 void generate_serialize_struct (std::ofstream& out,
204 t_struct* tstruct,
205 std::string prefix="");
206
207 void generate_serialize_container (std::ofstream& out,
208 t_type* ttype,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000209 std::string prefix="",
210 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000211
212 void generate_serialize_map_element (std::ofstream& out,
213 t_map* tmap,
214 std::string iter,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000215 std::string map,
216 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000217
218 void generate_serialize_set_element (std::ofstream& out,
219 t_set* tmap,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000220 std::string iter,
221 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000222
223 void generate_serialize_list_element (std::ofstream& out,
224 t_list* tlist,
Bryan Duxbury1121b472011-08-11 18:50:58 +0000225 std::string iter,
226 bool has_metadata = true);
David Reissdc61be92008-02-27 01:55:09 +0000227
228 void generate_java_doc (std::ofstream& out,
Bryan Duxbury3d5db202009-07-29 23:44:44 +0000229 t_field* field);
230
231 void generate_java_doc (std::ofstream& out,
232 t_doc* tdoc);
David Reissdc61be92008-02-27 01:55:09 +0000233
David Reiss7bcf8662009-01-06 20:54:27 +0000234 void generate_java_doc (std::ofstream& out,
235 t_function* tdoc);
236
Bryan Duxbury3d5db202009-07-29 23:44:44 +0000237 void generate_java_docstring_comment (std::ofstream &out,
238 string contents);
239
David Reiss603d5042008-12-02 02:06:31 +0000240 void generate_deep_copy_container(std::ofstream& out, std::string source_name_p1, std::string source_name_p2, std::string result_name, t_type* type);
David Reiss5455f002009-01-05 21:02:48 +0000241 void generate_deep_copy_non_container(std::ofstream& out, std::string source_name, std::string dest_name, t_type* type);
David Reissdc61be92008-02-27 01:55:09 +0000242
Bryan Duxbury3efce232009-08-03 19:37:26 +0000243 bool has_bit_vector(t_struct* tstruct);
244
David Reissdc61be92008-02-27 01:55:09 +0000245 /**
246 * Helper rendering functions
247 */
248
249 std::string java_package();
250 std::string java_type_imports();
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000251 std::string type_name(t_type* ttype, bool in_container=false, bool in_init=false, bool skip_generic=false);
David Reissdc61be92008-02-27 01:55:09 +0000252 std::string base_type_name(t_base_type* tbase, bool in_container=false);
253 std::string declare_field(t_field* tfield, bool init=false);
254 std::string function_signature(t_function* tfunction, std::string prefix="");
Bryan Duxburyd58ccec2010-05-26 16:34:48 +0000255 std::string function_signature_async(t_function* tfunction, bool use_base_method = false, std::string prefix="");
256 std::string argument_list(t_struct* tstruct, bool include_types = true);
257 std::string async_function_call_arglist(t_function* tfunc, bool use_base_method = true, bool include_types = true);
258 std::string async_argument_list(t_function* tfunct, t_struct* tstruct, t_type* ttype, bool include_types=false);
David Reissdc61be92008-02-27 01:55:09 +0000259 std::string type_to_enum(t_type* ttype);
Bryan Duxbury3696d642009-03-18 03:14:56 +0000260 std::string get_enum_class_name(t_type* type);
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000261 void generate_struct_desc(ofstream& out, t_struct* tstruct);
262 void generate_field_descs(ofstream& out, t_struct* tstruct);
263 void generate_field_name_constants(ofstream& out, t_struct* tstruct);
Bryan Duxburyd58ccec2010-05-26 16:34:48 +0000264
David Reissdc61be92008-02-27 01:55:09 +0000265 bool type_can_be_null(t_type* ttype) {
266 ttype = get_true_type(ttype);
267
268 return
269 ttype->is_container() ||
270 ttype->is_struct() ||
271 ttype->is_xception() ||
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000272 ttype->is_string() ||
273 ttype->is_enum();
David Reissdc61be92008-02-27 01:55:09 +0000274 }
275
Bryan Duxburybb7826d2009-02-08 00:12:38 +0000276 std::string constant_name(std::string name);
David Reissdc61be92008-02-27 01:55:09 +0000277
278 private:
279
280 /**
281 * File streams
282 */
283
284 std::string package_name_;
285 std::ofstream f_service_;
286 std::string package_dir_;
287
288 bool bean_style_;
Bryan Duxburyea7910f2010-04-03 05:04:48 +0000289 bool private_members_;
David Reiss70e329f2008-07-14 19:35:50 +0000290 bool nocamel_style_;
David Reiss14feb412008-03-02 06:29:23 +0000291 bool gen_hash_code_;
Roger Meier6b38cf62011-04-16 20:05:51 +0000292 bool android_legacy_;
Bryan Duxbury9a422392011-05-23 21:41:02 +0000293 bool java5_;
David Reissdc61be92008-02-27 01:55:09 +0000294};
295
296
Mark Sleeb15a68b2006-06-07 06:46:24 +0000297/**
298 * Prepares for file generation by opening up the necessary file output
299 * streams.
300 *
301 * @param tprogram The program to generate
302 */
Mark Sleef0712dc2006-10-25 19:03:57 +0000303void t_java_generator::init_generator() {
Mark Sleeb15a68b2006-06-07 06:46:24 +0000304 // Make output directory
David Reiss204420f2008-01-11 20:59:03 +0000305 MKDIR(get_out_dir().c_str());
David Reiss771f8c72008-02-27 01:55:25 +0000306 package_name_ = program_->get_namespace("java");
Mark Slee98e962b2007-02-20 18:44:05 +0000307
308 string dir = package_name_;
dweatherford65b70752007-10-31 02:18:14 +0000309 string subdir = get_out_dir();
Mark Slee98e962b2007-02-20 18:44:05 +0000310 string::size_type loc;
311 while ((loc = dir.find(".")) != string::npos) {
312 subdir = subdir + "/" + dir.substr(0, loc);
David Reiss204420f2008-01-11 20:59:03 +0000313 MKDIR(subdir.c_str());
Mark Slee98e962b2007-02-20 18:44:05 +0000314 dir = dir.substr(loc+1);
315 }
316 if (dir.size() > 0) {
317 subdir = subdir + "/" + dir;
David Reiss204420f2008-01-11 20:59:03 +0000318 MKDIR(subdir.c_str());
Mark Slee98e962b2007-02-20 18:44:05 +0000319 }
320
321 package_dir_ = subdir;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000322}
323
324/**
325 * Packages the generated file
Mark Sleef5377b32006-10-10 01:42:59 +0000326 *
Bryan Duxburyafa80ea2009-01-15 23:47:51 +0000327 * @return String of the package, i.e. "package org.apache.thriftdemo;"
Mark Sleeb15a68b2006-06-07 06:46:24 +0000328 */
329string t_java_generator::java_package() {
Mark Sleef0712dc2006-10-25 19:03:57 +0000330 if (!package_name_.empty()) {
331 return string("package ") + package_name_ + ";\n\n";
332 }
333 return "";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000334}
335
336/**
337 * Prints standard java imports
Mark Sleef5377b32006-10-10 01:42:59 +0000338 *
339 * @return List of imports for Java types that are used in here
Mark Sleeb15a68b2006-06-07 06:46:24 +0000340 */
341string t_java_generator::java_type_imports() {
David Reiss14feb412008-03-02 06:29:23 +0000342 string hash_builder;
343 if (gen_hash_code_) {
344 hash_builder = "import org.apache.commons.lang.builder.HashCodeBuilder;\n";
345 }
346
Mark Sleeb15a68b2006-06-07 06:46:24 +0000347 return
348 string() +
Bryan Duxbury2ad9eb72009-03-24 00:43:33 +0000349 hash_builder +
Bryan Duxbury1121b472011-08-11 18:50:58 +0000350 "import org.apache.thrift.scheme.IScheme;\n" +
351 "import org.apache.thrift.scheme.SchemeFactory;\n" +
352 "import org.apache.thrift.scheme.StandardScheme;\n\n" +
353 "import org.apache.thrift.scheme.TupleScheme;\n" +
354 "import org.apache.thrift.protocol.TTupleProtocol;\n" +
Mark Slee22360b22008-02-09 00:18:32 +0000355 "import java.util.List;\n" +
Mark Sleeb15a68b2006-06-07 06:46:24 +0000356 "import java.util.ArrayList;\n" +
Mark Slee22360b22008-02-09 00:18:32 +0000357 "import java.util.Map;\n" +
Mark Sleeb15a68b2006-06-07 06:46:24 +0000358 "import java.util.HashMap;\n" +
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +0000359 "import java.util.EnumMap;\n" +
Mark Slee22360b22008-02-09 00:18:32 +0000360 "import java.util.Set;\n" +
Mark Sleeb15a68b2006-06-07 06:46:24 +0000361 "import java.util.HashSet;\n" +
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +0000362 "import java.util.EnumSet;\n" +
Bryan Duxburyef73b0e2009-06-17 16:43:25 +0000363 "import java.util.Collections;\n" +
Bryan Duxbury3efce232009-08-03 19:37:26 +0000364 "import java.util.BitSet;\n" +
Bryan Duxburyf5abd262010-08-06 00:18:25 +0000365 "import java.nio.ByteBuffer;\n"
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000366 "import java.util.Arrays;\n" +
Bryan Duxburyc27cda52009-08-14 20:04:15 +0000367 "import org.slf4j.Logger;\n" +
368 "import org.slf4j.LoggerFactory;\n\n";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000369}
370
371/**
Mark Sleef5377b32006-10-10 01:42:59 +0000372 * Nothing in Java
Mark Sleeb15a68b2006-06-07 06:46:24 +0000373 */
Mark Sleef0712dc2006-10-25 19:03:57 +0000374void t_java_generator::close_generator() {}
Mark Sleeb15a68b2006-06-07 06:46:24 +0000375
376/**
Mark Sleef5377b32006-10-10 01:42:59 +0000377 * Generates a typedef. This is not done in Java, since it does
378 * not support arbitrary name replacements, and it'd be a wacky waste
379 * of overhead to make wrapper classes.
Mark Sleeb15a68b2006-06-07 06:46:24 +0000380 *
381 * @param ttypedef The type definition
382 */
Roger Meier3b771a12010-11-17 22:11:26 +0000383void t_java_generator::generate_typedef(t_typedef* ttypedef) {
384 (void) ttypedef;
385}
Mark Sleeb15a68b2006-06-07 06:46:24 +0000386
387/**
Mark Slee5ab57052007-11-27 08:38:16 +0000388 * Enums are a class with a set of static constants.
Mark Sleeb15a68b2006-06-07 06:46:24 +0000389 *
390 * @param tenum The enumeration
391 */
392void t_java_generator::generate_enum(t_enum* tenum) {
393 // Make output file
Mark Slee98e962b2007-02-20 18:44:05 +0000394 string f_enum_name = package_dir_+"/"+(tenum->get_name())+".java";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000395 ofstream f_enum;
396 f_enum.open(f_enum_name.c_str());
397
Mark Sleef5377b32006-10-10 01:42:59 +0000398 // Comment and package it
Mark Sleeb15a68b2006-06-07 06:46:24 +0000399 f_enum <<
400 autogen_comment() <<
Mark Slee52f643d2006-08-09 00:03:43 +0000401 java_package() << endl;
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000402
Bryan Duxbury8bbd8442009-01-20 01:54:14 +0000403 // Add java imports
404 f_enum << string() +
Bryan Duxbury3696d642009-03-18 03:14:56 +0000405 "import java.util.Map;\n" +
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000406 "import java.util.HashMap;\n" +
Bryan Duxbury2d804702009-12-18 19:41:11 +0000407 "import org.apache.thrift.TEnum;" << endl << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000408
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000409 generate_java_doc(f_enum, tenum);
410 indent(f_enum) <<
Bryan Duxbury932ce2b2010-12-07 18:28:48 +0000411 "public enum " << tenum->get_name() << " implements org.apache.thrift.TEnum ";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000412 scope_up(f_enum);
413
Mark Slee30152872006-11-28 01:24:07 +0000414 vector<t_enum_value*> constants = tenum->get_constants();
415 vector<t_enum_value*>::iterator c_iter;
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000416 bool first = true;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000417 for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
Bryan Duxburya406b902010-09-27 23:37:44 +0000418 int value = (*c_iter)->get_value();
Mark Sleeb15a68b2006-06-07 06:46:24 +0000419
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000420 if (first) {
421 first = false;
422 } else {
423 f_enum << "," << endl;
424 }
425
Bryan Duxbury3d5db202009-07-29 23:44:44 +0000426 generate_java_doc(f_enum, *c_iter);
Bryan Duxbury2d804702009-12-18 19:41:11 +0000427 indent(f_enum) << (*c_iter)->get_name() << "(" << value << ")";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000428 }
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000429 f_enum << ";" << endl << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +0000430
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000431 // Field for thriftCode
432 indent(f_enum) << "private final int value;" << endl << endl;
433
434 indent(f_enum) << "private " << tenum->get_name() << "(int value) {" << endl;
435 indent(f_enum) << " this.value = value;" <<endl;
436 indent(f_enum) << "}" << endl << endl;
Bryan Duxburyc4ad9be2010-01-16 09:13:20 +0000437
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000438 indent(f_enum) << "/**" << endl;
439 indent(f_enum) << " * Get the integer value of this enum value, as defined in the Thrift IDL." << endl;
440 indent(f_enum) << " */" << endl;
441 indent(f_enum) << "public int getValue() {" << endl;
442 indent(f_enum) << " return value;" <<endl;
443 indent(f_enum) << "}" << endl << endl;
444
445 indent(f_enum) << "/**" << endl;
446 indent(f_enum) << " * Find a the enum type by its integer value, as defined in the Thrift IDL." << endl;
447 indent(f_enum) << " * @return null if the value is not found." << endl;
448 indent(f_enum) << " */" << endl;
449 indent(f_enum) << "public static "+ tenum->get_name() + " findByValue(int value) { " << endl;
Bryan Duxburyc4ad9be2010-01-16 09:13:20 +0000450
451 indent_up();
452
453 indent(f_enum) << "switch (value) {" << endl;
454 indent_up();
455
Bryan Duxburyc4ad9be2010-01-16 09:13:20 +0000456 for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
Bryan Duxburya406b902010-09-27 23:37:44 +0000457 int value = (*c_iter)->get_value();
Bryan Duxburyc4ad9be2010-01-16 09:13:20 +0000458 indent(f_enum) << "case " << value << ":" << endl;
459 indent(f_enum) << " return " << (*c_iter)->get_name() << ";" << endl;
460 }
Bryan Duxbury1121b472011-08-11 18:50:58 +0000461
Bryan Duxburyc4ad9be2010-01-16 09:13:20 +0000462 indent(f_enum) << "default:" << endl;
463 indent(f_enum) << " return null;" << endl;
464
465 indent_down();
466
467 indent(f_enum) << "}" << endl;
Bryan Duxbury1121b472011-08-11 18:50:58 +0000468
Bryan Duxburyc4ad9be2010-01-16 09:13:20 +0000469 indent_down();
470
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000471 indent(f_enum) << "}" << endl;
472
Mark Sleeb15a68b2006-06-07 06:46:24 +0000473 scope_down(f_enum);
Bryan Duxbury9af23d92009-11-19 17:26:38 +0000474
Mark Sleef5377b32006-10-10 01:42:59 +0000475 f_enum.close();
Mark Sleeb15a68b2006-06-07 06:46:24 +0000476}
477
478/**
Mark Sleeaa7671d2006-11-29 03:19:31 +0000479 * Generates a class that holds all the constants.
480 */
481void t_java_generator::generate_consts(std::vector<t_const*> consts) {
David Reissa1e0a6f2008-06-10 22:56:43 +0000482 if (consts.empty()) {
483 return;
484 }
485
Mark Slee98e962b2007-02-20 18:44:05 +0000486 string f_consts_name = package_dir_+"/Constants.java";
Mark Sleeaa7671d2006-11-29 03:19:31 +0000487 ofstream f_consts;
488 f_consts.open(f_consts_name.c_str());
489
490 // Print header
491 f_consts <<
492 autogen_comment() <<
Mark Slee5ab57052007-11-27 08:38:16 +0000493 java_package() <<
Mark Sleeaa7671d2006-11-29 03:19:31 +0000494 java_type_imports();
495
496 f_consts <<
497 "public class Constants {" << endl <<
498 endl;
499 indent_up();
500 vector<t_const*>::iterator c_iter;
501 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
Bryan Duxburyd4235e02010-09-13 16:28:53 +0000502 generate_java_doc(f_consts, (*c_iter));
Mark Sleeaa7671d2006-11-29 03:19:31 +0000503 print_const_value(f_consts,
504 (*c_iter)->get_name(),
505 (*c_iter)->get_type(),
506 (*c_iter)->get_value(),
507 false);
508 }
509 indent_down();
Bryan Duxbury1121b472011-08-11 18:50:58 +0000510 indent(f_consts) << "}" << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000511 f_consts.close();
512}
513
514
515/**
516 * Prints the value of a constant with the given type. Note that type checking
517 * is NOT performed in this function as it is always run beforehand using the
518 * validate_types method in main.cc
519 */
Mark Slee7ff32452007-02-01 05:26:18 +0000520void t_java_generator::print_const_value(std::ofstream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval) {
David Reiss9a4edfa2008-05-01 05:52:50 +0000521 type = get_true_type(type);
Mark Slee7ff32452007-02-01 05:26:18 +0000522
523 indent(out);
524 if (!defval) {
525 out <<
526 (in_static ? "" : "public static final ") <<
527 type_name(type) << " ";
528 }
Mark Sleeaa7671d2006-11-29 03:19:31 +0000529 if (type->is_base_type()) {
Roger Meiere0cac982010-12-16 13:15:49 +0000530 string v2 = render_const_value(out, type, value);
Mark Slee7ff32452007-02-01 05:26:18 +0000531 out << name << " = " << v2 << ";" << endl << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000532 } else if (type->is_enum()) {
Roger Meiere0cac982010-12-16 13:15:49 +0000533 out << name << " = " << render_const_value(out, type, value) << ";" << endl << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000534 } else if (type->is_struct() || type->is_xception()) {
535 const vector<t_field*>& fields = ((t_struct*)type)->get_members();
536 vector<t_field*>::const_iterator f_iter;
537 const map<t_const_value*, t_const_value*>& val = value->get_map();
538 map<t_const_value*, t_const_value*>::const_iterator v_iter;
Mark Sleedd43eb82008-02-13 22:03:15 +0000539 out << name << " = new " << type_name(type, false, true) << "();" << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000540 if (!in_static) {
541 indent(out) << "static {" << endl;
542 indent_up();
543 }
544 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
545 t_type* field_type = NULL;
546 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
547 if ((*f_iter)->get_name() == v_iter->first->get_string()) {
548 field_type = (*f_iter)->get_type();
549 }
550 }
551 if (field_type == NULL) {
552 throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
553 }
Roger Meiere0cac982010-12-16 13:15:49 +0000554 string val = render_const_value(out, field_type, v_iter->second);
David Reiss87e9ac62008-06-10 22:56:34 +0000555 indent(out) << name << ".";
David Reiss2bcf3992009-04-07 20:51:37 +0000556 std::string cap_name = get_cap_name(v_iter->first->get_string());
557 out << "set" << cap_name << "(" << val << ");" << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000558 }
559 if (!in_static) {
560 indent_down();
561 indent(out) << "}" << endl;
562 }
563 out << endl;
564 } else if (type->is_map()) {
Mark Sleedd43eb82008-02-13 22:03:15 +0000565 out << name << " = new " << type_name(type, false, true) << "();" << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000566 if (!in_static) {
567 indent(out) << "static {" << endl;
568 indent_up();
569 }
570 t_type* ktype = ((t_map*)type)->get_key_type();
571 t_type* vtype = ((t_map*)type)->get_val_type();
572 const map<t_const_value*, t_const_value*>& val = value->get_map();
573 map<t_const_value*, t_const_value*>::const_iterator v_iter;
574 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
Roger Meiere0cac982010-12-16 13:15:49 +0000575 string key = render_const_value(out, ktype, v_iter->first);
576 string val = render_const_value(out, vtype, v_iter->second);
Mark Sleeaa7671d2006-11-29 03:19:31 +0000577 indent(out) << name << ".put(" << key << ", " << val << ");" << endl;
578 }
579 if (!in_static) {
580 indent_down();
581 indent(out) << "}" << endl;
582 }
583 out << endl;
584 } else if (type->is_list() || type->is_set()) {
Mark Sleedd43eb82008-02-13 22:03:15 +0000585 out << name << " = new " << type_name(type, false, true) << "();" << endl;
Mark Sleeaa7671d2006-11-29 03:19:31 +0000586 if (!in_static) {
587 indent(out) << "static {" << endl;
588 indent_up();
589 }
590 t_type* etype;
591 if (type->is_list()) {
592 etype = ((t_list*)type)->get_elem_type();
593 } else {
594 etype = ((t_set*)type)->get_elem_type();
595 }
596 const vector<t_const_value*>& val = value->get_list();
597 vector<t_const_value*>::const_iterator v_iter;
598 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
Roger Meiere0cac982010-12-16 13:15:49 +0000599 string val = render_const_value(out, etype, *v_iter);
Mark Sleeaa7671d2006-11-29 03:19:31 +0000600 indent(out) << name << ".add(" << val << ");" << endl;
601 }
602 if (!in_static) {
603 indent_down();
604 indent(out) << "}" << endl;
605 }
606 out << endl;
David Reiss9a4edfa2008-05-01 05:52:50 +0000607 } else {
608 throw "compiler error: no const of type " + type->get_name();
Mark Sleeaa7671d2006-11-29 03:19:31 +0000609 }
610}
611
Roger Meiere0cac982010-12-16 13:15:49 +0000612string t_java_generator::render_const_value(ofstream& out, t_type* type, t_const_value* value) {
David Reiss9a4edfa2008-05-01 05:52:50 +0000613 type = get_true_type(type);
Mark Sleeaa7671d2006-11-29 03:19:31 +0000614 std::ostringstream render;
615
616 if (type->is_base_type()) {
617 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
618 switch (tbase) {
Bryan Duxbury1121b472011-08-11 18:50:58 +0000619 case t_base_type::TYPE_STRING:
620 render << '"' << get_escaped_string(value) << '"';
621 break;
622 case t_base_type::TYPE_BOOL:
623 render << ((value->get_integer() > 0) ? "true" : "false");
624 break;
625 case t_base_type::TYPE_BYTE:
626 render << "(byte)" << value->get_integer();
627 break;
628 case t_base_type::TYPE_I16:
629 render << "(short)" << value->get_integer();
630 break;
631 case t_base_type::TYPE_I32:
632 render << value->get_integer();
633 break;
634 case t_base_type::TYPE_I64:
635 render << value->get_integer() << "L";
636 break;
637 case t_base_type::TYPE_DOUBLE:
638 if (value->get_type() == t_const_value::CV_INTEGER) {
639 render << "(double)" << value->get_integer();
640 } else {
641 render << value->get_double();
642 }
643 break;
644 default:
645 throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
Mark Sleeaa7671d2006-11-29 03:19:31 +0000646 }
647 } else if (type->is_enum()) {
Bryan Duxbury1606f252010-11-24 00:25:57 +0000648 render << type->get_program()->get_namespace("java") << "." << value->get_identifier_with_parent();
Mark Sleeaa7671d2006-11-29 03:19:31 +0000649 } else {
650 string t = tmp("tmp");
651 print_const_value(out, t, type, value, true);
652 render << t;
653 }
654
655 return render.str();
656}
657
658/**
Bryan Duxbury932ce2b2010-12-07 18:28:48 +0000659 * Generates a struct definition for a thrift data type. This will be a org.apache.thrift.TBase
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000660 * implementor.
Mark Sleeb15a68b2006-06-07 06:46:24 +0000661 *
662 * @param tstruct The struct definition
663 */
664void t_java_generator::generate_struct(t_struct* tstruct) {
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000665 if (tstruct->is_union()) {
666 generate_java_union(tstruct);
667 } else {
668 generate_java_struct(tstruct, false);
669 }
Mark Slee78f58e22006-09-02 04:17:07 +0000670}
671
Mark Sleef5377b32006-10-10 01:42:59 +0000672/**
673 * Exceptions are structs, but they inherit from Exception
674 *
675 * @param tstruct The struct definition
676 */
Mark Slee78f58e22006-09-02 04:17:07 +0000677void t_java_generator::generate_xception(t_struct* txception) {
678 generate_java_struct(txception, true);
679}
680
Mark Sleef5377b32006-10-10 01:42:59 +0000681
682/**
683 * Java struct definition.
684 *
685 * @param tstruct The struct definition
686 */
Mark Slee78f58e22006-09-02 04:17:07 +0000687void t_java_generator::generate_java_struct(t_struct* tstruct,
688 bool is_exception) {
Mark Sleeb15a68b2006-06-07 06:46:24 +0000689 // Make output file
Mark Slee98e962b2007-02-20 18:44:05 +0000690 string f_struct_name = package_dir_+"/"+(tstruct->get_name())+".java";
Mark Sleeb15a68b2006-06-07 06:46:24 +0000691 ofstream f_struct;
692 f_struct.open(f_struct_name.c_str());
693
694 f_struct <<
695 autogen_comment() <<
696 java_package() <<
Bryan Duxbury1121b472011-08-11 18:50:58 +0000697 java_type_imports();
Mark Sleeb15a68b2006-06-07 06:46:24 +0000698
Mark Slee78f58e22006-09-02 04:17:07 +0000699 generate_java_struct_definition(f_struct,
700 tstruct,
701 is_exception);
702 f_struct.close();
703}
704
Mark Sleef5377b32006-10-10 01:42:59 +0000705/**
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000706 * Java union definition.
707 *
708 * @param tstruct The struct definition
709 */
710void t_java_generator::generate_java_union(t_struct* tstruct) {
711 // Make output file
712 string f_struct_name = package_dir_+"/"+(tstruct->get_name())+".java";
713 ofstream f_struct;
714 f_struct.open(f_struct_name.c_str());
715
716 f_struct <<
717 autogen_comment() <<
718 java_package() <<
Bryan Duxbury932ce2b2010-12-07 18:28:48 +0000719 java_type_imports();
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000720
721 generate_java_doc(f_struct, tstruct);
722
723 bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
724
725 indent(f_struct) <<
Bryan Duxbury0fab12e2010-04-22 00:22:34 +0000726 "public " << (is_final ? "final " : "") << "class " << tstruct->get_name()
Bryan Duxbury932ce2b2010-12-07 18:28:48 +0000727 << " extends org.apache.thrift.TUnion<" << tstruct->get_name() << ", " << tstruct->get_name() << "._Fields> ";
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000728
729 scope_up(f_struct);
730
731 generate_struct_desc(f_struct, tstruct);
732 generate_field_descs(f_struct, tstruct);
733
734 f_struct << endl;
735
736 generate_field_name_constants(f_struct, tstruct);
737
738 f_struct << endl;
739
740 generate_java_meta_data_map(f_struct, tstruct);
741
742 generate_union_constructor(f_struct, tstruct);
743
744 f_struct << endl;
745
746 generate_union_abstract_methods(f_struct, tstruct);
747
748 f_struct << endl;
749
Bryan Duxbury66467a72010-08-21 17:48:18 +0000750 generate_java_struct_field_by_id(f_struct, tstruct);
751
752 f_struct << endl;
753
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000754 generate_union_getters_and_setters(f_struct, tstruct);
Bryan Duxbury63c2d372011-06-08 17:46:55 +0000755
756 f_struct << endl;
757
758 generate_union_is_set_methods(f_struct, tstruct);
Bryan Duxbury1121b472011-08-11 18:50:58 +0000759
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000760 f_struct << endl;
761
762 generate_union_comparisons(f_struct, tstruct);
763
764 f_struct << endl;
Bryan Duxbury5226eea2010-08-05 20:44:53 +0000765
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000766 generate_union_hashcode(f_struct, tstruct);
767
768 f_struct << endl;
769
Bryan Duxburyc8d533b2011-01-26 22:42:02 +0000770 generate_java_struct_write_object(f_struct, tstruct);
771
772 f_struct << endl;
773
774 generate_java_struct_read_object(f_struct, tstruct);
775
776 f_struct << endl;
777
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000778 scope_down(f_struct);
779
780 f_struct.close();
781}
782
783void t_java_generator::generate_union_constructor(ofstream& out, t_struct* tstruct) {
784 indent(out) << "public " << type_name(tstruct) << "() {" << endl;
785 indent(out) << " super();" << endl;
786 indent(out) << "}" << endl << endl;
787
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +0000788 indent(out) << "public " << type_name(tstruct) << "(_Fields setField, Object value) {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000789 indent(out) << " super(setField, value);" << endl;
790 indent(out) << "}" << endl << endl;
791
792 indent(out) << "public " << type_name(tstruct) << "(" << type_name(tstruct) << " other) {" << endl;
793 indent(out) << " super(other);" << endl;
794 indent(out) << "}" << endl;
795
796 indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
797 indent(out) << " return new " << tstruct->get_name() << "(this);" << endl;
798 indent(out) << "}" << endl << endl;
799
800 // generate "constructors" for each field
801 const vector<t_field*>& members = tstruct->get_members();
802 vector<t_field*>::const_iterator m_iter;
803 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Bryan Duxbury1606f252010-11-24 00:25:57 +0000804 t_type* type = (*m_iter)->get_type();
805 indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name() << "(" << type_name(type) << " value) {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000806 indent(out) << " " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();" << endl;
807 indent(out) << " x.set" << get_cap_name((*m_iter)->get_name()) << "(value);" << endl;
808 indent(out) << " return x;" << endl;
Bryan Duxbury1606f252010-11-24 00:25:57 +0000809 indent(out) << "}" << endl << endl;
810
811 if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
812 indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name() << "(byte[] value) {" << endl;
813 indent(out) << " " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();" << endl;
814 indent(out) << " x.set" << get_cap_name((*m_iter)->get_name()) << "(ByteBuffer.wrap(value));" << endl;
815 indent(out) << " return x;" << endl;
816 indent(out) << "}" << endl << endl;
817 }
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000818 }
819}
820
821void t_java_generator::generate_union_getters_and_setters(ofstream& out, t_struct* tstruct) {
822 const vector<t_field*>& members = tstruct->get_members();
823 vector<t_field*>::const_iterator m_iter;
Bryan Duxbury1121b472011-08-11 18:50:58 +0000824
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000825 bool first = true;
826 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
827 if (first) {
828 first = false;
829 } else {
830 out << endl;
831 }
832
833 t_field* field = (*m_iter);
Bryan Duxbury1606f252010-11-24 00:25:57 +0000834 t_type* type = field->get_type();
835 std::string cap_name = get_cap_name(field->get_name());
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000836
837 generate_java_doc(out, field);
Bryan Duxbury1606f252010-11-24 00:25:57 +0000838 if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
839 indent(out) << "public byte[] get" << cap_name << "() {" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +0000840 indent(out) << " set" << cap_name << "(org.apache.thrift.TBaseHelper.rightSize(buffer" << get_cap_name("for") << cap_name << "()));" << endl;
Bryan Duxburya5eb8482010-11-24 22:30:38 +0000841 indent(out) << " ByteBuffer b = buffer" << get_cap_name("for") << cap_name << "();" << endl;
842 indent(out) << " return b == null ? null : b.array();" << endl;
Bryan Duxbury1606f252010-11-24 00:25:57 +0000843 indent(out) << "}" << endl;
844
845 out << endl;
846
847 indent(out) << "public ByteBuffer buffer" << get_cap_name("for") << get_cap_name(field->get_name()) << "() {" << endl;
848 indent(out) << " if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {" << endl;
849 indent(out) << " return (ByteBuffer)getFieldValue();" << endl;
850 indent(out) << " } else {" << endl;
851 indent(out) << " throw new RuntimeException(\"Cannot get field '" << field->get_name()
852 << "' because union is currently set to \" + getFieldDesc(getSetField()).name);" << endl;
853 indent(out) << " }" << endl;
854 indent(out) << "}" << endl;
855 } else {
856 indent(out) << "public " << type_name(field->get_type()) << " get" << get_cap_name(field->get_name()) << "() {" << endl;
857 indent(out) << " if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {" << endl;
858 indent(out) << " return (" << type_name(field->get_type(), true) << ")getFieldValue();" << endl;
859 indent(out) << " } else {" << endl;
860 indent(out) << " throw new RuntimeException(\"Cannot get field '" << field->get_name()
861 << "' because union is currently set to \" + getFieldDesc(getSetField()).name);" << endl;
862 indent(out) << " }" << endl;
863 indent(out) << "}" << endl;
864 }
865
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000866 out << endl;
867
868 generate_java_doc(out, field);
Bryan Duxbury1606f252010-11-24 00:25:57 +0000869 if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
870 indent(out) << "public void set" << get_cap_name(field->get_name()) << "(byte[] value) {" << endl;
871 indent(out) << " set" << get_cap_name(field->get_name()) << "(ByteBuffer.wrap(value));" << endl;
872 indent(out) << "}" << endl;
873
874 out << endl;
875 }
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000876 indent(out) << "public void set" << get_cap_name(field->get_name()) << "(" << type_name(field->get_type()) << " value) {" << endl;
877 if (type_can_be_null(field->get_type())) {
878 indent(out) << " if (value == null) throw new NullPointerException();" << endl;
879 }
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +0000880 indent(out) << " setField_ = _Fields." << constant_name(field->get_name()) << ";" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000881 indent(out) << " value_ = value;" << endl;
882 indent(out) << "}" << endl;
883 }
884}
885
Bryan Duxbury63c2d372011-06-08 17:46:55 +0000886void t_java_generator::generate_union_is_set_methods(ofstream& out, t_struct* tstruct) {
887 const vector<t_field*>& members = tstruct->get_members();
888 vector<t_field*>::const_iterator m_iter;
889
890 bool first = true;
891 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
892 if (first) {
893 first = false;
894 } else {
895 out << endl;
896 }
897
898 std::string field_name = (*m_iter)->get_name();
899
900 indent(out) << "public boolean is" << get_cap_name("set") << get_cap_name(field_name) << "() {" << endl;
901 indent_up();
902 indent(out) << "return setField_ == _Fields." << constant_name(field_name) << ";" << endl;
903 indent_down();
904 indent(out) << "}" << endl << endl;
905 }
906}
907
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000908void t_java_generator::generate_union_abstract_methods(ofstream& out, t_struct* tstruct) {
909 generate_check_type(out, tstruct);
910 out << endl;
Bryan Duxbury18784d72011-09-20 22:53:31 +0000911 generate_standard_scheme_read_value(out, tstruct);
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000912 out << endl;
Bryan Duxbury18784d72011-09-20 22:53:31 +0000913 generate_standard_scheme_write_value(out, tstruct);
914 out << endl;
915 generate_tuple_scheme_read_value(out, tstruct);
916 out << endl;
917 generate_tuple_scheme_write_value(out, tstruct);
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000918 out << endl;
919 generate_get_field_desc(out, tstruct);
920 out << endl;
921 generate_get_struct_desc(out, tstruct);
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +0000922 out << endl;
923 indent(out) << "@Override" << endl;
924 indent(out) << "protected _Fields enumForId(short id) {" << endl;
925 indent(out) << " return _Fields.findByThriftIdOrThrow(id);" << endl;
926 indent(out) << "}" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000927}
928
929void t_java_generator::generate_check_type(ofstream& out, t_struct* tstruct) {
930 indent(out) << "@Override" << endl;
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +0000931 indent(out) << "protected void checkType(_Fields setField, Object value) throws ClassCastException {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000932 indent_up();
933
934 indent(out) << "switch (setField) {" << endl;
935 indent_up();
936
937 const vector<t_field*>& members = tstruct->get_members();
938 vector<t_field*>::const_iterator m_iter;
939
940 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
941 t_field* field = (*m_iter);
Bryan Duxbury1121b472011-08-11 18:50:58 +0000942
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +0000943 indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000944 indent(out) << " if (value instanceof " << type_name(field->get_type(), true, false, true) << ") {" << endl;
945 indent(out) << " break;" << endl;
946 indent(out) << " }" << endl;
947 indent(out) << " throw new ClassCastException(\"Was expecting value of type "
948 << type_name(field->get_type(), true, false) << " for field '" << field->get_name()
949 << "', but got \" + value.getClass().getSimpleName());" << endl;
950 // do the real check here
951 }
Bryan Duxbury1121b472011-08-11 18:50:58 +0000952
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000953 indent(out) << "default:" << endl;
954 indent(out) << " throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
955
956 indent_down();
957 indent(out) << "}" << endl;
Bryan Duxbury1121b472011-08-11 18:50:58 +0000958
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000959 indent_down();
960 indent(out) << "}" << endl;
961}
962
Bryan Duxbury18784d72011-09-20 22:53:31 +0000963void t_java_generator::generate_standard_scheme_read_value(ofstream& out, t_struct* tstruct) {
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000964 indent(out) << "@Override" << endl;
Bryan Duxbury18784d72011-09-20 22:53:31 +0000965 indent(out) << "protected Object standardSchemeReadValue(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TField field) throws org.apache.thrift.TException {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000966
967 indent_up();
968
Bryan Duxburyc2ec7ca2009-12-31 18:59:15 +0000969 indent(out) << "_Fields setField = _Fields.findByThriftId(field.id);" << endl;
970 indent(out) << "if (setField != null) {" << endl;
971 indent_up();
972 indent(out) << "switch (setField) {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000973 indent_up();
974
975 const vector<t_field*>& members = tstruct->get_members();
976 vector<t_field*>::const_iterator m_iter;
977
978 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
979 t_field* field = (*m_iter);
Bryan Duxbury1121b472011-08-11 18:50:58 +0000980
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +0000981 indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000982 indent_up();
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +0000983 indent(out) << "if (field.type == " << constant_name(field->get_name()) << "_FIELD_DESC.type) {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000984 indent_up();
985 indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";" << endl;
986 generate_deserialize_field(out, field, "");
987 indent(out) << "return " << field->get_name() << ";" << endl;
988 indent_down();
989 indent(out) << "} else {" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +0000990 indent(out) << " org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000991 indent(out) << " return null;" << endl;
992 indent(out) << "}" << endl;
993 indent_down();
994 }
Bryan Duxburyab3666e2009-09-01 23:03:47 +0000995
Bryan Duxburyc2ec7ca2009-12-31 18:59:15 +0000996 indent(out) << "default:" << endl;
997 indent(out) << " throw new IllegalStateException(\"setField wasn't null, but didn't match any of the case statements!\");" << endl;
998
999 indent_down();
1000 indent(out) << "}" << endl;
1001
1002 indent_down();
1003 indent(out) << "} else {" << endl;
Bryan Duxbury18784d72011-09-20 22:53:31 +00001004 indent_up();
Bryan Duxburyc2ec7ca2009-12-31 18:59:15 +00001005 indent(out) << "return null;" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001006 indent_down();
1007 indent(out) << "}" << endl;
1008
1009 indent_down();
1010 indent(out) << "}" << endl;
1011}
1012
Bryan Duxbury18784d72011-09-20 22:53:31 +00001013void t_java_generator::generate_standard_scheme_write_value(ofstream& out, t_struct* tstruct) {
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001014 indent(out) << "@Override" << endl;
Bryan Duxbury18784d72011-09-20 22:53:31 +00001015 indent(out) << "protected void standardSchemeWriteValue(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001016
1017 indent_up();
1018
Bryan Duxbury4e7cf252010-02-28 05:19:38 +00001019 indent(out) << "switch (setField_) {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001020 indent_up();
1021
1022 const vector<t_field*>& members = tstruct->get_members();
1023 vector<t_field*>::const_iterator m_iter;
1024
1025 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1026 t_field* field = (*m_iter);
Bryan Duxbury1121b472011-08-11 18:50:58 +00001027
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001028 indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001029 indent_up();
1030 indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name()
Bryan Duxbury4e7cf252010-02-28 05:19:38 +00001031 << " = (" << type_name(field->get_type(), true, false) << ")value_;" << endl;
Bryan Duxburyadaf8262011-09-01 18:54:07 +00001032 generate_serialize_field(out, field, "");
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001033 indent(out) << "return;" << endl;
1034 indent_down();
1035 }
Bryan Duxbury1121b472011-08-11 18:50:58 +00001036
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001037 indent(out) << "default:" << endl;
Bryan Duxbury4e7cf252010-02-28 05:19:38 +00001038 indent(out) << " throw new IllegalStateException(\"Cannot write union with unknown field \" + setField_);" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001039
1040 indent_down();
1041 indent(out) << "}" << endl;
1042
1043 indent_down();
1044
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001045 indent(out) << "}" << endl;
1046}
1047
Bryan Duxbury18784d72011-09-20 22:53:31 +00001048void t_java_generator::generate_tuple_scheme_read_value(ofstream& out, t_struct* tstruct) {
1049 indent(out) << "@Override" << endl;
1050 indent(out) << "protected Object tupleSchemeReadValue(org.apache.thrift.protocol.TProtocol iprot, short fieldID) throws org.apache.thrift.TException {" << endl;
1051
1052 indent_up();
1053
1054 indent(out) << "_Fields setField = _Fields.findByThriftId(fieldID);" << endl;
1055 indent(out) << "if (setField != null) {" << endl;
1056 indent_up();
1057 indent(out) << "switch (setField) {" << endl;
1058 indent_up();
1059
1060 const vector<t_field*>& members = tstruct->get_members();
1061 vector<t_field*>::const_iterator m_iter;
1062
1063 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1064 t_field* field = (*m_iter);
1065
1066 indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
1067 indent_up();
1068 indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";" << endl;
1069 generate_deserialize_field(out, field, "");
1070 indent(out) << "return " << field->get_name() << ";" << endl;
1071 indent_down();
1072 }
1073
1074 indent(out) << "default:" << endl;
1075 indent(out) << " throw new IllegalStateException(\"setField wasn't null, but didn't match any of the case statements!\");" << endl;
1076
1077 indent_down();
1078 indent(out) << "}" << endl;
1079
1080 indent_down();
1081 indent(out) << "} else {" << endl;
1082 indent_up();
1083 indent(out) << "return null;" << endl;
1084 indent_down();
1085 indent(out) << "}" << endl;
1086 indent_down();
1087 indent(out) << "}" << endl;
1088}
1089
1090void t_java_generator::generate_tuple_scheme_write_value(ofstream& out, t_struct* tstruct) {
1091 indent(out) << "@Override" << endl;
1092 indent(out) << "protected void tupleSchemeWriteValue(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {" << endl;
1093
1094 indent_up();
1095
1096 indent(out) << "switch (setField_) {" << endl;
1097 indent_up();
1098
1099 const vector<t_field*>& members = tstruct->get_members();
1100 vector<t_field*>::const_iterator m_iter;
1101
1102 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1103 t_field* field = (*m_iter);
1104
1105 indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
1106 indent_up();
1107 indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name()
1108 << " = (" << type_name(field->get_type(), true, false) << ")value_;" << endl;
1109 generate_serialize_field(out, field, "");
1110 indent(out) << "return;" << endl;
1111 indent_down();
1112 }
1113
1114 indent(out) << "default:" << endl;
1115 indent(out) << " throw new IllegalStateException(\"Cannot write union with unknown field \" + setField_);" << endl;
1116
1117 indent_down();
1118 indent(out) << "}" << endl;
1119
1120 indent_down();
1121
1122 indent(out) << "}" << endl;
1123}
1124
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001125void t_java_generator::generate_get_field_desc(ofstream& out, t_struct* tstruct) {
1126 indent(out) << "@Override" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001127 indent(out) << "protected org.apache.thrift.protocol.TField getFieldDesc(_Fields setField) {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001128 indent_up();
Bryan Duxbury1121b472011-08-11 18:50:58 +00001129
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001130 const vector<t_field*>& members = tstruct->get_members();
1131 vector<t_field*>::const_iterator m_iter;
1132
1133 indent(out) << "switch (setField) {" << endl;
1134 indent_up();
1135
1136 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1137 t_field* field = (*m_iter);
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001138 indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
1139 indent(out) << " return " << constant_name(field->get_name()) << "_FIELD_DESC;" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001140 }
1141
1142 indent(out) << "default:" << endl;
1143 indent(out) << " throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl;
1144
1145 indent_down();
1146 indent(out) << "}" << endl;
1147
1148 indent_down();
1149 indent(out) << "}" << endl;
1150}
1151
1152void t_java_generator::generate_get_struct_desc(ofstream& out, t_struct* tstruct) {
Roger Meier3b771a12010-11-17 22:11:26 +00001153 (void) tstruct;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001154 indent(out) << "@Override" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001155 indent(out) << "protected org.apache.thrift.protocol.TStruct getStructDesc() {" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001156 indent(out) << " return STRUCT_DESC;" << endl;
1157 indent(out) << "}" << endl;
1158}
1159
1160void t_java_generator::generate_union_comparisons(ofstream& out, t_struct* tstruct) {
1161 // equality
1162 indent(out) << "public boolean equals(Object other) {" << endl;
1163 indent(out) << " if (other instanceof " << tstruct->get_name() << ") {" << endl;
1164 indent(out) << " return equals((" << tstruct->get_name() << ")other);" << endl;
1165 indent(out) << " } else {" << endl;
1166 indent(out) << " return false;" << endl;
1167 indent(out) << " }" << endl;
1168 indent(out) << "}" << endl;
1169
1170 out << endl;
1171
1172 indent(out) << "public boolean equals(" << tstruct->get_name() << " other) {" << endl;
Bryan Duxburyf5abd262010-08-06 00:18:25 +00001173 indent(out) << " return other != null && getSetField() == other.getSetField() && getFieldValue().equals(other.getFieldValue());" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001174 indent(out) << "}" << endl;
1175 out << endl;
1176
Bryan Duxbury5557bef2010-03-29 23:57:09 +00001177 indent(out) << "@Override" << endl;
1178 indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001179 indent(out) << " int lastComparison = org.apache.thrift.TBaseHelper.compareTo(getSetField(), other.getSetField());" << endl;
Bryan Duxbury5557bef2010-03-29 23:57:09 +00001180 indent(out) << " if (lastComparison == 0) {" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001181 indent(out) << " return org.apache.thrift.TBaseHelper.compareTo(getFieldValue(), other.getFieldValue());" << endl;
Bryan Duxbury5557bef2010-03-29 23:57:09 +00001182 indent(out) << " }" << endl;
1183 indent(out) << " return lastComparison;" << endl;
1184 indent(out) << "}" << endl;
1185 out << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001186}
1187
1188void t_java_generator::generate_union_hashcode(ofstream& out, t_struct* tstruct) {
Roger Meier3b771a12010-11-17 22:11:26 +00001189 (void) tstruct;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001190 if (gen_hash_code_) {
1191 indent(out) << "@Override" << endl;
1192 indent(out) << "public int hashCode() {" << endl;
Bryan Duxburycd43a062010-02-17 20:01:29 +00001193 indent(out) << " HashCodeBuilder hcb = new HashCodeBuilder();" << endl;
1194 indent(out) << " hcb.append(this.getClass().getName());" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001195 indent(out) << " org.apache.thrift.TFieldIdEnum setField = getSetField();" << endl;
Bryan Duxburycd43a062010-02-17 20:01:29 +00001196 indent(out) << " if (setField != null) {" << endl;
1197 indent(out) << " hcb.append(setField.getThriftFieldId());" << endl;
1198 indent(out) << " Object value = getFieldValue();" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001199 indent(out) << " if (value instanceof org.apache.thrift.TEnum) {" << endl;
1200 indent(out) << " hcb.append(((org.apache.thrift.TEnum)getFieldValue()).getValue());" << endl;
Bryan Duxburycd43a062010-02-17 20:01:29 +00001201 indent(out) << " } else {" << endl;
1202 indent(out) << " hcb.append(value);" << endl;
1203 indent(out) << " }" << endl;
1204 indent(out) << " }" << endl;
1205 indent(out) << " return hcb.toHashCode();" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001206 indent(out) << "}";
1207 } else {
1208 indent(out) << "/**" << endl;
1209 indent(out) << " * If you'd like this to perform more respectably, use the hashcode generator option." << endl;
1210 indent(out) << " */" << endl;
1211 indent(out) << "@Override" << endl;
1212 indent(out) << "public int hashCode() {" << endl;
1213 indent(out) << " return 0;" << endl;
1214 indent(out) << "}" << endl;
1215 }
1216}
1217
1218/**
Mark Sleef5377b32006-10-10 01:42:59 +00001219 * Java struct definition. This has various parameters, as it could be
1220 * generated standalone or inside another class as a helper. If it
1221 * is a helper than it is a static class.
1222 *
1223 * @param tstruct The struct definition
1224 * @param is_exception Is this an exception?
1225 * @param in_class If inside a class, needs to be static class
1226 * @param is_result If this is a result it needs a different writer
1227 */
Mark Slee78f58e22006-09-02 04:17:07 +00001228void t_java_generator::generate_java_struct_definition(ofstream &out,
1229 t_struct* tstruct,
1230 bool is_exception,
1231 bool in_class,
1232 bool is_result) {
Mark Slee8775c732007-09-10 22:33:05 +00001233 generate_java_doc(out, tstruct);
1234
Bryan Duxbury056bcb62009-02-01 16:56:29 +00001235 bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
1236
Mark Sleef0712dc2006-10-25 19:03:57 +00001237 indent(out) <<
Bryan Duxbury056bcb62009-02-01 16:56:29 +00001238 "public " << (is_final ? "final " : "") <<
Bryan Duxbury1121b472011-08-11 18:50:58 +00001239 (in_class ? "static " : "") << "class " << tstruct->get_name() << " ";
Mark Slee5ab57052007-11-27 08:38:16 +00001240
Mark Slee78f58e22006-09-02 04:17:07 +00001241 if (is_exception) {
1242 out << "extends Exception ";
1243 }
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001244 out << "implements org.apache.thrift.TBase<" << tstruct->get_name() << ", " << tstruct->get_name() << "._Fields>, java.io.Serializable, Cloneable";
Bryan Duxbury684b4f92009-07-31 00:12:21 +00001245
1246 out << " ";
Mark Slee5ab57052007-11-27 08:38:16 +00001247
Mark Slee78f58e22006-09-02 04:17:07 +00001248 scope_up(out);
Mark Sleeb15a68b2006-06-07 06:46:24 +00001249
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001250 generate_struct_desc(out, tstruct);
Bryan Duxburybb7826d2009-02-08 00:12:38 +00001251
Mark Slee01a9f882007-08-31 00:55:28 +00001252 // Members are public for -java, private for -javabean
Mark Sleeb15a68b2006-06-07 06:46:24 +00001253 const vector<t_field*>& members = tstruct->get_members();
Mark Slee5ab57052007-11-27 08:38:16 +00001254 vector<t_field*>::const_iterator m_iter;
Bryan Duxburybb7826d2009-02-08 00:12:38 +00001255
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001256 out << endl;
1257
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001258 generate_field_descs(out, tstruct);
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001259
Bryan Duxburybb7826d2009-02-08 00:12:38 +00001260 out << endl;
1261
Bryan Duxbury1121b472011-08-11 18:50:58 +00001262 generate_scheme_map(out, tstruct);
1263
1264 out << endl;
1265
Mark Sleeb15a68b2006-06-07 06:46:24 +00001266 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Bryan Duxburyea7910f2010-04-03 05:04:48 +00001267 if (bean_style_ || private_members_) {
Mark Slee01a9f882007-08-31 00:55:28 +00001268 indent(out) << "private ";
1269 } else {
David Reissf33e03c2008-10-29 00:07:49 +00001270 generate_java_doc(out, *m_iter);
Mark Slee01a9f882007-08-31 00:55:28 +00001271 indent(out) << "public ";
1272 }
1273 out << declare_field(*m_iter, false) << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001274 }
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001275
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001276 out << endl;
1277
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001278 generate_field_name_constants(out, tstruct);
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001279
Bryan Duxbury3efce232009-08-03 19:37:26 +00001280 // isset data
Mark Slee78f58e22006-09-02 04:17:07 +00001281 if (members.size() > 0) {
Bryan Duxbury3efce232009-08-03 19:37:26 +00001282 out << endl;
1283
1284 indent(out) << "// isset id assignments" << endl;
1285
1286 int i = 0;
Bryan Duxbury1121b472011-08-11 18:50:58 +00001287 int optionals = 0;
Bryan Duxbury3efce232009-08-03 19:37:26 +00001288 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00001289 if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
1290 optionals++;
1291 }
Bryan Duxbury3efce232009-08-03 19:37:26 +00001292 if (!type_can_be_null((*m_iter)->get_type())) {
1293 indent(out) << "private static final int " << isset_field_id(*m_iter)
1294 << " = " << i << ";" << endl;
1295 i++;
Mark Slee78f58e22006-09-02 04:17:07 +00001296 }
Bryan Duxbury3efce232009-08-03 19:37:26 +00001297 }
1298
1299 if (i > 0) {
1300 indent(out) << "private BitSet __isset_bit_vector = new BitSet(" << i << ");" << endl;
1301 }
Bryan Duxbury1121b472011-08-11 18:50:58 +00001302 if (optionals > 0) {
1303 std::string output_string = "private _Fields optionals[] = {";
1304 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1305 if ((*m_iter)->get_req() == t_field::T_OPTIONAL) {
1306 output_string = output_string + "_Fields." + constant_name((*m_iter)->get_name()) + ",";
1307 }
1308 }
1309 indent(out) << output_string.substr(0, output_string.length() - 1) << "};" << endl;
1310 }
Mark Slee78f58e22006-09-02 04:17:07 +00001311 }
Mark Slee5ab57052007-11-27 08:38:16 +00001312
David Reissb936ffd2009-01-05 21:02:52 +00001313 generate_java_meta_data_map(out, tstruct);
1314
Bryan Duxbury364902e2009-10-02 00:56:53 +00001315 bool all_optional_members = true;
1316
Mark Slee7ff32452007-02-01 05:26:18 +00001317 // Default constructor
1318 indent(out) <<
1319 "public " << tstruct->get_name() << "() {" << endl;
1320 indent_up();
1321 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
David Reisse087a302007-08-23 21:43:25 +00001322 t_type* t = get_true_type((*m_iter)->get_type());
David Reiss80a702f2007-12-18 02:54:06 +00001323 if ((*m_iter)->get_value() != NULL) {
Mark Slee7ff32452007-02-01 05:26:18 +00001324 print_const_value(out, "this." + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true);
1325 }
Bryan Duxbury364902e2009-10-02 00:56:53 +00001326 if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
1327 all_optional_members = false;
1328 }
Mark Slee7ff32452007-02-01 05:26:18 +00001329 }
1330 indent_down();
1331 indent(out) << "}" << endl << endl;
1332
Bryan Duxbury364902e2009-10-02 00:56:53 +00001333 if (!members.empty() && !all_optional_members) {
David Reiss603d5042008-12-02 02:06:31 +00001334 // Full constructor for all fields
Mark Sleea0f8bdc2007-08-29 04:36:28 +00001335 indent(out) <<
1336 "public " << tstruct->get_name() << "(" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +00001337 indent_up();
Bryan Duxbury364902e2009-10-02 00:56:53 +00001338 bool first = true;
1339 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1340 if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
1341 if (!first) {
1342 out << "," << endl;
1343 }
1344 first = false;
1345 indent(out) << type_name((*m_iter)->get_type()) << " " <<
1346 (*m_iter)->get_name();
Mark Sleea0f8bdc2007-08-29 04:36:28 +00001347 }
1348 }
1349 out << ")" << endl;
1350 indent_down();
1351 indent(out) << "{" << endl;
1352 indent_up();
1353 indent(out) << "this();" << endl;
1354 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Bryan Duxbury364902e2009-10-02 00:56:53 +00001355 if ((*m_iter)->get_req() != t_field::T_OPTIONAL) {
1356 indent(out) << "this." << (*m_iter)->get_name() << " = " <<
1357 (*m_iter)->get_name() << ";" << endl;
Bryan Duxbury1121b472011-08-11 18:50:58 +00001358 generate_isset_set(out, (*m_iter), "");
Bryan Duxbury364902e2009-10-02 00:56:53 +00001359 }
Mark Sleea0f8bdc2007-08-29 04:36:28 +00001360 }
Bryan Duxbury1121b472011-08-11 18:50:58 +00001361
Mark Sleea0f8bdc2007-08-29 04:36:28 +00001362 indent_down();
1363 indent(out) << "}" << endl << endl;
1364 }
1365
David Reiss603d5042008-12-02 02:06:31 +00001366 // copy constructor
1367 indent(out) << "/**" << endl;
1368 indent(out) << " * Performs a deep copy on <i>other</i>." << endl;
1369 indent(out) << " */" << endl;
1370 indent(out) << "public " << tstruct->get_name() << "(" << tstruct->get_name() << " other) {" << endl;
1371 indent_up();
1372
Bryan Duxbury3efce232009-08-03 19:37:26 +00001373 if (has_bit_vector(tstruct)) {
1374 indent(out) << "__isset_bit_vector.clear();" << endl;
1375 indent(out) << "__isset_bit_vector.or(other.__isset_bit_vector);" << endl;
1376 }
1377
David Reiss603d5042008-12-02 02:06:31 +00001378 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1379 t_field* field = (*m_iter);
1380 std::string field_name = field->get_name();
1381 t_type* type = field->get_type();
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001382 bool can_be_null = type_can_be_null(type);
David Reiss603d5042008-12-02 02:06:31 +00001383
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001384 if (can_be_null) {
1385 indent(out) << "if (other." << generate_isset_check(field) << ") {" << endl;
David Reiss603d5042008-12-02 02:06:31 +00001386 indent_up();
1387 }
1388
1389 if (type->is_container()) {
1390 generate_deep_copy_container(out, "other", field_name, "__this__" + field_name, type);
1391 indent(out) << "this." << field_name << " = __this__" << field_name << ";" << endl;
1392 } else {
1393 indent(out) << "this." << field_name << " = ";
David Reiss5455f002009-01-05 21:02:48 +00001394 generate_deep_copy_non_container(out, "other." + field_name, field_name, type);
David Reiss603d5042008-12-02 02:06:31 +00001395 out << ";" << endl;
1396 }
1397
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001398 if (can_be_null) {
David Reiss603d5042008-12-02 02:06:31 +00001399 indent_down();
1400 indent(out) << "}" << endl;
1401 }
1402 }
1403
1404 indent_down();
1405 indent(out) << "}" << endl << endl;
1406
1407 // clone method, so that you can deep copy an object when you don't know its class.
Bryan Duxburyab3666e2009-09-01 23:03:47 +00001408 indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl;
1409 indent(out) << " return new " << tstruct->get_name() << "(this);" << endl;
1410 indent(out) << "}" << endl << endl;
1411
Bryan Duxbury5226eea2010-08-05 20:44:53 +00001412 generate_java_struct_clear(out, tstruct);
1413
Bryan Duxburyf5383b62009-02-03 00:49:25 +00001414 generate_java_bean_boilerplate(out, tstruct);
1415 generate_generic_field_getters_setters(out, tstruct);
1416 generate_generic_isset_method(out, tstruct);
David Reiss3b15ebc2008-03-02 06:29:19 +00001417
1418 generate_java_struct_equality(out, tstruct);
Bryan Duxbury5557bef2010-03-29 23:57:09 +00001419 generate_java_struct_compare_to(out, tstruct);
Bryan Duxbury66467a72010-08-21 17:48:18 +00001420 generate_java_struct_field_by_id(out, tstruct);
David Reiss3b15ebc2008-03-02 06:29:19 +00001421
Mark Slee78f58e22006-09-02 04:17:07 +00001422 generate_java_struct_reader(out, tstruct);
1423 if (is_result) {
1424 generate_java_struct_result_writer(out, tstruct);
1425 } else {
1426 generate_java_struct_writer(out, tstruct);
1427 }
Mark Slee81097572007-03-14 03:07:00 +00001428 generate_java_struct_tostring(out, tstruct);
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001429 generate_java_validator(out, tstruct);
Bryan Duxburyc8d533b2011-01-26 22:42:02 +00001430
1431 generate_java_struct_write_object(out, tstruct);
1432 generate_java_struct_read_object(out, tstruct);
1433
Bryan Duxbury1121b472011-08-11 18:50:58 +00001434 generate_java_struct_standard_scheme(out, tstruct);
1435 generate_java_struct_tuple_scheme(out, tstruct);
1436
Mark Slee78f58e22006-09-02 04:17:07 +00001437 scope_down(out);
Mark Sleeb7f58ff2006-09-02 21:59:28 +00001438 out << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00001439}
1440
Mark Sleef5377b32006-10-10 01:42:59 +00001441/**
David Reiss3b15ebc2008-03-02 06:29:19 +00001442 * Generates equals methods and a hashCode method for a structure.
1443 *
1444 * @param tstruct The struct definition
1445 */
1446void t_java_generator::generate_java_struct_equality(ofstream& out,
1447 t_struct* tstruct) {
Bryan Duxbury369417a2009-01-27 22:09:33 +00001448 out << indent() << "@Override" << endl <<
David Reiss3b15ebc2008-03-02 06:29:19 +00001449 indent() << "public boolean equals(Object that) {" << endl;
1450 indent_up();
1451 out <<
1452 indent() << "if (that == null)" << endl <<
1453 indent() << " return false;" << endl <<
1454 indent() << "if (that instanceof " << tstruct->get_name() << ")" << endl <<
1455 indent() << " return this.equals((" << tstruct->get_name() << ")that);" << endl <<
1456 indent() << "return false;" << endl;
1457 scope_down(out);
1458 out << endl;
1459
1460 out <<
1461 indent() << "public boolean equals(" << tstruct->get_name() << " that) {" << endl;
1462 indent_up();
1463 out <<
1464 indent() << "if (that == null)" << endl <<
1465 indent() << " return false;" << endl;
1466
1467 const vector<t_field*>& members = tstruct->get_members();
1468 vector<t_field*>::const_iterator m_iter;
1469 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1470 out << endl;
1471
1472 t_type* t = get_true_type((*m_iter)->get_type());
1473 // Most existing Thrift code does not use isset or optional/required,
1474 // so we treat "default" fields as required.
1475 bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
1476 bool can_be_null = type_can_be_null(t);
1477 string name = (*m_iter)->get_name();
1478
1479 string this_present = "true";
1480 string that_present = "true";
1481 string unequal;
1482
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001483 if (is_optional || can_be_null) {
1484 this_present += " && this." + generate_isset_check(*m_iter);
1485 that_present += " && that." + generate_isset_check(*m_iter);
David Reiss3b15ebc2008-03-02 06:29:19 +00001486 }
1487
1488 out <<
1489 indent() << "boolean this_present_" << name << " = "
Bryan Duxbury1121b472011-08-11 18:50:58 +00001490 << this_present << ";" << endl <<
David Reiss3b15ebc2008-03-02 06:29:19 +00001491 indent() << "boolean that_present_" << name << " = "
Bryan Duxbury1121b472011-08-11 18:50:58 +00001492 << that_present << ";" << endl <<
David Reiss3b15ebc2008-03-02 06:29:19 +00001493 indent() << "if (" << "this_present_" << name
Bryan Duxbury1121b472011-08-11 18:50:58 +00001494 << " || that_present_" << name << ") {" << endl;
David Reiss3b15ebc2008-03-02 06:29:19 +00001495 indent_up();
1496 out <<
1497 indent() << "if (!(" << "this_present_" << name
Bryan Duxbury1121b472011-08-11 18:50:58 +00001498 << " && that_present_" << name << "))" << endl <<
David Reiss3b15ebc2008-03-02 06:29:19 +00001499 indent() << " return false;" << endl;
1500
1501 if (t->is_base_type() && ((t_base_type*)t)->is_binary()) {
Bryan Duxburyf5abd262010-08-06 00:18:25 +00001502 unequal = "!this." + name + ".equals(that." + name + ")";
David Reiss3b15ebc2008-03-02 06:29:19 +00001503 } else if (can_be_null) {
1504 unequal = "!this." + name + ".equals(that." + name + ")";
1505 } else {
1506 unequal = "this." + name + " != that." + name;
1507 }
1508
1509 out <<
1510 indent() << "if (" << unequal << ")" << endl <<
1511 indent() << " return false;" << endl;
1512
1513 scope_down(out);
1514 }
1515 out << endl;
1516 indent(out) << "return true;" << endl;
1517 scope_down(out);
1518 out << endl;
1519
Bryan Duxbury30e1de92009-02-10 18:36:56 +00001520 out << indent() << "@Override" << endl <<
1521 indent() << "public int hashCode() {" << endl;
1522 indent_up();
David Reiss14feb412008-03-02 06:29:23 +00001523 if (gen_hash_code_) {
Bryan Duxbury30e1de92009-02-10 18:36:56 +00001524 indent(out) << "HashCodeBuilder builder = new HashCodeBuilder();" << endl;
David Reiss14feb412008-03-02 06:29:23 +00001525
1526 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1527 out << endl;
1528
1529 t_type* t = get_true_type((*m_iter)->get_type());
1530 bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL;
1531 bool can_be_null = type_can_be_null(t);
1532 string name = (*m_iter)->get_name();
1533
1534 string present = "true";
1535
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001536 if (is_optional || can_be_null) {
1537 present += " && (" + generate_isset_check(*m_iter) + ")";
David Reiss14feb412008-03-02 06:29:23 +00001538 }
1539
Bryan Duxbury9af23d92009-11-19 17:26:38 +00001540 indent(out) << "boolean present_" << name << " = " << present << ";" << endl;
1541 indent(out) << "builder.append(present_" << name << ");" << endl;
1542 indent(out) << "if (present_" << name << ")" << endl;
1543 if (t->is_enum()) {
1544 indent(out) << " builder.append(" << name << ".getValue());" << endl;
1545 } else {
1546 indent(out) << " builder.append(" << name << ");" << endl;
1547 }
David Reiss14feb412008-03-02 06:29:23 +00001548 }
1549
1550 out << endl;
Bryan Duxbury30e1de92009-02-10 18:36:56 +00001551 indent(out) << "return builder.toHashCode();" << endl;
David Reiss14feb412008-03-02 06:29:23 +00001552 } else {
Bryan Duxbury30e1de92009-02-10 18:36:56 +00001553 indent(out) << "return 0;" << endl;
David Reiss14feb412008-03-02 06:29:23 +00001554 }
Bryan Duxbury30e1de92009-02-10 18:36:56 +00001555 indent_down();
1556 indent(out) << "}" << endl << endl;
David Reiss3b15ebc2008-03-02 06:29:19 +00001557}
1558
Bryan Duxbury684b4f92009-07-31 00:12:21 +00001559void t_java_generator::generate_java_struct_compare_to(ofstream& out, t_struct* tstruct) {
1560 indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl;
1561 indent_up();
1562
1563 indent(out) << "if (!getClass().equals(other.getClass())) {" << endl;
1564 indent(out) << " return getClass().getName().compareTo(other.getClass().getName());" << endl;
1565 indent(out) << "}" << endl;
1566 out << endl;
1567
1568 indent(out) << "int lastComparison = 0;" << endl;
1569 indent(out) << type_name(tstruct) << " typedOther = (" << type_name(tstruct) << ")other;" << endl;
1570 out << endl;
1571
1572 const vector<t_field*>& members = tstruct->get_members();
1573 vector<t_field*>::const_iterator m_iter;
1574 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1575 t_field* field = *m_iter;
Bryan Duxburydee6d422010-02-23 19:06:25 +00001576 indent(out) << "lastComparison = Boolean.valueOf(" << generate_isset_check(field) << ").compareTo(typedOther." << generate_isset_check(field) << ");" << endl;
Bryan Duxbury684b4f92009-07-31 00:12:21 +00001577 indent(out) << "if (lastComparison != 0) {" << endl;
1578 indent(out) << " return lastComparison;" << endl;
1579 indent(out) << "}" << endl;
1580
Bryan Duxburyd9207652010-09-17 19:27:36 +00001581 indent(out) << "if (" << generate_isset_check(field) << ") {" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001582 indent(out) << " lastComparison = org.apache.thrift.TBaseHelper.compareTo(this." << field->get_name() << ", typedOther." << field->get_name() << ");" << endl;
Bryan Duxburydee6d422010-02-23 19:06:25 +00001583 indent(out) << " if (lastComparison != 0) {" << endl;
1584 indent(out) << " return lastComparison;" << endl;
1585 indent(out) << " }" << endl;
Bryan Duxbury684b4f92009-07-31 00:12:21 +00001586 indent(out) << "}" << endl;
1587 }
1588
1589 indent(out) << "return 0;" << endl;
1590
1591 indent_down();
1592 indent(out) << "}" << endl << endl;
1593}
1594
David Reiss3b15ebc2008-03-02 06:29:19 +00001595/**
Mark Sleef5377b32006-10-10 01:42:59 +00001596 * Generates a function to read all the fields of the struct.
1597 *
1598 * @param tstruct The struct definition
1599 */
Mark Slee78f58e22006-09-02 04:17:07 +00001600void t_java_generator::generate_java_struct_reader(ofstream& out,
1601 t_struct* tstruct) {
Roger Meierb6af6db2011-08-18 20:31:16 +00001602 (void) tstruct;
Bryan Duxbury1121b472011-08-11 18:50:58 +00001603 indent(out) << "public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001604 indent_up();
Bryan Duxbury1121b472011-08-11 18:50:58 +00001605 indent(out) << "schemes.get(iprot.getScheme()).getScheme().read(iprot, this);" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001606 indent_down();
Bryan Duxbury1121b472011-08-11 18:50:58 +00001607 indent(out) << "}" << endl <<
1608 endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001609}
1610
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001611// generates java method to perform various checks
1612// (e.g. check that all required fields are set)
1613void t_java_generator::generate_java_validator(ofstream& out,
Bryan Duxbury1121b472011-08-11 18:50:58 +00001614 t_struct* tstruct){
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001615 indent(out) << "public void validate() throws org.apache.thrift.TException {" << endl;
Bryan Duxbury9af23d92009-11-19 17:26:38 +00001616 indent_up();
1617
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001618 const vector<t_field*>& fields = tstruct->get_members();
1619 vector<t_field*>::const_iterator f_iter;
Bryan Duxbury9af23d92009-11-19 17:26:38 +00001620
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001621 out << indent() << "// check for required fields" << endl;
1622 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
David Reissaf81de02009-08-27 20:27:09 +00001623 if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001624 if (bean_style_) {
1625 out <<
Bryan Duxburyf4c71c72009-02-23 17:49:24 +00001626 indent() << "if (!" << generate_isset_check(*f_iter) << ") {" << endl <<
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001627 indent() << " throw new org.apache.thrift.protocol.TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' is unset! Struct:\" + toString());" << endl <<
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001628 indent() << "}" << endl << endl;
1629 } else{
1630 if (type_can_be_null((*f_iter)->get_type())) {
1631 indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001632 indent(out) << " throw new org.apache.thrift.protocol.TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());" << endl;
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001633 indent(out) << "}" << endl;
1634 } else {
David Reissaf81de02009-08-27 20:27:09 +00001635 indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name() << "' because it's a primitive and you chose the non-beans generator." << endl;
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001636 }
Bryan Duxbury9af23d92009-11-19 17:26:38 +00001637 }
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001638 }
1639 }
Bryan Duxbury9af23d92009-11-19 17:26:38 +00001640
Bryan Duxbury8bbd8442009-01-20 01:54:14 +00001641 indent_down();
1642 indent(out) << "}" << endl << endl;
1643}
1644
Mark Sleef5377b32006-10-10 01:42:59 +00001645/**
1646 * Generates a function to write all the fields of the struct
1647 *
1648 * @param tstruct The struct definition
1649 */
Mark Slee78f58e22006-09-02 04:17:07 +00001650void t_java_generator::generate_java_struct_writer(ofstream& out,
1651 t_struct* tstruct) {
Roger Meierb6af6db2011-08-18 20:31:16 +00001652 (void) tstruct;
Bryan Duxbury1121b472011-08-11 18:50:58 +00001653 indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001654 indent_up();
Bryan Duxbury1121b472011-08-11 18:50:58 +00001655 indent(out) << "schemes.get(oprot.getScheme()).getScheme().write(oprot, this);" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001656
1657 indent_down();
Bryan Duxburyf3574172011-09-26 20:32:59 +00001658 indent(out) << "}" << endl << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001659}
1660
Mark Sleef5377b32006-10-10 01:42:59 +00001661/**
1662 * Generates a function to write all the fields of the struct,
1663 * which is a function result. These fields are only written
1664 * if they are set in the Isset array, and only one of them
1665 * can be set at a time.
1666 *
1667 * @param tstruct The struct definition
1668 */
Mark Slee78f58e22006-09-02 04:17:07 +00001669void t_java_generator::generate_java_struct_result_writer(ofstream& out,
1670 t_struct* tstruct) {
Roger Meierb6af6db2011-08-18 20:31:16 +00001671 (void) tstruct;
Bryan Duxbury1121b472011-08-11 18:50:58 +00001672 indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001673 indent_up();
Bryan Duxbury1121b472011-08-11 18:50:58 +00001674 indent(out) << "schemes.get(oprot.getScheme()).getScheme().write(oprot, this);" << endl;
1675
Mark Slee78f58e22006-09-02 04:17:07 +00001676 indent_down();
Bryan Duxbury1121b472011-08-11 18:50:58 +00001677 indent(out) << " }" << endl << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00001678}
1679
Bryan Duxbury66467a72010-08-21 17:48:18 +00001680void t_java_generator::generate_java_struct_field_by_id(ofstream& out, t_struct* tstruct) {
Roger Meier3b771a12010-11-17 22:11:26 +00001681 (void) tstruct;
Bryan Duxbury66467a72010-08-21 17:48:18 +00001682 indent(out) << "public _Fields fieldForId(int fieldId) {" << endl;
1683 indent(out) << " return _Fields.findByThriftId(fieldId);" << endl;
1684 indent(out) << "}" << endl << endl;
1685}
1686
David Reiss31997ca2008-10-09 00:08:46 +00001687void t_java_generator::generate_reflection_getters(ostringstream& out, t_type* type, string field_name, string cap_name) {
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001688 indent(out) << "case " << constant_name(field_name) << ":" << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001689 indent_up();
1690
1691 if (type->is_base_type() && !type->is_string()) {
1692 t_base_type* base_type = (t_base_type*)type;
1693
Bryan Duxburyd94cb082011-01-26 18:29:33 +00001694 indent(out) << "return " << type_name(type, true, false) << ".valueOf(" << (base_type->is_bool() ? "is" : "get") << cap_name << "());" << endl << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001695 } else {
1696 indent(out) << "return get" << cap_name << "();" << endl << endl;
1697 }
1698
1699 indent_down();
1700}
1701
1702void t_java_generator::generate_reflection_setters(ostringstream& out, t_type* type, string field_name, string cap_name) {
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001703 indent(out) << "case " << constant_name(field_name) << ":" << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001704 indent_up();
Bryan Duxbury42336c12009-03-13 18:28:40 +00001705 indent(out) << "if (value == null) {" << endl;
1706 indent(out) << " unset" << get_cap_name(field_name) << "();" << endl;
1707 indent(out) << "} else {" << endl;
1708 indent(out) << " set" << cap_name << "((" << type_name(type, true, false) << ")value);" << endl;
1709 indent(out) << "}" << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001710 indent(out) << "break;" << endl << endl;
1711
1712 indent_down();
1713}
1714
1715void t_java_generator::generate_generic_field_getters_setters(std::ofstream& out, t_struct* tstruct) {
David Reiss31997ca2008-10-09 00:08:46 +00001716 std::ostringstream getter_stream;
1717 std::ostringstream setter_stream;
1718
1719 // build up the bodies of both the getter and setter at once
1720 const vector<t_field*>& fields = tstruct->get_members();
1721 vector<t_field*>::const_iterator f_iter;
1722 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1723 t_field* field = *f_iter;
1724 t_type* type = get_true_type(field->get_type());
1725 std::string field_name = field->get_name();
David Reiss2db737d2009-01-05 21:02:55 +00001726 std::string cap_name = get_cap_name(field_name);
David Reiss31997ca2008-10-09 00:08:46 +00001727
1728 indent_up();
1729 generate_reflection_setters(setter_stream, type, field_name, cap_name);
1730 generate_reflection_getters(getter_stream, type, field_name, cap_name);
1731 indent_down();
1732 }
1733
1734
1735 // create the setter
Bryan Duxbury66467a72010-08-21 17:48:18 +00001736
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001737 indent(out) << "public void setFieldValue(_Fields field, Object value) {" << endl;
1738 indent(out) << " switch (field) {" << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001739 out << setter_stream.str();
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001740 indent(out) << " }" << endl;
1741 indent(out) << "}" << endl << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001742
David Reiss31997ca2008-10-09 00:08:46 +00001743 // create the getter
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001744 indent(out) << "public Object getFieldValue(_Fields field) {" << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001745 indent_up();
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001746 indent(out) << "switch (field) {" << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001747 out << getter_stream.str();
David Reiss31997ca2008-10-09 00:08:46 +00001748 indent(out) << "}" << endl;
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001749 indent(out) << "throw new IllegalStateException();" << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001750 indent_down();
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001751 indent(out) << "}" << endl << endl;
David Reiss31997ca2008-10-09 00:08:46 +00001752}
1753
David Reiss25be92b2009-01-05 21:02:58 +00001754// Creates a generic isSet method that takes the field number as argument
1755void t_java_generator::generate_generic_isset_method(std::ofstream& out, t_struct* tstruct){
1756 const vector<t_field*>& fields = tstruct->get_members();
1757 vector<t_field*>::const_iterator f_iter;
David Reiss31997ca2008-10-09 00:08:46 +00001758
David Reiss25be92b2009-01-05 21:02:58 +00001759 // create the isSet method
Roger Meier26f817a2010-11-30 19:46:56 +00001760 indent(out) << "/** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */" << endl;
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001761 indent(out) << "public boolean isSet(_Fields field) {" << endl;
David Reiss25be92b2009-01-05 21:02:58 +00001762 indent_up();
Bryan Duxbury66467a72010-08-21 17:48:18 +00001763 indent(out) << "if (field == null) {" << endl;
1764 indent(out) << " throw new IllegalArgumentException();" << endl;
1765 indent(out) << "}" << endl << endl;
1766
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001767 indent(out) << "switch (field) {" << endl;
David Reiss25be92b2009-01-05 21:02:58 +00001768
1769 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1770 t_field* field = *f_iter;
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001771 indent(out) << "case " << constant_name(field->get_name()) << ":" << endl;
David Reiss25be92b2009-01-05 21:02:58 +00001772 indent_up();
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001773 indent(out) << "return " << generate_isset_check(field) << ";" << endl;
David Reiss25be92b2009-01-05 21:02:58 +00001774 indent_down();
1775 }
1776
David Reiss25be92b2009-01-05 21:02:58 +00001777 indent(out) << "}" << endl;
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00001778 indent(out) << "throw new IllegalStateException();" << endl;
David Reiss25be92b2009-01-05 21:02:58 +00001779 indent_down();
1780 indent(out) << "}" << endl << endl;
1781}
David Reiss31997ca2008-10-09 00:08:46 +00001782
Mark Slee81097572007-03-14 03:07:00 +00001783/**
Mark Slee01a9f882007-08-31 00:55:28 +00001784 * Generates a set of Java Bean boilerplate functions (setters, getters, etc.)
1785 * for the given struct.
1786 *
1787 * @param tstruct The struct definition
1788 */
1789void t_java_generator::generate_java_bean_boilerplate(ofstream& out,
1790 t_struct* tstruct) {
1791 const vector<t_field*>& fields = tstruct->get_members();
1792 vector<t_field*>::const_iterator f_iter;
1793 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1794 t_field* field = *f_iter;
1795 t_type* type = get_true_type(field->get_type());
1796 std::string field_name = field->get_name();
David Reiss2db737d2009-01-05 21:02:55 +00001797 std::string cap_name = get_cap_name(field_name);
Mark Slee01a9f882007-08-31 00:55:28 +00001798
Bryan Duxburyf18202f2009-10-01 22:52:25 +00001799 if (type->is_container()) {
1800 // Method to return the size of the collection
1801 indent(out) << "public int get" << cap_name;
1802 out << get_cap_name("size() {") << endl;
1803
1804 indent_up();
1805 indent(out) << "return (this." << field_name << " == null) ? 0 : " <<
1806 "this." << field_name << ".size();" << endl;
1807 indent_down();
1808 indent(out) << "}" << endl << endl;
1809 }
1810
1811 if (type->is_set() || type->is_list()) {
Bryan Duxburyf18202f2009-10-01 22:52:25 +00001812 t_type* element_type;
1813 if (type->is_set()) {
1814 element_type = ((t_set*)type)->get_elem_type();
1815 } else {
1816 element_type = ((t_list*)type)->get_elem_type();
1817 }
1818
1819 // Iterator getter for sets and lists
1820 indent(out) << "public java.util.Iterator<" <<
1821 type_name(element_type, true, false) << "> get" << cap_name;
1822 out << get_cap_name("iterator() {") << endl;
1823
1824 indent_up();
1825 indent(out) << "return (this." << field_name << " == null) ? null : " <<
1826 "this." << field_name << ".iterator();" << endl;
1827 indent_down();
1828 indent(out) << "}" << endl << endl;
1829
1830 // Add to set or list, create if the set/list is null
1831 indent(out);
1832 out << "public void add" << get_cap_name("to");
1833 out << cap_name << "(" << type_name(element_type) << " elem) {" << endl;
1834
1835 indent_up();
1836 indent(out) << "if (this." << field_name << " == null) {" << endl;
1837 indent_up();
1838 indent(out) << "this." << field_name << " = new " << type_name(type, false, true) <<
1839 "();" << endl;
1840 indent_down();
1841 indent(out) << "}" << endl;
1842 indent(out) << "this." << field_name << ".add(elem);" << endl;
1843 indent_down();
1844 indent(out) << "}" << endl << endl;
Bryan Duxburyf18202f2009-10-01 22:52:25 +00001845 } else if (type->is_map()) {
1846 // Put to map
1847 t_type* key_type = ((t_map*)type)->get_key_type();
1848 t_type* val_type = ((t_map*)type)->get_val_type();
1849
1850 indent(out);
1851 out << "public void put" << get_cap_name("to");
1852 out << cap_name << "(" << type_name(key_type) << " key, "
1853 << type_name(val_type) << " val) {" << endl;
1854
1855 indent_up();
1856 indent(out) << "if (this." << field_name << " == null) {" << endl;
1857 indent_up();
1858 indent(out) << "this." << field_name << " = new " <<
1859 type_name(type, false, true) << "();" << endl;
1860 indent_down();
1861 indent(out) << "}" << endl;
1862 indent(out) << "this." << field_name << ".put(key, val);" << endl;
1863 indent_down();
1864 indent(out) << "}" << endl << endl;
1865 }
1866
Mark Slee01a9f882007-08-31 00:55:28 +00001867 // Simple getter
David Reissf33e03c2008-10-29 00:07:49 +00001868 generate_java_doc(out, field);
Bryan Duxburya7420b62010-09-13 15:42:36 +00001869 if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
1870 indent(out) << "public byte[] get" << cap_name << "() {" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00001871 indent(out) << " set" << cap_name << "(org.apache.thrift.TBaseHelper.rightSize(" << field_name << "));" << endl;
Bryan Duxburya5eb8482010-11-24 22:30:38 +00001872 indent(out) << " return " << field_name << " == null ? null : " << field_name << ".array();" << endl;
Bryan Duxburya7420b62010-09-13 15:42:36 +00001873 indent(out) << "}" << endl << endl;
1874
Bryan Duxbury1606f252010-11-24 00:25:57 +00001875 indent(out) << "public ByteBuffer buffer" << get_cap_name("for") << cap_name << "() {" << endl;
Bryan Duxburya7420b62010-09-13 15:42:36 +00001876 indent(out) << " return " << field_name << ";" << endl;
1877 indent(out) << "}" << endl << endl;
Mark Slee01a9f882007-08-31 00:55:28 +00001878 } else {
Bryan Duxburya7420b62010-09-13 15:42:36 +00001879 indent(out) << "public " << type_name(type);
1880 if (type->is_base_type() &&
1881 ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) {
1882 out << " is";
1883 } else {
1884 out << " get";
1885 }
1886 out << cap_name << "() {" << endl;
1887 indent_up();
1888 indent(out) << "return this." << field_name << ";" << endl;
1889 indent_down();
1890 indent(out) << "}" << endl << endl;
Mark Slee01a9f882007-08-31 00:55:28 +00001891 }
Mark Slee01a9f882007-08-31 00:55:28 +00001892
1893 // Simple setter
David Reissf33e03c2008-10-29 00:07:49 +00001894 generate_java_doc(out, field);
Bryan Duxburya7420b62010-09-13 15:42:36 +00001895 if (type->is_base_type() && ((t_base_type*)type)->is_binary()) {
1896 indent(out) << "public ";
1897 if (bean_style_) {
1898 out << "void";
1899 } else {
1900 out << type_name(tstruct);
1901 }
1902 out << " set" << cap_name << "(byte[] " << field_name << ") {" << endl;
Bryan Duxburya5eb8482010-11-24 22:30:38 +00001903 indent(out) << " set" << cap_name << "(" << field_name << " == null ? (ByteBuffer)null : ByteBuffer.wrap(" << field_name << "));" << endl;
Bryan Duxburya7420b62010-09-13 15:42:36 +00001904 if (!bean_style_) {
1905 indent(out) << " return this;" << endl;
1906 }
1907 indent(out) << "}" << endl << endl;
1908 }
Bryan Duxburyea7910f2010-04-03 05:04:48 +00001909 indent(out) << "public ";
1910 if (bean_style_) {
1911 out << "void";
1912 } else {
1913 out << type_name(tstruct);
1914 }
1915 out << " set" << cap_name << "(" << type_name(type) << " " << field_name << ") {" << endl;
Mark Slee01a9f882007-08-31 00:55:28 +00001916 indent_up();
Bryan Duxbury1121b472011-08-11 18:50:58 +00001917 indent(out) << "this." << field_name << " = " << field_name << ";" << endl;
1918 generate_isset_set(out, field, "");
Bryan Duxburyea7910f2010-04-03 05:04:48 +00001919 if (!bean_style_) {
1920 indent(out) << "return this;" << endl;
1921 }
David Reiss5af01bc2008-10-01 03:24:50 +00001922
Mark Slee01a9f882007-08-31 00:55:28 +00001923 indent_down();
1924 indent(out) << "}" << endl << endl;
1925
1926 // Unsetter
1927 indent(out) << "public void unset" << cap_name << "() {" << endl;
1928 indent_up();
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001929 if (type_can_be_null(type)) {
Mark Slee01a9f882007-08-31 00:55:28 +00001930 indent(out) << "this." << field_name << " = null;" << endl;
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001931 } else {
Bryan Duxbury3efce232009-08-03 19:37:26 +00001932 indent(out) << "__isset_bit_vector.clear(" << isset_field_id(field) << ");" << endl;
Mark Slee01a9f882007-08-31 00:55:28 +00001933 }
Mark Slee01a9f882007-08-31 00:55:28 +00001934 indent_down();
1935 indent(out) << "}" << endl << endl;
David Reiss25be92b2009-01-05 21:02:58 +00001936
1937 // isSet method
Roger Meier26f817a2010-11-30 19:46:56 +00001938 indent(out) << "/** Returns true if field " << field_name << " is set (has been assigned a value) and false otherwise */" << endl;
David Reiss25be92b2009-01-05 21:02:58 +00001939 indent(out) << "public boolean is" << get_cap_name("set") << cap_name << "() {" << endl;
1940 indent_up();
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001941 if (type_can_be_null(type)) {
Bryan Duxburyc8ee3582010-05-04 14:01:14 +00001942 indent(out) << "return this." << field_name << " != null;" << endl;
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001943 } else {
Bryan Duxbury3efce232009-08-03 19:37:26 +00001944 indent(out) << "return __isset_bit_vector.get(" << isset_field_id(field) << ");" << endl;
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001945 }
David Reiss25be92b2009-01-05 21:02:58 +00001946 indent_down();
1947 indent(out) << "}" << endl << endl;
Bryan Duxbury3efce232009-08-03 19:37:26 +00001948
1949 indent(out) << "public void set" << cap_name << get_cap_name("isSet") << "(boolean value) {" << endl;
1950 indent_up();
1951 if (type_can_be_null(type)) {
1952 indent(out) << "if (!value) {" << endl;
1953 indent(out) << " this." << field_name << " = null;" << endl;
1954 indent(out) << "}" << endl;
1955 } else {
1956 indent(out) << "__isset_bit_vector.set(" << isset_field_id(field) << ", value);" << endl;
Bryan Duxburyd20a1d32009-02-07 01:08:58 +00001957 }
Bryan Duxbury3efce232009-08-03 19:37:26 +00001958 indent_down();
1959 indent(out) << "}" << endl << endl;
Mark Slee01a9f882007-08-31 00:55:28 +00001960 }
1961}
1962
1963/**
Mark Slee81097572007-03-14 03:07:00 +00001964 * Generates a toString() method for the given struct
1965 *
1966 * @param tstruct The struct definition
1967 */
1968void t_java_generator::generate_java_struct_tostring(ofstream& out,
1969 t_struct* tstruct) {
Bryan Duxbury369417a2009-01-27 22:09:33 +00001970 out << indent() << "@Override" << endl <<
Mark Slee81097572007-03-14 03:07:00 +00001971 indent() << "public String toString() {" << endl;
1972 indent_up();
1973
1974 out <<
eletuchy447d7d232007-06-13 04:24:11 +00001975 indent() << "StringBuilder sb = new StringBuilder(\"" << tstruct->get_name() << "(\");" << endl;
David Reiss86845542008-10-01 18:32:47 +00001976 out << indent() << "boolean first = true;" << endl << endl;
Mark Slee81097572007-03-14 03:07:00 +00001977
1978 const vector<t_field*>& fields = tstruct->get_members();
1979 vector<t_field*>::const_iterator f_iter;
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001980 bool first = true;
Mark Slee81097572007-03-14 03:07:00 +00001981 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001982 bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL;
1983 if(could_be_unset) {
1984 indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl;
David Reiss86845542008-10-01 18:32:47 +00001985 indent_up();
Mark Slee81097572007-03-14 03:07:00 +00001986 }
David Reiss86845542008-10-01 18:32:47 +00001987
David Reiss30a93602008-11-21 21:31:36 +00001988 t_field* field = (*f_iter);
1989
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001990 if (!first) {
1991 indent(out) << "if (!first) sb.append(\", \");" << endl;
1992 }
David Reiss86845542008-10-01 18:32:47 +00001993 indent(out) << "sb.append(\"" << (*f_iter)->get_name() << ":\");" << endl;
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001994 bool can_be_null = type_can_be_null(field->get_type());
1995 if (can_be_null) {
1996 indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl;
David Reiss30a93602008-11-21 21:31:36 +00001997 indent(out) << " sb.append(\"null\");" << endl;
1998 indent(out) << "} else {" << endl;
Bryan Duxburyd11f2412009-02-19 21:21:44 +00001999 indent_up();
2000 }
Bryan Duxbury1121b472011-08-11 18:50:58 +00002001
Bryan Duxburyd11f2412009-02-19 21:21:44 +00002002 if (field->get_type()->is_base_type() && ((t_base_type*)(field->get_type()))->is_binary()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002003 indent(out) << "org.apache.thrift.TBaseHelper.toString(this." << field->get_name() << ", sb);" << endl;
David Reiss30a93602008-11-21 21:31:36 +00002004 } else {
2005 indent(out) << "sb.append(this." << (*f_iter)->get_name() << ");" << endl;
2006 }
Bryan Duxbury1121b472011-08-11 18:50:58 +00002007
Bryan Duxburyd11f2412009-02-19 21:21:44 +00002008 if (can_be_null) {
David Reiss86845542008-10-01 18:32:47 +00002009 indent_down();
2010 indent(out) << "}" << endl;
2011 }
Bryan Duxburyd11f2412009-02-19 21:21:44 +00002012 indent(out) << "first = false;" << endl;
2013
2014 if(could_be_unset) {
2015 indent_down();
2016 indent(out) << "}" << endl;
2017 }
2018 first = false;
Mark Slee81097572007-03-14 03:07:00 +00002019 }
2020 out <<
2021 indent() << "sb.append(\")\");" << endl <<
2022 indent() << "return sb.toString();" << endl;
2023
2024 indent_down();
Bryan Duxbury1121b472011-08-11 18:50:58 +00002025 indent(out) << "}" << endl << endl;
Mark Slee81097572007-03-14 03:07:00 +00002026}
2027
David Reissb936ffd2009-01-05 21:02:52 +00002028/**
2029 * Generates a static map with meta data to store information such as fieldID to
2030 * fieldName mapping
2031 *
2032 * @param tstruct The struct definition
2033 */
2034void t_java_generator::generate_java_meta_data_map(ofstream& out,
2035 t_struct* tstruct) {
2036 const vector<t_field*>& fields = tstruct->get_members();
2037 vector<t_field*>::const_iterator f_iter;
2038
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002039 // Static Map with fieldID -> org.apache.thrift.meta_data.FieldMetaData mappings
2040 indent(out) << "public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;" << endl;
Bryan Duxbury15b7b282010-03-23 05:39:18 +00002041 indent(out) << "static {" << endl;
2042 indent_up();
2043
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002044 indent(out) << "Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);" << endl;
David Reissb936ffd2009-01-05 21:02:52 +00002045
2046 // Populate map
David Reissb936ffd2009-01-05 21:02:52 +00002047 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2048 t_field* field = *f_iter;
2049 std::string field_name = field->get_name();
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002050 indent(out) << "tmpMap.put(_Fields." << constant_name(field_name) << ", new org.apache.thrift.meta_data.FieldMetaData(\"" << field_name << "\", ";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002051
2052 // Set field requirement type (required, optional, etc.)
2053 if (field->get_req() == t_field::T_REQUIRED) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002054 out << "org.apache.thrift.TFieldRequirementType.REQUIRED, ";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002055 } else if (field->get_req() == t_field::T_OPTIONAL) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002056 out << "org.apache.thrift.TFieldRequirementType.OPTIONAL, ";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002057 } else {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002058 out << "org.apache.thrift.TFieldRequirementType.DEFAULT, ";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002059 }
2060
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00002061 // Create value meta data
Bryan Duxbury986d7052009-01-29 01:51:08 +00002062 generate_field_value_meta_data(out, field->get_type());
2063 out << "));" << endl;
David Reissb936ffd2009-01-05 21:02:52 +00002064 }
Bryan Duxburyab3666e2009-09-01 23:03:47 +00002065
Bryan Duxbury15b7b282010-03-23 05:39:18 +00002066 indent(out) << "metaDataMap = Collections.unmodifiableMap(tmpMap);" << endl;
2067
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002068 indent(out) << "org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(" << type_name(tstruct) << ".class, metaDataMap);" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00002069 indent_down();
2070 indent(out) << "}" << endl << endl;
David Reissb936ffd2009-01-05 21:02:52 +00002071}
2072
Bryan Duxbury986d7052009-01-29 01:51:08 +00002073/**
2074 * Returns a string with the java representation of the given thrift type
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002075 * (e.g. for the type struct it returns "org.apache.thrift.protocol.TType.STRUCT")
Bryan Duxbury986d7052009-01-29 01:51:08 +00002076 */
2077std::string t_java_generator::get_java_type_string(t_type* type) {
2078 if (type->is_list()){
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002079 return "org.apache.thrift.protocol.TType.LIST";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002080 } else if (type->is_map()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002081 return "org.apache.thrift.protocol.TType.MAP";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002082 } else if (type->is_set()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002083 return "org.apache.thrift.protocol.TType.SET";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002084 } else if (type->is_struct() || type->is_xception()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002085 return "org.apache.thrift.protocol.TType.STRUCT";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002086 } else if (type->is_enum()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002087 return "org.apache.thrift.protocol.TType.ENUM";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002088 } else if (type->is_typedef()) {
2089 return get_java_type_string(((t_typedef*)type)->get_type());
2090 } else if (type->is_base_type()) {
2091 switch (((t_base_type*)type)->get_base()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002092 case t_base_type::TYPE_VOID : return "org.apache.thrift.protocol.TType.VOID"; break;
2093 case t_base_type::TYPE_STRING : return "org.apache.thrift.protocol.TType.STRING"; break;
2094 case t_base_type::TYPE_BOOL : return "org.apache.thrift.protocol.TType.BOOL"; break;
2095 case t_base_type::TYPE_BYTE : return "org.apache.thrift.protocol.TType.BYTE"; break;
2096 case t_base_type::TYPE_I16 : return "org.apache.thrift.protocol.TType.I16"; break;
2097 case t_base_type::TYPE_I32 : return "org.apache.thrift.protocol.TType.I32"; break;
2098 case t_base_type::TYPE_I64 : return "org.apache.thrift.protocol.TType.I64"; break;
2099 case t_base_type::TYPE_DOUBLE : return "org.apache.thrift.protocol.TType.DOUBLE"; break;
Bryan Duxbury986d7052009-01-29 01:51:08 +00002100 default : throw std::runtime_error("Unknown thrift type \"" + type->get_name() + "\" passed to t_java_generator::get_java_type_string!"); break; // This should never happen!
2101 }
2102 } else {
2103 throw std::runtime_error("Unknown thrift type \"" + type->get_name() + "\" passed to t_java_generator::get_java_type_string!"); // This should never happen!
2104 }
2105}
2106
2107void t_java_generator::generate_field_value_meta_data(std::ofstream& out, t_type* type){
2108 out << endl;
2109 indent_up();
2110 indent_up();
2111 if (type->is_struct()){
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002112 indent(out) << "new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, " << type_name(type) << ".class";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002113 } else if (type->is_container()){
2114 if (type->is_list()){
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002115 indent(out) << "new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, ";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002116 t_type* elem_type = ((t_list*)type)->get_elem_type();
2117 generate_field_value_meta_data(out, elem_type);
2118 } else if (type->is_set()){
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002119 indent(out) << "new org.apache.thrift.meta_data.SetMetaData(org.apache.thrift.protocol.TType.SET, ";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002120 t_type* elem_type = ((t_list*)type)->get_elem_type();
2121 generate_field_value_meta_data(out, elem_type);
2122 } else{ // map
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002123 indent(out) << "new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP, ";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002124 t_type* key_type = ((t_map*)type)->get_key_type();
2125 t_type* val_type = ((t_map*)type)->get_val_type();
2126 generate_field_value_meta_data(out, key_type);
2127 out << ", ";
2128 generate_field_value_meta_data(out, val_type);
2129 }
Bryan Duxbury9af23d92009-11-19 17:26:38 +00002130 } else if (type->is_enum()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002131 indent(out) << "new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, " << type_name(type) << ".class";
Bryan Duxbury986d7052009-01-29 01:51:08 +00002132 } else {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002133 indent(out) << "new org.apache.thrift.meta_data.FieldValueMetaData(" << get_java_type_string(type);
Bryan Duxbury15e29302010-04-22 01:05:02 +00002134 if (type->is_typedef()) {
2135 indent(out) << ", \"" << ((t_typedef*)type)->get_symbolic() << "\"";
Bryan Duxburyb3d0aa02010-10-06 20:00:03 +00002136 } else if (((t_base_type*)type)->is_binary()) {
2137 indent(out) << ", true";
Bryan Duxbury15e29302010-04-22 01:05:02 +00002138 }
Bryan Duxbury986d7052009-01-29 01:51:08 +00002139 }
2140 out << ")";
2141 indent_down();
2142 indent_down();
2143}
2144
Mark Slee78f58e22006-09-02 04:17:07 +00002145
Mark Sleeb15a68b2006-06-07 06:46:24 +00002146/**
2147 * Generates a thrift service. In C++, this comprises an entirely separate
2148 * header and source file. The header file defines the methods and includes
2149 * the data types defined in the main header file, and the implementation
2150 * file contains implementations of the basic printer and default interfaces.
2151 *
2152 * @param tservice The service definition
2153 */
2154void t_java_generator::generate_service(t_service* tservice) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002155 // Make output file
Mark Slee98e962b2007-02-20 18:44:05 +00002156 string f_service_name = package_dir_+"/"+service_name_+".java";
Mark Slee78f58e22006-09-02 04:17:07 +00002157 f_service_.open(f_service_name.c_str());
Mark Sleeb15a68b2006-06-07 06:46:24 +00002158
2159 f_service_ <<
2160 autogen_comment() <<
2161 java_package() <<
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002162 java_type_imports();
Mark Sleeb15a68b2006-06-07 06:46:24 +00002163
Bryan Duxbury1121b472011-08-11 18:50:58 +00002164 f_service_ << "public class " << service_name_ << " {" << endl << endl;
Mark Sleedafa3cf2006-09-02 23:56:49 +00002165 indent_up();
Mark Slee78f58e22006-09-02 04:17:07 +00002166
2167 // Generate the three main parts of the service
2168 generate_service_interface(tservice);
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002169 generate_service_async_interface(tservice);
Mark Slee78f58e22006-09-02 04:17:07 +00002170 generate_service_client(tservice);
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002171 generate_service_async_client(tservice);
Mark Slee78f58e22006-09-02 04:17:07 +00002172 generate_service_server(tservice);
2173 generate_service_helpers(tservice);
2174
Mark Sleedafa3cf2006-09-02 23:56:49 +00002175 indent_down();
Mark Slee78f58e22006-09-02 04:17:07 +00002176 f_service_ <<
2177 "}" << endl;
2178 f_service_.close();
2179}
2180
2181/**
2182 * Generates a service interface definition.
2183 *
2184 * @param tservice The service to generate a header definition for
2185 */
2186void t_java_generator::generate_service_interface(t_service* tservice) {
Mark Sleef0712dc2006-10-25 19:03:57 +00002187 string extends = "";
2188 string extends_iface = "";
2189 if (tservice->get_extends() != NULL) {
2190 extends = type_name(tservice->get_extends());
2191 extends_iface = " extends " + extends + ".Iface";
2192 }
2193
Mark Slee8775c732007-09-10 22:33:05 +00002194 generate_java_doc(f_service_, tservice);
2195 f_service_ << indent() << "public interface Iface" << extends_iface <<
2196 " {" << endl << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002197 indent_up();
2198 vector<t_function*> functions = tservice->get_functions();
Mark Slee5ab57052007-11-27 08:38:16 +00002199 vector<t_function*>::iterator f_iter;
Mark Slee78f58e22006-09-02 04:17:07 +00002200 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
Mark Slee8775c732007-09-10 22:33:05 +00002201 generate_java_doc(f_service_, *f_iter);
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002202 indent(f_service_) << "public " << function_signature(*f_iter) << ";" << endl << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002203 }
2204 indent_down();
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002205 f_service_ << indent() << "}" << endl << endl;
2206}
2207
2208void t_java_generator::generate_service_async_interface(t_service* tservice) {
2209 string extends = "";
2210 string extends_iface = "";
2211 if (tservice->get_extends() != NULL) {
2212 extends = type_name(tservice->get_extends());
2213 extends_iface = " extends " + extends + " .AsyncIface";
2214 }
2215
2216 f_service_ << indent() << "public interface AsyncIface" << extends_iface << " {" << endl << endl;
2217 indent_up();
2218 vector<t_function*> functions = tservice->get_functions();
2219 vector<t_function*>::iterator f_iter;
2220 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002221 indent(f_service_) << "public " << function_signature_async(*f_iter, true) << " throws org.apache.thrift.TException;" << endl << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002222 }
2223 indent_down();
2224 f_service_ << indent() << "}" << endl << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002225}
2226
Mark Sleef5377b32006-10-10 01:42:59 +00002227/**
2228 * Generates structs for all the service args and return types
2229 *
2230 * @param tservice The service
2231 */
Mark Slee78f58e22006-09-02 04:17:07 +00002232void t_java_generator::generate_service_helpers(t_service* tservice) {
2233 vector<t_function*> functions = tservice->get_functions();
Mark Slee5ab57052007-11-27 08:38:16 +00002234 vector<t_function*>::iterator f_iter;
Mark Slee78f58e22006-09-02 04:17:07 +00002235 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2236 t_struct* ts = (*f_iter)->get_arglist();
2237 generate_java_struct_definition(f_service_, ts, false, true);
2238 generate_function_helpers(*f_iter);
2239 }
2240}
2241
2242/**
2243 * Generates a service client definition.
2244 *
2245 * @param tservice The service to generate a server for.
2246 */
2247void t_java_generator::generate_service_client(t_service* tservice) {
Mark Sleef0712dc2006-10-25 19:03:57 +00002248 string extends = "";
2249 string extends_client = "";
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002250 if (tservice->get_extends() == NULL) {
2251 extends_client = "org.apache.thrift.TServiceClient";
2252 } else {
Mark Sleef0712dc2006-10-25 19:03:57 +00002253 extends = type_name(tservice->get_extends());
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002254 extends_client = extends + ".Client";
Mark Sleef0712dc2006-10-25 19:03:57 +00002255 }
2256
2257 indent(f_service_) <<
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002258 "public static class Client extends " << extends_client << " implements Iface {" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002259 indent_up();
2260
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002261 indent(f_service_) << "public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {" << endl;
Bryan Duxburyb1f7f792010-04-03 23:19:52 +00002262 indent_up();
2263 indent(f_service_) << "public Factory() {}" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002264 indent(f_service_) << "public Client getClient(org.apache.thrift.protocol.TProtocol prot) {" << endl;
Bryan Duxburyb1f7f792010-04-03 23:19:52 +00002265 indent_up();
2266 indent(f_service_) << "return new Client(prot);" << endl;
2267 indent_down();
2268 indent(f_service_) << "}" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002269 indent(f_service_) << "public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {" << endl;
Bryan Duxburyb1f7f792010-04-03 23:19:52 +00002270 indent_up();
2271 indent(f_service_) << "return new Client(iprot, oprot);" << endl;
2272 indent_down();
2273 indent(f_service_) << "}" << endl;
2274 indent_down();
2275 indent(f_service_) << "}" << endl << endl;
2276
Bryan Duxbury1121b472011-08-11 18:50:58 +00002277 indent(f_service_) << "public Client(org.apache.thrift.protocol.TProtocol prot)" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002278 scope_up(f_service_);
Bryan Duxbury1121b472011-08-11 18:50:58 +00002279 indent(f_service_) << "super(prot, prot);" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002280 scope_down(f_service_);
2281 f_service_ << endl;
2282
2283 indent(f_service_) <<
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002284 "public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {" << endl;
2285 indent(f_service_) << " super(iprot, oprot);" << endl;
2286 indent(f_service_) << "}" << endl << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002287
2288 // Generate client method implementations
2289 vector<t_function*> functions = tservice->get_functions();
Mark Slee5ab57052007-11-27 08:38:16 +00002290 vector<t_function*>::const_iterator f_iter;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002291 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2292 string funname = (*f_iter)->get_name();
2293
2294 // Open function
Bryan Duxbury1121b472011-08-11 18:50:58 +00002295 indent(f_service_) << "public " << function_signature(*f_iter) << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002296 scope_up(f_service_);
Bryan Duxbury1121b472011-08-11 18:50:58 +00002297 indent(f_service_) << "send_" << funname << "(";
Mark Slee52f643d2006-08-09 00:03:43 +00002298
2299 // Get the struct of function call params
2300 t_struct* arg_struct = (*f_iter)->get_arglist();
Mark Slee5ab57052007-11-27 08:38:16 +00002301
Mark Slee52f643d2006-08-09 00:03:43 +00002302 // Declare the function arguments
2303 const vector<t_field*>& fields = arg_struct->get_members();
2304 vector<t_field*>::const_iterator fld_iter;
2305 bool first = true;
2306 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
2307 if (first) {
2308 first = false;
2309 } else {
2310 f_service_ << ", ";
2311 }
2312 f_service_ << (*fld_iter)->get_name();
2313 }
2314 f_service_ << ");" << endl;
2315
David Reiss47329252009-03-24 20:01:02 +00002316 if (!(*f_iter)->is_oneway()) {
Mark Slee52f643d2006-08-09 00:03:43 +00002317 f_service_ << indent();
2318 if (!(*f_iter)->get_returntype()->is_void()) {
2319 f_service_ << "return ";
2320 }
2321 f_service_ <<
2322 "recv_" << funname << "();" << endl;
2323 }
2324 scope_down(f_service_);
2325 f_service_ << endl;
Mark Slee5ab57052007-11-27 08:38:16 +00002326
Mark Sleef0712dc2006-10-25 19:03:57 +00002327 t_function send_function(g_type_void,
Mark Slee52f643d2006-08-09 00:03:43 +00002328 string("send_") + (*f_iter)->get_name(),
2329 (*f_iter)->get_arglist());
2330
Mark Slee78f58e22006-09-02 04:17:07 +00002331 string argsname = (*f_iter)->get_name() + "_args";
2332
Mark Slee52f643d2006-08-09 00:03:43 +00002333 // Open function
2334 indent(f_service_) <<
Mark Slee78f58e22006-09-02 04:17:07 +00002335 "public " << function_signature(&send_function) << endl;
Mark Slee52f643d2006-08-09 00:03:43 +00002336 scope_up(f_service_);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002337
2338 // Serialize the request
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002339 indent(f_service_) << argsname << " args = new " << argsname << "();" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002340
2341 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002342 indent(f_service_) << "args.set" << get_cap_name((*fld_iter)->get_name()) << "(" << (*fld_iter)->get_name() << ");" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002343 }
2344
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002345 indent(f_service_) << "sendBase(\"" << funname << "\", args);" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002346
Mark Sleeb15a68b2006-06-07 06:46:24 +00002347 scope_down(f_service_);
2348 f_service_ << endl;
Mark Slee52f643d2006-08-09 00:03:43 +00002349
David Reiss47329252009-03-24 20:01:02 +00002350 if (!(*f_iter)->is_oneway()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002351 string resultname = (*f_iter)->get_name() + "_result";
2352
Mark Sleef0712dc2006-10-25 19:03:57 +00002353 t_struct noargs(program_);
Mark Slee52f643d2006-08-09 00:03:43 +00002354 t_function recv_function((*f_iter)->get_returntype(),
2355 string("recv_") + (*f_iter)->get_name(),
Mark Slee78f58e22006-09-02 04:17:07 +00002356 &noargs,
2357 (*f_iter)->get_xceptions());
Mark Slee52f643d2006-08-09 00:03:43 +00002358 // Open function
2359 indent(f_service_) <<
Mark Slee78f58e22006-09-02 04:17:07 +00002360 "public " << function_signature(&recv_function) << endl;
Mark Slee52f643d2006-08-09 00:03:43 +00002361 scope_up(f_service_);
Mark Slee5ab57052007-11-27 08:38:16 +00002362
Mark Slee78f58e22006-09-02 04:17:07 +00002363 f_service_ <<
Mark Slee575fa9a2006-10-25 20:54:10 +00002364 indent() << resultname << " result = new " << resultname << "();" << endl <<
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002365 indent() << "receiveBase(result, \"" << funname << "\");" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002366
Mark Slee52f643d2006-08-09 00:03:43 +00002367 // Careful, only return _result if not a void function
2368 if (!(*f_iter)->get_returntype()->is_void()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002369 f_service_ <<
Bryan Duxburye3c3d192009-03-07 03:08:37 +00002370 indent() << "if (result." << generate_isset_check("success") << ") {" << endl <<
Mark Slee575fa9a2006-10-25 20:54:10 +00002371 indent() << " return result.success;" << endl <<
Mark Slee78f58e22006-09-02 04:17:07 +00002372 indent() << "}" << endl;
2373 }
2374
2375 t_struct* xs = (*f_iter)->get_xceptions();
2376 const std::vector<t_field*>& xceptions = xs->get_members();
2377 vector<t_field*>::const_iterator x_iter;
2378 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
2379 f_service_ <<
Bryan Duxburyd11f2412009-02-19 21:21:44 +00002380 indent() << "if (result." << (*x_iter)->get_name() << " != null) {" << endl <<
Mark Slee575fa9a2006-10-25 20:54:10 +00002381 indent() << " throw result." << (*x_iter)->get_name() << ";" << endl <<
Mark Slee78f58e22006-09-02 04:17:07 +00002382 indent() << "}" << endl;
2383 }
2384
Mark Sleef5377b32006-10-10 01:42:59 +00002385 // If you get here it's an exception, unless a void function
Mark Slee78f58e22006-09-02 04:17:07 +00002386 if ((*f_iter)->get_returntype()->is_void()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002387 indent(f_service_) << "return;" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002388 } else {
2389 f_service_ <<
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002390 indent() << "throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
Mark Slee52f643d2006-08-09 00:03:43 +00002391 }
Mark Slee5ab57052007-11-27 08:38:16 +00002392
Mark Slee52f643d2006-08-09 00:03:43 +00002393 // Close function
2394 scope_down(f_service_);
2395 f_service_ << endl;
2396 }
Mark Sleeb15a68b2006-06-07 06:46:24 +00002397 }
2398
2399 indent_down();
Bryan Duxbury1121b472011-08-11 18:50:58 +00002400 indent(f_service_) << "}" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002401}
2402
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002403void t_java_generator::generate_service_async_client(t_service* tservice) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002404 string extends = "org.apache.thrift.async.TAsyncClient";
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002405 string extends_client = "";
2406 if (tservice->get_extends() != NULL) {
2407 extends = type_name(tservice->get_extends()) + ".AsyncClient";
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002408 }
2409
2410 indent(f_service_) <<
2411 "public static class AsyncClient extends " << extends << " implements AsyncIface {" << endl;
2412 indent_up();
2413
2414 // Factory method
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002415 indent(f_service_) << "public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {" << endl;
2416 indent(f_service_) << " private org.apache.thrift.async.TAsyncClientManager clientManager;" << endl;
2417 indent(f_service_) << " private org.apache.thrift.protocol.TProtocolFactory protocolFactory;" << endl;
2418 indent(f_service_) << " public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002419 indent(f_service_) << " this.clientManager = clientManager;" << endl;
2420 indent(f_service_) << " this.protocolFactory = protocolFactory;" << endl;
2421 indent(f_service_) << " }" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002422 indent(f_service_) << " public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002423 indent(f_service_) << " return new AsyncClient(protocolFactory, clientManager, transport);" << endl;
2424 indent(f_service_) << " }" << endl;
2425 indent(f_service_) << "}" << endl << endl;
2426
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002427 indent(f_service_) << "public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002428 indent(f_service_) << " super(protocolFactory, clientManager, transport);" << endl;
2429 indent(f_service_) << "}" << endl << endl;
2430
2431 // Generate client method implementations
2432 vector<t_function*> functions = tservice->get_functions();
2433 vector<t_function*>::const_iterator f_iter;
2434 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2435 string funname = (*f_iter)->get_name();
2436 t_type* ret_type = (*f_iter)->get_returntype();
2437 t_struct* arg_struct = (*f_iter)->get_arglist();
2438 string funclassname = funname + "_call";
2439 const vector<t_field*>& fields = arg_struct->get_members();
2440 const std::vector<t_field*>& xceptions = (*f_iter)->get_xceptions()->get_members();
2441 vector<t_field*>::const_iterator fld_iter;
2442 string args_name = (*f_iter)->get_name() + "_args";
2443 string result_name = (*f_iter)->get_name() + "_result";
2444
2445 // Main method body
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002446 indent(f_service_) << "public " << function_signature_async(*f_iter, false) << " throws org.apache.thrift.TException {" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002447 indent(f_service_) << " checkReady();" << endl;
Bryan Duxburyee7c7bb2011-03-15 17:25:23 +00002448 indent(f_service_) << " " << funclassname << " method_call = new " + funclassname + "(" << async_argument_list(*f_iter, arg_struct, ret_type) << ", this, ___protocolFactory, ___transport);" << endl;
2449 indent(f_service_) << " this.___currentMethod = method_call;" << endl;
2450 indent(f_service_) << " ___manager.call(method_call);" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002451 indent(f_service_) << "}" << endl;
2452
2453 f_service_ << endl;
2454
2455 // TAsyncMethod object for this function call
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002456 indent(f_service_) << "public static class " + funclassname + " extends org.apache.thrift.async.TAsyncMethodCall {" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002457 indent_up();
2458
2459 // Member variables
2460 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
2461 indent(f_service_) << "private " + type_name((*fld_iter)->get_type()) + " " + (*fld_iter)->get_name() + ";" << endl;
2462 }
2463
2464 // NOTE since we use a new Client instance to deserialize, let's keep seqid to 0 for now
2465 // indent(f_service_) << "private int seqid;" << endl << endl;
2466
2467 // Constructor
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002468 indent(f_service_) << "public " + funclassname + "(" + async_argument_list(*f_iter, arg_struct, ret_type, true) << ", org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002469 indent(f_service_) << " super(client, protocolFactory, transport, resultHandler, " << ((*f_iter)->is_oneway() ? "true" : "false") << ");" << endl;
2470
2471 // Assign member variables
2472 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
2473 indent(f_service_) << " this." + (*fld_iter)->get_name() + " = " + (*fld_iter)->get_name() + ";" << endl;
2474 }
2475
2476 indent(f_service_) << "}" << endl << endl;
2477
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002478 indent(f_service_) << "public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002479 indent_up();
2480
2481 // Serialize request
2482 // NOTE we are leaving seqid as 0, for now (see above)
2483 f_service_ <<
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002484 indent() << "prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage(\"" << funname << "\", org.apache.thrift.protocol.TMessageType.CALL, 0));" << endl <<
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002485 indent() << args_name << " args = new " << args_name << "();" << endl;
2486
2487 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
2488 f_service_ << indent() << "args.set" << get_cap_name((*fld_iter)->get_name()) << "(" << (*fld_iter)->get_name() << ");" << endl;
2489 }
2490
2491 f_service_ <<
2492 indent() << "args.write(prot);" << endl <<
2493 indent() << "prot.writeMessageEnd();" << endl;
2494
2495 indent_down();
2496 indent(f_service_) << "}" << endl << endl;
2497
2498 // Return method
2499 indent(f_service_) << "public " + type_name(ret_type) + " getResult() throws ";
2500 vector<t_field*>::const_iterator x_iter;
2501 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
2502 f_service_ << type_name((*x_iter)->get_type(), false, false) + ", ";
2503 }
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002504 f_service_ << "org.apache.thrift.TException {" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002505
2506 indent_up();
2507 f_service_ <<
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002508 indent() << "if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {" << endl <<
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002509 indent() << " throw new IllegalStateException(\"Method call not finished!\");" << endl <<
2510 indent() << "}" << endl <<
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00002511 indent() << "org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());" << endl <<
2512 indent() << "org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);" << endl;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00002513 if (!(*f_iter)->is_oneway()) {
2514 indent(f_service_);
2515 if (!ret_type->is_void()) {
2516 f_service_ << "return ";
2517 }
2518 f_service_ << "(new Client(prot)).recv_" + funname + "();" << endl;
2519 }
2520
2521 // Close function
2522 indent_down();
2523 indent(f_service_) << "}" << endl;
2524
2525 // Close class
2526 indent_down();
2527 indent(f_service_) << "}" << endl << endl;
2528 }
2529
2530 // Close AsyncClient
2531 scope_down(f_service_);
2532 f_service_ << endl;
2533}
2534
Mark Sleeb15a68b2006-06-07 06:46:24 +00002535/**
2536 * Generates a service server definition.
2537 *
2538 * @param tservice The service to generate a server for.
2539 */
2540void t_java_generator::generate_service_server(t_service* tservice) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002541 // Generate the dispatch methods
2542 vector<t_function*> functions = tservice->get_functions();
Mark Slee5ab57052007-11-27 08:38:16 +00002543 vector<t_function*>::iterator f_iter;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002544
Mark Sleef0712dc2006-10-25 19:03:57 +00002545 // Extends stuff
2546 string extends = "";
2547 string extends_processor = "";
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002548 if (tservice->get_extends() == NULL) {
Bryan Duxbury02357f22011-11-14 23:12:20 +00002549 extends_processor = "org.apache.thrift.TBaseProcessor<I>";
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002550 } else {
Mark Sleef0712dc2006-10-25 19:03:57 +00002551 extends = type_name(tservice->get_extends());
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002552 extends_processor = extends + ".Processor";
Mark Sleef0712dc2006-10-25 19:03:57 +00002553 }
2554
Mark Sleeb15a68b2006-06-07 06:46:24 +00002555 // Generate the header portion
Mark Sleef0712dc2006-10-25 19:03:57 +00002556 indent(f_service_) <<
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002557 "public static class Processor<I extends Iface> extends " << extends_processor << " implements org.apache.thrift.TProcessor {" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002558 indent_up();
2559
Bryan Duxburyc27cda52009-08-14 20:04:15 +00002560 indent(f_service_) << "private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());" << endl;
Bryan Duxburyef73b0e2009-06-17 16:43:25 +00002561
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002562 indent(f_service_) << "public Processor(I iface) {" << endl;
2563 indent(f_service_) << " super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));" << endl;
2564 indent(f_service_) << "}" << endl << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00002565
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002566 indent(f_service_) << "protected Processor(I iface, Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {" << endl;
2567 indent(f_service_) << " super(iface, getProcessMap(processMap));" << endl;
2568 indent(f_service_) << "}" << endl << endl;
2569
2570 indent(f_service_) << "private static <I extends Iface> Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> getProcessMap(Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {" << endl;
2571 indent_up();
Mark Sleef0712dc2006-10-25 19:03:57 +00002572 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002573 indent(f_service_) << "processMap.put(\"" << (*f_iter)->get_name() << "\", new " << (*f_iter)->get_name() << "());" << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00002574 }
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002575 indent(f_service_) << "return processMap;" << endl;
2576 indent_down();
2577 indent(f_service_) << "}" << endl << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002578
2579 // Generate the process subfunctions
2580 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2581 generate_process_function(tservice, *f_iter);
2582 }
2583
2584 indent_down();
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002585 indent(f_service_) << "}" << endl << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002586}
Mark Sleeb15a68b2006-06-07 06:46:24 +00002587
Mark Slee78f58e22006-09-02 04:17:07 +00002588/**
2589 * Generates a struct and helpers for a function.
2590 *
2591 * @param tfunction The function
2592 */
2593void t_java_generator::generate_function_helpers(t_function* tfunction) {
David Reiss47329252009-03-24 20:01:02 +00002594 if (tfunction->is_oneway()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002595 return;
2596 }
2597
Mark Sleef0712dc2006-10-25 19:03:57 +00002598 t_struct result(program_, tfunction->get_name() + "_result");
Mark Slee78f58e22006-09-02 04:17:07 +00002599 t_field success(tfunction->get_returntype(), "success", 0);
2600 if (!tfunction->get_returntype()->is_void()) {
2601 result.append(&success);
2602 }
2603
2604 t_struct* xs = tfunction->get_xceptions();
2605 const vector<t_field*>& fields = xs->get_members();
2606 vector<t_field*>::const_iterator f_iter;
2607 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2608 result.append(*f_iter);
2609 }
2610
2611 generate_java_struct_definition(f_service_, &result, false, true, true);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002612}
2613
2614/**
2615 * Generates a process function definition.
2616 *
2617 * @param tfunction The function to write a dispatcher for
2618 */
2619void t_java_generator::generate_process_function(t_service* tservice,
2620 t_function* tfunction) {
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002621 string argsname = tfunction->get_name() + "_args";
2622 string resultname = tfunction->get_name() + "_result";
2623 if (tfunction->is_oneway()) {
2624 resultname = "org.apache.thrift.TBase";
2625 }
2626
Roger Meier3b771a12010-11-17 22:11:26 +00002627 (void) tservice;
Mark Sleef0712dc2006-10-25 19:03:57 +00002628 // Open class
2629 indent(f_service_) <<
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002630 "private static class " << tfunction->get_name() << "<I extends Iface> extends org.apache.thrift.ProcessFunction<I, " << argsname << "> {" << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00002631 indent_up();
2632
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002633 indent(f_service_) << "public " << tfunction->get_name() << "() {" << endl;
2634 indent(f_service_) << " super(\"" << tfunction->get_name() << "\");" << endl;
2635 indent(f_service_) << "}" << endl << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002636
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002637 indent(f_service_) << "protected " << argsname << " getEmptyArgsInstance() {" << endl;
2638 indent(f_service_) << " return new " << argsname << "();" << endl;
2639 indent(f_service_) << "}" << endl << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002640
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002641 indent(f_service_) << "protected " << resultname << " getResult(I iface, " << argsname << " args) throws org.apache.thrift.TException {" << endl;
Bryan Duxbury53cba3c2010-02-26 21:38:42 +00002642 indent_up();
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002643 if (!tfunction->is_oneway()) {
2644 indent(f_service_) << resultname << " result = new " << resultname << "();" << endl;
2645 }
Mark Slee78f58e22006-09-02 04:17:07 +00002646
2647 t_struct* xs = tfunction->get_xceptions();
2648 const std::vector<t_field*>& xceptions = xs->get_members();
2649 vector<t_field*>::const_iterator x_iter;
2650
Mark Slee78f58e22006-09-02 04:17:07 +00002651 // Try block for a function with exceptions
2652 if (xceptions.size() > 0) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002653 f_service_ << indent() << "try {" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002654 indent_up();
2655 }
Mark Slee5ab57052007-11-27 08:38:16 +00002656
Mark Slee78f58e22006-09-02 04:17:07 +00002657 // Generate the function call
2658 t_struct* arg_struct = tfunction->get_arglist();
2659 const std::vector<t_field*>& fields = arg_struct->get_members();
2660 vector<t_field*>::const_iterator f_iter;
Mark Slee78f58e22006-09-02 04:17:07 +00002661 f_service_ << indent();
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002662
David Reiss47329252009-03-24 20:01:02 +00002663 if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
Mark Slee575fa9a2006-10-25 20:54:10 +00002664 f_service_ << "result.success = ";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002665 }
Bryan Duxbury1121b472011-08-11 18:50:58 +00002666 f_service_ << "iface." << tfunction->get_name() << "(";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002667 bool first = true;
2668 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2669 if (first) {
2670 first = false;
2671 } else {
2672 f_service_ << ", ";
2673 }
Mark Slee575fa9a2006-10-25 20:54:10 +00002674 f_service_ << "args." << (*f_iter)->get_name();
Mark Sleeb15a68b2006-06-07 06:46:24 +00002675 }
2676 f_service_ << ");" << endl;
2677
Mark Slee78f58e22006-09-02 04:17:07 +00002678 // Set isset on success field
David Reiss47329252009-03-24 20:01:02 +00002679 if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void() && !type_can_be_null(tfunction->get_returntype())) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002680 indent(f_service_) << "result.set" << get_cap_name("success") << get_cap_name("isSet") << "(true);" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002681 }
Mark Slee78f58e22006-09-02 04:17:07 +00002682
David Reiss47329252009-03-24 20:01:02 +00002683 if (!tfunction->is_oneway() && xceptions.size() > 0) {
Mark Slee78f58e22006-09-02 04:17:07 +00002684 indent_down();
2685 f_service_ << indent() << "}";
2686 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
Mark Sleea0f8bdc2007-08-29 04:36:28 +00002687 f_service_ << " catch (" << type_name((*x_iter)->get_type(), false, false) << " " << (*x_iter)->get_name() << ") {" << endl;
David Reiss47329252009-03-24 20:01:02 +00002688 if (!tfunction->is_oneway()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002689 indent_up();
2690 f_service_ <<
Bryan Duxburyd11f2412009-02-19 21:21:44 +00002691 indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002692 indent_down();
2693 f_service_ << indent() << "}";
2694 } else {
2695 f_service_ << "}";
2696 }
2697 }
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002698 f_service_ << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002699 }
2700
David Reiss47329252009-03-24 20:01:02 +00002701 if (tfunction->is_oneway()) {
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002702 indent(f_service_) << "return null;" << endl;
2703 } else {
2704 indent(f_service_) << "return result;" << endl;
Mark Slee78f58e22006-09-02 04:17:07 +00002705 }
Bryan Duxbury0fd37f02011-02-08 17:26:37 +00002706 indent_down();
2707 indent(f_service_) << "}";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002708
2709 // Close function
Mark Sleeb15a68b2006-06-07 06:46:24 +00002710 f_service_ << endl;
Mark Sleef0712dc2006-10-25 19:03:57 +00002711
2712 // Close class
2713 indent_down();
Bryan Duxbury1121b472011-08-11 18:50:58 +00002714 f_service_ << indent() << "}" << endl << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002715}
2716
2717/**
2718 * Deserializes a field of any type.
Mark Sleef5377b32006-10-10 01:42:59 +00002719 *
2720 * @param tfield The field
2721 * @param prefix The variable name or container for this field
Mark Sleeb15a68b2006-06-07 06:46:24 +00002722 */
Mark Slee78f58e22006-09-02 04:17:07 +00002723void t_java_generator::generate_deserialize_field(ofstream& out,
2724 t_field* tfield,
Bryan Duxbury1121b472011-08-11 18:50:58 +00002725 string prefix, bool has_metadata) {
David Reisse087a302007-08-23 21:43:25 +00002726 t_type* type = get_true_type(tfield->get_type());
Mark Sleeb15a68b2006-06-07 06:46:24 +00002727
2728 if (type->is_void()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002729 throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
Mark Sleeb15a68b2006-06-07 06:46:24 +00002730 }
2731
2732 string name = prefix + tfield->get_name();
2733
Mark Slee78f58e22006-09-02 04:17:07 +00002734 if (type->is_struct() || type->is_xception()) {
2735 generate_deserialize_struct(out,
Mark Slee216e7d62006-11-21 00:44:23 +00002736 (t_struct*)type,
Mark Slee78f58e22006-09-02 04:17:07 +00002737 name);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002738 } else if (type->is_container()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002739 generate_deserialize_container(out, type, name, has_metadata);
Bryan Duxbury9af23d92009-11-19 17:26:38 +00002740 } else if (type->is_base_type()) {
2741 indent(out) << name << " = iprot.";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002742
Bryan Duxbury1121b472011-08-11 18:50:58 +00002743
Bryan Duxbury9af23d92009-11-19 17:26:38 +00002744 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2745 switch (tbase) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002746 case t_base_type::TYPE_VOID:
Bryan Duxbury1121b472011-08-11 18:50:58 +00002747 throw "compiler error: cannot serialize void field in a struct: " + name;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002748 break;
Mark Slee5ab57052007-11-27 08:38:16 +00002749 case t_base_type::TYPE_STRING:
Mark Slee8d725a22007-04-13 01:57:12 +00002750 if (((t_base_type*)type)->is_binary()) {
2751 out << "readBinary();";
2752 } else {
2753 out << "readString();";
2754 }
Mark Slee78f58e22006-09-02 04:17:07 +00002755 break;
2756 case t_base_type::TYPE_BOOL:
Mark Slee575fa9a2006-10-25 20:54:10 +00002757 out << "readBool();";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002758 break;
2759 case t_base_type::TYPE_BYTE:
Mark Slee575fa9a2006-10-25 20:54:10 +00002760 out << "readByte();";
Mark Slee78f58e22006-09-02 04:17:07 +00002761 break;
2762 case t_base_type::TYPE_I16:
Mark Slee575fa9a2006-10-25 20:54:10 +00002763 out << "readI16();";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002764 break;
2765 case t_base_type::TYPE_I32:
Mark Slee575fa9a2006-10-25 20:54:10 +00002766 out << "readI32();";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002767 break;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002768 case t_base_type::TYPE_I64:
Mark Slee575fa9a2006-10-25 20:54:10 +00002769 out << "readI64();";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002770 break;
Mark Sleec98d0502006-09-06 02:42:25 +00002771 case t_base_type::TYPE_DOUBLE:
Mark Slee575fa9a2006-10-25 20:54:10 +00002772 out << "readDouble();";
Mark Sleec98d0502006-09-06 02:42:25 +00002773 break;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002774 default:
David Reissdd7796f2007-08-28 21:09:06 +00002775 throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002776 }
Bryan Duxbury9af23d92009-11-19 17:26:38 +00002777 out << endl;
2778 } else if (type->is_enum()) {
2779 indent(out) << name << " = " << type_name(tfield->get_type(), true, false) + ".findByValue(iprot.readI32());" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002780 } else {
2781 printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
2782 tfield->get_name().c_str(), type_name(type).c_str());
2783 }
2784}
2785
2786/**
Mark Sleef5377b32006-10-10 01:42:59 +00002787 * Generates an unserializer for a struct, invokes read()
Mark Sleeb15a68b2006-06-07 06:46:24 +00002788 */
Mark Slee78f58e22006-09-02 04:17:07 +00002789void t_java_generator::generate_deserialize_struct(ofstream& out,
2790 t_struct* tstruct,
2791 string prefix) {
2792 out <<
Mark Sleef0712dc2006-10-25 19:03:57 +00002793 indent() << prefix << " = new " << type_name(tstruct) << "();" << endl <<
Mark Slee575fa9a2006-10-25 20:54:10 +00002794 indent() << prefix << ".read(iprot);" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002795}
2796
Mark Sleef5377b32006-10-10 01:42:59 +00002797/**
2798 * Deserializes a container by reading its size and then iterating
2799 */
Mark Slee78f58e22006-09-02 04:17:07 +00002800void t_java_generator::generate_deserialize_container(ofstream& out,
2801 t_type* ttype,
Bryan Duxbury1121b472011-08-11 18:50:58 +00002802 string prefix, bool has_metadata) {
2803
Mark Slee78f58e22006-09-02 04:17:07 +00002804 scope_up(out);
Mark Slee5ab57052007-11-27 08:38:16 +00002805
Mark Sleeb15a68b2006-06-07 06:46:24 +00002806 string obj;
2807
2808 if (ttype->is_map()) {
2809 obj = tmp("_map");
2810 } else if (ttype->is_set()) {
2811 obj = tmp("_set");
2812 } else if (ttype->is_list()) {
2813 obj = tmp("_list");
2814 }
2815
Bryan Duxbury1121b472011-08-11 18:50:58 +00002816 if (has_metadata) {
2817 // Declare variables, read header
2818 if (ttype->is_map()) {
2819 indent(out) << "org.apache.thrift.protocol.TMap " << obj << " = iprot.readMapBegin();" << endl;
2820 } else if (ttype->is_set()) {
2821 indent(out) << "org.apache.thrift.protocol.TSet " << obj << " = iprot.readSetBegin();" << endl;
2822 } else if (ttype->is_list()) {
2823 indent(out) << "org.apache.thrift.protocol.TList " << obj << " = iprot.readListBegin();" << endl;
2824 }
2825 } else {
2826 // Declare variables, read header
2827 if (ttype->is_map()) {
2828 indent(out) << "org.apache.thrift.protocol.TMap " << obj << " = new org.apache.thrift.protocol.TMap(" <<
2829 type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << "iprot.readI32());" << endl;
2830 } else if (ttype->is_set()) {
2831 indent(out) << "org.apache.thrift.protocol.TSet " << obj << " = new org.apache.thrift.protocol.TSet(" <<
2832 type_to_enum(((t_set*)ttype)->get_elem_type()) << ", iprot.readI32());" << endl;
2833 } else if (ttype->is_list()) {
2834 indent(out) << "org.apache.thrift.protocol.TList " << obj << " = new org.apache.thrift.protocol.TList(" <<
2835 type_to_enum(((t_set*)ttype)->get_elem_type()) << ", iprot.readI32());" << endl;
2836 }
Mark Sleeb15a68b2006-06-07 06:46:24 +00002837 }
2838
Bryan Duxbury1121b472011-08-11 18:50:58 +00002839 indent(out) << prefix << " = new " << type_name(ttype, false, true);
2840 // size the collection correctly
2841 out << "("
eletuchy447d7d232007-06-13 04:24:11 +00002842 << (ttype->is_list() ? "" : "2*" )
2843 << obj << ".size"
2844 << ");" << endl;
2845
Mark Sleeb15a68b2006-06-07 06:46:24 +00002846 // For loop iterates over elements
2847 string i = tmp("_i");
Mark Slee78f58e22006-09-02 04:17:07 +00002848 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00002849 "for (int " << i << " = 0; " <<
Mark Slee52f643d2006-08-09 00:03:43 +00002850 i << " < " << obj << ".size" << "; " <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00002851 "++" << i << ")" << endl;
Mark Slee5ab57052007-11-27 08:38:16 +00002852
Bryan Duxbury1121b472011-08-11 18:50:58 +00002853 scope_up(out);
Mark Slee5ab57052007-11-27 08:38:16 +00002854
Mark Sleeb15a68b2006-06-07 06:46:24 +00002855 if (ttype->is_map()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002856 generate_deserialize_map_element(out, (t_map*)ttype, prefix, has_metadata);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002857 } else if (ttype->is_set()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002858 generate_deserialize_set_element(out, (t_set*)ttype, prefix, has_metadata);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002859 } else if (ttype->is_list()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002860 generate_deserialize_list_element(out, (t_list*)ttype, prefix, has_metadata);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002861 }
2862
Mark Slee78f58e22006-09-02 04:17:07 +00002863 scope_down(out);
Bryan Duxbury1121b472011-08-11 18:50:58 +00002864
2865 if (has_metadata) {
2866 // Read container end
2867 if (ttype->is_map()) {
2868 indent(out) << "iprot.readMapEnd();" << endl;
2869 } else if (ttype->is_set()) {
2870 indent(out) << "iprot.readSetEnd();" << endl;
2871 } else if (ttype->is_list()) {
2872 indent(out) << "iprot.readListEnd();" << endl;
2873 }
2874 }
2875 scope_down(out);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002876}
2877
2878
2879/**
2880 * Generates code to deserialize a map
2881 */
Mark Slee78f58e22006-09-02 04:17:07 +00002882void t_java_generator::generate_deserialize_map_element(ofstream& out,
2883 t_map* tmap,
Bryan Duxbury1121b472011-08-11 18:50:58 +00002884 string prefix, bool has_metadata) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002885 string key = tmp("_key");
2886 string val = tmp("_val");
2887 t_field fkey(tmap->get_key_type(), key);
2888 t_field fval(tmap->get_val_type(), val);
2889
Bryan Duxbury1121b472011-08-11 18:50:58 +00002890 indent(out) << declare_field(&fkey) << endl;
2891 indent(out) << declare_field(&fval) << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002892
Bryan Duxbury1121b472011-08-11 18:50:58 +00002893 generate_deserialize_field(out, &fkey, "", has_metadata);
2894 generate_deserialize_field(out, &fval, "", has_metadata);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002895
Bryan Duxbury1121b472011-08-11 18:50:58 +00002896 indent(out) << prefix << ".put(" << key << ", " << val << ");" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002897}
2898
Mark Sleef5377b32006-10-10 01:42:59 +00002899/**
2900 * Deserializes a set element
2901 */
Mark Slee78f58e22006-09-02 04:17:07 +00002902void t_java_generator::generate_deserialize_set_element(ofstream& out,
2903 t_set* tset,
Bryan Duxbury1121b472011-08-11 18:50:58 +00002904 string prefix, bool has_metadata) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002905 string elem = tmp("_elem");
2906 t_field felem(tset->get_elem_type(), elem);
2907
Bryan Duxbury1121b472011-08-11 18:50:58 +00002908 indent(out) << declare_field(&felem) << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002909
Bryan Duxbury1121b472011-08-11 18:50:58 +00002910 generate_deserialize_field(out, &felem, "", has_metadata);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002911
Bryan Duxbury1121b472011-08-11 18:50:58 +00002912 indent(out) << prefix << ".add(" << elem << ");" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002913}
2914
Mark Sleef5377b32006-10-10 01:42:59 +00002915/**
2916 * Deserializes a list element
2917 */
Mark Slee78f58e22006-09-02 04:17:07 +00002918void t_java_generator::generate_deserialize_list_element(ofstream& out,
2919 t_list* tlist,
Bryan Duxbury1121b472011-08-11 18:50:58 +00002920 string prefix, bool has_metadata) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002921 string elem = tmp("_elem");
2922 t_field felem(tlist->get_elem_type(), elem);
2923
Bryan Duxbury1121b472011-08-11 18:50:58 +00002924 indent(out) << declare_field(&felem) << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002925
Bryan Duxbury1121b472011-08-11 18:50:58 +00002926 generate_deserialize_field(out, &felem, "", has_metadata);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002927
Bryan Duxbury1121b472011-08-11 18:50:58 +00002928 indent(out) << prefix << ".add(" << elem << ");" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002929}
2930
Mark Sleeb15a68b2006-06-07 06:46:24 +00002931/**
2932 * Serializes a field of any type.
2933 *
2934 * @param tfield The field to serialize
2935 * @param prefix Name to prepend to field name
2936 */
Mark Slee78f58e22006-09-02 04:17:07 +00002937void t_java_generator::generate_serialize_field(ofstream& out,
2938 t_field* tfield,
Bryan Duxbury1121b472011-08-11 18:50:58 +00002939 string prefix, bool has_metadata) {
David Reisse087a302007-08-23 21:43:25 +00002940 t_type* type = get_true_type(tfield->get_type());
Mark Sleeb15a68b2006-06-07 06:46:24 +00002941
2942 // Do nothing for void types
2943 if (type->is_void()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002944 throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
Mark Sleeb15a68b2006-06-07 06:46:24 +00002945 }
Mark Slee5ab57052007-11-27 08:38:16 +00002946
Mark Slee78f58e22006-09-02 04:17:07 +00002947 if (type->is_struct() || type->is_xception()) {
2948 generate_serialize_struct(out,
Mark Slee216e7d62006-11-21 00:44:23 +00002949 (t_struct*)type,
Mark Slee78f58e22006-09-02 04:17:07 +00002950 prefix + tfield->get_name());
Mark Sleeb15a68b2006-06-07 06:46:24 +00002951 } else if (type->is_container()) {
Mark Slee78f58e22006-09-02 04:17:07 +00002952 generate_serialize_container(out,
Mark Slee216e7d62006-11-21 00:44:23 +00002953 type,
Bryan Duxbury1121b472011-08-11 18:50:58 +00002954 prefix + tfield->get_name(), has_metadata);
Bryan Duxbury9af23d92009-11-19 17:26:38 +00002955 } else if (type->is_enum()){
2956 indent(out) << "oprot.writeI32(" << prefix + tfield->get_name() << ".getValue());" << endl;
2957 } else if (type->is_base_type()) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00002958 string name = prefix + tfield->get_name();
Bryan Duxbury1121b472011-08-11 18:50:58 +00002959 indent(out) << "oprot.";
Mark Slee5ab57052007-11-27 08:38:16 +00002960
Mark Sleeb15a68b2006-06-07 06:46:24 +00002961 if (type->is_base_type()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002962 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
Mark Sleeb15a68b2006-06-07 06:46:24 +00002963 switch (tbase) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002964 case t_base_type::TYPE_VOID:
2965 throw "compiler error: cannot serialize void field in a struct: " + name;
2966 break;
2967 case t_base_type::TYPE_STRING:
2968 if (((t_base_type*)type)->is_binary()) {
2969 out << "writeBinary(" << name << ");";
2970 } else {
2971 out << "writeString(" << name << ");";
2972 }
2973 break;
2974 case t_base_type::TYPE_BOOL:
2975 out << "writeBool(" << name << ");";
2976 break;
2977 case t_base_type::TYPE_BYTE:
2978 out << "writeByte(" << name << ");";
2979 break;
2980 case t_base_type::TYPE_I16:
2981 out << "writeI16(" << name << ");";
2982 break;
2983 case t_base_type::TYPE_I32:
2984 out << "writeI32(" << name << ");";
2985 break;
2986 case t_base_type::TYPE_I64:
2987 out << "writeI64(" << name << ");";
2988 break;
2989 case t_base_type::TYPE_DOUBLE:
2990 out << "writeDouble(" << name << ");";
2991 break;
2992 default:
2993 throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
Mark Sleeb15a68b2006-06-07 06:46:24 +00002994 }
2995 } else if (type->is_enum()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00002996 out << "writeI32(struct." << name << ");";
Mark Sleeb15a68b2006-06-07 06:46:24 +00002997 }
Mark Slee78f58e22006-09-02 04:17:07 +00002998 out << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00002999 } else {
3000 printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
3001 prefix.c_str(),
3002 tfield->get_name().c_str(),
3003 type_name(type).c_str());
3004 }
3005}
3006
3007/**
3008 * Serializes all the members of a struct.
3009 *
3010 * @param tstruct The struct to serialize
3011 * @param prefix String prefix to attach to all fields
3012 */
Mark Slee78f58e22006-09-02 04:17:07 +00003013void t_java_generator::generate_serialize_struct(ofstream& out,
3014 t_struct* tstruct,
Mark Sleeb15a68b2006-06-07 06:46:24 +00003015 string prefix) {
Roger Meier3b771a12010-11-17 22:11:26 +00003016 (void) tstruct;
Bryan Duxbury1121b472011-08-11 18:50:58 +00003017 out << indent() << prefix << ".write(oprot);" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00003018}
3019
Mark Sleef5377b32006-10-10 01:42:59 +00003020/**
3021 * Serializes a container by writing its size then the elements.
3022 *
3023 * @param ttype The type of container
3024 * @param prefix String prefix for fields
3025 */
Mark Slee78f58e22006-09-02 04:17:07 +00003026void t_java_generator::generate_serialize_container(ofstream& out,
3027 t_type* ttype,
Bryan Duxbury1121b472011-08-11 18:50:58 +00003028 string prefix, bool has_metadata) {
Mark Slee78f58e22006-09-02 04:17:07 +00003029 scope_up(out);
Mark Slee5ab57052007-11-27 08:38:16 +00003030
Bryan Duxbury1121b472011-08-11 18:50:58 +00003031 if (has_metadata) {
3032 if (ttype->is_map()) {
3033 indent(out) <<
3034 "oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(" <<
3035 type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
3036 type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
3037 prefix << ".size()));" << endl;
3038 } else if (ttype->is_set()) {
3039 indent(out) <<
3040 "oprot.writeSetBegin(new org.apache.thrift.protocol.TSet(" <<
3041 type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
3042 prefix << ".size()));" << endl;
3043 } else if (ttype->is_list()) {
3044 indent(out) <<
3045 "oprot.writeListBegin(new org.apache.thrift.protocol.TList(" <<
3046 type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
3047 prefix << ".size()));" << endl;
3048 }
3049 } else {
3050 indent(out) << "oprot.writeI32(" << prefix << ".size());" << endl;
Mark Sleeb15a68b2006-06-07 06:46:24 +00003051 }
3052
3053 string iter = tmp("_iter");
3054 if (ttype->is_map()) {
Mark Slee78f58e22006-09-02 04:17:07 +00003055 indent(out) <<
Bryan Duxbury9f427ee2009-01-29 05:47:21 +00003056 "for (Map.Entry<" <<
3057 type_name(((t_map*)ttype)->get_key_type(), true, false) << ", " <<
3058 type_name(((t_map*)ttype)->get_val_type(), true, false) << "> " << iter <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00003059 " : " <<
Bryan Duxbury9f427ee2009-01-29 05:47:21 +00003060 prefix << ".entrySet())";
Mark Sleeb15a68b2006-06-07 06:46:24 +00003061 } else if (ttype->is_set()) {
Mark Slee78f58e22006-09-02 04:17:07 +00003062 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00003063 "for (" <<
3064 type_name(((t_set*)ttype)->get_elem_type()) << " " << iter <<
3065 " : " <<
3066 prefix << ")";
3067 } else if (ttype->is_list()) {
Mark Slee78f58e22006-09-02 04:17:07 +00003068 indent(out) <<
Mark Sleeb15a68b2006-06-07 06:46:24 +00003069 "for (" <<
3070 type_name(((t_list*)ttype)->get_elem_type()) << " " << iter <<
3071 " : " <<
3072 prefix << ")";
3073 }
3074
David Reissdb5d5892009-09-01 21:36:46 +00003075 out << endl;
3076 scope_up(out);
3077 if (ttype->is_map()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00003078 generate_serialize_map_element(out, (t_map*)ttype, iter, prefix, has_metadata);
David Reissdb5d5892009-09-01 21:36:46 +00003079 } else if (ttype->is_set()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00003080 generate_serialize_set_element(out, (t_set*)ttype, iter, has_metadata);
David Reissdb5d5892009-09-01 21:36:46 +00003081 } else if (ttype->is_list()) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00003082 generate_serialize_list_element(out, (t_list*)ttype, iter, has_metadata);
David Reissdb5d5892009-09-01 21:36:46 +00003083 }
3084 scope_down(out);
Mark Slee5ab57052007-11-27 08:38:16 +00003085
Bryan Duxbury1121b472011-08-11 18:50:58 +00003086 if (has_metadata) {
3087 if (ttype->is_map()) {
3088 indent(out) << "oprot.writeMapEnd();" << endl;
3089 } else if (ttype->is_set()) {
3090 indent(out) << "oprot.writeSetEnd();" << endl;
3091 } else if (ttype->is_list()) {
3092 indent(out) << "oprot.writeListEnd();" << endl;
3093 }
Mark Slee5ab57052007-11-27 08:38:16 +00003094 }
3095
3096 scope_down(out);
Mark Sleeb15a68b2006-06-07 06:46:24 +00003097}
3098
3099/**
3100 * Serializes the members of a map.
Mark Slee5ab57052007-11-27 08:38:16 +00003101 */
Mark Slee78f58e22006-09-02 04:17:07 +00003102void t_java_generator::generate_serialize_map_element(ofstream& out,
3103 t_map* tmap,
Mark Sleeb15a68b2006-06-07 06:46:24 +00003104 string iter,
Bryan Duxbury1121b472011-08-11 18:50:58 +00003105 string map, bool has_metadata) {
Roger Meier3b771a12010-11-17 22:11:26 +00003106 (void) map;
Bryan Duxbury9f427ee2009-01-29 05:47:21 +00003107 t_field kfield(tmap->get_key_type(), iter + ".getKey()");
Bryan Duxbury1121b472011-08-11 18:50:58 +00003108 generate_serialize_field(out, &kfield, "", has_metadata);
Bryan Duxbury9f427ee2009-01-29 05:47:21 +00003109 t_field vfield(tmap->get_val_type(), iter + ".getValue()");
Bryan Duxbury1121b472011-08-11 18:50:58 +00003110 generate_serialize_field(out, &vfield, "", has_metadata);
Mark Sleeb15a68b2006-06-07 06:46:24 +00003111}
3112
3113/**
3114 * Serializes the members of a set.
3115 */
Mark Slee78f58e22006-09-02 04:17:07 +00003116void t_java_generator::generate_serialize_set_element(ofstream& out,
3117 t_set* tset,
Bryan Duxbury1121b472011-08-11 18:50:58 +00003118 string iter,
3119 bool has_metadata) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00003120 t_field efield(tset->get_elem_type(), iter);
Bryan Duxbury1121b472011-08-11 18:50:58 +00003121 generate_serialize_field(out, &efield, "", has_metadata);
Mark Sleeb15a68b2006-06-07 06:46:24 +00003122}
3123
3124/**
3125 * Serializes the members of a list.
3126 */
Mark Slee78f58e22006-09-02 04:17:07 +00003127void t_java_generator::generate_serialize_list_element(ofstream& out,
3128 t_list* tlist,
Bryan Duxbury1121b472011-08-11 18:50:58 +00003129 string iter,
3130 bool has_metadata) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00003131 t_field efield(tlist->get_elem_type(), iter);
Bryan Duxbury1121b472011-08-11 18:50:58 +00003132 generate_serialize_field(out, &efield, "", has_metadata);
Mark Sleeb15a68b2006-06-07 06:46:24 +00003133}
3134
3135/**
3136 * Returns a Java type name
3137 *
3138 * @param ttype The type
Mark Slee52f643d2006-08-09 00:03:43 +00003139 * @param container Is the type going inside a container?
Mark Sleef5377b32006-10-10 01:42:59 +00003140 * @return Java type name, i.e. HashMap<Key,Value>
Mark Sleeb15a68b2006-06-07 06:46:24 +00003141 */
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003142string t_java_generator::type_name(t_type* ttype, bool in_container, bool in_init, bool skip_generic) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00003143 // In Java typedefs are just resolved to their real type
David Reisse087a302007-08-23 21:43:25 +00003144 ttype = get_true_type(ttype);
Mark Slee22360b22008-02-09 00:18:32 +00003145 string prefix;
Mark Sleeb15a68b2006-06-07 06:46:24 +00003146
3147 if (ttype->is_base_type()) {
Mark Slee8d725a22007-04-13 01:57:12 +00003148 return base_type_name((t_base_type*)ttype, in_container);
Mark Sleeb15a68b2006-06-07 06:46:24 +00003149 } else if (ttype->is_map()) {
3150 t_map* tmap = (t_map*) ttype;
Mark Slee725f9e62006-10-31 05:08:33 +00003151 if (in_init) {
3152 prefix = "HashMap";
3153 } else {
Mark Slee22360b22008-02-09 00:18:32 +00003154 prefix = "Map";
Mark Slee725f9e62006-10-31 05:08:33 +00003155 }
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003156 return prefix + (skip_generic ? "" : "<" +
Bryan Duxbury1121b472011-08-11 18:50:58 +00003157 type_name(tmap->get_key_type(), true) + "," +
3158 type_name(tmap->get_val_type(), true) + ">");
Mark Sleeb15a68b2006-06-07 06:46:24 +00003159 } else if (ttype->is_set()) {
3160 t_set* tset = (t_set*) ttype;
Mark Slee22360b22008-02-09 00:18:32 +00003161 if (in_init) {
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003162 prefix = "HashSet";
Mark Slee22360b22008-02-09 00:18:32 +00003163 } else {
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003164 prefix = "Set";
Mark Slee22360b22008-02-09 00:18:32 +00003165 }
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003166 return prefix + (skip_generic ? "" : "<" + type_name(tset->get_elem_type(), true) + ">");
Mark Sleeb15a68b2006-06-07 06:46:24 +00003167 } else if (ttype->is_list()) {
3168 t_list* tlist = (t_list*) ttype;
Mark Slee22360b22008-02-09 00:18:32 +00003169 if (in_init) {
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003170 prefix = "ArrayList";
Mark Slee22360b22008-02-09 00:18:32 +00003171 } else {
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003172 prefix = "List";
Mark Slee22360b22008-02-09 00:18:32 +00003173 }
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003174 return prefix + (skip_generic ? "" : "<" + type_name(tlist->get_elem_type(), true) + ">");
Mark Sleeb15a68b2006-06-07 06:46:24 +00003175 }
Mark Sleef0712dc2006-10-25 19:03:57 +00003176
3177 // Check for namespacing
3178 t_program* program = ttype->get_program();
3179 if (program != NULL && program != program_) {
David Reiss771f8c72008-02-27 01:55:25 +00003180 string package = program->get_namespace("java");
Mark Sleef0712dc2006-10-25 19:03:57 +00003181 if (!package.empty()) {
3182 return package + "." + ttype->get_name();
3183 }
3184 }
3185
3186 return ttype->get_name();
Mark Sleeb15a68b2006-06-07 06:46:24 +00003187}
3188
3189/**
Roger Meiere0cac982010-12-16 13:15:49 +00003190 * Returns the Java type that corresponds to the thrift type.
Mark Sleeb15a68b2006-06-07 06:46:24 +00003191 *
3192 * @param tbase The base type
Mark Slee52f643d2006-08-09 00:03:43 +00003193 * @param container Is it going in a Java container?
Mark Sleeb15a68b2006-06-07 06:46:24 +00003194 */
Mark Slee8d725a22007-04-13 01:57:12 +00003195string t_java_generator::base_type_name(t_base_type* type,
Mark Slee52f643d2006-08-09 00:03:43 +00003196 bool in_container) {
Mark Slee8d725a22007-04-13 01:57:12 +00003197 t_base_type::t_base tbase = type->get_base();
3198
Mark Sleeb15a68b2006-06-07 06:46:24 +00003199 switch (tbase) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00003200 case t_base_type::TYPE_VOID:
3201 return "void";
3202 case t_base_type::TYPE_STRING:
3203 if (type->is_binary()) {
3204 return "ByteBuffer";
3205 } else {
3206 return "String";
3207 }
3208 case t_base_type::TYPE_BOOL:
3209 return (in_container ? "Boolean" : "boolean");
3210 case t_base_type::TYPE_BYTE:
3211 return (in_container ? "Byte" : "byte");
3212 case t_base_type::TYPE_I16:
3213 return (in_container ? "Short" : "short");
3214 case t_base_type::TYPE_I32:
3215 return (in_container ? "Integer" : "int");
3216 case t_base_type::TYPE_I64:
3217 return (in_container ? "Long" : "long");
3218 case t_base_type::TYPE_DOUBLE:
3219 return (in_container ? "Double" : "double");
3220 default:
3221 throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase);
Mark Sleeb15a68b2006-06-07 06:46:24 +00003222 }
3223}
3224
3225/**
3226 * Declares a field, which may include initialization as necessary.
3227 *
Roger Meiere0cac982010-12-16 13:15:49 +00003228 * @param tfield The field
3229 * @param init Whether to initialize the field
Mark Sleeb15a68b2006-06-07 06:46:24 +00003230 */
3231string t_java_generator::declare_field(t_field* tfield, bool init) {
3232 // TODO(mcslee): do we ever need to initialize the field?
3233 string result = type_name(tfield->get_type()) + " " + tfield->get_name();
3234 if (init) {
David Reisse087a302007-08-23 21:43:25 +00003235 t_type* ttype = get_true_type(tfield->get_type());
Mark Slee7ff32452007-02-01 05:26:18 +00003236 if (ttype->is_base_type() && tfield->get_value() != NULL) {
3237 ofstream dummy;
Roger Meiere0cac982010-12-16 13:15:49 +00003238 result += " = " + render_const_value(dummy, ttype, tfield->get_value());
Mark Slee7ff32452007-02-01 05:26:18 +00003239 } else if (ttype->is_base_type()) {
Mark Slee52f643d2006-08-09 00:03:43 +00003240 t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
3241 switch (tbase) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00003242 case t_base_type::TYPE_VOID:
3243 throw "NO T_VOID CONSTRUCT";
3244 case t_base_type::TYPE_STRING:
3245 result += " = null";
3246 break;
3247 case t_base_type::TYPE_BOOL:
3248 result += " = false";
3249 break;
3250 case t_base_type::TYPE_BYTE:
3251 case t_base_type::TYPE_I16:
3252 case t_base_type::TYPE_I32:
3253 case t_base_type::TYPE_I64:
3254 result += " = 0";
3255 break;
3256 case t_base_type::TYPE_DOUBLE:
3257 result += " = (double)0";
3258 break;
3259 }
Mark Sleeb7f58ff2006-09-02 21:59:28 +00003260 } else if (ttype->is_enum()) {
Mark Slee52f643d2006-08-09 00:03:43 +00003261 result += " = 0";
Mark Sleeb7f58ff2006-09-02 21:59:28 +00003262 } else if (ttype->is_container()) {
Mark Slee725f9e62006-10-31 05:08:33 +00003263 result += " = new " + type_name(ttype, false, true) + "()";
Mark Slee52f643d2006-08-09 00:03:43 +00003264 } else {
Mark Slee7ff32452007-02-01 05:26:18 +00003265 result += " = new " + type_name(ttype, false, true) + "()";;
Mark Slee52f643d2006-08-09 00:03:43 +00003266 }
Mark Sleeb15a68b2006-06-07 06:46:24 +00003267 }
Bryan Duxburyb342ddf2011-08-02 23:10:32 +00003268 result += "; // ";
Jake Farrell605c7602011-11-06 15:02:30 +00003269 if (tfield->get_req() == t_field::T_OPTIONAL) {
Bryan Duxburyb342ddf2011-08-02 23:10:32 +00003270 result += "optional";
3271 } else {
3272 result += "required";
3273 }
3274 return result;
Mark Sleeb15a68b2006-06-07 06:46:24 +00003275}
3276
3277/**
3278 * Renders a function signature of the form 'type name(args)'
3279 *
3280 * @param tfunction Function definition
3281 * @return String of rendered function definition
3282 */
3283string t_java_generator::function_signature(t_function* tfunction,
Mark Slee78f58e22006-09-02 04:17:07 +00003284 string prefix) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00003285 t_type* ttype = tfunction->get_returntype();
Mark Slee78f58e22006-09-02 04:17:07 +00003286 std::string result =
Mark Sleef5377b32006-10-10 01:42:59 +00003287 type_name(ttype) + " " + prefix + tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ") throws ";
Mark Slee78f58e22006-09-02 04:17:07 +00003288 t_struct* xs = tfunction->get_xceptions();
3289 const std::vector<t_field*>& xceptions = xs->get_members();
3290 vector<t_field*>::const_iterator x_iter;
3291 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
Mark Sleea0f8bdc2007-08-29 04:36:28 +00003292 result += type_name((*x_iter)->get_type(), false, false) + ", ";
Mark Slee78f58e22006-09-02 04:17:07 +00003293 }
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003294 result += "org.apache.thrift.TException";
Mark Slee78f58e22006-09-02 04:17:07 +00003295 return result;
Mark Sleeb15a68b2006-06-07 06:46:24 +00003296}
3297
3298/**
Bryan Duxbury1121b472011-08-11 18:50:58 +00003299 * Renders a function signature of the form 'void name(args, resultHandler)'
3300 *
3301 * @params tfunction Function definition
3302 * @return String of rendered function definition
3303 */
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00003304string t_java_generator::function_signature_async(t_function* tfunction, bool use_base_method, string prefix) {
3305 std::string arglist = async_function_call_arglist(tfunction, use_base_method, true);
3306
3307 std::string ret_type = "";
3308 if (use_base_method) {
3309 ret_type += "AsyncClient.";
3310 }
3311 ret_type += tfunction->get_name() + "_call";
3312
3313 std::string result = prefix + "void " + tfunction->get_name() + "(" + arglist + ")";
3314 return result;
3315}
3316
3317string t_java_generator::async_function_call_arglist(t_function* tfunc, bool use_base_method, bool include_types) {
3318 std::string arglist = "";
3319 if (tfunc->get_arglist()->get_members().size() > 0) {
3320 arglist = argument_list(tfunc->get_arglist(), include_types) + ", ";
3321 }
3322
3323 std::string ret_type = "";
3324 if (use_base_method) {
3325 ret_type += "AsyncClient.";
3326 }
3327 ret_type += tfunc->get_name() + "_call";
3328
3329 if (include_types) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003330 arglist += "org.apache.thrift.async.AsyncMethodCallback<" + ret_type + "> ";
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00003331 }
3332 arglist += "resultHandler";
3333
3334 return arglist;
3335}
3336
3337/**
Mark Sleef5377b32006-10-10 01:42:59 +00003338 * Renders a comma separated field list, with type names
Mark Sleeb15a68b2006-06-07 06:46:24 +00003339 */
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00003340string t_java_generator::argument_list(t_struct* tstruct, bool include_types) {
Mark Sleeb15a68b2006-06-07 06:46:24 +00003341 string result = "";
3342
3343 const vector<t_field*>& fields = tstruct->get_members();
3344 vector<t_field*>::const_iterator f_iter;
3345 bool first = true;
3346 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3347 if (first) {
3348 first = false;
3349 } else {
3350 result += ", ";
3351 }
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00003352 if (include_types) {
3353 result += type_name((*f_iter)->get_type()) + " ";
3354 }
3355 result += (*f_iter)->get_name();
Mark Sleeb15a68b2006-06-07 06:46:24 +00003356 }
3357 return result;
3358}
3359
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00003360string t_java_generator::async_argument_list(t_function* tfunct, t_struct* tstruct, t_type* ttype, bool include_types) {
Roger Meier3b771a12010-11-17 22:11:26 +00003361 (void) ttype;
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00003362 string result = "";
3363 const vector<t_field*>& fields = tstruct->get_members();
3364 vector<t_field*>::const_iterator f_iter;
3365 bool first = true;
3366 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3367 if (first) {
3368 first = false;
3369 } else {
3370 result += ", ";
3371 }
3372 if (include_types) {
3373 result += type_name((*f_iter)->get_type()) + " ";
3374 }
3375 result += (*f_iter)->get_name();
3376 }
3377 if (!first) {
3378 result += ", ";
3379 }
3380 if (include_types) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003381 result += "org.apache.thrift.async.AsyncMethodCallback<" + tfunct->get_name() + "_call" + "> ";
Bryan Duxburyd58ccec2010-05-26 16:34:48 +00003382 }
3383 result += "resultHandler";
3384 return result;
3385}
3386
Mark Sleeb15a68b2006-06-07 06:46:24 +00003387/**
Roger Meiere0cac982010-12-16 13:15:49 +00003388 * Converts the parse type to a Java enum string for the given type.
Mark Sleeb15a68b2006-06-07 06:46:24 +00003389 */
3390string t_java_generator::type_to_enum(t_type* type) {
David Reisse087a302007-08-23 21:43:25 +00003391 type = get_true_type(type);
Mark Slee5ab57052007-11-27 08:38:16 +00003392
Mark Sleeb15a68b2006-06-07 06:46:24 +00003393 if (type->is_base_type()) {
3394 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3395 switch (tbase) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00003396 case t_base_type::TYPE_VOID:
3397 throw "NO T_VOID CONSTRUCT";
3398 case t_base_type::TYPE_STRING:
3399 return "org.apache.thrift.protocol.TType.STRING";
3400 case t_base_type::TYPE_BOOL:
3401 return "org.apache.thrift.protocol.TType.BOOL";
3402 case t_base_type::TYPE_BYTE:
3403 return "org.apache.thrift.protocol.TType.BYTE";
3404 case t_base_type::TYPE_I16:
3405 return "org.apache.thrift.protocol.TType.I16";
3406 case t_base_type::TYPE_I32:
3407 return "org.apache.thrift.protocol.TType.I32";
3408 case t_base_type::TYPE_I64:
3409 return "org.apache.thrift.protocol.TType.I64";
3410 case t_base_type::TYPE_DOUBLE:
3411 return "org.apache.thrift.protocol.TType.DOUBLE";
Mark Sleeb15a68b2006-06-07 06:46:24 +00003412 }
3413 } else if (type->is_enum()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003414 return "org.apache.thrift.protocol.TType.I32";
Mark Slee78f58e22006-09-02 04:17:07 +00003415 } else if (type->is_struct() || type->is_xception()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003416 return "org.apache.thrift.protocol.TType.STRUCT";
Mark Sleeb15a68b2006-06-07 06:46:24 +00003417 } else if (type->is_map()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003418 return "org.apache.thrift.protocol.TType.MAP";
Mark Sleeb15a68b2006-06-07 06:46:24 +00003419 } else if (type->is_set()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003420 return "org.apache.thrift.protocol.TType.SET";
Mark Sleeb15a68b2006-06-07 06:46:24 +00003421 } else if (type->is_list()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003422 return "org.apache.thrift.protocol.TType.LIST";
Mark Sleeb15a68b2006-06-07 06:46:24 +00003423 }
3424
3425 throw "INVALID TYPE IN type_to_enum: " + type->get_name();
3426}
Mark Slee8775c732007-09-10 22:33:05 +00003427
3428/**
David Reiss2db737d2009-01-05 21:02:55 +00003429 * Applies the correct style to a string based on the value of nocamel_style_
3430 */
3431std::string t_java_generator::get_cap_name(std::string name){
3432 if (nocamel_style_) {
3433 return "_" + name;
3434 } else {
3435 name[0] = toupper(name[0]);
3436 return name;
3437 }
3438}
3439
Bryan Duxburybb7826d2009-02-08 00:12:38 +00003440string t_java_generator::constant_name(string name) {
3441 string constant_name;
3442
3443 bool is_first = true;
3444 bool was_previous_char_upper = false;
3445 for (string::iterator iter = name.begin(); iter != name.end(); ++iter) {
3446 string::value_type character = (*iter);
3447
3448 bool is_upper = isupper(character);
3449
3450 if (is_upper && !is_first && !was_previous_char_upper) {
3451 constant_name += '_';
3452 }
3453 constant_name += toupper(character);
3454
3455 is_first = false;
3456 was_previous_char_upper = is_upper;
3457 }
3458
3459 return constant_name;
3460}
3461
Bryan Duxbury3d5db202009-07-29 23:44:44 +00003462void t_java_generator::generate_java_docstring_comment(ofstream &out, string contents) {
3463 generate_docstring_comment(out,
Bryan Duxbury1121b472011-08-11 18:50:58 +00003464 "/**\n",
3465 " * ", contents,
3466 " */\n");
Bryan Duxbury3d5db202009-07-29 23:44:44 +00003467}
3468
3469void t_java_generator::generate_java_doc(ofstream &out,
3470 t_field* field) {
3471 if (field->get_type()->is_enum()) {
3472 string combined_message = field->get_doc() + "\n@see " + get_enum_class_name(field->get_type());
3473 generate_java_docstring_comment(out, combined_message);
3474 } else {
3475 generate_java_doc(out, (t_doc*)field);
3476 }
3477}
3478
David Reiss2db737d2009-01-05 21:02:55 +00003479/**
Mark Slee8775c732007-09-10 22:33:05 +00003480 * Emits a JavaDoc comment if the provided object has a doc in Thrift
3481 */
3482void t_java_generator::generate_java_doc(ofstream &out,
3483 t_doc* tdoc) {
3484 if (tdoc->has_doc()) {
Bryan Duxbury3d5db202009-07-29 23:44:44 +00003485 generate_java_docstring_comment(out, tdoc->get_doc());
Mark Slee8775c732007-09-10 22:33:05 +00003486 }
3487}
David Reisse1404d22008-02-27 01:55:05 +00003488
David Reiss7bcf8662009-01-06 20:54:27 +00003489/**
3490 * Emits a JavaDoc comment if the provided function object has a doc in Thrift
3491 */
3492void t_java_generator::generate_java_doc(ofstream &out,
3493 t_function* tfunction) {
3494 if (tfunction->has_doc()) {
3495 stringstream ss;
3496 ss << tfunction->get_doc();
3497 const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
3498 vector<t_field*>::const_iterator p_iter;
3499 for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
3500 t_field* p = *p_iter;
3501 ss << "\n@param " << p->get_name();
3502 if (p->has_doc()) {
3503 ss << " " << p->get_doc();
3504 }
3505 }
3506 generate_docstring_comment(out,
Bryan Duxbury1121b472011-08-11 18:50:58 +00003507 "/**\n",
3508 " * ", ss.str(),
3509 " */\n");
David Reiss7bcf8662009-01-06 20:54:27 +00003510 }
3511}
3512
David Reiss603d5042008-12-02 02:06:31 +00003513void t_java_generator::generate_deep_copy_container(ofstream &out, std::string source_name_p1, std::string source_name_p2,
3514 std::string result_name, t_type* type) {
3515
3516 t_container* container = (t_container*)type;
3517 std::string source_name;
3518 if (source_name_p2 == "")
Bryan Duxbury1121b472011-08-11 18:50:58 +00003519 source_name = source_name_p1;
David Reiss603d5042008-12-02 02:06:31 +00003520 else
Bryan Duxbury1121b472011-08-11 18:50:58 +00003521 source_name = source_name_p1 + "." + source_name_p2;
David Reiss603d5042008-12-02 02:06:31 +00003522
3523 indent(out) << type_name(type, true, false) << " " << result_name << " = new " << type_name(container, false, true) << "();" << endl;
3524
3525 std::string iterator_element_name = source_name_p1 + "_element";
3526 std::string result_element_name = result_name + "_copy";
3527
3528 if(container->is_map()) {
3529 t_type* key_type = ((t_map*)container)->get_key_type();
3530 t_type* val_type = ((t_map*)container)->get_val_type();
3531
3532 indent(out) <<
3533 "for (Map.Entry<" << type_name(key_type, true, false) << ", " << type_name(val_type, true, false) << "> " << iterator_element_name << " : " << source_name << ".entrySet()) {" << endl;
3534 indent_up();
3535
3536 out << endl;
3537
3538 indent(out) << type_name(key_type, true, false) << " " << iterator_element_name << "_key = " << iterator_element_name << ".getKey();" << endl;
3539 indent(out) << type_name(val_type, true, false) << " " << iterator_element_name << "_value = " << iterator_element_name << ".getValue();" << endl;
3540
3541 out << endl;
3542
3543 if (key_type->is_container()) {
3544 generate_deep_copy_container(out, iterator_element_name + "_key", "", result_element_name + "_key", key_type);
3545 } else {
3546 indent(out) << type_name(key_type, true, false) << " " << result_element_name << "_key = ";
David Reiss5455f002009-01-05 21:02:48 +00003547 generate_deep_copy_non_container(out, iterator_element_name + "_key", result_element_name + "_key", key_type);
David Reiss603d5042008-12-02 02:06:31 +00003548 out << ";" << endl;
3549 }
3550
3551 out << endl;
3552
3553 if (val_type->is_container()) {
3554 generate_deep_copy_container(out, iterator_element_name + "_value", "", result_element_name + "_value", val_type);
3555 } else {
3556 indent(out) << type_name(val_type, true, false) << " " << result_element_name << "_value = ";
David Reiss5455f002009-01-05 21:02:48 +00003557 generate_deep_copy_non_container(out, iterator_element_name + "_value", result_element_name + "_value", val_type);
David Reiss603d5042008-12-02 02:06:31 +00003558 out << ";" << endl;
3559 }
3560
3561 out << endl;
3562
3563 indent(out) << result_name << ".put(" << result_element_name << "_key, " << result_element_name << "_value);" << endl;
3564
3565 indent_down();
3566 indent(out) << "}" << endl;
3567
3568 } else {
3569 t_type* elem_type;
3570
3571 if (container->is_set()) {
3572 elem_type = ((t_set*)container)->get_elem_type();
3573 } else {
3574 elem_type = ((t_list*)container)->get_elem_type();
3575 }
3576
3577 indent(out)
3578 << "for (" << type_name(elem_type, true, false) << " " << iterator_element_name << " : " << source_name << ") {" << endl;
3579
3580 indent_up();
3581
3582 if (elem_type->is_container()) {
3583 // recursive deep copy
3584 generate_deep_copy_container(out, iterator_element_name, "", result_element_name, elem_type);
3585 indent(out) << result_name << ".add(" << result_element_name << ");" << endl;
3586 } else {
3587 // iterative copy
David Reiss5455f002009-01-05 21:02:48 +00003588 if(((t_base_type*)elem_type)->is_binary()){
Bryan Duxburyf5abd262010-08-06 00:18:25 +00003589 indent(out) << "ByteBuffer temp_binary_element = ";
David Reiss5455f002009-01-05 21:02:48 +00003590 generate_deep_copy_non_container(out, iterator_element_name, "temp_binary_element", elem_type);
3591 out << ";" << endl;
3592 indent(out) << result_name << ".add(temp_binary_element);" << endl;
Bryan Duxbury1121b472011-08-11 18:50:58 +00003593 } else{
David Reiss5455f002009-01-05 21:02:48 +00003594 indent(out) << result_name << ".add(";
3595 generate_deep_copy_non_container(out, iterator_element_name, result_name, elem_type);
3596 out << ");" << endl;
3597 }
David Reiss603d5042008-12-02 02:06:31 +00003598 }
3599
3600 indent_down();
3601
3602 indent(out) << "}" << endl;
3603
3604 }
3605}
3606
David Reiss5455f002009-01-05 21:02:48 +00003607void t_java_generator::generate_deep_copy_non_container(ofstream& out, std::string source_name, std::string dest_name, t_type* type) {
Roger Meier3b771a12010-11-17 22:11:26 +00003608 (void) dest_name;
David Reiss603d5042008-12-02 02:06:31 +00003609 if (type->is_base_type() || type->is_enum() || type->is_typedef()) {
Bryan Duxburyd9207652010-09-17 19:27:36 +00003610 if (((t_base_type*)type)->is_binary()) {
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003611 out << "org.apache.thrift.TBaseHelper.copyBinary(" << source_name << ");" << endl;
Bryan Duxburyd9207652010-09-17 19:27:36 +00003612 } else {
3613 // everything else can be copied directly
David Reiss5455f002009-01-05 21:02:48 +00003614 out << source_name;
Bryan Duxburyd9207652010-09-17 19:27:36 +00003615 }
David Reiss603d5042008-12-02 02:06:31 +00003616 } else {
3617 out << "new " << type_name(type, true, true) << "(" << source_name << ")";
3618 }
3619}
3620
Bryan Duxburyd11f2412009-02-19 21:21:44 +00003621std::string t_java_generator::generate_isset_check(t_field* field) {
Bryan Duxburye3c3d192009-03-07 03:08:37 +00003622 return generate_isset_check(field->get_name());
3623}
3624
Bryan Duxbury3efce232009-08-03 19:37:26 +00003625std::string t_java_generator::isset_field_id(t_field* field) {
3626 return "__" + upcase_string(field->get_name() + "_isset_id");
3627}
3628
Bryan Duxburye3c3d192009-03-07 03:08:37 +00003629std::string t_java_generator::generate_isset_check(std::string field_name) {
3630 return "is" + get_cap_name("set") + get_cap_name(field_name) + "()";
Bryan Duxburyd11f2412009-02-19 21:21:44 +00003631}
3632
Bryan Duxbury1121b472011-08-11 18:50:58 +00003633void t_java_generator::generate_isset_set(ofstream& out, t_field* field, string prefix) {
Bryan Duxburyd11f2412009-02-19 21:21:44 +00003634 if (!type_can_be_null(field->get_type())) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00003635 indent(out) << prefix << "set" << get_cap_name(field->get_name()) << get_cap_name("isSet") << "(true);" << endl;
Bryan Duxburyd11f2412009-02-19 21:21:44 +00003636 }
3637}
3638
Bryan Duxbury3696d642009-03-18 03:14:56 +00003639std::string t_java_generator::get_enum_class_name(t_type* type) {
3640 string package = "";
3641 t_program* program = type->get_program();
3642 if (program != NULL && program != program_) {
3643 package = program->get_namespace("java") + ".";
3644 }
3645 return package + type->get_name();
3646}
David Reisse1404d22008-02-27 01:55:05 +00003647
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003648void t_java_generator::generate_struct_desc(ofstream& out, t_struct* tstruct) {
3649 indent(out) <<
Bryan Duxbury1121b472011-08-11 18:50:58 +00003650 "private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct(\"" << tstruct->get_name() << "\");" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003651}
3652
3653void t_java_generator::generate_field_descs(ofstream& out, t_struct* tstruct) {
3654 const vector<t_field*>& members = tstruct->get_members();
3655 vector<t_field*>::const_iterator m_iter;
3656
3657 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
3658 indent(out) <<
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003659 "private static final org.apache.thrift.protocol.TField " << constant_name((*m_iter)->get_name()) <<
3660 "_FIELD_DESC = new org.apache.thrift.protocol.TField(\"" << (*m_iter)->get_name() << "\", " <<
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003661 type_to_enum((*m_iter)->get_type()) << ", " <<
3662 "(short)" << (*m_iter)->get_key() << ");" << endl;
3663 }
3664}
3665
Bryan Duxbury1121b472011-08-11 18:50:58 +00003666void t_java_generator::generate_scheme_map(ofstream& out, t_struct* tstruct) {
3667 indent(out) << "private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();" << endl;
3668 indent(out) << "static {" << endl;
3669 indent(out) << " schemes.put(StandardScheme.class, new " << tstruct->get_name() << "StandardSchemeFactory());" << endl;
3670 indent(out) << " schemes.put(TupleScheme.class, new " << tstruct->get_name() << "TupleSchemeFactory());" << endl;
3671 indent(out) << "}" << endl;
3672}
3673
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003674void t_java_generator::generate_field_name_constants(ofstream& out, t_struct* tstruct) {
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00003675 indent(out) << "/** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */" << endl;
Bryan Duxbury932ce2b2010-12-07 18:28:48 +00003676 indent(out) << "public enum _Fields implements org.apache.thrift.TFieldIdEnum {" << endl;
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00003677
3678 indent_up();
3679 bool first = true;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003680 const vector<t_field*>& members = tstruct->get_members();
3681 vector<t_field*>::const_iterator m_iter;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003682 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00003683 if (!first) {
3684 out << "," << endl;
3685 }
3686 first = false;
3687 generate_java_doc(out, *m_iter);
3688 indent(out) << constant_name((*m_iter)->get_name()) << "((short)" << (*m_iter)->get_key() << ", \"" << (*m_iter)->get_name() << "\")";
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003689 }
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00003690
3691 out << ";" << endl << endl;
3692
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00003693 indent(out) << "private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();" << endl;
3694 out << endl;
3695
3696 indent(out) << "static {" << endl;
3697 indent(out) << " for (_Fields field : EnumSet.allOf(_Fields.class)) {" << endl;
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00003698 indent(out) << " byName.put(field.getFieldName(), field);" << endl;
3699 indent(out) << " }" << endl;
3700 indent(out) << "}" << endl << endl;
3701
3702 indent(out) << "/**" << endl;
3703 indent(out) << " * Find the _Fields constant that matches fieldId, or null if its not found." << endl;
3704 indent(out) << " */" << endl;
3705 indent(out) << "public static _Fields findByThriftId(int fieldId) {" << endl;
Bryan Duxbury49b38012010-04-04 04:01:07 +00003706 indent_up();
3707 indent(out) << "switch(fieldId) {" << endl;
3708 indent_up();
3709
3710 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
3711 indent(out) << "case " << (*m_iter)->get_key() << ": // " << constant_name((*m_iter)->get_name()) << endl;
3712 indent(out) << " return " << constant_name((*m_iter)->get_name()) << ";" << endl;
3713 }
3714
3715 indent(out) << "default:" << endl;
3716 indent(out) << " return null;" << endl;
3717
3718 indent_down();
3719 indent(out) << "}" << endl;
3720
3721 indent_down();
Bryan Duxburyaa9fb5d2009-11-12 20:52:25 +00003722 indent(out) << "}" << endl << endl;
3723
3724 indent(out) << "/**" << endl;
3725 indent(out) << " * Find the _Fields constant that matches fieldId, throwing an exception" << endl;
3726 indent(out) << " * if it is not found." << endl;
3727 indent(out) << " */" << endl;
3728 indent(out) << "public static _Fields findByThriftIdOrThrow(int fieldId) {" << endl;
3729 indent(out) << " _Fields fields = findByThriftId(fieldId);" << endl;
3730 indent(out) << " if (fields == null) throw new IllegalArgumentException(\"Field \" + fieldId + \" doesn't exist!\");" << endl;
3731 indent(out) << " return fields;" << endl;
3732 indent(out) << "}" << endl << endl;
3733
3734 indent(out) << "/**" << endl;
3735 indent(out) << " * Find the _Fields constant that matches name, or null if its not found." << endl;
3736 indent(out) << " */" << endl;
3737 indent(out) << "public static _Fields findByName(String name) {" << endl;
3738 indent(out) << " return byName.get(name);" << endl;
3739 indent(out) << "}" << endl << endl;
3740
3741 indent(out) << "private final short _thriftId;" << endl;
3742 indent(out) << "private final String _fieldName;" << endl << endl;
3743
3744 indent(out) << "_Fields(short thriftId, String fieldName) {" << endl;
3745 indent(out) << " _thriftId = thriftId;" << endl;
3746 indent(out) << " _fieldName = fieldName;" << endl;
3747 indent(out) << "}" << endl << endl;
3748
3749 indent(out) << "public short getThriftFieldId() {" << endl;
3750 indent(out) << " return _thriftId;" << endl;
3751 indent(out) << "}" << endl << endl;
3752
3753 indent(out) << "public String getFieldName() {" << endl;
3754 indent(out) << " return _fieldName;" << endl;
3755 indent(out) << "}" << endl;
3756
3757 indent_down();
3758
3759 indent(out) << "}" << endl;
Bryan Duxburyab3666e2009-09-01 23:03:47 +00003760}
3761
Bryan Duxbury3efce232009-08-03 19:37:26 +00003762bool t_java_generator::has_bit_vector(t_struct* tstruct) {
3763 const vector<t_field*>& members = tstruct->get_members();
3764 vector<t_field*>::const_iterator m_iter;
3765
3766 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Bryan Duxbury2845b162009-11-09 15:55:22 +00003767 if (!type_can_be_null(get_true_type((*m_iter)->get_type()))) {
Bryan Duxbury3efce232009-08-03 19:37:26 +00003768 return true;
3769 }
3770 }
Bryan Duxbury2845b162009-11-09 15:55:22 +00003771 return false;
Bryan Duxbury3efce232009-08-03 19:37:26 +00003772}
3773
Bryan Duxbury5226eea2010-08-05 20:44:53 +00003774void t_java_generator::generate_java_struct_clear(std::ofstream& out, t_struct* tstruct) {
Bryan Duxbury9a422392011-05-23 21:41:02 +00003775 if (!java5_) {
Bryan Duxbury1121b472011-08-11 18:50:58 +00003776 indent(out) << "@Override" << endl;
Bryan Duxbury9a422392011-05-23 21:41:02 +00003777 }
Bryan Duxbury5226eea2010-08-05 20:44:53 +00003778 indent(out) << "public void clear() {" << endl;
3779
3780 const vector<t_field*>& members = tstruct->get_members();
3781 vector<t_field*>::const_iterator m_iter;
3782
3783 indent_up();
3784 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Roger Meier5e64d512010-10-16 15:54:36 +00003785 t_field* field = *m_iter;
3786 t_type* t = get_true_type(field->get_type());
3787
3788 if (field->get_value() != NULL) {
3789 print_const_value(out, "this." + field->get_name(), t, field->get_value(), true, true);
3790 continue;
3791 }
3792
3793 if (type_can_be_null(t)) {
3794 indent(out) << "this." << field->get_name() << " = null;" << endl;
3795 continue;
3796 }
3797
3798 // must be a base type
3799 // means it also needs to be explicitly unset
3800 indent(out) << "set" << get_cap_name(field->get_name()) << get_cap_name("isSet") << "(false);" << endl;
3801 t_base_type* base_type = (t_base_type*) t;
3802
3803 switch (base_type->get_base()) {
3804 case t_base_type::TYPE_BYTE:
3805 case t_base_type::TYPE_I16:
3806 case t_base_type::TYPE_I32:
3807 case t_base_type::TYPE_I64:
3808 indent(out) << "this." << field->get_name() << " = 0;" << endl;
3809 break;
3810 case t_base_type::TYPE_DOUBLE:
3811 indent(out) << "this." << field->get_name() << " = 0.0;" << endl;
3812 break;
3813 case t_base_type::TYPE_BOOL:
3814 indent(out) << "this." << field->get_name() << " = false;" << endl;
3815 break;
3816 default:
3817 throw "unsupported type: " + base_type->get_name() + " for field " + field->get_name();
Bryan Duxbury5226eea2010-08-05 20:44:53 +00003818 }
3819 }
3820 indent_down();
3821
3822 indent(out) << "}" << endl << endl;
3823}
3824
Bryan Duxburyc8d533b2011-01-26 22:42:02 +00003825// generates java method to serialize (in the Java sense) the object
3826void t_java_generator::generate_java_struct_write_object(ofstream& out, t_struct* tstruct) {
Roger Meiera8cef6e2011-07-17 18:55:59 +00003827 (void) tstruct;
Bryan Duxburyc8d533b2011-01-26 22:42:02 +00003828 indent(out) << "private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {" << endl;
3829 indent(out) << " try {" << endl;
3830 indent(out) << " write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));" << endl;
3831 indent(out) << " } catch (org.apache.thrift.TException te) {" << endl;
Roger Meier6b38cf62011-04-16 20:05:51 +00003832 indent(out) << " throw new java.io.IOException(te" << (android_legacy_? ".getMessage()" : "") << ");" << endl;
Bryan Duxburyc8d533b2011-01-26 22:42:02 +00003833 indent(out) << " }" << endl;
3834 indent(out) << "}" << endl << endl;
3835}
3836
3837// generates java method to serialize (in the Java sense) the object
3838void t_java_generator::generate_java_struct_read_object(ofstream& out, t_struct* tstruct) {
3839 indent(out) << "private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {" << endl;
3840 indent(out) << " try {" << endl;
3841 if (!tstruct->is_union() && has_bit_vector(tstruct)) {
3842 indent(out) << " // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor." << endl;
3843 indent(out) << " __isset_bit_vector = new BitSet(1);" << endl;
3844 }
3845 indent(out) << " read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));" << endl;
3846 indent(out) << " } catch (org.apache.thrift.TException te) {" << endl;
Roger Meier6b38cf62011-04-16 20:05:51 +00003847 indent(out) << " throw new java.io.IOException(te" << (android_legacy_? ".getMessage()" : "") << ");" << endl;
Bryan Duxburyc8d533b2011-01-26 22:42:02 +00003848 indent(out) << " }" << endl;
3849 indent(out) << "}" << endl << endl;
3850}
3851
Bryan Duxbury1121b472011-08-11 18:50:58 +00003852void t_java_generator::generate_standard_reader(ofstream& out, t_struct* tstruct) {
3853 out <<
3854 indent() << "public void read(org.apache.thrift.protocol.TProtocol iprot, " << tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
3855 indent_up();
3856
3857 const vector<t_field*>& fields = tstruct->get_members();
3858 vector<t_field*>::const_iterator f_iter;
3859
3860 // Declare stack tmp variables and read struct header
3861 out <<
3862 indent() << "org.apache.thrift.protocol.TField schemeField;" << endl <<
3863 indent() << "iprot.readStructBegin();" << endl;
3864
3865 // Loop over reading in fields
3866 indent(out) << "while (true)" << endl;
3867 scope_up(out);
3868
3869 // Read beginning field marker
3870 indent(out) << "schemeField = iprot.readFieldBegin();" << endl;
3871
3872 // Check for field STOP marker and break
3873 indent(out) << "if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { " << endl;
3874 indent_up();
3875 indent(out) << "break;" << endl;
3876 indent_down();
3877 indent(out) << "}" << endl;
3878
3879 // Switch statement on the field we are reading
3880 indent(out) << "switch (schemeField.id) {" << endl;
3881
3882 indent_up();
3883
3884 // Generate deserialization code for known cases
3885 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3886 indent(out) <<
3887 "case " << (*f_iter)->get_key() << ": // " << constant_name((*f_iter)->get_name()) << endl;
3888 indent_up();
3889 indent(out) <<
3890 "if (schemeField.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl;
3891 indent_up();
3892
Bryan Duxburyb8c8e0b2011-08-29 17:50:31 +00003893 generate_deserialize_field(out, *f_iter, "struct.", true);
Bryan Duxbury1121b472011-08-11 18:50:58 +00003894 indent(out) << "struct." << "set" << get_cap_name((*f_iter)->get_name()) << get_cap_name("isSet") << "(true);" << endl;
3895 indent_down();
3896 out <<
3897 indent() << "} else { " << endl <<
3898 indent() << " org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);" << endl <<
3899 indent() << "}" << endl <<
3900 indent() << "break;" << endl;
3901 indent_down();
3902 }
3903
3904 indent(out) << "default:" << endl;
3905 indent(out) << " org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);" << endl;
3906
3907 indent_down();
3908 indent(out) << "}" << endl;
3909
3910 // Read field end marker
3911 indent(out) << "iprot.readFieldEnd();" << endl;
3912
3913 indent_down();
3914 indent(out) << "}" << endl;
3915
3916 out <<
3917 indent() << "iprot.readStructEnd();" << endl;
3918
3919 // in non-beans style, check for required fields of primitive type
3920 // (which can be checked here but not in the general validate method)
3921 if (!bean_style_){
3922 out << endl << indent() << "// check for required fields of primitive type, which can't be checked in the validate method" << endl;
3923 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3924 if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) {
3925 out <<
3926 indent() << "if (!struct." << generate_isset_check(*f_iter) << ") {" << endl <<
3927 indent() << " throw new org.apache.thrift.protocol.TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' was not found in serialized data! Struct: \" + toString());" << endl <<
3928 indent() << "}" << endl;
3929 }
3930 }
3931 }
3932
3933 // performs various checks (e.g. check that all required fields are set)
3934 indent(out) << "struct.validate();" << endl;
3935
3936 indent_down();
3937 out << indent() << "}" << endl;
3938}
3939
3940void t_java_generator::generate_standard_writer(ofstream& out, t_struct* tstruct) {
3941 indent_up();
3942 out <<
3943 indent() << "public void write(org.apache.thrift.protocol.TProtocol oprot, " <<
3944 tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
3945 indent_up();
3946 const vector<t_field*>& fields = tstruct->get_sorted_members();
3947 vector<t_field*>::const_iterator f_iter;
3948
3949 // performs various checks (e.g. check that all required fields are set)
3950 indent(out) << "struct.validate();" << endl << endl;
3951
3952 indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl;
3953
3954 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3955 bool null_allowed = type_can_be_null((*f_iter)->get_type());
3956 if (null_allowed) {
3957 out <<
3958 indent() << "if (struct." << (*f_iter)->get_name() << " != null) {" << endl;
3959 indent_up();
3960 }
3961 bool optional = (*f_iter)->get_req() == t_field::T_OPTIONAL;
3962 if (optional) {
3963 indent(out) << "if (" << "struct." << generate_isset_check((*f_iter)) << ") {" << endl;
3964 indent_up();
3965 }
3966
3967 indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl;
3968
3969 // Write field contents
Bryan Duxburyb8c8e0b2011-08-29 17:50:31 +00003970 generate_serialize_field(out, *f_iter, "struct.", true);
Bryan Duxbury1121b472011-08-11 18:50:58 +00003971
3972 // Write field closer
3973 indent(out) << "oprot.writeFieldEnd();" << endl;
3974
3975 if (optional) {
3976 indent_down();
3977 indent(out) << "}" << endl;
3978 }
3979 if (null_allowed) {
3980 indent_down();
3981 indent(out) << "}" << endl;
3982 }
3983 }
3984 // Write the struct map
3985 out <<
3986 indent() << "oprot.writeFieldStop();" << endl <<
3987 indent() << "oprot.writeStructEnd();" << endl;
3988
3989 indent_down();
3990 out << indent() << "}" << endl << endl;
3991 indent_down();
3992}
3993
3994void t_java_generator::generate_java_struct_standard_scheme(ofstream& out, t_struct* tstruct){
3995 indent(out) << "private static class " << tstruct->get_name() << "StandardSchemeFactory implements SchemeFactory {" << endl;
3996 indent_up();
3997 indent(out) << "public " << tstruct->get_name() << "StandardScheme getScheme() {" << endl;
3998 indent_up();
3999 indent(out) << "return new " << tstruct->get_name() << "StandardScheme();" << endl;
4000 indent_down();
4001 indent(out) << "}" << endl;
4002 indent_down();
4003 indent(out) << "}" << endl << endl;
4004
4005 out << indent() << "private static class " << tstruct->get_name() << "StandardScheme extends StandardScheme<" << tstruct->get_name() << "> {" << endl << endl;
4006 indent_up();
4007 generate_standard_reader(out, tstruct);
4008 indent_down();
4009 out << endl;
4010 generate_standard_writer(out, tstruct);
4011
4012 out <<
4013 indent() << "}" << endl <<
4014 endl;
4015}
4016
4017void t_java_generator::generate_java_struct_tuple_reader(ofstream& out, t_struct* tstruct) {
4018 indent(out) << "@Override" << endl;
4019 indent(out) << "public void read(org.apache.thrift.protocol.TProtocol prot, " << tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
4020 indent_up();
4021 indent(out) << "TTupleProtocol iprot = (TTupleProtocol) prot;" << endl;
4022 int optional_count = 0;
4023 const vector<t_field*>& fields = tstruct->get_members();
4024 vector<t_field*>::const_iterator f_iter;
4025 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4026 if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
4027 optional_count++;
4028 }
4029 if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
4030 generate_deserialize_field(out, (*f_iter), "struct.", false);
4031 indent(out) << "struct.set" << get_cap_name((*f_iter)->get_name()) << get_cap_name("isSet") << "(true);" << endl;
4032 }
4033 }
4034 if (optional_count > 0) {
4035 indent(out) << "BitSet incoming = iprot.readBitSet(" << optional_count << ");" << endl;
4036 int i = 0;
4037 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4038 if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
4039 indent(out) << "if (incoming.get(" << i << ")) {" << endl;
4040 indent_up();
4041 generate_deserialize_field(out, (*f_iter), "struct.", false);
4042 indent(out) << "struct.set" << get_cap_name((*f_iter)->get_name()) << get_cap_name("isSet") << "(true);" << endl;
4043 indent_down();
4044 indent(out) << "}" << endl;
4045 i++;
4046 }
4047 }
4048 }
4049 indent_down();
4050 indent(out) << "}" << endl;
4051}
4052
4053void t_java_generator::generate_java_struct_tuple_writer(ofstream& out, t_struct* tstruct) {
4054 indent(out) << "@Override" << endl;
4055 indent(out) << "public void write(org.apache.thrift.protocol.TProtocol prot, " << tstruct->get_name() << " struct) throws org.apache.thrift.TException {" << endl;
4056 indent_up();
4057 indent(out) << "TTupleProtocol oprot = (TTupleProtocol) prot;" << endl;
4058
4059 const vector<t_field*>& fields = tstruct->get_members();
4060 vector<t_field*>::const_iterator f_iter;
4061 bool has_optional = false;
Bryan Duxbury40d51a22011-09-26 21:29:15 +00004062 int optional_count = 0;
Bryan Duxbury1121b472011-08-11 18:50:58 +00004063 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4064 if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
Bryan Duxbury40d51a22011-09-26 21:29:15 +00004065 optional_count++;
Bryan Duxbury1121b472011-08-11 18:50:58 +00004066 has_optional = true;
4067 }
4068 if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
4069 generate_serialize_field(out, (*f_iter), "struct.", false);
4070 }
4071 }
4072 if (has_optional) {
4073 indent(out) << "BitSet optionals = new BitSet();" << endl;
4074 int i = 0;
4075 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4076 if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
4077 indent(out) << "if (struct." << generate_isset_check((*f_iter)) << ") {" << endl;
4078 indent_up();
4079 indent(out) << "optionals.set(" << i << ");" << endl;
4080 indent_down();
4081 indent(out) << "}" << endl;
4082 i++;
4083 }
4084 }
4085
Bryan Duxbury40d51a22011-09-26 21:29:15 +00004086 indent(out) << "oprot.writeBitSet(optionals, " << optional_count << ");" << endl;
Bryan Duxbury1121b472011-08-11 18:50:58 +00004087 int j = 0;
4088 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4089 if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) {
4090 indent(out) << "if (struct." << generate_isset_check(*f_iter) << ") {" << endl;
4091 indent_up();
4092 generate_serialize_field(out, (*f_iter), "struct.", false);
4093 indent_down();
4094 indent(out) << "}" << endl;
4095 j++;
4096 }
4097 }
4098 }
4099 indent_down();
4100 indent(out) << "}" << endl;
4101}
4102
4103void t_java_generator::generate_java_struct_tuple_scheme(ofstream& out, t_struct* tstruct){
4104 indent(out) << "private static class " << tstruct->get_name() << "TupleSchemeFactory implements SchemeFactory {" << endl;
4105 indent_up();
4106 indent(out) << "public " << tstruct->get_name() << "TupleScheme getScheme() {" << endl;
4107 indent_up();
4108 indent(out) << "return new " << tstruct->get_name() << "TupleScheme();" << endl;
4109 indent_down();
4110 indent(out) << "}" << endl;
4111 indent_down();
4112 indent(out) << "}" << endl << endl;
4113 out << indent() << "private static class " << tstruct->get_name() << "TupleScheme extends TupleScheme<" << tstruct->get_name() << "> {" << endl << endl;
4114 indent_up();
4115 generate_java_struct_tuple_writer(out, tstruct);
4116 out << endl;
4117 generate_java_struct_tuple_reader(out, tstruct);
4118 indent_down();
4119 out << indent() << "}" << endl << endl;
4120}
4121
David Reisse1404d22008-02-27 01:55:05 +00004122THRIFT_REGISTER_GENERATOR(java, "Java",
Bryan Duxburyea7910f2010-04-03 05:04:48 +00004123" beans: Members will be private, and setter methods will return void.\n"
4124" private-members: Members will be private, but setter methods will return 'this' like usual.\n"
David Reiss70e329f2008-07-14 19:35:50 +00004125" nocamel: Do not use CamelCase field accessors with beans.\n"
David Reiss69875352008-03-04 21:10:41 +00004126" hashcode: Generate quality hashCode methods.\n"
Roger Meier6b38cf62011-04-16 20:05:51 +00004127" android_legacy: Do not use java.io.IOException(throwable) (available for Android 2.3 and above).\n"
Jake Farrellfae04ea2011-10-07 23:15:03 +00004128" java5: Generate Java 1.5 compliant code (includes android_legacy flag).\n"
Roger Meier0069cc42010-10-13 18:10:18 +00004129)
Bryan Duxburyab3666e2009-09-01 23:03:47 +00004130