blob: 455516f67756acd2f14e255ced79c8485e779ac3 [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
temporal40ee5512008-07-10 02:12:20 +00004//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
temporal40ee5512008-07-10 02:12:20 +000030
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34
35#include <map>
36#include <string>
37
jieluo@google.com4de8f552014-07-18 00:47:59 +000038#include <google/protobuf/compiler/java/java_context.h>
temporal40ee5512008-07-10 02:12:20 +000039#include <google/protobuf/compiler/java/java_message_field.h>
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +000040#include <google/protobuf/compiler/java/java_doc_comment.h>
temporal40ee5512008-07-10 02:12:20 +000041#include <google/protobuf/compiler/java/java_helpers.h>
jieluo@google.com4de8f552014-07-18 00:47:59 +000042#include <google/protobuf/compiler/java/java_name_resolver.h>
temporal40ee5512008-07-10 02:12:20 +000043#include <google/protobuf/io/printer.h>
44#include <google/protobuf/wire_format.h>
45#include <google/protobuf/stubs/strutil.h>
46
47namespace google {
48namespace protobuf {
49namespace compiler {
50namespace java {
51
52namespace {
53
temporal40ee5512008-07-10 02:12:20 +000054void SetMessageVariables(const FieldDescriptor* descriptor,
liujisi@google.com33165fe2010-11-02 13:14:58 +000055 int messageBitIndex,
56 int builderBitIndex,
jieluo@google.com4de8f552014-07-18 00:47:59 +000057 const FieldGeneratorInfo* info,
58 ClassNameResolver* name_resolver,
temporal40ee5512008-07-10 02:12:20 +000059 map<string, string>* variables) {
jieluo@google.com4de8f552014-07-18 00:47:59 +000060 SetCommonFieldVariables(descriptor, info, variables);
61
62 (*variables)["type"] =
63 name_resolver->GetImmutableClassName(descriptor->message_type());
64 (*variables)["mutable_type"] =
65 name_resolver->GetMutableClassName(descriptor->message_type());
temporal40ee5512008-07-10 02:12:20 +000066 (*variables)["group_or_message"] =
kenton@google.comfccb1462009-12-18 02:11:36 +000067 (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
temporal40ee5512008-07-10 02:12:20 +000068 "Group" : "Message";
liujisi@google.com33165fe2010-11-02 13:14:58 +000069 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
70 // by the proto compiler
71 (*variables)["deprecation"] = descriptor->options().deprecated()
72 ? "@java.lang.Deprecated " : "";
Jisi Liu3b3c8ab2016-03-30 11:39:59 -070073 (*variables)["on_changed"] = "onChanged();";
liujisi@google.com33165fe2010-11-02 13:14:58 +000074
jieluo@google.com4de8f552014-07-18 00:47:59 +000075 if (SupportFieldPresence(descriptor->file())) {
76 // For singular messages and builders, one bit is used for the hasField bit.
77 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
78 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
liujisi@google.com33165fe2010-11-02 13:14:58 +000079
jieluo@google.com4de8f552014-07-18 00:47:59 +000080 // Note that these have a trailing ";".
81 (*variables)["set_has_field_bit_message"] =
82 GenerateSetBit(messageBitIndex) + ";";
83 (*variables)["set_has_field_bit_builder"] =
84 GenerateSetBit(builderBitIndex) + ";";
85 (*variables)["clear_has_field_bit_builder"] =
86 GenerateClearBit(builderBitIndex) + ";";
87
88 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
89 } else {
90 (*variables)["set_has_field_bit_message"] = "";
91 (*variables)["set_has_field_bit_builder"] = "";
92 (*variables)["clear_has_field_bit_builder"] = "";
93
94 (*variables)["is_field_present_message"] =
95 (*variables)["name"] + "_ != null";
96 }
liujisi@google.com33165fe2010-11-02 13:14:58 +000097
98 // For repated builders, one bit is used for whether the array is immutable.
99 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
100 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
101 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
102
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000103 // For repeated fields, one bit is used for whether the array is immutable
104 // in the parsing constructor.
105 (*variables)["get_mutable_bit_parser"] =
106 GenerateGetBitMutableLocal(builderBitIndex);
107 (*variables)["set_mutable_bit_parser"] =
108 GenerateSetBitMutableLocal(builderBitIndex);
109
liujisi@google.com33165fe2010-11-02 13:14:58 +0000110 (*variables)["get_has_field_bit_from_local"] =
111 GenerateGetBitFromLocal(builderBitIndex);
112 (*variables)["set_has_field_bit_to_local"] =
113 GenerateSetBitToLocal(messageBitIndex);
temporal40ee5512008-07-10 02:12:20 +0000114}
115
116} // namespace
117
118// ===================================================================
119
jieluo@google.com4de8f552014-07-18 00:47:59 +0000120ImmutableMessageFieldGenerator::
121ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000122 int messageBitIndex,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000123 int builderBitIndex,
124 Context* context)
liujisi@google.com33165fe2010-11-02 13:14:58 +0000125 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
jieluo@google.com4de8f552014-07-18 00:47:59 +0000126 builderBitIndex_(builderBitIndex), context_(context),
127 name_resolver_(context->GetNameResolver()) {
128 SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
129 context->GetFieldGeneratorInfo(descriptor),
130 name_resolver_, &variables_);
temporal40ee5512008-07-10 02:12:20 +0000131}
132
jieluo@google.com4de8f552014-07-18 00:47:59 +0000133ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {}
temporal40ee5512008-07-10 02:12:20 +0000134
jieluo@google.com4de8f552014-07-18 00:47:59 +0000135int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000136 return 1;
137}
138
jieluo@google.com4de8f552014-07-18 00:47:59 +0000139int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000140 return 1;
141}
142
jieluo@google.com4de8f552014-07-18 00:47:59 +0000143void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000144GenerateInterfaceMembers(io::Printer* printer) const {
145 // TODO(jonp): In the future, consider having a method specific to the
146 // interface so that builders can choose dynamically to either return a
147 // message or a nested builder, so that asking for the interface doesn't
148 // cause a message to ever be built.
jieluo@google.com4de8f552014-07-18 00:47:59 +0000149 if (SupportFieldPresence(descriptor_->file()) ||
150 descriptor_->containing_oneof() == NULL) {
151 WriteFieldDocComment(printer, descriptor_);
152 printer->Print(variables_,
153 "$deprecation$boolean has$capitalized_name$();\n");
154 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000155 WriteFieldDocComment(printer, descriptor_);
156 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000157 "$deprecation$$type$ get$capitalized_name$();\n");
158
Bo Yang5db21732015-05-21 14:28:59 -0700159 WriteFieldDocComment(printer, descriptor_);
160 printer->Print(variables_,
161 "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000162}
163
jieluo@google.com4de8f552014-07-18 00:47:59 +0000164void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000165GenerateMembers(io::Printer* printer) const {
166 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000167 "private $type$ $name$_;\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000168 PrintExtraFieldInfo(variables_, printer);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000169
jieluo@google.com4de8f552014-07-18 00:47:59 +0000170 if (SupportFieldPresence(descriptor_->file())) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000171 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000172 printer->Print(variables_,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000173 "$deprecation$public boolean has$capitalized_name$() {\n"
174 " return $get_has_field_bit_message$;\n"
175 "}\n");
176 WriteFieldDocComment(printer, descriptor_);
177 printer->Print(variables_,
178 "$deprecation$public $type$ get$capitalized_name$() {\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800179 " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000180 "}\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000181
Bo Yang5db21732015-05-21 14:28:59 -0700182 WriteFieldDocComment(printer, descriptor_);
183 printer->Print(variables_,
184 "$deprecation$public $type$OrBuilder "
185 "get$capitalized_name$OrBuilder() {\n"
186 " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
187 "}\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000188 } else {
189 WriteFieldDocComment(printer, descriptor_);
190 printer->Print(variables_,
191 "$deprecation$public boolean has$capitalized_name$() {\n"
192 " return $name$_ != null;\n"
193 "}\n");
194 WriteFieldDocComment(printer, descriptor_);
195 printer->Print(variables_,
196 "$deprecation$public $type$ get$capitalized_name$() {\n"
197 " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
198 "}\n");
199
Bo Yang5db21732015-05-21 14:28:59 -0700200 WriteFieldDocComment(printer, descriptor_);
201 printer->Print(variables_,
202 "$deprecation$public $type$OrBuilder "
203 "get$capitalized_name$OrBuilder() {\n"
204 " return get$capitalized_name$();\n"
205 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000206 }
207}
208
jieluo@google.com4de8f552014-07-18 00:47:59 +0000209void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000210 io::Printer* printer,
211 const char* regular_case,
212 const char* nested_builder_case) const {
Bo Yang5db21732015-05-21 14:28:59 -0700213 printer->Print(variables_, "if ($name$Builder_ == null) {\n");
214 printer->Indent();
215 printer->Print(variables_, regular_case);
216 printer->Outdent();
217 printer->Print("} else {\n");
218 printer->Indent();
219 printer->Print(variables_, nested_builder_case);
220 printer->Outdent();
221 printer->Print("}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000222}
223
jieluo@google.com4de8f552014-07-18 00:47:59 +0000224void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000225 io::Printer* printer,
226 const char* method_prototype,
227 const char* regular_case,
228 const char* nested_builder_case,
229 const char* trailing_code) const {
230 printer->Print(variables_, method_prototype);
231 printer->Print(" {\n");
232 printer->Indent();
233 PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
234 if (trailing_code != NULL) {
235 printer->Print(variables_, trailing_code);
236 }
237 printer->Outdent();
238 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000239}
240
jieluo@google.com4de8f552014-07-18 00:47:59 +0000241void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000242GenerateBuilderMembers(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000243 // When using nested-builders, the code initially works just like the
244 // non-nested builder case. It only creates a nested builder lazily on
245 // demand and then forever delegates to it after creation.
246
jieluo@google.com4de8f552014-07-18 00:47:59 +0000247 bool support_field_presence = SupportFieldPresence(descriptor_->file());
248
Feng Xiao6ef984a2014-11-10 17:34:54 -0800249 printer->Print(variables_,
250 "private $type$ $name$_ = null;\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000251
Bo Yang5db21732015-05-21 14:28:59 -0700252 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000253 // If this builder is non-null, it is used and the other fields are
254 // ignored.
255 "private com.google.protobuf.SingleFieldBuilder<\n"
256 " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
257 "\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000258
259 // The comments above the methods below are based on a hypothetical
260 // field of type "Field" called "Field".
261
262 // boolean hasField()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000263 WriteFieldDocComment(printer, descriptor_);
jieluo@google.com4de8f552014-07-18 00:47:59 +0000264 if (support_field_presence) {
265 printer->Print(variables_,
266 "$deprecation$public boolean has$capitalized_name$() {\n"
267 " return $get_has_field_bit_builder$;\n"
268 "}\n");
269 } else {
270 printer->Print(variables_,
271 "$deprecation$public boolean has$capitalized_name$() {\n"
272 " return $name$Builder_ != null || $name$_ != null;\n"
273 "}\n");
274 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000275
276 // Field getField()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000277 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000278 PrintNestedBuilderFunction(printer,
279 "$deprecation$public $type$ get$capitalized_name$()",
Feng Xiao6ef984a2014-11-10 17:34:54 -0800280 "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000281 "return $name$Builder_.getMessage();\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000282 NULL);
283
284 // Field.Builder setField(Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000285 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000286 PrintNestedBuilderFunction(printer,
287 "$deprecation$public Builder set$capitalized_name$($type$ value)",
288
289 "if (value == null) {\n"
290 " throw new NullPointerException();\n"
291 "}\n"
292 "$name$_ = value;\n"
293 "$on_changed$\n",
294
295 "$name$Builder_.setMessage(value);\n",
296
jieluo@google.com4de8f552014-07-18 00:47:59 +0000297 "$set_has_field_bit_builder$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000298 "return this;\n");
299
300 // Field.Builder setField(Field.Builder builderForValue)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000301 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000302 PrintNestedBuilderFunction(printer,
303 "$deprecation$public Builder set$capitalized_name$(\n"
304 " $type$.Builder builderForValue)",
305
306 "$name$_ = builderForValue.build();\n"
307 "$on_changed$\n",
308
309 "$name$Builder_.setMessage(builderForValue.build());\n",
310
jieluo@google.com4de8f552014-07-18 00:47:59 +0000311 "$set_has_field_bit_builder$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000312 "return this;\n");
313
314 // Field.Builder mergeField(Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000315 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000316 PrintNestedBuilderFunction(printer,
317 "$deprecation$public Builder merge$capitalized_name$($type$ value)",
318
jieluo@google.com4de8f552014-07-18 00:47:59 +0000319 support_field_presence
320 ? "if ($get_has_field_bit_builder$ &&\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800321 " $name$_ != null &&\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000322 " $name$_ != $type$.getDefaultInstance()) {\n"
323 " $name$_ =\n"
324 " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
325 "} else {\n"
326 " $name$_ = value;\n"
327 "}\n"
328 "$on_changed$\n"
329 : "if ($name$_ != null) {\n"
330 " $name$_ =\n"
331 " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
332 "} else {\n"
333 " $name$_ = value;\n"
334 "}\n"
335 "$on_changed$\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000336
337 "$name$Builder_.mergeFrom(value);\n",
338
jieluo@google.com4de8f552014-07-18 00:47:59 +0000339 "$set_has_field_bit_builder$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000340 "return this;\n");
341
342 // Field.Builder clearField()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000343 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000344 PrintNestedBuilderFunction(printer,
345 "$deprecation$public Builder clear$capitalized_name$()",
346
Feng Xiao6ef984a2014-11-10 17:34:54 -0800347 "$name$_ = null;\n"
348 "$on_changed$\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000349
jieluo@google.com4de8f552014-07-18 00:47:59 +0000350 support_field_presence
351 ? "$name$Builder_.clear();\n"
352 : "$name$_ = null;\n"
353 "$name$Builder_ = null;\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000354
jieluo@google.com4de8f552014-07-18 00:47:59 +0000355 "$clear_has_field_bit_builder$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000356 "return this;\n");
357
Bo Yang5db21732015-05-21 14:28:59 -0700358 WriteFieldDocComment(printer, descriptor_);
359 printer->Print(variables_,
360 "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
361 " $set_has_field_bit_builder$\n"
362 " $on_changed$\n"
363 " return get$capitalized_name$FieldBuilder().getBuilder();\n"
364 "}\n");
365 WriteFieldDocComment(printer, descriptor_);
366 printer->Print(variables_,
367 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
368 " if ($name$Builder_ != null) {\n"
369 " return $name$Builder_.getMessageOrBuilder();\n"
370 " } else {\n"
371 " return $name$_ == null ?\n"
372 " $type$.getDefaultInstance() : $name$_;\n"
373 " }\n"
374 "}\n");
375 WriteFieldDocComment(printer, descriptor_);
376 printer->Print(variables_,
377 "private com.google.protobuf.SingleFieldBuilder<\n"
378 " $type$, $type$.Builder, $type$OrBuilder> \n"
379 " get$capitalized_name$FieldBuilder() {\n"
380 " if ($name$Builder_ == null) {\n"
381 " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
382 " $type$, $type$.Builder, $type$OrBuilder>(\n"
383 " get$capitalized_name$(),\n"
384 " getParentForChildren(),\n"
385 " isClean());\n"
386 " $name$_ = null;\n"
387 " }\n"
388 " return $name$Builder_;\n"
389 "}\n");
temporal40ee5512008-07-10 02:12:20 +0000390}
391
jieluo@google.com4de8f552014-07-18 00:47:59 +0000392void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000393GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000394 if (SupportFieldPresence(descriptor_->file())) {
395 printer->Print(variables_,
396 "get$capitalized_name$FieldBuilder();\n");
397 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000398}
399
400
jieluo@google.com4de8f552014-07-18 00:47:59 +0000401void ImmutableMessageFieldGenerator::
Feng Xiao6ef984a2014-11-10 17:34:54 -0800402GenerateInitializationCode(io::Printer* printer) const {}
kenton@google.comfccb1462009-12-18 02:11:36 +0000403
jieluo@google.com4de8f552014-07-18 00:47:59 +0000404void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000405GenerateBuilderClearCode(io::Printer* printer) const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000406 if (SupportFieldPresence(descriptor_->file())) {
407 PrintNestedBuilderCondition(printer,
Feng Xiao6ef984a2014-11-10 17:34:54 -0800408 "$name$_ = null;\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000409
jieluo@google.com4de8f552014-07-18 00:47:59 +0000410 "$name$Builder_.clear();\n");
411 printer->Print(variables_, "$clear_has_field_bit_builder$\n");
412 } else {
413 PrintNestedBuilderCondition(printer,
414 "$name$_ = null;\n",
415
416 "$name$_ = null;\n"
417 "$name$Builder_ = null;\n");
418 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000419}
420
jieluo@google.com4de8f552014-07-18 00:47:59 +0000421void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000422GenerateMergingCode(io::Printer* printer) const {
423 printer->Print(variables_,
424 "if (other.has$capitalized_name$()) {\n"
425 " merge$capitalized_name$(other.get$capitalized_name$());\n"
426 "}\n");
427}
428
jieluo@google.com4de8f552014-07-18 00:47:59 +0000429void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000430GenerateBuildingCode(io::Printer* printer) const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000431 if (SupportFieldPresence(descriptor_->file())) {
432 printer->Print(variables_,
433 "if ($get_has_field_bit_from_local$) {\n"
434 " $set_has_field_bit_to_local$;\n"
435 "}\n");
436 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000437
438 PrintNestedBuilderCondition(printer,
439 "result.$name$_ = $name$_;\n",
440
441 "result.$name$_ = $name$Builder_.build();\n");
temporal40ee5512008-07-10 02:12:20 +0000442}
443
jieluo@google.com4de8f552014-07-18 00:47:59 +0000444void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000445GenerateParsingCode(io::Printer* printer) const {
446 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000447 "$type$.Builder subBuilder = null;\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000448 "if ($is_field_present_message$) {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000449 " subBuilder = $name$_.toBuilder();\n"
temporal40ee5512008-07-10 02:12:20 +0000450 "}\n");
451
kenton@google.comfccb1462009-12-18 02:11:36 +0000452 if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
temporal40ee5512008-07-10 02:12:20 +0000453 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700454 "$name$_ = input.readGroup($number$, $type$.parser(),\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000455 " extensionRegistry);\n");
temporal40ee5512008-07-10 02:12:20 +0000456 } else {
457 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700458 "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n");
temporal40ee5512008-07-10 02:12:20 +0000459 }
460
461 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000462 "if (subBuilder != null) {\n"
463 " subBuilder.mergeFrom($name$_);\n"
464 " $name$_ = subBuilder.buildPartial();\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000465 "}\n"
466 "$set_has_field_bit_message$\n");
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000467}
468
jieluo@google.com4de8f552014-07-18 00:47:59 +0000469void ImmutableMessageFieldGenerator::
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000470GenerateParsingDoneCode(io::Printer* printer) const {
471 // noop for messages.
temporal40ee5512008-07-10 02:12:20 +0000472}
473
jieluo@google.com4de8f552014-07-18 00:47:59 +0000474void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000475GenerateSerializationCode(io::Printer* printer) const {
476 printer->Print(variables_,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000477 "if ($is_field_present_message$) {\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800478 " output.write$group_or_message$($number$, get$capitalized_name$());\n"
temporal40ee5512008-07-10 02:12:20 +0000479 "}\n");
480}
481
jieluo@google.com4de8f552014-07-18 00:47:59 +0000482void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000483GenerateSerializedSizeCode(io::Printer* printer) const {
484 printer->Print(variables_,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000485 "if ($is_field_present_message$) {\n"
temporal40ee5512008-07-10 02:12:20 +0000486 " size += com.google.protobuf.CodedOutputStream\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800487 " .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
temporal40ee5512008-07-10 02:12:20 +0000488 "}\n");
489}
490
jieluo@google.com4de8f552014-07-18 00:47:59 +0000491void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000492GenerateEqualsCode(io::Printer* printer) const {
493 printer->Print(variables_,
494 "result = result && get$capitalized_name$()\n"
495 " .equals(other.get$capitalized_name$());\n");
496}
497
jieluo@google.com4de8f552014-07-18 00:47:59 +0000498void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000499GenerateHashCode(io::Printer* printer) const {
500 printer->Print(variables_,
501 "hash = (37 * hash) + $constant_name$;\n"
502 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
503}
504
jieluo@google.com4de8f552014-07-18 00:47:59 +0000505string ImmutableMessageFieldGenerator::GetBoxedType() const {
506 return name_resolver_->GetImmutableClassName(descriptor_->message_type());
temporal40ee5512008-07-10 02:12:20 +0000507}
508
509// ===================================================================
510
jieluo@google.com4de8f552014-07-18 00:47:59 +0000511ImmutableMessageOneofFieldGenerator::
512ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor,
513 int messageBitIndex,
514 int builderBitIndex,
515 Context* context)
516 : ImmutableMessageFieldGenerator(
517 descriptor, messageBitIndex, builderBitIndex, context) {
518 const OneofGeneratorInfo* info =
519 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
520 SetCommonOneofVariables(descriptor, info, &variables_);
temporal40ee5512008-07-10 02:12:20 +0000521}
522
jieluo@google.com4de8f552014-07-18 00:47:59 +0000523ImmutableMessageOneofFieldGenerator::
524~ImmutableMessageOneofFieldGenerator() {}
temporal40ee5512008-07-10 02:12:20 +0000525
jieluo@google.com4de8f552014-07-18 00:47:59 +0000526void ImmutableMessageOneofFieldGenerator::
527GenerateMembers(io::Printer* printer) const {
528 PrintExtraFieldInfo(variables_, printer);
529 if (SupportFieldPresence(descriptor_->file())) {
530 WriteFieldDocComment(printer, descriptor_);
531 printer->Print(variables_,
532 "$deprecation$public boolean has$capitalized_name$() {\n"
533 " return $has_oneof_case_message$;\n"
534 "}\n");
535 }
536 WriteFieldDocComment(printer, descriptor_);
537 printer->Print(variables_,
538 "$deprecation$public $type$ get$capitalized_name$() {\n"
539 " if ($has_oneof_case_message$) {\n"
540 " return ($type$) $oneof_name$_;\n"
541 " }\n"
542 " return $type$.getDefaultInstance();\n"
543 "}\n");
544
Bo Yang5db21732015-05-21 14:28:59 -0700545 WriteFieldDocComment(printer, descriptor_);
546 printer->Print(variables_,
547 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
548 " if ($has_oneof_case_message$) {\n"
549 " return ($type$) $oneof_name$_;\n"
550 " }\n"
551 " return $type$.getDefaultInstance();\n"
552 "}\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000553}
554
555void ImmutableMessageOneofFieldGenerator::
556GenerateBuilderMembers(io::Printer* printer) const {
557 // When using nested-builders, the code initially works just like the
558 // non-nested builder case. It only creates a nested builder lazily on
559 // demand and then forever delegates to it after creation.
Bo Yang5db21732015-05-21 14:28:59 -0700560 printer->Print(variables_,
561 // If this builder is non-null, it is used and the other fields are
562 // ignored.
563 "private com.google.protobuf.SingleFieldBuilder<\n"
564 " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
565 "\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000566
567 // The comments above the methods below are based on a hypothetical
568 // field of type "Field" called "Field".
569
570 if (SupportFieldPresence(descriptor_->file())) {
571 // boolean hasField()
572 WriteFieldDocComment(printer, descriptor_);
573 printer->Print(variables_,
574 "$deprecation$public boolean has$capitalized_name$() {\n"
575 " return $has_oneof_case_message$;\n"
576 "}\n");
577 }
578
579 // Field getField()
580 WriteFieldDocComment(printer, descriptor_);
581 PrintNestedBuilderFunction(printer,
582 "$deprecation$public $type$ get$capitalized_name$()",
583
584 "if ($has_oneof_case_message$) {\n"
585 " return ($type$) $oneof_name$_;\n"
586 "}\n"
587 "return $type$.getDefaultInstance();\n",
588
589 "if ($has_oneof_case_message$) {\n"
590 " return $name$Builder_.getMessage();\n"
591 "}\n"
592 "return $type$.getDefaultInstance();\n",
593
594 NULL);
595
596 // Field.Builder setField(Field value)
597 WriteFieldDocComment(printer, descriptor_);
598 PrintNestedBuilderFunction(printer,
599 "$deprecation$public Builder set$capitalized_name$($type$ value)",
600
601 "if (value == null) {\n"
602 " throw new NullPointerException();\n"
603 "}\n"
604 "$oneof_name$_ = value;\n"
605 "$on_changed$\n",
606
607 "$name$Builder_.setMessage(value);\n",
608
609 "$set_oneof_case_message$;\n"
610 "return this;\n");
611
612 // Field.Builder setField(Field.Builder builderForValue)
613 WriteFieldDocComment(printer, descriptor_);
614 PrintNestedBuilderFunction(printer,
615 "$deprecation$public Builder set$capitalized_name$(\n"
616 " $type$.Builder builderForValue)",
617
618 "$oneof_name$_ = builderForValue.build();\n"
619 "$on_changed$\n",
620
621 "$name$Builder_.setMessage(builderForValue.build());\n",
622
623 "$set_oneof_case_message$;\n"
624 "return this;\n");
625
626 // Field.Builder mergeField(Field value)
627 WriteFieldDocComment(printer, descriptor_);
628 PrintNestedBuilderFunction(printer,
629 "$deprecation$public Builder merge$capitalized_name$($type$ value)",
630
631 "if ($has_oneof_case_message$ &&\n"
632 " $oneof_name$_ != $type$.getDefaultInstance()) {\n"
633 " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
634 " .mergeFrom(value).buildPartial();\n"
635 "} else {\n"
636 " $oneof_name$_ = value;\n"
637 "}\n"
638 "$on_changed$\n",
639
640 "if ($has_oneof_case_message$) {\n"
641 " $name$Builder_.mergeFrom(value);\n"
642 "}\n"
643 "$name$Builder_.setMessage(value);\n",
644
645 "$set_oneof_case_message$;\n"
646 "return this;\n");
647
648 // Field.Builder clearField()
649 WriteFieldDocComment(printer, descriptor_);
650 PrintNestedBuilderFunction(printer,
651 "$deprecation$public Builder clear$capitalized_name$()",
652
653 "if ($has_oneof_case_message$) {\n"
654 " $clear_oneof_case_message$;\n"
655 " $oneof_name$_ = null;\n"
656 " $on_changed$\n"
657 "}\n",
658
659 "if ($has_oneof_case_message$) {\n"
660 " $clear_oneof_case_message$;\n"
661 " $oneof_name$_ = null;\n"
662 "}\n"
663 "$name$Builder_.clear();\n",
664
665 "return this;\n");
666
Bo Yang5db21732015-05-21 14:28:59 -0700667 WriteFieldDocComment(printer, descriptor_);
668 printer->Print(variables_,
669 "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
670 " return get$capitalized_name$FieldBuilder().getBuilder();\n"
671 "}\n");
672 WriteFieldDocComment(printer, descriptor_);
673 printer->Print(variables_,
674 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
675 " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
676 " return $name$Builder_.getMessageOrBuilder();\n"
677 " } else {\n"
678 " if ($has_oneof_case_message$) {\n"
679 " return ($type$) $oneof_name$_;\n"
680 " }\n"
681 " return $type$.getDefaultInstance();\n"
682 " }\n"
683 "}\n");
684 WriteFieldDocComment(printer, descriptor_);
685 printer->Print(variables_,
686 "private com.google.protobuf.SingleFieldBuilder<\n"
687 " $type$, $type$.Builder, $type$OrBuilder> \n"
688 " get$capitalized_name$FieldBuilder() {\n"
689 " if ($name$Builder_ == null) {\n"
690 " if (!($has_oneof_case_message$)) {\n"
691 " $oneof_name$_ = $type$.getDefaultInstance();\n"
692 " }\n"
693 " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
694 " $type$, $type$.Builder, $type$OrBuilder>(\n"
695 " ($type$) $oneof_name$_,\n"
696 " getParentForChildren(),\n"
697 " isClean());\n"
698 " $oneof_name$_ = null;\n"
699 " }\n"
700 " $set_oneof_case_message$;\n"
701 " $on_changed$;\n"
702 " return $name$Builder_;\n"
703 "}\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000704}
705
706void ImmutableMessageOneofFieldGenerator::
707GenerateBuildingCode(io::Printer* printer) const {
708
709 printer->Print(variables_,
710 "if ($has_oneof_case_message$) {\n");
711 printer->Indent();
712
713 PrintNestedBuilderCondition(printer,
714 "result.$oneof_name$_ = $oneof_name$_;\n",
715
716 "result.$oneof_name$_ = $name$Builder_.build();\n");
717
718 printer->Outdent();
719 printer->Print("}\n");
720}
721
722void ImmutableMessageOneofFieldGenerator::
723GenerateMergingCode(io::Printer* printer) const {
724 printer->Print(variables_,
725 "merge$capitalized_name$(other.get$capitalized_name$());\n");
726}
727
728void ImmutableMessageOneofFieldGenerator::
729GenerateParsingCode(io::Printer* printer) const {
730 printer->Print(variables_,
731 "$type$.Builder subBuilder = null;\n"
732 "if ($has_oneof_case_message$) {\n"
733 " subBuilder = (($type$) $oneof_name$_).toBuilder();\n"
734 "}\n");
735
736 if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
737 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700738 "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000739 " extensionRegistry);\n");
740 } else {
741 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700742 "$oneof_name$_ =\n"
743 " input.readMessage($type$.parser(), extensionRegistry);\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000744 }
745
746 printer->Print(variables_,
747 "if (subBuilder != null) {\n"
748 " subBuilder.mergeFrom(($type$) $oneof_name$_);\n"
749 " $oneof_name$_ = subBuilder.buildPartial();\n"
750 "}\n");
751 printer->Print(variables_,
752 "$set_oneof_case_message$;\n");
753}
754
755void ImmutableMessageOneofFieldGenerator::
756GenerateSerializationCode(io::Printer* printer) const {
757 printer->Print(variables_,
758 "if ($has_oneof_case_message$) {\n"
759 " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n"
760 "}\n");
761}
762
763void ImmutableMessageOneofFieldGenerator::
764GenerateSerializedSizeCode(io::Printer* printer) const {
765 printer->Print(variables_,
766 "if ($has_oneof_case_message$) {\n"
767 " size += com.google.protobuf.CodedOutputStream\n"
768 " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n"
769 "}\n");
770}
771
772// ===================================================================
773
774RepeatedImmutableMessageFieldGenerator::
775RepeatedImmutableMessageFieldGenerator(const FieldDescriptor* descriptor,
776 int messageBitIndex,
777 int builderBitIndex,
778 Context* context)
779 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
780 builderBitIndex_(builderBitIndex), context_(context),
781 name_resolver_(context->GetNameResolver()) {
782 SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
783 context->GetFieldGeneratorInfo(descriptor),
784 name_resolver_, &variables_);
785}
786
787RepeatedImmutableMessageFieldGenerator::
788~RepeatedImmutableMessageFieldGenerator() {}
789
790int RepeatedImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000791 return 0;
792}
793
jieluo@google.com4de8f552014-07-18 00:47:59 +0000794int RepeatedImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000795 return 1;
796}
797
jieluo@google.com4de8f552014-07-18 00:47:59 +0000798void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000799GenerateInterfaceMembers(io::Printer* printer) const {
800 // TODO(jonp): In the future, consider having methods specific to the
801 // interface so that builders can choose dynamically to either return a
802 // message or a nested builder, so that asking for the interface doesn't
803 // cause a message to ever be built.
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000804 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000805 printer->Print(variables_,
806 "$deprecation$java.util.List<$type$> \n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000807 " get$capitalized_name$List();\n");
808 WriteFieldDocComment(printer, descriptor_);
809 printer->Print(variables_,
810 "$deprecation$$type$ get$capitalized_name$(int index);\n");
811 WriteFieldDocComment(printer, descriptor_);
812 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000813 "$deprecation$int get$capitalized_name$Count();\n");
Bo Yang5db21732015-05-21 14:28:59 -0700814
815 WriteFieldDocComment(printer, descriptor_);
816 printer->Print(variables_,
817 "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
818 " get$capitalized_name$OrBuilderList();\n");
819 WriteFieldDocComment(printer, descriptor_);
820 printer->Print(variables_,
821 "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
822 " int index);\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000823}
824
jieluo@google.com4de8f552014-07-18 00:47:59 +0000825void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000826GenerateMembers(io::Printer* printer) const {
827 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000828 "private java.util.List<$type$> $name$_;\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000829 PrintExtraFieldInfo(variables_, printer);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000830 WriteFieldDocComment(printer, descriptor_);
831 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000832 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
temporal40ee5512008-07-10 02:12:20 +0000833 " return $name$_;\n" // note: unmodifiable list
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000834 "}\n");
835 WriteFieldDocComment(printer, descriptor_);
836 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000837 "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
838 " get$capitalized_name$OrBuilderList() {\n"
839 " return $name$_;\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000840 "}\n");
841 WriteFieldDocComment(printer, descriptor_);
842 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000843 "$deprecation$public int get$capitalized_name$Count() {\n"
844 " return $name$_.size();\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000845 "}\n");
846 WriteFieldDocComment(printer, descriptor_);
847 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000848 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
849 " return $name$_.get(index);\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000850 "}\n");
851 WriteFieldDocComment(printer, descriptor_);
852 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000853 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
854 " int index) {\n"
temporal40ee5512008-07-10 02:12:20 +0000855 " return $name$_.get(index);\n"
856 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000857
858}
859
jieluo@google.com4de8f552014-07-18 00:47:59 +0000860void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000861 io::Printer* printer,
862 const char* regular_case,
863 const char* nested_builder_case) const {
Bo Yang5db21732015-05-21 14:28:59 -0700864 printer->Print(variables_, "if ($name$Builder_ == null) {\n");
865 printer->Indent();
866 printer->Print(variables_, regular_case);
867 printer->Outdent();
868 printer->Print("} else {\n");
869 printer->Indent();
870 printer->Print(variables_, nested_builder_case);
871 printer->Outdent();
872 printer->Print("}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000873}
874
jieluo@google.com4de8f552014-07-18 00:47:59 +0000875void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000876 io::Printer* printer,
877 const char* method_prototype,
878 const char* regular_case,
879 const char* nested_builder_case,
880 const char* trailing_code) const {
881 printer->Print(variables_, method_prototype);
882 printer->Print(" {\n");
883 printer->Indent();
884 PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
885 if (trailing_code != NULL) {
886 printer->Print(variables_, trailing_code);
887 }
888 printer->Outdent();
889 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000890}
891
jieluo@google.com4de8f552014-07-18 00:47:59 +0000892void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000893GenerateBuilderMembers(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000894 // When using nested-builders, the code initially works just like the
895 // non-nested builder case. It only creates a nested builder lazily on
896 // demand and then forever delegates to it after creation.
897
temporal40ee5512008-07-10 02:12:20 +0000898 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000899 // Used when the builder is null.
900 // One field is the list and the other field keeps track of whether the
901 // list is immutable. If it's immutable, the invariant is that it must
902 // either an instance of Collections.emptyList() or it's an ArrayList
903 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
904 // a refererence to the underlying ArrayList. This invariant allows us to
905 // share instances of lists between protocol buffers avoiding expensive
906 // memory allocations. Note, immutable is a strong guarantee here -- not
907 // just that the list cannot be modified via the reference but that the
908 // list can never be modified.
909 "private java.util.List<$type$> $name$_ =\n"
910 " java.util.Collections.emptyList();\n"
911
912 "private void ensure$capitalized_name$IsMutable() {\n"
913 " if (!$get_mutable_bit_builder$) {\n"
914 " $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
915 " $set_mutable_bit_builder$;\n"
916 " }\n"
temporal40ee5512008-07-10 02:12:20 +0000917 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000918 "\n");
919
Bo Yang5db21732015-05-21 14:28:59 -0700920 printer->Print(variables_,
921 // If this builder is non-null, it is used and the other fields are
922 // ignored.
923 "private com.google.protobuf.RepeatedFieldBuilder<\n"
924 " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
925 "\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000926
927 // The comments above the methods below are based on a hypothetical
928 // repeated field of type "Field" called "RepeatedField".
929
930 // List<Field> getRepeatedFieldList()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000931 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000932 PrintNestedBuilderFunction(printer,
933 "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
934
935 "return java.util.Collections.unmodifiableList($name$_);\n",
936 "return $name$Builder_.getMessageList();\n",
937
938 NULL);
939
940 // int getRepeatedFieldCount()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000941 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000942 PrintNestedBuilderFunction(printer,
943 "$deprecation$public int get$capitalized_name$Count()",
944
945 "return $name$_.size();\n",
946 "return $name$Builder_.getCount();\n",
947
948 NULL);
949
950 // Field getRepeatedField(int index)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000951 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000952 PrintNestedBuilderFunction(printer,
953 "$deprecation$public $type$ get$capitalized_name$(int index)",
954
955 "return $name$_.get(index);\n",
956
957 "return $name$Builder_.getMessage(index);\n",
958
959 NULL);
960
961 // Builder setRepeatedField(int index, Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000962 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000963 PrintNestedBuilderFunction(printer,
964 "$deprecation$public Builder set$capitalized_name$(\n"
965 " int index, $type$ value)",
966 "if (value == null) {\n"
967 " throw new NullPointerException();\n"
temporal40ee5512008-07-10 02:12:20 +0000968 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000969 "ensure$capitalized_name$IsMutable();\n"
970 "$name$_.set(index, value);\n"
971 "$on_changed$\n",
972 "$name$Builder_.setMessage(index, value);\n",
973 "return this;\n");
974
975 // Builder setRepeatedField(int index, Field.Builder builderForValue)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000976 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000977 PrintNestedBuilderFunction(printer,
978 "$deprecation$public Builder set$capitalized_name$(\n"
979 " int index, $type$.Builder builderForValue)",
980
981 "ensure$capitalized_name$IsMutable();\n"
982 "$name$_.set(index, builderForValue.build());\n"
983 "$on_changed$\n",
984
985 "$name$Builder_.setMessage(index, builderForValue.build());\n",
986
987 "return this;\n");
988
989 // Builder addRepeatedField(Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000990 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000991 PrintNestedBuilderFunction(printer,
992 "$deprecation$public Builder add$capitalized_name$($type$ value)",
993
994 "if (value == null) {\n"
995 " throw new NullPointerException();\n"
temporal40ee5512008-07-10 02:12:20 +0000996 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000997 "ensure$capitalized_name$IsMutable();\n"
998 "$name$_.add(value);\n"
999
1000 "$on_changed$\n",
1001
1002 "$name$Builder_.addMessage(value);\n",
1003
1004 "return this;\n");
1005
1006 // Builder addRepeatedField(int index, Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001007 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001008 PrintNestedBuilderFunction(printer,
1009 "$deprecation$public Builder add$capitalized_name$(\n"
1010 " int index, $type$ value)",
1011
1012 "if (value == null) {\n"
1013 " throw new NullPointerException();\n"
temporal40ee5512008-07-10 02:12:20 +00001014 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001015 "ensure$capitalized_name$IsMutable();\n"
1016 "$name$_.add(index, value);\n"
1017 "$on_changed$\n",
1018
1019 "$name$Builder_.addMessage(index, value);\n",
1020
1021 "return this;\n");
1022
1023 // Builder addRepeatedField(Field.Builder builderForValue)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001024 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001025 PrintNestedBuilderFunction(printer,
1026 "$deprecation$public Builder add$capitalized_name$(\n"
1027 " $type$.Builder builderForValue)",
1028
1029 "ensure$capitalized_name$IsMutable();\n"
1030 "$name$_.add(builderForValue.build());\n"
1031 "$on_changed$\n",
1032
1033 "$name$Builder_.addMessage(builderForValue.build());\n",
1034
1035 "return this;\n");
1036
1037 // Builder addRepeatedField(int index, Field.Builder builderForValue)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001038 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001039 PrintNestedBuilderFunction(printer,
1040 "$deprecation$public Builder add$capitalized_name$(\n"
1041 " int index, $type$.Builder builderForValue)",
1042
1043 "ensure$capitalized_name$IsMutable();\n"
1044 "$name$_.add(index, builderForValue.build());\n"
1045 "$on_changed$\n",
1046
1047 "$name$Builder_.addMessage(index, builderForValue.build());\n",
1048
1049 "return this;\n");
1050
1051 // Builder addAllRepeatedField(Iterable<Field> values)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001052 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001053 PrintNestedBuilderFunction(printer,
1054 "$deprecation$public Builder addAll$capitalized_name$(\n"
1055 " java.lang.Iterable<? extends $type$> values)",
1056
1057 "ensure$capitalized_name$IsMutable();\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00001058 "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
1059 " values, $name$_);\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001060 "$on_changed$\n",
1061
1062 "$name$Builder_.addAllMessages(values);\n",
1063
1064 "return this;\n");
1065
1066 // Builder clearAllRepeatedField()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001067 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001068 PrintNestedBuilderFunction(printer,
1069 "$deprecation$public Builder clear$capitalized_name$()",
1070
1071 "$name$_ = java.util.Collections.emptyList();\n"
1072 "$clear_mutable_bit_builder$;\n"
1073 "$on_changed$\n",
1074
1075 "$name$Builder_.clear();\n",
1076
1077 "return this;\n");
1078
1079 // Builder removeRepeatedField(int index)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001080 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001081 PrintNestedBuilderFunction(printer,
1082 "$deprecation$public Builder remove$capitalized_name$(int index)",
1083
1084 "ensure$capitalized_name$IsMutable();\n"
1085 "$name$_.remove(index);\n"
1086 "$on_changed$\n",
1087
1088 "$name$Builder_.remove(index);\n",
1089
1090 "return this;\n");
1091
Bo Yang5db21732015-05-21 14:28:59 -07001092 WriteFieldDocComment(printer, descriptor_);
1093 printer->Print(variables_,
1094 "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
1095 " int index) {\n"
1096 " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
1097 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001098
Bo Yang5db21732015-05-21 14:28:59 -07001099 WriteFieldDocComment(printer, descriptor_);
1100 printer->Print(variables_,
1101 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
1102 " int index) {\n"
1103 " if ($name$Builder_ == null) {\n"
1104 " return $name$_.get(index);"
1105 " } else {\n"
1106 " return $name$Builder_.getMessageOrBuilder(index);\n"
1107 " }\n"
1108 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001109
Bo Yang5db21732015-05-21 14:28:59 -07001110 WriteFieldDocComment(printer, descriptor_);
1111 printer->Print(variables_,
1112 "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
1113 " get$capitalized_name$OrBuilderList() {\n"
1114 " if ($name$Builder_ != null) {\n"
1115 " return $name$Builder_.getMessageOrBuilderList();\n"
1116 " } else {\n"
1117 " return java.util.Collections.unmodifiableList($name$_);\n"
1118 " }\n"
1119 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001120
Bo Yang5db21732015-05-21 14:28:59 -07001121 WriteFieldDocComment(printer, descriptor_);
1122 printer->Print(variables_,
1123 "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
1124 " return get$capitalized_name$FieldBuilder().addBuilder(\n"
1125 " $type$.getDefaultInstance());\n"
1126 "}\n");
1127 WriteFieldDocComment(printer, descriptor_);
1128 printer->Print(variables_,
1129 "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
1130 " int index) {\n"
1131 " return get$capitalized_name$FieldBuilder().addBuilder(\n"
1132 " index, $type$.getDefaultInstance());\n"
1133 "}\n");
1134 WriteFieldDocComment(printer, descriptor_);
1135 printer->Print(variables_,
1136 "$deprecation$public java.util.List<$type$.Builder> \n"
1137 " get$capitalized_name$BuilderList() {\n"
1138 " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
1139 "}\n"
1140 "private com.google.protobuf.RepeatedFieldBuilder<\n"
1141 " $type$, $type$.Builder, $type$OrBuilder> \n"
1142 " get$capitalized_name$FieldBuilder() {\n"
1143 " if ($name$Builder_ == null) {\n"
1144 " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
1145 " $type$, $type$.Builder, $type$OrBuilder>(\n"
1146 " $name$_,\n"
1147 " $get_mutable_bit_builder$,\n"
1148 " getParentForChildren(),\n"
1149 " isClean());\n"
1150 " $name$_ = null;\n"
1151 " }\n"
1152 " return $name$Builder_;\n"
1153 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001154}
1155
jieluo@google.com4de8f552014-07-18 00:47:59 +00001156void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +00001157GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
1158 printer->Print(variables_,
1159 "get$capitalized_name$FieldBuilder();\n");
temporal40ee5512008-07-10 02:12:20 +00001160}
1161
jieluo@google.com4de8f552014-07-18 00:47:59 +00001162void RepeatedImmutableMessageFieldGenerator::
kenton@google.comfccb1462009-12-18 02:11:36 +00001163GenerateInitializationCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001164 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
1165}
1166
jieluo@google.com4de8f552014-07-18 00:47:59 +00001167void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +00001168GenerateBuilderClearCode(io::Printer* printer) const {
1169 PrintNestedBuilderCondition(printer,
1170 "$name$_ = java.util.Collections.emptyList();\n"
1171 "$clear_mutable_bit_builder$;\n",
1172
1173 "$name$Builder_.clear();\n");
kenton@google.comfccb1462009-12-18 02:11:36 +00001174}
1175
jieluo@google.com4de8f552014-07-18 00:47:59 +00001176void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001177GenerateMergingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001178 // The code below does two optimizations (non-nested builder case):
1179 // 1. If the other list is empty, there's nothing to do. This ensures we
1180 // don't allocate a new array if we already have an immutable one.
1181 // 2. If the other list is non-empty and our current list is empty, we can
1182 // reuse the other list which is guaranteed to be immutable.
1183 PrintNestedBuilderCondition(printer,
temporal40ee5512008-07-10 02:12:20 +00001184 "if (!other.$name$_.isEmpty()) {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001185 " if ($name$_.isEmpty()) {\n"
1186 " $name$_ = other.$name$_;\n"
1187 " $clear_mutable_bit_builder$;\n"
1188 " } else {\n"
1189 " ensure$capitalized_name$IsMutable();\n"
1190 " $name$_.addAll(other.$name$_);\n"
temporal40ee5512008-07-10 02:12:20 +00001191 " }\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001192 " $on_changed$\n"
1193 "}\n",
1194
1195 "if (!other.$name$_.isEmpty()) {\n"
1196 " if ($name$Builder_.isEmpty()) {\n"
1197 " $name$Builder_.dispose();\n"
1198 " $name$Builder_ = null;\n"
1199 " $name$_ = other.$name$_;\n"
1200 " $clear_mutable_bit_builder$;\n"
1201 " $name$Builder_ = \n"
1202 " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
1203 " get$capitalized_name$FieldBuilder() : null;\n"
1204 " } else {\n"
1205 " $name$Builder_.addAllMessages(other.$name$_);\n"
1206 " }\n"
temporal40ee5512008-07-10 02:12:20 +00001207 "}\n");
1208}
1209
jieluo@google.com4de8f552014-07-18 00:47:59 +00001210void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001211GenerateBuildingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001212 // The code below (non-nested builder case) ensures that the result has an
1213 // immutable list. If our list is immutable, we can just reuse it. If not,
1214 // we make it immutable.
1215 PrintNestedBuilderCondition(printer,
1216 "if ($get_mutable_bit_builder$) {\n"
1217 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
1218 " $clear_mutable_bit_builder$;\n"
1219 "}\n"
1220 "result.$name$_ = $name$_;\n",
1221
1222 "result.$name$_ = $name$Builder_.build();\n");
temporal40ee5512008-07-10 02:12:20 +00001223}
1224
jieluo@google.com4de8f552014-07-18 00:47:59 +00001225void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001226GenerateParsingCode(io::Printer* printer) const {
1227 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001228 "if (!$get_mutable_bit_parser$) {\n"
1229 " $name$_ = new java.util.ArrayList<$type$>();\n"
1230 " $set_mutable_bit_parser$;\n"
1231 "}\n");
temporal40ee5512008-07-10 02:12:20 +00001232
kenton@google.comfccb1462009-12-18 02:11:36 +00001233 if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
temporal40ee5512008-07-10 02:12:20 +00001234 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001235 "$name$_.add(input.readGroup($number$, $type$.parser(),\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001236 " extensionRegistry));\n");
temporal40ee5512008-07-10 02:12:20 +00001237 } else {
1238 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001239 "$name$_.add(input.readMessage($type$.parser(), extensionRegistry));\n");
temporal40ee5512008-07-10 02:12:20 +00001240 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001241}
temporal40ee5512008-07-10 02:12:20 +00001242
jieluo@google.com4de8f552014-07-18 00:47:59 +00001243void RepeatedImmutableMessageFieldGenerator::
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001244GenerateParsingDoneCode(io::Printer* printer) const {
temporal40ee5512008-07-10 02:12:20 +00001245 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001246 "if ($get_mutable_bit_parser$) {\n"
1247 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
1248 "}\n");
temporal40ee5512008-07-10 02:12:20 +00001249}
1250
jieluo@google.com4de8f552014-07-18 00:47:59 +00001251void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001252GenerateSerializationCode(io::Printer* printer) const {
1253 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +00001254 "for (int i = 0; i < $name$_.size(); i++) {\n"
1255 " output.write$group_or_message$($number$, $name$_.get(i));\n"
temporal40ee5512008-07-10 02:12:20 +00001256 "}\n");
1257}
1258
jieluo@google.com4de8f552014-07-18 00:47:59 +00001259void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001260GenerateSerializedSizeCode(io::Printer* printer) const {
1261 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +00001262 "for (int i = 0; i < $name$_.size(); i++) {\n"
temporal40ee5512008-07-10 02:12:20 +00001263 " size += com.google.protobuf.CodedOutputStream\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001264 " .compute$group_or_message$Size($number$, $name$_.get(i));\n"
1265 "}\n");
1266}
1267
jieluo@google.com4de8f552014-07-18 00:47:59 +00001268void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +00001269GenerateEqualsCode(io::Printer* printer) const {
1270 printer->Print(variables_,
1271 "result = result && get$capitalized_name$List()\n"
1272 " .equals(other.get$capitalized_name$List());\n");
1273}
1274
jieluo@google.com4de8f552014-07-18 00:47:59 +00001275void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +00001276GenerateHashCode(io::Printer* printer) const {
1277 printer->Print(variables_,
1278 "if (get$capitalized_name$Count() > 0) {\n"
1279 " hash = (37 * hash) + $constant_name$;\n"
1280 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
temporal40ee5512008-07-10 02:12:20 +00001281 "}\n");
1282}
1283
jieluo@google.com4de8f552014-07-18 00:47:59 +00001284string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const {
1285 return name_resolver_->GetImmutableClassName(descriptor_->message_type());
temporal40ee5512008-07-10 02:12:20 +00001286}
1287
1288} // namespace java
1289} // namespace compiler
1290} // namespace protobuf
1291} // namespace google