blob: 251945afd55927ab2a73713364602057d3637cbd [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.
temporal40ee5512008-07-10 02:12:20 +00003// http://code.google.com/p/protobuf/
4//
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
38#include <google/protobuf/compiler/java/java_message_field.h>
39#include <google/protobuf/compiler/java/java_helpers.h>
40#include <google/protobuf/io/printer.h>
41#include <google/protobuf/wire_format.h>
42#include <google/protobuf/stubs/strutil.h>
43
44namespace google {
45namespace protobuf {
46namespace compiler {
47namespace java {
48
49namespace {
50
51// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
52// repeat code between this and the other field types.
53void SetMessageVariables(const FieldDescriptor* descriptor,
liujisi@google.com33165fe2010-11-02 13:14:58 +000054 int messageBitIndex,
55 int builderBitIndex,
temporal40ee5512008-07-10 02:12:20 +000056 map<string, string>* variables) {
57 (*variables)["name"] =
58 UnderscoresToCamelCase(descriptor);
59 (*variables)["capitalized_name"] =
60 UnderscoresToCapitalizedCamelCase(descriptor);
liujisi@google.com33165fe2010-11-02 13:14:58 +000061 (*variables)["constant_name"] = FieldConstantName(descriptor);
temporal40ee5512008-07-10 02:12:20 +000062 (*variables)["number"] = SimpleItoa(descriptor->number());
63 (*variables)["type"] = ClassName(descriptor->message_type());
64 (*variables)["group_or_message"] =
kenton@google.comfccb1462009-12-18 02:11:36 +000065 (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
temporal40ee5512008-07-10 02:12:20 +000066 "Group" : "Message";
liujisi@google.com33165fe2010-11-02 13:14:58 +000067 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
68 // by the proto compiler
69 (*variables)["deprecation"] = descriptor->options().deprecated()
70 ? "@java.lang.Deprecated " : "";
71 (*variables)["on_changed"] =
72 HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
73
74 // For singular messages and builders, one bit is used for the hasField bit.
75 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
76
77 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
78 (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
79 (*variables)["clear_has_field_bit_builder"] =
80 GenerateClearBit(builderBitIndex);
81
82 // For repated builders, one bit is used for whether the array is immutable.
83 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
84 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
85 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
86
87 (*variables)["get_has_field_bit_from_local"] =
88 GenerateGetBitFromLocal(builderBitIndex);
89 (*variables)["set_has_field_bit_to_local"] =
90 GenerateSetBitToLocal(messageBitIndex);
temporal40ee5512008-07-10 02:12:20 +000091}
92
93} // namespace
94
95// ===================================================================
96
97MessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +000098MessageFieldGenerator(const FieldDescriptor* descriptor,
99 int messageBitIndex,
100 int builderBitIndex)
101 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
102 builderBitIndex_(builderBitIndex) {
103 SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
104 &variables_);
temporal40ee5512008-07-10 02:12:20 +0000105}
106
107MessageFieldGenerator::~MessageFieldGenerator() {}
108
liujisi@google.com33165fe2010-11-02 13:14:58 +0000109int MessageFieldGenerator::GetNumBitsForMessage() const {
110 return 1;
111}
112
113int MessageFieldGenerator::GetNumBitsForBuilder() const {
114 return 1;
115}
116
117void MessageFieldGenerator::
118GenerateInterfaceMembers(io::Printer* printer) const {
119 // TODO(jonp): In the future, consider having a method specific to the
120 // interface so that builders can choose dynamically to either return a
121 // message or a nested builder, so that asking for the interface doesn't
122 // cause a message to ever be built.
123 printer->Print(variables_,
124 "$deprecation$boolean has$capitalized_name$();\n"
125 "$deprecation$$type$ get$capitalized_name$();\n");
126
127 if (HasNestedBuilders(descriptor_->containing_type())) {
128 printer->Print(variables_,
129 "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
130 }
131}
132
temporal40ee5512008-07-10 02:12:20 +0000133void MessageFieldGenerator::
134GenerateMembers(io::Printer* printer) const {
135 printer->Print(variables_,
kenton@google.comfccb1462009-12-18 02:11:36 +0000136 "private $type$ $name$_;\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000137 "$deprecation$public boolean has$capitalized_name$() {\n"
138 " return $get_has_field_bit_message$;\n"
139 "}\n"
140 "$deprecation$public $type$ get$capitalized_name$() {\n"
141 " return $name$_;\n"
142 "}\n");
143
144 if (HasNestedBuilders(descriptor_->containing_type())) {
145 printer->Print(variables_,
146 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
147 " return $name$_;\n"
148 "}\n");
149 }
150}
151
152void MessageFieldGenerator::PrintNestedBuilderCondition(
153 io::Printer* printer,
154 const char* regular_case,
155 const char* nested_builder_case) const {
156 if (HasNestedBuilders(descriptor_->containing_type())) {
157 printer->Print(variables_, "if ($name$Builder_ == null) {\n");
158 printer->Indent();
159 printer->Print(variables_, regular_case);
160 printer->Outdent();
161 printer->Print("} else {\n");
162 printer->Indent();
163 printer->Print(variables_, nested_builder_case);
164 printer->Outdent();
165 printer->Print("}\n");
166 } else {
167 printer->Print(variables_, regular_case);
168 }
169}
170
171void MessageFieldGenerator::PrintNestedBuilderFunction(
172 io::Printer* printer,
173 const char* method_prototype,
174 const char* regular_case,
175 const char* nested_builder_case,
176 const char* trailing_code) const {
177 printer->Print(variables_, method_prototype);
178 printer->Print(" {\n");
179 printer->Indent();
180 PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
181 if (trailing_code != NULL) {
182 printer->Print(variables_, trailing_code);
183 }
184 printer->Outdent();
185 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000186}
187
188void MessageFieldGenerator::
189GenerateBuilderMembers(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000190 // When using nested-builders, the code initially works just like the
191 // non-nested builder case. It only creates a nested builder lazily on
192 // demand and then forever delegates to it after creation.
193
temporal40ee5512008-07-10 02:12:20 +0000194 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000195 // Used when the builder is null.
196 "private $type$ $name$_ = $type$.getDefaultInstance();\n");
197
198 if (HasNestedBuilders(descriptor_->containing_type())) {
199 printer->Print(variables_,
200 // If this builder is non-null, it is used and the other fields are
201 // ignored.
202 "private com.google.protobuf.SingleFieldBuilder<\n"
203 " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
204 "\n");
205 }
206
207 // The comments above the methods below are based on a hypothetical
208 // field of type "Field" called "Field".
209
210 // boolean hasField()
211 printer->Print(variables_,
212 "$deprecation$public boolean has$capitalized_name$() {\n"
213 " return $get_has_field_bit_builder$;\n"
temporal40ee5512008-07-10 02:12:20 +0000214 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000215
216 // Field getField()
217 PrintNestedBuilderFunction(printer,
218 "$deprecation$public $type$ get$capitalized_name$()",
219
220 "return $name$_;\n",
221
222 "return $name$Builder_.getMessage();\n",
223
224 NULL);
225
226 // Field.Builder setField(Field value)
227 PrintNestedBuilderFunction(printer,
228 "$deprecation$public Builder set$capitalized_name$($type$ value)",
229
230 "if (value == null) {\n"
231 " throw new NullPointerException();\n"
232 "}\n"
233 "$name$_ = value;\n"
234 "$on_changed$\n",
235
236 "$name$Builder_.setMessage(value);\n",
237
238 "$set_has_field_bit_builder$;\n"
239 "return this;\n");
240
241 // Field.Builder setField(Field.Builder builderForValue)
242 PrintNestedBuilderFunction(printer,
243 "$deprecation$public Builder set$capitalized_name$(\n"
244 " $type$.Builder builderForValue)",
245
246 "$name$_ = builderForValue.build();\n"
247 "$on_changed$\n",
248
249 "$name$Builder_.setMessage(builderForValue.build());\n",
250
251 "$set_has_field_bit_builder$;\n"
252 "return this;\n");
253
254 // Field.Builder mergeField(Field value)
255 PrintNestedBuilderFunction(printer,
256 "$deprecation$public Builder merge$capitalized_name$($type$ value)",
257
258 "if ($get_has_field_bit_builder$ &&\n"
259 " $name$_ != $type$.getDefaultInstance()) {\n"
260 " $name$_ =\n"
261 " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
262 "} else {\n"
263 " $name$_ = value;\n"
264 "}\n"
265 "$on_changed$\n",
266
267 "$name$Builder_.mergeFrom(value);\n",
268
269 "$set_has_field_bit_builder$;\n"
270 "return this;\n");
271
272 // Field.Builder clearField()
273 PrintNestedBuilderFunction(printer,
274 "$deprecation$public Builder clear$capitalized_name$()",
275
276 "$name$_ = $type$.getDefaultInstance();\n"
277 "$on_changed$\n",
278
279 "$name$Builder_.clear();\n",
280
281 "$clear_has_field_bit_builder$;\n"
282 "return this;\n");
283
284 if (HasNestedBuilders(descriptor_->containing_type())) {
285 printer->Print(variables_,
286 "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
287 " $set_has_field_bit_builder$;\n"
288 " $on_changed$\n"
289 " return get$capitalized_name$FieldBuilder().getBuilder();\n"
290 "}\n"
291 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
292 " if ($name$Builder_ != null) {\n"
293 " return $name$Builder_.getMessageOrBuilder();\n"
294 " } else {\n"
295 " return $name$_;\n"
296 " }\n"
297 "}\n"
298 "private com.google.protobuf.SingleFieldBuilder<\n"
299 " $type$, $type$.Builder, $type$OrBuilder> \n"
300 " get$capitalized_name$FieldBuilder() {\n"
301 " if ($name$Builder_ == null) {\n"
302 " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
303 " $type$, $type$.Builder, $type$OrBuilder>(\n"
304 " $name$_,\n"
305 " getParentForChildren(),\n"
306 " isClean());\n"
307 " $name$_ = null;\n"
308 " }\n"
309 " return $name$Builder_;\n"
310 "}\n");
311 }
temporal40ee5512008-07-10 02:12:20 +0000312}
313
314void MessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000315GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
316 printer->Print(variables_,
317 "get$capitalized_name$FieldBuilder();\n");
318}
319
320
321void MessageFieldGenerator::
kenton@google.comfccb1462009-12-18 02:11:36 +0000322GenerateInitializationCode(io::Printer* printer) const {
323 printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
324}
325
326void MessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000327GenerateBuilderClearCode(io::Printer* printer) const {
328 PrintNestedBuilderCondition(printer,
329 "$name$_ = $type$.getDefaultInstance();\n",
330
331 "$name$Builder_.clear();\n");
332 printer->Print(variables_, "$clear_has_field_bit_builder$;\n");
333}
334
335void MessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000336GenerateMergingCode(io::Printer* printer) const {
337 printer->Print(variables_,
338 "if (other.has$capitalized_name$()) {\n"
339 " merge$capitalized_name$(other.get$capitalized_name$());\n"
340 "}\n");
341}
342
343void MessageFieldGenerator::
344GenerateBuildingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000345
346 printer->Print(variables_,
347 "if ($get_has_field_bit_from_local$) {\n"
348 " $set_has_field_bit_to_local$;\n"
349 "}\n");
350
351 PrintNestedBuilderCondition(printer,
352 "result.$name$_ = $name$_;\n",
353
354 "result.$name$_ = $name$Builder_.build();\n");
temporal40ee5512008-07-10 02:12:20 +0000355}
356
357void MessageFieldGenerator::
358GenerateParsingCode(io::Printer* printer) const {
359 printer->Print(variables_,
360 "$type$.Builder subBuilder = $type$.newBuilder();\n"
361 "if (has$capitalized_name$()) {\n"
362 " subBuilder.mergeFrom(get$capitalized_name$());\n"
363 "}\n");
364
kenton@google.comfccb1462009-12-18 02:11:36 +0000365 if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
temporal40ee5512008-07-10 02:12:20 +0000366 printer->Print(variables_,
367 "input.readGroup($number$, subBuilder, extensionRegistry);\n");
368 } else {
369 printer->Print(variables_,
370 "input.readMessage(subBuilder, extensionRegistry);\n");
371 }
372
373 printer->Print(variables_,
374 "set$capitalized_name$(subBuilder.buildPartial());\n");
375}
376
377void MessageFieldGenerator::
378GenerateSerializationCode(io::Printer* printer) const {
379 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000380 "if ($get_has_field_bit_message$) {\n"
381 " output.write$group_or_message$($number$, $name$_);\n"
temporal40ee5512008-07-10 02:12:20 +0000382 "}\n");
383}
384
385void MessageFieldGenerator::
386GenerateSerializedSizeCode(io::Printer* printer) const {
387 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000388 "if ($get_has_field_bit_message$) {\n"
temporal40ee5512008-07-10 02:12:20 +0000389 " size += com.google.protobuf.CodedOutputStream\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000390 " .compute$group_or_message$Size($number$, $name$_);\n"
temporal40ee5512008-07-10 02:12:20 +0000391 "}\n");
392}
393
liujisi@google.com33165fe2010-11-02 13:14:58 +0000394void MessageFieldGenerator::
395GenerateEqualsCode(io::Printer* printer) const {
396 printer->Print(variables_,
397 "result = result && get$capitalized_name$()\n"
398 " .equals(other.get$capitalized_name$());\n");
399}
400
401void MessageFieldGenerator::
402GenerateHashCode(io::Printer* printer) const {
403 printer->Print(variables_,
404 "hash = (37 * hash) + $constant_name$;\n"
405 "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
406}
407
temporal40ee5512008-07-10 02:12:20 +0000408string MessageFieldGenerator::GetBoxedType() const {
409 return ClassName(descriptor_->message_type());
410}
411
412// ===================================================================
413
414RepeatedMessageFieldGenerator::
liujisi@google.com33165fe2010-11-02 13:14:58 +0000415RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
416 int messageBitIndex,
417 int builderBitIndex)
418 : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
419 builderBitIndex_(builderBitIndex) {
420 SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
421 &variables_);
temporal40ee5512008-07-10 02:12:20 +0000422}
423
424RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
425
liujisi@google.com33165fe2010-11-02 13:14:58 +0000426int RepeatedMessageFieldGenerator::GetNumBitsForMessage() const {
427 return 0;
428}
429
430int RepeatedMessageFieldGenerator::GetNumBitsForBuilder() const {
431 return 1;
432}
433
434void RepeatedMessageFieldGenerator::
435GenerateInterfaceMembers(io::Printer* printer) const {
436 // TODO(jonp): In the future, consider having methods specific to the
437 // interface so that builders can choose dynamically to either return a
438 // message or a nested builder, so that asking for the interface doesn't
439 // cause a message to ever be built.
440 printer->Print(variables_,
441 "$deprecation$java.util.List<$type$> \n"
442 " get$capitalized_name$List();\n"
443 "$deprecation$$type$ get$capitalized_name$(int index);\n"
444 "$deprecation$int get$capitalized_name$Count();\n");
445 if (HasNestedBuilders(descriptor_->containing_type())) {
446 printer->Print(variables_,
447 "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
448 " get$capitalized_name$OrBuilderList();\n"
449 "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
450 " int index);\n");
451 }
452}
453
temporal40ee5512008-07-10 02:12:20 +0000454void RepeatedMessageFieldGenerator::
455GenerateMembers(io::Printer* printer) const {
456 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000457 "private java.util.List<$type$> $name$_;\n"
458 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
temporal40ee5512008-07-10 02:12:20 +0000459 " return $name$_;\n" // note: unmodifiable list
460 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000461 "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
462 " get$capitalized_name$OrBuilderList() {\n"
463 " return $name$_;\n"
464 "}\n"
465 "$deprecation$public int get$capitalized_name$Count() {\n"
466 " return $name$_.size();\n"
467 "}\n"
468 "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
469 " return $name$_.get(index);\n"
470 "}\n"
471 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
472 " int index) {\n"
temporal40ee5512008-07-10 02:12:20 +0000473 " return $name$_.get(index);\n"
474 "}\n");
liujisi@google.com33165fe2010-11-02 13:14:58 +0000475
476}
477
478void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition(
479 io::Printer* printer,
480 const char* regular_case,
481 const char* nested_builder_case) const {
482 if (HasNestedBuilders(descriptor_->containing_type())) {
483 printer->Print(variables_, "if ($name$Builder_ == null) {\n");
484 printer->Indent();
485 printer->Print(variables_, regular_case);
486 printer->Outdent();
487 printer->Print("} else {\n");
488 printer->Indent();
489 printer->Print(variables_, nested_builder_case);
490 printer->Outdent();
491 printer->Print("}\n");
492 } else {
493 printer->Print(variables_, regular_case);
494 }
495}
496
497void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction(
498 io::Printer* printer,
499 const char* method_prototype,
500 const char* regular_case,
501 const char* nested_builder_case,
502 const char* trailing_code) const {
503 printer->Print(variables_, method_prototype);
504 printer->Print(" {\n");
505 printer->Indent();
506 PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
507 if (trailing_code != NULL) {
508 printer->Print(variables_, trailing_code);
509 }
510 printer->Outdent();
511 printer->Print("}\n");
temporal40ee5512008-07-10 02:12:20 +0000512}
513
514void RepeatedMessageFieldGenerator::
515GenerateBuilderMembers(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000516 // When using nested-builders, the code initially works just like the
517 // non-nested builder case. It only creates a nested builder lazily on
518 // demand and then forever delegates to it after creation.
519
temporal40ee5512008-07-10 02:12:20 +0000520 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000521 // Used when the builder is null.
522 // One field is the list and the other field keeps track of whether the
523 // list is immutable. If it's immutable, the invariant is that it must
524 // either an instance of Collections.emptyList() or it's an ArrayList
525 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
526 // a refererence to the underlying ArrayList. This invariant allows us to
527 // share instances of lists between protocol buffers avoiding expensive
528 // memory allocations. Note, immutable is a strong guarantee here -- not
529 // just that the list cannot be modified via the reference but that the
530 // list can never be modified.
531 "private java.util.List<$type$> $name$_ =\n"
532 " java.util.Collections.emptyList();\n"
533
534 "private void ensure$capitalized_name$IsMutable() {\n"
535 " if (!$get_mutable_bit_builder$) {\n"
536 " $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
537 " $set_mutable_bit_builder$;\n"
538 " }\n"
temporal40ee5512008-07-10 02:12:20 +0000539 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000540 "\n");
541
542 if (HasNestedBuilders(descriptor_->containing_type())) {
543 printer->Print(variables_,
544 // If this builder is non-null, it is used and the other fields are
545 // ignored.
546 "private com.google.protobuf.RepeatedFieldBuilder<\n"
547 " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
548 "\n");
549 }
550
551 // The comments above the methods below are based on a hypothetical
552 // repeated field of type "Field" called "RepeatedField".
553
554 // List<Field> getRepeatedFieldList()
555 PrintNestedBuilderFunction(printer,
556 "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
557
558 "return java.util.Collections.unmodifiableList($name$_);\n",
559 "return $name$Builder_.getMessageList();\n",
560
561 NULL);
562
563 // int getRepeatedFieldCount()
564 PrintNestedBuilderFunction(printer,
565 "$deprecation$public int get$capitalized_name$Count()",
566
567 "return $name$_.size();\n",
568 "return $name$Builder_.getCount();\n",
569
570 NULL);
571
572 // Field getRepeatedField(int index)
573 PrintNestedBuilderFunction(printer,
574 "$deprecation$public $type$ get$capitalized_name$(int index)",
575
576 "return $name$_.get(index);\n",
577
578 "return $name$Builder_.getMessage(index);\n",
579
580 NULL);
581
582 // Builder setRepeatedField(int index, Field value)
583 PrintNestedBuilderFunction(printer,
584 "$deprecation$public Builder set$capitalized_name$(\n"
585 " int index, $type$ value)",
586 "if (value == null) {\n"
587 " throw new NullPointerException();\n"
temporal40ee5512008-07-10 02:12:20 +0000588 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000589 "ensure$capitalized_name$IsMutable();\n"
590 "$name$_.set(index, value);\n"
591 "$on_changed$\n",
592 "$name$Builder_.setMessage(index, value);\n",
593 "return this;\n");
594
595 // Builder setRepeatedField(int index, Field.Builder builderForValue)
596 PrintNestedBuilderFunction(printer,
597 "$deprecation$public Builder set$capitalized_name$(\n"
598 " int index, $type$.Builder builderForValue)",
599
600 "ensure$capitalized_name$IsMutable();\n"
601 "$name$_.set(index, builderForValue.build());\n"
602 "$on_changed$\n",
603
604 "$name$Builder_.setMessage(index, builderForValue.build());\n",
605
606 "return this;\n");
607
608 // Builder addRepeatedField(Field value)
609 PrintNestedBuilderFunction(printer,
610 "$deprecation$public Builder add$capitalized_name$($type$ value)",
611
612 "if (value == null) {\n"
613 " throw new NullPointerException();\n"
temporal40ee5512008-07-10 02:12:20 +0000614 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000615 "ensure$capitalized_name$IsMutable();\n"
616 "$name$_.add(value);\n"
617
618 "$on_changed$\n",
619
620 "$name$Builder_.addMessage(value);\n",
621
622 "return this;\n");
623
624 // Builder addRepeatedField(int index, Field value)
625 PrintNestedBuilderFunction(printer,
626 "$deprecation$public Builder add$capitalized_name$(\n"
627 " int index, $type$ value)",
628
629 "if (value == null) {\n"
630 " throw new NullPointerException();\n"
temporal40ee5512008-07-10 02:12:20 +0000631 "}\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000632 "ensure$capitalized_name$IsMutable();\n"
633 "$name$_.add(index, value);\n"
634 "$on_changed$\n",
635
636 "$name$Builder_.addMessage(index, value);\n",
637
638 "return this;\n");
639
640 // Builder addRepeatedField(Field.Builder builderForValue)
641 PrintNestedBuilderFunction(printer,
642 "$deprecation$public Builder add$capitalized_name$(\n"
643 " $type$.Builder builderForValue)",
644
645 "ensure$capitalized_name$IsMutable();\n"
646 "$name$_.add(builderForValue.build());\n"
647 "$on_changed$\n",
648
649 "$name$Builder_.addMessage(builderForValue.build());\n",
650
651 "return this;\n");
652
653 // Builder addRepeatedField(int index, Field.Builder builderForValue)
654 PrintNestedBuilderFunction(printer,
655 "$deprecation$public Builder add$capitalized_name$(\n"
656 " int index, $type$.Builder builderForValue)",
657
658 "ensure$capitalized_name$IsMutable();\n"
659 "$name$_.add(index, builderForValue.build());\n"
660 "$on_changed$\n",
661
662 "$name$Builder_.addMessage(index, builderForValue.build());\n",
663
664 "return this;\n");
665
666 // Builder addAllRepeatedField(Iterable<Field> values)
667 PrintNestedBuilderFunction(printer,
668 "$deprecation$public Builder addAll$capitalized_name$(\n"
669 " java.lang.Iterable<? extends $type$> values)",
670
671 "ensure$capitalized_name$IsMutable();\n"
672 "super.addAll(values, $name$_);\n"
673 "$on_changed$\n",
674
675 "$name$Builder_.addAllMessages(values);\n",
676
677 "return this;\n");
678
679 // Builder clearAllRepeatedField()
680 PrintNestedBuilderFunction(printer,
681 "$deprecation$public Builder clear$capitalized_name$()",
682
683 "$name$_ = java.util.Collections.emptyList();\n"
684 "$clear_mutable_bit_builder$;\n"
685 "$on_changed$\n",
686
687 "$name$Builder_.clear();\n",
688
689 "return this;\n");
690
691 // Builder removeRepeatedField(int index)
692 PrintNestedBuilderFunction(printer,
693 "$deprecation$public Builder remove$capitalized_name$(int index)",
694
695 "ensure$capitalized_name$IsMutable();\n"
696 "$name$_.remove(index);\n"
697 "$on_changed$\n",
698
699 "$name$Builder_.remove(index);\n",
700
701 "return this;\n");
702
703 if (HasNestedBuilders(descriptor_->containing_type())) {
704 printer->Print(variables_,
705 "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
706 " int index) {\n"
707 " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
708 "}\n"
709
710 "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
711 " int index) {\n"
712 " if ($name$Builder_ == null) {\n"
713 " return $name$_.get(index);"
714 " } else {\n"
715 " return $name$Builder_.getMessageOrBuilder(index);\n"
716 " }\n"
717 "}\n"
718
719 "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
720 " get$capitalized_name$OrBuilderList() {\n"
721 " if ($name$Builder_ != null) {\n"
722 " return $name$Builder_.getMessageOrBuilderList();\n"
723 " } else {\n"
724 " return java.util.Collections.unmodifiableList($name$_);\n"
725 " }\n"
726 "}\n"
727
728 "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
729 " return get$capitalized_name$FieldBuilder().addBuilder(\n"
730 " $type$.getDefaultInstance());\n"
731 "}\n"
732 "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
733 " int index) {\n"
734 " return get$capitalized_name$FieldBuilder().addBuilder(\n"
735 " index, $type$.getDefaultInstance());\n"
736 "}\n"
737 "$deprecation$public java.util.List<$type$.Builder> \n"
738 " get$capitalized_name$BuilderList() {\n"
739 " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
740 "}\n"
741 "private com.google.protobuf.RepeatedFieldBuilder<\n"
742 " $type$, $type$.Builder, $type$OrBuilder> \n"
743 " get$capitalized_name$FieldBuilder() {\n"
744 " if ($name$Builder_ == null) {\n"
745 " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
746 " $type$, $type$.Builder, $type$OrBuilder>(\n"
747 " $name$_,\n"
748 " $get_mutable_bit_builder$,\n"
749 " getParentForChildren(),\n"
750 " isClean());\n"
751 " $name$_ = null;\n"
752 " }\n"
753 " return $name$Builder_;\n"
754 "}\n");
755 }
756}
757
758void RepeatedMessageFieldGenerator::
759GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
760 printer->Print(variables_,
761 "get$capitalized_name$FieldBuilder();\n");
temporal40ee5512008-07-10 02:12:20 +0000762}
763
764void RepeatedMessageFieldGenerator::
kenton@google.comfccb1462009-12-18 02:11:36 +0000765GenerateInitializationCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000766 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
767}
768
769void RepeatedMessageFieldGenerator::
770GenerateBuilderClearCode(io::Printer* printer) const {
771 PrintNestedBuilderCondition(printer,
772 "$name$_ = java.util.Collections.emptyList();\n"
773 "$clear_mutable_bit_builder$;\n",
774
775 "$name$Builder_.clear();\n");
kenton@google.comfccb1462009-12-18 02:11:36 +0000776}
777
778void RepeatedMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000779GenerateMergingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000780 // The code below does two optimizations (non-nested builder case):
781 // 1. If the other list is empty, there's nothing to do. This ensures we
782 // don't allocate a new array if we already have an immutable one.
783 // 2. If the other list is non-empty and our current list is empty, we can
784 // reuse the other list which is guaranteed to be immutable.
785 PrintNestedBuilderCondition(printer,
temporal40ee5512008-07-10 02:12:20 +0000786 "if (!other.$name$_.isEmpty()) {\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000787 " if ($name$_.isEmpty()) {\n"
788 " $name$_ = other.$name$_;\n"
789 " $clear_mutable_bit_builder$;\n"
790 " } else {\n"
791 " ensure$capitalized_name$IsMutable();\n"
792 " $name$_.addAll(other.$name$_);\n"
temporal40ee5512008-07-10 02:12:20 +0000793 " }\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000794 " $on_changed$\n"
795 "}\n",
796
797 "if (!other.$name$_.isEmpty()) {\n"
798 " if ($name$Builder_.isEmpty()) {\n"
799 " $name$Builder_.dispose();\n"
800 " $name$Builder_ = null;\n"
801 " $name$_ = other.$name$_;\n"
802 " $clear_mutable_bit_builder$;\n"
803 " $name$Builder_ = \n"
804 " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n"
805 " get$capitalized_name$FieldBuilder() : null;\n"
806 " } else {\n"
807 " $name$Builder_.addAllMessages(other.$name$_);\n"
808 " }\n"
temporal40ee5512008-07-10 02:12:20 +0000809 "}\n");
810}
811
812void RepeatedMessageFieldGenerator::
813GenerateBuildingCode(io::Printer* printer) const {
liujisi@google.com33165fe2010-11-02 13:14:58 +0000814 // The code below (non-nested builder case) ensures that the result has an
815 // immutable list. If our list is immutable, we can just reuse it. If not,
816 // we make it immutable.
817 PrintNestedBuilderCondition(printer,
818 "if ($get_mutable_bit_builder$) {\n"
819 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
820 " $clear_mutable_bit_builder$;\n"
821 "}\n"
822 "result.$name$_ = $name$_;\n",
823
824 "result.$name$_ = $name$Builder_.build();\n");
temporal40ee5512008-07-10 02:12:20 +0000825}
826
827void RepeatedMessageFieldGenerator::
828GenerateParsingCode(io::Printer* printer) const {
829 printer->Print(variables_,
830 "$type$.Builder subBuilder = $type$.newBuilder();\n");
831
kenton@google.comfccb1462009-12-18 02:11:36 +0000832 if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
temporal40ee5512008-07-10 02:12:20 +0000833 printer->Print(variables_,
834 "input.readGroup($number$, subBuilder, extensionRegistry);\n");
835 } else {
836 printer->Print(variables_,
837 "input.readMessage(subBuilder, extensionRegistry);\n");
838 }
839
840 printer->Print(variables_,
841 "add$capitalized_name$(subBuilder.buildPartial());\n");
842}
843
844void RepeatedMessageFieldGenerator::
845GenerateSerializationCode(io::Printer* printer) const {
846 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000847 "for (int i = 0; i < $name$_.size(); i++) {\n"
848 " output.write$group_or_message$($number$, $name$_.get(i));\n"
temporal40ee5512008-07-10 02:12:20 +0000849 "}\n");
850}
851
852void RepeatedMessageFieldGenerator::
853GenerateSerializedSizeCode(io::Printer* printer) const {
854 printer->Print(variables_,
liujisi@google.com33165fe2010-11-02 13:14:58 +0000855 "for (int i = 0; i < $name$_.size(); i++) {\n"
temporal40ee5512008-07-10 02:12:20 +0000856 " size += com.google.protobuf.CodedOutputStream\n"
liujisi@google.com33165fe2010-11-02 13:14:58 +0000857 " .compute$group_or_message$Size($number$, $name$_.get(i));\n"
858 "}\n");
859}
860
861void RepeatedMessageFieldGenerator::
862GenerateEqualsCode(io::Printer* printer) const {
863 printer->Print(variables_,
864 "result = result && get$capitalized_name$List()\n"
865 " .equals(other.get$capitalized_name$List());\n");
866}
867
868void RepeatedMessageFieldGenerator::
869GenerateHashCode(io::Printer* printer) const {
870 printer->Print(variables_,
871 "if (get$capitalized_name$Count() > 0) {\n"
872 " hash = (37 * hash) + $constant_name$;\n"
873 " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
temporal40ee5512008-07-10 02:12:20 +0000874 "}\n");
875}
876
877string RepeatedMessageFieldGenerator::GetBoxedType() const {
878 return ClassName(descriptor_->message_type());
879}
880
881} // namespace java
882} // namespace compiler
883} // namespace protobuf
884} // namespace google