blob: b5f8e626fdd54073f0575baabc0a7470832c8f5f [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 " : "";
73 (*variables)["on_changed"] =
74 HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
75
jieluo@google.com4de8f552014-07-18 00:47:59 +000076 if (SupportFieldPresence(descriptor->file())) {
77 // For singular messages and builders, one bit is used for the hasField bit.
78 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
79 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
liujisi@google.com33165fe2010-11-02 13:14:58 +000080
jieluo@google.com4de8f552014-07-18 00:47:59 +000081 // Note that these have a trailing ";".
82 (*variables)["set_has_field_bit_message"] =
83 GenerateSetBit(messageBitIndex) + ";";
84 (*variables)["set_has_field_bit_builder"] =
85 GenerateSetBit(builderBitIndex) + ";";
86 (*variables)["clear_has_field_bit_builder"] =
87 GenerateClearBit(builderBitIndex) + ";";
88
89 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
90 } else {
91 (*variables)["set_has_field_bit_message"] = "";
92 (*variables)["set_has_field_bit_builder"] = "";
93 (*variables)["clear_has_field_bit_builder"] = "";
94
95 (*variables)["is_field_present_message"] =
96 (*variables)["name"] + "_ != null";
97 }
liujisi@google.com33165fe2010-11-02 13:14:58 +000098
99 // For repated builders, one bit is used for whether the array is immutable.
100 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
101 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
102 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
103
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000104 // For repeated fields, one bit is used for whether the array is immutable
105 // in the parsing constructor.
106 (*variables)["get_mutable_bit_parser"] =
107 GenerateGetBitMutableLocal(builderBitIndex);
108 (*variables)["set_mutable_bit_parser"] =
109 GenerateSetBitMutableLocal(builderBitIndex);
110
liujisi@google.com33165fe2010-11-02 13:14:58 +0000111 (*variables)["get_has_field_bit_from_local"] =
112 GenerateGetBitFromLocal(builderBitIndex);
113 (*variables)["set_has_field_bit_to_local"] =
114 GenerateSetBitToLocal(messageBitIndex);
temporal40ee5512008-07-10 02:12:20 +0000115}
116
117} // namespace
118
119// ===================================================================
120
jieluo@google.com4de8f552014-07-18 00:47:59 +0000121ImmutableMessageFieldGenerator::
122ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000123 int messageBitIndex,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000124 int builderBitIndex,
125 Context* context)
liujisi@google.com33165fe2010-11-02 13:14:58 +0000126 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
jieluo@google.com4de8f552014-07-18 00:47:59 +0000127 builderBitIndex_(builderBitIndex), context_(context),
128 name_resolver_(context->GetNameResolver()) {
129 SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
130 context->GetFieldGeneratorInfo(descriptor),
131 name_resolver_, &variables_);
temporal40ee5512008-07-10 02:12:20 +0000132}
133
jieluo@google.com4de8f552014-07-18 00:47:59 +0000134ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {}
temporal40ee5512008-07-10 02:12:20 +0000135
jieluo@google.com4de8f552014-07-18 00:47:59 +0000136int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000137 return 1;
138}
139
jieluo@google.com4de8f552014-07-18 00:47:59 +0000140int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000141 return 1;
142}
143
jieluo@google.com4de8f552014-07-18 00:47:59 +0000144void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000145GenerateInterfaceMembers(io::Printer* printer) const {
146 // TODO(jonp): In the future, consider having a method specific to the
147 // interface so that builders can choose dynamically to either return a
148 // message or a nested builder, so that asking for the interface doesn't
149 // cause a message to ever be built.
jieluo@google.com4de8f552014-07-18 00:47:59 +0000150 if (SupportFieldPresence(descriptor_->file()) ||
151 descriptor_->containing_oneof() == NULL) {
152 WriteFieldDocComment(printer, descriptor_);
153 printer->Print(variables_,
154 "$deprecation$boolean has$capitalized_name$();\n");
155 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000156 WriteFieldDocComment(printer, descriptor_);
157 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000158 "$deprecation$$type$ get$capitalized_name$();\n");
159
Bo Yang5db21732015-05-21 14:28:59 -0700160 WriteFieldDocComment(printer, descriptor_);
161 printer->Print(variables_,
162 "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000163}
164
jieluo@google.com4de8f552014-07-18 00:47:59 +0000165void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000166GenerateMembers(io::Printer* printer) const {
167 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000168 "private $type$ $name$_;\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000169 PrintExtraFieldInfo(variables_, printer);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000170
jieluo@google.com4de8f552014-07-18 00:47:59 +0000171 if (SupportFieldPresence(descriptor_->file())) {
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000172 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000173 printer->Print(variables_,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000174 "$deprecation$public boolean has$capitalized_name$() {\n"
175 " return $get_has_field_bit_message$;\n"
176 "}\n");
177 WriteFieldDocComment(printer, descriptor_);
178 printer->Print(variables_,
179 "$deprecation$public $type$ get$capitalized_name$() {\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800180 " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000181 "}\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000182
Bo Yang5db21732015-05-21 14:28:59 -0700183 WriteFieldDocComment(printer, descriptor_);
184 printer->Print(variables_,
185 "$deprecation$public $type$OrBuilder "
186 "get$capitalized_name$OrBuilder() {\n"
187 " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
188 "}\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000189 } else {
190 WriteFieldDocComment(printer, descriptor_);
191 printer->Print(variables_,
192 "$deprecation$public boolean has$capitalized_name$() {\n"
193 " return $name$_ != null;\n"
194 "}\n");
195 WriteFieldDocComment(printer, descriptor_);
196 printer->Print(variables_,
197 "$deprecation$public $type$ get$capitalized_name$() {\n"
198 " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
199 "}\n");
200
Bo Yang5db21732015-05-21 14:28:59 -0700201 WriteFieldDocComment(printer, descriptor_);
202 printer->Print(variables_,
203 "$deprecation$public $type$OrBuilder "
204 "get$capitalized_name$OrBuilder() {\n"
205 " return get$capitalized_name$();\n"
206 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000207 }
208}
209
jieluo@google.com4de8f552014-07-18 00:47:59 +0000210void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000211 io::Printer* printer,
212 const char* regular_case,
213 const char* nested_builder_case) const {
Bo Yang5db21732015-05-21 14:28:59 -0700214 printer->Print(variables_, "if ($name$Builder_ == null) {\n");
215 printer->Indent();
216 printer->Print(variables_, regular_case);
217 printer->Outdent();
218 printer->Print("} else {\n");
219 printer->Indent();
220 printer->Print(variables_, nested_builder_case);
221 printer->Outdent();
222 printer->Print("}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000223}
224
jieluo@google.com4de8f552014-07-18 00:47:59 +0000225void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000226 io::Printer* printer,
227 const char* method_prototype,
228 const char* regular_case,
229 const char* nested_builder_case,
230 const char* trailing_code) const {
231 printer->Print(variables_, method_prototype);
232 printer->Print(" {\n");
233 printer->Indent();
234 PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
235 if (trailing_code != NULL) {
236 printer->Print(variables_, trailing_code);
237 }
238 printer->Outdent();
239 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000240}
241
jieluo@google.com4de8f552014-07-18 00:47:59 +0000242void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000243GenerateBuilderMembers(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000244 // When using nested-builders, the code initially works just like the
245 // non-nested builder case. It only creates a nested builder lazily on
246 // demand and then forever delegates to it after creation.
247
jieluo@google.com4de8f552014-07-18 00:47:59 +0000248 bool support_field_presence = SupportFieldPresence(descriptor_->file());
249
Feng Xiao6ef984a2014-11-10 17:34:54 -0800250 printer->Print(variables_,
251 "private $type$ $name$_ = null;\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000252
Bo Yang5db21732015-05-21 14:28:59 -0700253 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000254 // If this builder is non-null, it is used and the other fields are
255 // ignored.
256 "private com.google.protobuf.SingleFieldBuilder<\n"
257 " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
258 "\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000259
260 // The comments above the methods below are based on a hypothetical
261 // field of type "Field" called "Field".
262
263 // boolean hasField()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000264 WriteFieldDocComment(printer, descriptor_);
jieluo@google.com4de8f552014-07-18 00:47:59 +0000265 if (support_field_presence) {
266 printer->Print(variables_,
267 "$deprecation$public boolean has$capitalized_name$() {\n"
268 " return $get_has_field_bit_builder$;\n"
269 "}\n");
270 } else {
271 printer->Print(variables_,
272 "$deprecation$public boolean has$capitalized_name$() {\n"
273 " return $name$Builder_ != null || $name$_ != null;\n"
274 "}\n");
275 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000276
277 // Field getField()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000278 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000279 PrintNestedBuilderFunction(printer,
280 "$deprecation$public $type$ get$capitalized_name$()",
Feng Xiao6ef984a2014-11-10 17:34:54 -0800281 "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000282 "return $name$Builder_.getMessage();\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000283 NULL);
284
285 // Field.Builder setField(Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000286 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000287 PrintNestedBuilderFunction(printer,
288 "$deprecation$public Builder set$capitalized_name$($type$ value)",
289
290 "if (value == null) {\n"
291 " throw new NullPointerException();\n"
292 "}\n"
293 "$name$_ = value;\n"
294 "$on_changed$\n",
295
296 "$name$Builder_.setMessage(value);\n",
297
jieluo@google.com4de8f552014-07-18 00:47:59 +0000298 "$set_has_field_bit_builder$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000299 "return this;\n");
300
301 // Field.Builder setField(Field.Builder builderForValue)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000302 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000303 PrintNestedBuilderFunction(printer,
304 "$deprecation$public Builder set$capitalized_name$(\n"
305 " $type$.Builder builderForValue)",
306
307 "$name$_ = builderForValue.build();\n"
308 "$on_changed$\n",
309
310 "$name$Builder_.setMessage(builderForValue.build());\n",
311
jieluo@google.com4de8f552014-07-18 00:47:59 +0000312 "$set_has_field_bit_builder$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000313 "return this;\n");
314
315 // Field.Builder mergeField(Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000316 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000317 PrintNestedBuilderFunction(printer,
318 "$deprecation$public Builder merge$capitalized_name$($type$ value)",
319
jieluo@google.com4de8f552014-07-18 00:47:59 +0000320 support_field_presence
321 ? "if ($get_has_field_bit_builder$ &&\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800322 " $name$_ != null &&\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000323 " $name$_ != $type$.getDefaultInstance()) {\n"
324 " $name$_ =\n"
325 " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
326 "} else {\n"
327 " $name$_ = value;\n"
328 "}\n"
329 "$on_changed$\n"
330 : "if ($name$_ != null) {\n"
331 " $name$_ =\n"
332 " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
333 "} else {\n"
334 " $name$_ = value;\n"
335 "}\n"
336 "$on_changed$\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000337
338 "$name$Builder_.mergeFrom(value);\n",
339
jieluo@google.com4de8f552014-07-18 00:47:59 +0000340 "$set_has_field_bit_builder$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000341 "return this;\n");
342
343 // Field.Builder clearField()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000344 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000345 PrintNestedBuilderFunction(printer,
346 "$deprecation$public Builder clear$capitalized_name$()",
347
Feng Xiao6ef984a2014-11-10 17:34:54 -0800348 "$name$_ = null;\n"
349 "$on_changed$\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000350
jieluo@google.com4de8f552014-07-18 00:47:59 +0000351 support_field_presence
352 ? "$name$Builder_.clear();\n"
353 : "$name$_ = null;\n"
354 "$name$Builder_ = null;\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000355
jieluo@google.com4de8f552014-07-18 00:47:59 +0000356 "$clear_has_field_bit_builder$\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000357 "return this;\n");
358
Bo Yang5db21732015-05-21 14:28:59 -0700359 WriteFieldDocComment(printer, descriptor_);
360 printer->Print(variables_,
361 "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
362 " $set_has_field_bit_builder$\n"
363 " $on_changed$\n"
364 " return get$capitalized_name$FieldBuilder().getBuilder();\n"
365 "}\n");
366 WriteFieldDocComment(printer, descriptor_);
367 printer->Print(variables_,
368 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
369 " if ($name$Builder_ != null) {\n"
370 " return $name$Builder_.getMessageOrBuilder();\n"
371 " } else {\n"
372 " return $name$_ == null ?\n"
373 " $type$.getDefaultInstance() : $name$_;\n"
374 " }\n"
375 "}\n");
376 WriteFieldDocComment(printer, descriptor_);
377 printer->Print(variables_,
378 "private com.google.protobuf.SingleFieldBuilder<\n"
379 " $type$, $type$.Builder, $type$OrBuilder> \n"
380 " get$capitalized_name$FieldBuilder() {\n"
381 " if ($name$Builder_ == null) {\n"
382 " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
383 " $type$, $type$.Builder, $type$OrBuilder>(\n"
384 " get$capitalized_name$(),\n"
385 " getParentForChildren(),\n"
386 " isClean());\n"
387 " $name$_ = null;\n"
388 " }\n"
389 " return $name$Builder_;\n"
390 "}\n");
temporal40ee5512008-07-10 02:12:20 +0000391}
392
jieluo@google.com4de8f552014-07-18 00:47:59 +0000393void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000394GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000395 if (SupportFieldPresence(descriptor_->file())) {
396 printer->Print(variables_,
397 "get$capitalized_name$FieldBuilder();\n");
398 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000399}
400
401
jieluo@google.com4de8f552014-07-18 00:47:59 +0000402void ImmutableMessageFieldGenerator::
Feng Xiao6ef984a2014-11-10 17:34:54 -0800403GenerateInitializationCode(io::Printer* printer) const {}
kenton@google.comfccb1462009-12-18 02:11:36 +0000404
jieluo@google.com4de8f552014-07-18 00:47:59 +0000405void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000406GenerateBuilderClearCode(io::Printer* printer) const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000407 if (SupportFieldPresence(descriptor_->file())) {
408 PrintNestedBuilderCondition(printer,
Feng Xiao6ef984a2014-11-10 17:34:54 -0800409 "$name$_ = null;\n",
liujisi@google.com33165fe2010-11-02 13:14:58 +0000410
jieluo@google.com4de8f552014-07-18 00:47:59 +0000411 "$name$Builder_.clear();\n");
412 printer->Print(variables_, "$clear_has_field_bit_builder$\n");
413 } else {
414 PrintNestedBuilderCondition(printer,
415 "$name$_ = null;\n",
416
417 "$name$_ = null;\n"
418 "$name$Builder_ = null;\n");
419 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000420}
421
jieluo@google.com4de8f552014-07-18 00:47:59 +0000422void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000423GenerateMergingCode(io::Printer* printer) const {
424 printer->Print(variables_,
425 "if (other.has$capitalized_name$()) {\n"
426 " merge$capitalized_name$(other.get$capitalized_name$());\n"
427 "}\n");
428}
429
jieluo@google.com4de8f552014-07-18 00:47:59 +0000430void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000431GenerateBuildingCode(io::Printer* printer) const {
jieluo@google.com4de8f552014-07-18 00:47:59 +0000432 if (SupportFieldPresence(descriptor_->file())) {
433 printer->Print(variables_,
434 "if ($get_has_field_bit_from_local$) {\n"
435 " $set_has_field_bit_to_local$;\n"
436 "}\n");
437 }
liujisi@google.com33165fe2010-11-02 13:14:58 +0000438
439 PrintNestedBuilderCondition(printer,
440 "result.$name$_ = $name$_;\n",
441
442 "result.$name$_ = $name$Builder_.build();\n");
temporal40ee5512008-07-10 02:12:20 +0000443}
444
jieluo@google.com4de8f552014-07-18 00:47:59 +0000445void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000446GenerateParsingCode(io::Printer* printer) const {
447 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000448 "$type$.Builder subBuilder = null;\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000449 "if ($is_field_present_message$) {\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000450 " subBuilder = $name$_.toBuilder();\n"
temporal40ee5512008-07-10 02:12:20 +0000451 "}\n");
452
kenton@google.comfccb1462009-12-18 02:11:36 +0000453 if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
temporal40ee5512008-07-10 02:12:20 +0000454 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700455 "$name$_ = input.readGroup($number$, $type$.parser(),\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000456 " extensionRegistry);\n");
temporal40ee5512008-07-10 02:12:20 +0000457 } else {
458 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700459 "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n");
temporal40ee5512008-07-10 02:12:20 +0000460 }
461
462 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000463 "if (subBuilder != null) {\n"
464 " subBuilder.mergeFrom($name$_);\n"
465 " $name$_ = subBuilder.buildPartial();\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000466 "}\n"
467 "$set_has_field_bit_message$\n");
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000468}
469
jieluo@google.com4de8f552014-07-18 00:47:59 +0000470void ImmutableMessageFieldGenerator::
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000471GenerateParsingDoneCode(io::Printer* printer) const {
472 // noop for messages.
temporal40ee5512008-07-10 02:12:20 +0000473}
474
jieluo@google.com4de8f552014-07-18 00:47:59 +0000475void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000476GenerateSerializationCode(io::Printer* printer) const {
477 printer->Print(variables_,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000478 "if ($is_field_present_message$) {\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800479 " output.write$group_or_message$($number$, get$capitalized_name$());\n"
temporal40ee5512008-07-10 02:12:20 +0000480 "}\n");
481}
482
jieluo@google.com4de8f552014-07-18 00:47:59 +0000483void ImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000484GenerateSerializedSizeCode(io::Printer* printer) const {
485 printer->Print(variables_,
jieluo@google.com4de8f552014-07-18 00:47:59 +0000486 "if ($is_field_present_message$) {\n"
temporal40ee5512008-07-10 02:12:20 +0000487 " size += com.google.protobuf.CodedOutputStream\n"
Feng Xiao6ef984a2014-11-10 17:34:54 -0800488 " .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
temporal40ee5512008-07-10 02:12:20 +0000489 "}\n");
490}
491
jieluo@google.com4de8f552014-07-18 00:47:59 +0000492void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000493GenerateEqualsCode(io::Printer* printer) const {
494 printer->Print(variables_,
495 "result = result && get$capitalized_name$()\n"
496 " .equals(other.get$capitalized_name$());\n");
497}
498
jieluo@google.com4de8f552014-07-18 00:47:59 +0000499void ImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000500GenerateHashCode(io::Printer* printer) const {
501 printer->Print(variables_,
502 "hash = (37 * hash) + $constant_name$;\n"
503 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
504}
505
jieluo@google.com4de8f552014-07-18 00:47:59 +0000506string ImmutableMessageFieldGenerator::GetBoxedType() const {
507 return name_resolver_->GetImmutableClassName(descriptor_->message_type());
temporal40ee5512008-07-10 02:12:20 +0000508}
509
510// ===================================================================
511
jieluo@google.com4de8f552014-07-18 00:47:59 +0000512ImmutableMessageOneofFieldGenerator::
513ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor,
514 int messageBitIndex,
515 int builderBitIndex,
516 Context* context)
517 : ImmutableMessageFieldGenerator(
518 descriptor, messageBitIndex, builderBitIndex, context) {
519 const OneofGeneratorInfo* info =
520 context->GetOneofGeneratorInfo(descriptor->containing_oneof());
521 SetCommonOneofVariables(descriptor, info, &variables_);
temporal40ee5512008-07-10 02:12:20 +0000522}
523
jieluo@google.com4de8f552014-07-18 00:47:59 +0000524ImmutableMessageOneofFieldGenerator::
525~ImmutableMessageOneofFieldGenerator() {}
temporal40ee5512008-07-10 02:12:20 +0000526
jieluo@google.com4de8f552014-07-18 00:47:59 +0000527void ImmutableMessageOneofFieldGenerator::
528GenerateMembers(io::Printer* printer) const {
529 PrintExtraFieldInfo(variables_, printer);
530 if (SupportFieldPresence(descriptor_->file())) {
531 WriteFieldDocComment(printer, descriptor_);
532 printer->Print(variables_,
533 "$deprecation$public boolean has$capitalized_name$() {\n"
534 " return $has_oneof_case_message$;\n"
535 "}\n");
536 }
537 WriteFieldDocComment(printer, descriptor_);
538 printer->Print(variables_,
539 "$deprecation$public $type$ get$capitalized_name$() {\n"
540 " if ($has_oneof_case_message$) {\n"
541 " return ($type$) $oneof_name$_;\n"
542 " }\n"
543 " return $type$.getDefaultInstance();\n"
544 "}\n");
545
Bo Yang5db21732015-05-21 14:28:59 -0700546 WriteFieldDocComment(printer, descriptor_);
547 printer->Print(variables_,
548 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
549 " if ($has_oneof_case_message$) {\n"
550 " return ($type$) $oneof_name$_;\n"
551 " }\n"
552 " return $type$.getDefaultInstance();\n"
553 "}\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000554}
555
556void ImmutableMessageOneofFieldGenerator::
557GenerateBuilderMembers(io::Printer* printer) const {
558 // When using nested-builders, the code initially works just like the
559 // non-nested builder case. It only creates a nested builder lazily on
560 // demand and then forever delegates to it after creation.
Bo Yang5db21732015-05-21 14:28:59 -0700561 printer->Print(variables_,
562 // If this builder is non-null, it is used and the other fields are
563 // ignored.
564 "private com.google.protobuf.SingleFieldBuilder<\n"
565 " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
566 "\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000567
568 // The comments above the methods below are based on a hypothetical
569 // field of type "Field" called "Field".
570
571 if (SupportFieldPresence(descriptor_->file())) {
572 // boolean hasField()
573 WriteFieldDocComment(printer, descriptor_);
574 printer->Print(variables_,
575 "$deprecation$public boolean has$capitalized_name$() {\n"
576 " return $has_oneof_case_message$;\n"
577 "}\n");
578 }
579
580 // Field getField()
581 WriteFieldDocComment(printer, descriptor_);
582 PrintNestedBuilderFunction(printer,
583 "$deprecation$public $type$ get$capitalized_name$()",
584
585 "if ($has_oneof_case_message$) {\n"
586 " return ($type$) $oneof_name$_;\n"
587 "}\n"
588 "return $type$.getDefaultInstance();\n",
589
590 "if ($has_oneof_case_message$) {\n"
591 " return $name$Builder_.getMessage();\n"
592 "}\n"
593 "return $type$.getDefaultInstance();\n",
594
595 NULL);
596
597 // Field.Builder setField(Field value)
598 WriteFieldDocComment(printer, descriptor_);
599 PrintNestedBuilderFunction(printer,
600 "$deprecation$public Builder set$capitalized_name$($type$ value)",
601
602 "if (value == null) {\n"
603 " throw new NullPointerException();\n"
604 "}\n"
605 "$oneof_name$_ = value;\n"
606 "$on_changed$\n",
607
608 "$name$Builder_.setMessage(value);\n",
609
610 "$set_oneof_case_message$;\n"
611 "return this;\n");
612
613 // Field.Builder setField(Field.Builder builderForValue)
614 WriteFieldDocComment(printer, descriptor_);
615 PrintNestedBuilderFunction(printer,
616 "$deprecation$public Builder set$capitalized_name$(\n"
617 " $type$.Builder builderForValue)",
618
619 "$oneof_name$_ = builderForValue.build();\n"
620 "$on_changed$\n",
621
622 "$name$Builder_.setMessage(builderForValue.build());\n",
623
624 "$set_oneof_case_message$;\n"
625 "return this;\n");
626
627 // Field.Builder mergeField(Field value)
628 WriteFieldDocComment(printer, descriptor_);
629 PrintNestedBuilderFunction(printer,
630 "$deprecation$public Builder merge$capitalized_name$($type$ value)",
631
632 "if ($has_oneof_case_message$ &&\n"
633 " $oneof_name$_ != $type$.getDefaultInstance()) {\n"
634 " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
635 " .mergeFrom(value).buildPartial();\n"
636 "} else {\n"
637 " $oneof_name$_ = value;\n"
638 "}\n"
639 "$on_changed$\n",
640
641 "if ($has_oneof_case_message$) {\n"
642 " $name$Builder_.mergeFrom(value);\n"
643 "}\n"
644 "$name$Builder_.setMessage(value);\n",
645
646 "$set_oneof_case_message$;\n"
647 "return this;\n");
648
649 // Field.Builder clearField()
650 WriteFieldDocComment(printer, descriptor_);
651 PrintNestedBuilderFunction(printer,
652 "$deprecation$public Builder clear$capitalized_name$()",
653
654 "if ($has_oneof_case_message$) {\n"
655 " $clear_oneof_case_message$;\n"
656 " $oneof_name$_ = null;\n"
657 " $on_changed$\n"
658 "}\n",
659
660 "if ($has_oneof_case_message$) {\n"
661 " $clear_oneof_case_message$;\n"
662 " $oneof_name$_ = null;\n"
663 "}\n"
664 "$name$Builder_.clear();\n",
665
666 "return this;\n");
667
Bo Yang5db21732015-05-21 14:28:59 -0700668 WriteFieldDocComment(printer, descriptor_);
669 printer->Print(variables_,
670 "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
671 " return get$capitalized_name$FieldBuilder().getBuilder();\n"
672 "}\n");
673 WriteFieldDocComment(printer, descriptor_);
674 printer->Print(variables_,
675 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
676 " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
677 " return $name$Builder_.getMessageOrBuilder();\n"
678 " } else {\n"
679 " if ($has_oneof_case_message$) {\n"
680 " return ($type$) $oneof_name$_;\n"
681 " }\n"
682 " return $type$.getDefaultInstance();\n"
683 " }\n"
684 "}\n");
685 WriteFieldDocComment(printer, descriptor_);
686 printer->Print(variables_,
687 "private com.google.protobuf.SingleFieldBuilder<\n"
688 " $type$, $type$.Builder, $type$OrBuilder> \n"
689 " get$capitalized_name$FieldBuilder() {\n"
690 " if ($name$Builder_ == null) {\n"
691 " if (!($has_oneof_case_message$)) {\n"
692 " $oneof_name$_ = $type$.getDefaultInstance();\n"
693 " }\n"
694 " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
695 " $type$, $type$.Builder, $type$OrBuilder>(\n"
696 " ($type$) $oneof_name$_,\n"
697 " getParentForChildren(),\n"
698 " isClean());\n"
699 " $oneof_name$_ = null;\n"
700 " }\n"
701 " $set_oneof_case_message$;\n"
702 " $on_changed$;\n"
703 " return $name$Builder_;\n"
704 "}\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000705}
706
707void ImmutableMessageOneofFieldGenerator::
708GenerateBuildingCode(io::Printer* printer) const {
709
710 printer->Print(variables_,
711 "if ($has_oneof_case_message$) {\n");
712 printer->Indent();
713
714 PrintNestedBuilderCondition(printer,
715 "result.$oneof_name$_ = $oneof_name$_;\n",
716
717 "result.$oneof_name$_ = $name$Builder_.build();\n");
718
719 printer->Outdent();
720 printer->Print("}\n");
721}
722
723void ImmutableMessageOneofFieldGenerator::
724GenerateMergingCode(io::Printer* printer) const {
725 printer->Print(variables_,
726 "merge$capitalized_name$(other.get$capitalized_name$());\n");
727}
728
729void ImmutableMessageOneofFieldGenerator::
730GenerateParsingCode(io::Printer* printer) const {
731 printer->Print(variables_,
732 "$type$.Builder subBuilder = null;\n"
733 "if ($has_oneof_case_message$) {\n"
734 " subBuilder = (($type$) $oneof_name$_).toBuilder();\n"
735 "}\n");
736
737 if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
738 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700739 "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +0000740 " extensionRegistry);\n");
741 } else {
742 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -0700743 "$oneof_name$_ =\n"
744 " input.readMessage($type$.parser(), extensionRegistry);\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000745 }
746
747 printer->Print(variables_,
748 "if (subBuilder != null) {\n"
749 " subBuilder.mergeFrom(($type$) $oneof_name$_);\n"
750 " $oneof_name$_ = subBuilder.buildPartial();\n"
751 "}\n");
752 printer->Print(variables_,
753 "$set_oneof_case_message$;\n");
754}
755
756void ImmutableMessageOneofFieldGenerator::
757GenerateSerializationCode(io::Printer* printer) const {
758 printer->Print(variables_,
759 "if ($has_oneof_case_message$) {\n"
760 " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n"
761 "}\n");
762}
763
764void ImmutableMessageOneofFieldGenerator::
765GenerateSerializedSizeCode(io::Printer* printer) const {
766 printer->Print(variables_,
767 "if ($has_oneof_case_message$) {\n"
768 " size += com.google.protobuf.CodedOutputStream\n"
769 " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n"
770 "}\n");
771}
772
773// ===================================================================
774
775RepeatedImmutableMessageFieldGenerator::
776RepeatedImmutableMessageFieldGenerator(const FieldDescriptor* descriptor,
777 int messageBitIndex,
778 int builderBitIndex,
779 Context* context)
780 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
781 builderBitIndex_(builderBitIndex), context_(context),
782 name_resolver_(context->GetNameResolver()) {
783 SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
784 context->GetFieldGeneratorInfo(descriptor),
785 name_resolver_, &variables_);
786}
787
788RepeatedImmutableMessageFieldGenerator::
789~RepeatedImmutableMessageFieldGenerator() {}
790
791int RepeatedImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000792 return 0;
793}
794
jieluo@google.com4de8f552014-07-18 00:47:59 +0000795int RepeatedImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000796 return 1;
797}
798
jieluo@google.com4de8f552014-07-18 00:47:59 +0000799void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000800GenerateInterfaceMembers(io::Printer* printer) const {
801 // TODO(jonp): In the future, consider having methods specific to the
802 // interface so that builders can choose dynamically to either return a
803 // message or a nested builder, so that asking for the interface doesn't
804 // cause a message to ever be built.
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000805 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000806 printer->Print(variables_,
807 "$deprecation$java.util.List<$type$> \n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000808 " get$capitalized_name$List();\n");
809 WriteFieldDocComment(printer, descriptor_);
810 printer->Print(variables_,
811 "$deprecation$$type$ get$capitalized_name$(int index);\n");
812 WriteFieldDocComment(printer, descriptor_);
813 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000814 "$deprecation$int get$capitalized_name$Count();\n");
Bo Yang5db21732015-05-21 14:28:59 -0700815
816 WriteFieldDocComment(printer, descriptor_);
817 printer->Print(variables_,
818 "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
819 " get$capitalized_name$OrBuilderList();\n");
820 WriteFieldDocComment(printer, descriptor_);
821 printer->Print(variables_,
822 "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
823 " int index);\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000824}
825
jieluo@google.com4de8f552014-07-18 00:47:59 +0000826void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000827GenerateMembers(io::Printer* printer) const {
828 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000829 "private java.util.List<$type$> $name$_;\n");
jieluo@google.com4de8f552014-07-18 00:47:59 +0000830 PrintExtraFieldInfo(variables_, printer);
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000831 WriteFieldDocComment(printer, descriptor_);
832 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000833 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
temporal40ee5512008-07-10 02:12:20 +0000834 " return $name$_;\n" // note: unmodifiable list
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000835 "}\n");
836 WriteFieldDocComment(printer, descriptor_);
837 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000838 "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
839 " get$capitalized_name$OrBuilderList() {\n"
840 " return $name$_;\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000841 "}\n");
842 WriteFieldDocComment(printer, descriptor_);
843 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000844 "$deprecation$public int get$capitalized_name$Count() {\n"
845 " return $name$_.size();\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000846 "}\n");
847 WriteFieldDocComment(printer, descriptor_);
848 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000849 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
850 " return $name$_.get(index);\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000851 "}\n");
852 WriteFieldDocComment(printer, descriptor_);
853 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000854 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
855 " int index) {\n"
temporal40ee5512008-07-10 02:12:20 +0000856 " return $name$_.get(index);\n"
857 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000858
859}
860
jieluo@google.com4de8f552014-07-18 00:47:59 +0000861void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000862 io::Printer* printer,
863 const char* regular_case,
864 const char* nested_builder_case) const {
Bo Yang5db21732015-05-21 14:28:59 -0700865 printer->Print(variables_, "if ($name$Builder_ == null) {\n");
866 printer->Indent();
867 printer->Print(variables_, regular_case);
868 printer->Outdent();
869 printer->Print("} else {\n");
870 printer->Indent();
871 printer->Print(variables_, nested_builder_case);
872 printer->Outdent();
873 printer->Print("}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000874}
875
jieluo@google.com4de8f552014-07-18 00:47:59 +0000876void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
liujisi@google.com33165fe2010-11-02 13:14:58 +0000877 io::Printer* printer,
878 const char* method_prototype,
879 const char* regular_case,
880 const char* nested_builder_case,
881 const char* trailing_code) const {
882 printer->Print(variables_, method_prototype);
883 printer->Print(" {\n");
884 printer->Indent();
885 PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
886 if (trailing_code != NULL) {
887 printer->Print(variables_, trailing_code);
888 }
889 printer->Outdent();
890 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000891}
892
jieluo@google.com4de8f552014-07-18 00:47:59 +0000893void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000894GenerateBuilderMembers(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000895 // When using nested-builders, the code initially works just like the
896 // non-nested builder case. It only creates a nested builder lazily on
897 // demand and then forever delegates to it after creation.
898
temporal40ee5512008-07-10 02:12:20 +0000899 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000900 // Used when the builder is null.
901 // One field is the list and the other field keeps track of whether the
902 // list is immutable. If it's immutable, the invariant is that it must
903 // either an instance of Collections.emptyList() or it's an ArrayList
904 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
905 // a refererence to the underlying ArrayList. This invariant allows us to
906 // share instances of lists between protocol buffers avoiding expensive
907 // memory allocations. Note, immutable is a strong guarantee here -- not
908 // just that the list cannot be modified via the reference but that the
909 // list can never be modified.
910 "private java.util.List<$type$> $name$_ =\n"
911 " java.util.Collections.emptyList();\n"
912
913 "private void ensure$capitalized_name$IsMutable() {\n"
914 " if (!$get_mutable_bit_builder$) {\n"
915 " $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
916 " $set_mutable_bit_builder$;\n"
917 " }\n"
temporal40ee5512008-07-10 02:12:20 +0000918 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000919 "\n");
920
Bo Yang5db21732015-05-21 14:28:59 -0700921 printer->Print(variables_,
922 // If this builder is non-null, it is used and the other fields are
923 // ignored.
924 "private com.google.protobuf.RepeatedFieldBuilder<\n"
925 " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
926 "\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000927
928 // The comments above the methods below are based on a hypothetical
929 // repeated field of type "Field" called "RepeatedField".
930
931 // List<Field> getRepeatedFieldList()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000932 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000933 PrintNestedBuilderFunction(printer,
934 "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
935
936 "return java.util.Collections.unmodifiableList($name$_);\n",
937 "return $name$Builder_.getMessageList();\n",
938
939 NULL);
940
941 // int getRepeatedFieldCount()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000942 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000943 PrintNestedBuilderFunction(printer,
944 "$deprecation$public int get$capitalized_name$Count()",
945
946 "return $name$_.size();\n",
947 "return $name$Builder_.getCount();\n",
948
949 NULL);
950
951 // Field getRepeatedField(int index)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000952 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000953 PrintNestedBuilderFunction(printer,
954 "$deprecation$public $type$ get$capitalized_name$(int index)",
955
956 "return $name$_.get(index);\n",
957
958 "return $name$Builder_.getMessage(index);\n",
959
960 NULL);
961
962 // Builder setRepeatedField(int index, Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000963 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000964 PrintNestedBuilderFunction(printer,
965 "$deprecation$public Builder set$capitalized_name$(\n"
966 " int index, $type$ value)",
967 "if (value == null) {\n"
968 " throw new NullPointerException();\n"
temporal40ee5512008-07-10 02:12:20 +0000969 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000970 "ensure$capitalized_name$IsMutable();\n"
971 "$name$_.set(index, value);\n"
972 "$on_changed$\n",
973 "$name$Builder_.setMessage(index, value);\n",
974 "return this;\n");
975
976 // Builder setRepeatedField(int index, Field.Builder builderForValue)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000977 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000978 PrintNestedBuilderFunction(printer,
979 "$deprecation$public Builder set$capitalized_name$(\n"
980 " int index, $type$.Builder builderForValue)",
981
982 "ensure$capitalized_name$IsMutable();\n"
983 "$name$_.set(index, builderForValue.build());\n"
984 "$on_changed$\n",
985
986 "$name$Builder_.setMessage(index, builderForValue.build());\n",
987
988 "return this;\n");
989
990 // Builder addRepeatedField(Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +0000991 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +0000992 PrintNestedBuilderFunction(printer,
993 "$deprecation$public Builder add$capitalized_name$($type$ value)",
994
995 "if (value == null) {\n"
996 " throw new NullPointerException();\n"
temporal40ee5512008-07-10 02:12:20 +0000997 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000998 "ensure$capitalized_name$IsMutable();\n"
999 "$name$_.add(value);\n"
1000
1001 "$on_changed$\n",
1002
1003 "$name$Builder_.addMessage(value);\n",
1004
1005 "return this;\n");
1006
1007 // Builder addRepeatedField(int index, Field value)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001008 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001009 PrintNestedBuilderFunction(printer,
1010 "$deprecation$public Builder add$capitalized_name$(\n"
1011 " int index, $type$ value)",
1012
1013 "if (value == null) {\n"
1014 " throw new NullPointerException();\n"
temporal40ee5512008-07-10 02:12:20 +00001015 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001016 "ensure$capitalized_name$IsMutable();\n"
1017 "$name$_.add(index, value);\n"
1018 "$on_changed$\n",
1019
1020 "$name$Builder_.addMessage(index, value);\n",
1021
1022 "return this;\n");
1023
1024 // Builder addRepeatedField(Field.Builder builderForValue)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001025 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001026 PrintNestedBuilderFunction(printer,
1027 "$deprecation$public Builder add$capitalized_name$(\n"
1028 " $type$.Builder builderForValue)",
1029
1030 "ensure$capitalized_name$IsMutable();\n"
1031 "$name$_.add(builderForValue.build());\n"
1032 "$on_changed$\n",
1033
1034 "$name$Builder_.addMessage(builderForValue.build());\n",
1035
1036 "return this;\n");
1037
1038 // Builder addRepeatedField(int index, Field.Builder builderForValue)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001039 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001040 PrintNestedBuilderFunction(printer,
1041 "$deprecation$public Builder add$capitalized_name$(\n"
1042 " int index, $type$.Builder builderForValue)",
1043
1044 "ensure$capitalized_name$IsMutable();\n"
1045 "$name$_.add(index, builderForValue.build());\n"
1046 "$on_changed$\n",
1047
1048 "$name$Builder_.addMessage(index, builderForValue.build());\n",
1049
1050 "return this;\n");
1051
1052 // Builder addAllRepeatedField(Iterable<Field> values)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001053 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001054 PrintNestedBuilderFunction(printer,
1055 "$deprecation$public Builder addAll$capitalized_name$(\n"
1056 " java.lang.Iterable<? extends $type$> values)",
1057
1058 "ensure$capitalized_name$IsMutable();\n"
jieluo@google.com4de8f552014-07-18 00:47:59 +00001059 "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
1060 " values, $name$_);\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001061 "$on_changed$\n",
1062
1063 "$name$Builder_.addAllMessages(values);\n",
1064
1065 "return this;\n");
1066
1067 // Builder clearAllRepeatedField()
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001068 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001069 PrintNestedBuilderFunction(printer,
1070 "$deprecation$public Builder clear$capitalized_name$()",
1071
1072 "$name$_ = java.util.Collections.emptyList();\n"
1073 "$clear_mutable_bit_builder$;\n"
1074 "$on_changed$\n",
1075
1076 "$name$Builder_.clear();\n",
1077
1078 "return this;\n");
1079
1080 // Builder removeRepeatedField(int index)
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001081 WriteFieldDocComment(printer, descriptor_);
liujisi@google.com33165fe2010-11-02 13:14:58 +00001082 PrintNestedBuilderFunction(printer,
1083 "$deprecation$public Builder remove$capitalized_name$(int index)",
1084
1085 "ensure$capitalized_name$IsMutable();\n"
1086 "$name$_.remove(index);\n"
1087 "$on_changed$\n",
1088
1089 "$name$Builder_.remove(index);\n",
1090
1091 "return this;\n");
1092
Bo Yang5db21732015-05-21 14:28:59 -07001093 WriteFieldDocComment(printer, descriptor_);
1094 printer->Print(variables_,
1095 "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
1096 " int index) {\n"
1097 " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
1098 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001099
Bo Yang5db21732015-05-21 14:28:59 -07001100 WriteFieldDocComment(printer, descriptor_);
1101 printer->Print(variables_,
1102 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
1103 " int index) {\n"
1104 " if ($name$Builder_ == null) {\n"
1105 " return $name$_.get(index);"
1106 " } else {\n"
1107 " return $name$Builder_.getMessageOrBuilder(index);\n"
1108 " }\n"
1109 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001110
Bo Yang5db21732015-05-21 14:28:59 -07001111 WriteFieldDocComment(printer, descriptor_);
1112 printer->Print(variables_,
1113 "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
1114 " get$capitalized_name$OrBuilderList() {\n"
1115 " if ($name$Builder_ != null) {\n"
1116 " return $name$Builder_.getMessageOrBuilderList();\n"
1117 " } else {\n"
1118 " return java.util.Collections.unmodifiableList($name$_);\n"
1119 " }\n"
1120 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001121
Bo Yang5db21732015-05-21 14:28:59 -07001122 WriteFieldDocComment(printer, descriptor_);
1123 printer->Print(variables_,
1124 "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
1125 " return get$capitalized_name$FieldBuilder().addBuilder(\n"
1126 " $type$.getDefaultInstance());\n"
1127 "}\n");
1128 WriteFieldDocComment(printer, descriptor_);
1129 printer->Print(variables_,
1130 "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
1131 " int index) {\n"
1132 " return get$capitalized_name$FieldBuilder().addBuilder(\n"
1133 " index, $type$.getDefaultInstance());\n"
1134 "}\n");
1135 WriteFieldDocComment(printer, descriptor_);
1136 printer->Print(variables_,
1137 "$deprecation$public java.util.List<$type$.Builder> \n"
1138 " get$capitalized_name$BuilderList() {\n"
1139 " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
1140 "}\n"
1141 "private com.google.protobuf.RepeatedFieldBuilder<\n"
1142 " $type$, $type$.Builder, $type$OrBuilder> \n"
1143 " get$capitalized_name$FieldBuilder() {\n"
1144 " if ($name$Builder_ == null) {\n"
1145 " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
1146 " $type$, $type$.Builder, $type$OrBuilder>(\n"
1147 " $name$_,\n"
1148 " $get_mutable_bit_builder$,\n"
1149 " getParentForChildren(),\n"
1150 " isClean());\n"
1151 " $name$_ = null;\n"
1152 " }\n"
1153 " return $name$Builder_;\n"
1154 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +00001155}
1156
jieluo@google.com4de8f552014-07-18 00:47:59 +00001157void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +00001158GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
1159 printer->Print(variables_,
1160 "get$capitalized_name$FieldBuilder();\n");
temporal40ee5512008-07-10 02:12:20 +00001161}
1162
jieluo@google.com4de8f552014-07-18 00:47:59 +00001163void RepeatedImmutableMessageFieldGenerator::
kenton@google.comfccb1462009-12-18 02:11:36 +00001164GenerateInitializationCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001165 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
1166}
1167
jieluo@google.com4de8f552014-07-18 00:47:59 +00001168void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +00001169GenerateBuilderClearCode(io::Printer* printer) const {
1170 PrintNestedBuilderCondition(printer,
1171 "$name$_ = java.util.Collections.emptyList();\n"
1172 "$clear_mutable_bit_builder$;\n",
1173
1174 "$name$Builder_.clear();\n");
kenton@google.comfccb1462009-12-18 02:11:36 +00001175}
1176
jieluo@google.com4de8f552014-07-18 00:47:59 +00001177void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001178GenerateMergingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001179 // The code below does two optimizations (non-nested builder case):
1180 // 1. If the other list is empty, there's nothing to do. This ensures we
1181 // don't allocate a new array if we already have an immutable one.
1182 // 2. If the other list is non-empty and our current list is empty, we can
1183 // reuse the other list which is guaranteed to be immutable.
1184 PrintNestedBuilderCondition(printer,
temporal40ee5512008-07-10 02:12:20 +00001185 "if (!other.$name$_.isEmpty()) {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001186 " if ($name$_.isEmpty()) {\n"
1187 " $name$_ = other.$name$_;\n"
1188 " $clear_mutable_bit_builder$;\n"
1189 " } else {\n"
1190 " ensure$capitalized_name$IsMutable();\n"
1191 " $name$_.addAll(other.$name$_);\n"
temporal40ee5512008-07-10 02:12:20 +00001192 " }\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001193 " $on_changed$\n"
1194 "}\n",
1195
1196 "if (!other.$name$_.isEmpty()) {\n"
1197 " if ($name$Builder_.isEmpty()) {\n"
1198 " $name$Builder_.dispose();\n"
1199 " $name$Builder_ = null;\n"
1200 " $name$_ = other.$name$_;\n"
1201 " $clear_mutable_bit_builder$;\n"
1202 " $name$Builder_ = \n"
1203 " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
1204 " get$capitalized_name$FieldBuilder() : null;\n"
1205 " } else {\n"
1206 " $name$Builder_.addAllMessages(other.$name$_);\n"
1207 " }\n"
temporal40ee5512008-07-10 02:12:20 +00001208 "}\n");
1209}
1210
jieluo@google.com4de8f552014-07-18 00:47:59 +00001211void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001212GenerateBuildingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +00001213 // The code below (non-nested builder case) ensures that the result has an
1214 // immutable list. If our list is immutable, we can just reuse it. If not,
1215 // we make it immutable.
1216 PrintNestedBuilderCondition(printer,
1217 "if ($get_mutable_bit_builder$) {\n"
1218 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
1219 " $clear_mutable_bit_builder$;\n"
1220 "}\n"
1221 "result.$name$_ = $name$_;\n",
1222
1223 "result.$name$_ = $name$Builder_.build();\n");
temporal40ee5512008-07-10 02:12:20 +00001224}
1225
jieluo@google.com4de8f552014-07-18 00:47:59 +00001226void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001227GenerateParsingCode(io::Printer* printer) const {
1228 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001229 "if (!$get_mutable_bit_parser$) {\n"
1230 " $name$_ = new java.util.ArrayList<$type$>();\n"
1231 " $set_mutable_bit_parser$;\n"
1232 "}\n");
temporal40ee5512008-07-10 02:12:20 +00001233
kenton@google.comfccb1462009-12-18 02:11:36 +00001234 if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
temporal40ee5512008-07-10 02:12:20 +00001235 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001236 "$name$_.add(input.readGroup($number$, $type$.parser(),\n"
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001237 " extensionRegistry));\n");
temporal40ee5512008-07-10 02:12:20 +00001238 } else {
1239 printer->Print(variables_,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001240 "$name$_.add(input.readMessage($type$.parser(), extensionRegistry));\n");
temporal40ee5512008-07-10 02:12:20 +00001241 }
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001242}
temporal40ee5512008-07-10 02:12:20 +00001243
jieluo@google.com4de8f552014-07-18 00:47:59 +00001244void RepeatedImmutableMessageFieldGenerator::
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001245GenerateParsingDoneCode(io::Printer* printer) const {
temporal40ee5512008-07-10 02:12:20 +00001246 printer->Print(variables_,
xiaofeng@google.comb55a20f2012-09-22 02:40:50 +00001247 "if ($get_mutable_bit_parser$) {\n"
1248 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
1249 "}\n");
temporal40ee5512008-07-10 02:12:20 +00001250}
1251
jieluo@google.com4de8f552014-07-18 00:47:59 +00001252void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001253GenerateSerializationCode(io::Printer* printer) const {
1254 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +00001255 "for (int i = 0; i < $name$_.size(); i++) {\n"
1256 " output.write$group_or_message$($number$, $name$_.get(i));\n"
temporal40ee5512008-07-10 02:12:20 +00001257 "}\n");
1258}
1259
jieluo@google.com4de8f552014-07-18 00:47:59 +00001260void RepeatedImmutableMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +00001261GenerateSerializedSizeCode(io::Printer* printer) const {
1262 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +00001263 "for (int i = 0; i < $name$_.size(); i++) {\n"
temporal40ee5512008-07-10 02:12:20 +00001264 " size += com.google.protobuf.CodedOutputStream\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +00001265 " .compute$group_or_message$Size($number$, $name$_.get(i));\n"
1266 "}\n");
1267}
1268
jieluo@google.com4de8f552014-07-18 00:47:59 +00001269void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +00001270GenerateEqualsCode(io::Printer* printer) const {
1271 printer->Print(variables_,
1272 "result = result && get$capitalized_name$List()\n"
1273 " .equals(other.get$capitalized_name$List());\n");
1274}
1275
jieluo@google.com4de8f552014-07-18 00:47:59 +00001276void RepeatedImmutableMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +00001277GenerateHashCode(io::Printer* printer) const {
1278 printer->Print(variables_,
1279 "if (get$capitalized_name$Count() > 0) {\n"
1280 " hash = (37 * hash) + $constant_name$;\n"
1281 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
temporal40ee5512008-07-10 02:12:20 +00001282 "}\n");
1283}
1284
jieluo@google.com4de8f552014-07-18 00:47:59 +00001285string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const {
1286 return name_resolver_->GetImmutableClassName(descriptor_->message_type());
temporal40ee5512008-07-10 02:12:20 +00001287}
1288
1289} // namespace java
1290} // namespace compiler
1291} // namespace protobuf
1292} // namespace google