1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * 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.
18//
19// 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.
30
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/stubs/common.h>
39#include <google/protobuf/compiler/java/java_context.h>
40#include <google/protobuf/compiler/java/java_doc_comment.h>
41#include <google/protobuf/compiler/java/java_helpers.h>
42#include <google/protobuf/compiler/java/java_name_resolver.h>
43#include <google/protobuf/compiler/java/java_primitive_field.h>
44#include <google/protobuf/io/printer.h>
45#include <google/protobuf/wire_format.h>
46#include <google/protobuf/stubs/strutil.h>
47
48namespace google {
49namespace protobuf {
50namespace compiler {
51namespace java {
52
53using internal::WireFormat;
54using internal::WireFormatLite;
55
56namespace {
57
58const char* PrimitiveTypeName(JavaType type) {
59  switch (type) {
60    case JAVATYPE_INT    : return "int";
61    case JAVATYPE_LONG   : return "long";
62    case JAVATYPE_FLOAT  : return "float";
63    case JAVATYPE_DOUBLE : return "double";
64    case JAVATYPE_BOOLEAN: return "boolean";
65    case JAVATYPE_STRING : return "java.lang.String";
66    case JAVATYPE_BYTES  : return "com.google.protobuf.ByteString";
67    case JAVATYPE_ENUM   : return NULL;
68    case JAVATYPE_MESSAGE: return NULL;
69
70    // No default because we want the compiler to complain if any new
71    // JavaTypes are added.
72  }
73
74  GOOGLE_LOG(FATAL) << "Can't get here.";
75  return NULL;
76}
77
78void SetPrimitiveVariables(const FieldDescriptor* descriptor,
79                           int messageBitIndex,
80                           int builderBitIndex,
81                           const FieldGeneratorInfo* info,
82                           ClassNameResolver* name_resolver,
83                           map<string, string>* variables) {
84  SetCommonFieldVariables(descriptor, info, variables);
85
86  (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
87  (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
88  (*variables)["field_type"] = (*variables)["type"];
89  (*variables)["field_list_type"] = "java.util.List<" +
90      (*variables)["boxed_type"] + ">";
91  (*variables)["empty_list"] = "java.util.Collections.emptyList()";
92  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
93  (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
94      "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
95  (*variables)["capitalized_type"] =
96      GetCapitalizedType(descriptor, /* immutable = */ true);
97  (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
98  (*variables)["tag_size"] = SimpleItoa(
99      WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
100  if (IsReferenceType(GetJavaType(descriptor))) {
101    (*variables)["null_check"] =
102        "  if (value == null) {\n"
103        "    throw new NullPointerException();\n"
104        "  }\n";
105  } else {
106    (*variables)["null_check"] = "";
107  }
108  // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
109  // by the proto compiler
110  (*variables)["deprecation"] = descriptor->options().deprecated()
111      ? "@java.lang.Deprecated " : "";
112  int fixed_size = FixedSize(GetType(descriptor));
113  if (fixed_size != -1) {
114    (*variables)["fixed_size"] = SimpleItoa(fixed_size);
115  }
116  (*variables)["on_changed"] =
117      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
118
119  if (SupportFieldPresence(descriptor->file())) {
120    // For singular messages and builders, one bit is used for the hasField bit.
121    (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
122    (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
123
124    // Note that these have a trailing ";".
125    (*variables)["set_has_field_bit_message"] =
126        GenerateSetBit(messageBitIndex) + ";";
127    (*variables)["set_has_field_bit_builder"] =
128        GenerateSetBit(builderBitIndex) + ";";
129    (*variables)["clear_has_field_bit_builder"] =
130        GenerateClearBit(builderBitIndex) + ";";
131
132    (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
133  } else {
134    (*variables)["set_has_field_bit_message"] = "";
135    (*variables)["set_has_field_bit_builder"] = "";
136    (*variables)["clear_has_field_bit_builder"] = "";
137
138    if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
139      (*variables)["is_field_present_message"] =
140          "!" + (*variables)["name"] + "_.isEmpty()";
141    } else {
142      (*variables)["is_field_present_message"] =
143          (*variables)["name"] + "_ != " + (*variables)["default"];
144    }
145  }
146
147  // For repated builders, one bit is used for whether the array is immutable.
148  (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex);
149  (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex);
150  (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex);
151
152  // For repeated fields, one bit is used for whether the array is immutable
153  // in the parsing constructor.
154  (*variables)["get_mutable_bit_parser"] =
155      GenerateGetBitMutableLocal(builderBitIndex);
156  (*variables)["set_mutable_bit_parser"] =
157      GenerateSetBitMutableLocal(builderBitIndex);
158
159  (*variables)["get_has_field_bit_from_local"] =
160      GenerateGetBitFromLocal(builderBitIndex);
161  (*variables)["set_has_field_bit_to_local"] =
162      GenerateSetBitToLocal(messageBitIndex);
163}
164
165}  // namespace
166
167// ===================================================================
168
169ImmutablePrimitiveFieldGenerator::
170ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
171                                 int messageBitIndex,
172                                 int builderBitIndex,
173                                 Context* context)
174  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
175    builderBitIndex_(builderBitIndex), context_(context),
176    name_resolver_(context->GetNameResolver()) {
177  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
178                        context->GetFieldGeneratorInfo(descriptor),
179                        name_resolver_, &variables_);
180}
181
182ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
183
184int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
185  return 1;
186}
187
188int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
189  return 1;
190}
191
192void ImmutablePrimitiveFieldGenerator::
193GenerateInterfaceMembers(io::Printer* printer) const {
194  if (SupportFieldPresence(descriptor_->file())) {
195    WriteFieldDocComment(printer, descriptor_);
196    printer->Print(variables_,
197      "$deprecation$boolean has$capitalized_name$();\n");
198  }
199  WriteFieldDocComment(printer, descriptor_);
200  printer->Print(variables_,
201    "$deprecation$$type$ get$capitalized_name$();\n");
202}
203
204void ImmutablePrimitiveFieldGenerator::
205GenerateMembers(io::Printer* printer) const {
206  printer->Print(variables_,
207    "private $field_type$ $name$_;\n");
208  PrintExtraFieldInfo(variables_, printer);
209  if (SupportFieldPresence(descriptor_->file())) {
210    WriteFieldDocComment(printer, descriptor_);
211    printer->Print(variables_,
212      "$deprecation$public boolean has$capitalized_name$() {\n"
213      "  return $get_has_field_bit_message$;\n"
214      "}\n");
215  }
216
217  WriteFieldDocComment(printer, descriptor_);
218  printer->Print(variables_,
219    "$deprecation$public $type$ get$capitalized_name$() {\n"
220    "  return $name$_;\n"
221    "}\n");
222}
223
224void ImmutablePrimitiveFieldGenerator::
225GenerateBuilderMembers(io::Printer* printer) const {
226  printer->Print(variables_,
227    "private $field_type$ $name$_ $default_init$;\n");
228
229  if (SupportFieldPresence(descriptor_->file())) {
230    WriteFieldDocComment(printer, descriptor_);
231    printer->Print(variables_,
232      "$deprecation$public boolean has$capitalized_name$() {\n"
233      "  return $get_has_field_bit_builder$;\n"
234      "}\n");
235  }
236
237  WriteFieldDocComment(printer, descriptor_);
238  printer->Print(variables_,
239    "$deprecation$public $type$ get$capitalized_name$() {\n"
240    "  return $name$_;\n"
241    "}\n");
242
243  WriteFieldDocComment(printer, descriptor_);
244  printer->Print(variables_,
245    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
246    "$null_check$"
247    "  $set_has_field_bit_builder$\n"
248    "  $name$_ = value;\n"
249    "  $on_changed$\n"
250    "  return this;\n"
251    "}\n");
252
253  WriteFieldDocComment(printer, descriptor_);
254  printer->Print(variables_,
255    "$deprecation$public Builder clear$capitalized_name$() {\n"
256    "  $clear_has_field_bit_builder$\n");
257  JavaType type = GetJavaType(descriptor_);
258  if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
259    // The default value is not a simple literal so we want to avoid executing
260    // it multiple times.  Instead, get the default out of the default instance.
261    printer->Print(variables_,
262      "  $name$_ = getDefaultInstance().get$capitalized_name$();\n");
263  } else {
264    printer->Print(variables_,
265      "  $name$_ = $default$;\n");
266  }
267  printer->Print(variables_,
268    "  $on_changed$\n"
269    "  return this;\n"
270    "}\n");
271}
272
273void ImmutablePrimitiveFieldGenerator::
274GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
275  // noop for primitives
276}
277
278void ImmutablePrimitiveFieldGenerator::
279GenerateInitializationCode(io::Printer* printer) const {
280  printer->Print(variables_, "$name$_ = $default$;\n");
281}
282
283void ImmutablePrimitiveFieldGenerator::
284GenerateBuilderClearCode(io::Printer* printer) const {
285  printer->Print(variables_,
286    "$name$_ = $default$;\n"
287    "$clear_has_field_bit_builder$\n");
288}
289
290void ImmutablePrimitiveFieldGenerator::
291GenerateMergingCode(io::Printer* printer) const {
292  if (SupportFieldPresence(descriptor_->file())) {
293    printer->Print(variables_,
294      "if (other.has$capitalized_name$()) {\n"
295      "  set$capitalized_name$(other.get$capitalized_name$());\n"
296      "}\n");
297  } else {
298    printer->Print(variables_,
299      "if (other.get$capitalized_name$() != $default$) {\n"
300      "  set$capitalized_name$(other.get$capitalized_name$());\n"
301      "}\n");
302  }
303}
304
305void ImmutablePrimitiveFieldGenerator::
306GenerateBuildingCode(io::Printer* printer) const {
307  if (SupportFieldPresence(descriptor_->file())) {
308    printer->Print(variables_,
309      "if ($get_has_field_bit_from_local$) {\n"
310      "  $set_has_field_bit_to_local$;\n"
311      "}\n");
312  }
313  printer->Print(variables_,
314    "result.$name$_ = $name$_;\n");
315}
316
317void ImmutablePrimitiveFieldGenerator::
318GenerateParsingCode(io::Printer* printer) const {
319  printer->Print(variables_,
320    "$set_has_field_bit_message$\n"
321    "$name$_ = input.read$capitalized_type$();\n");
322}
323
324void ImmutablePrimitiveFieldGenerator::
325GenerateParsingDoneCode(io::Printer* printer) const {
326  // noop for primitives.
327}
328
329void ImmutablePrimitiveFieldGenerator::
330GenerateSerializationCode(io::Printer* printer) const {
331  printer->Print(variables_,
332    "if ($is_field_present_message$) {\n"
333    "  output.write$capitalized_type$($number$, $name$_);\n"
334    "}\n");
335}
336
337void ImmutablePrimitiveFieldGenerator::
338GenerateSerializedSizeCode(io::Printer* printer) const {
339  printer->Print(variables_,
340    "if ($is_field_present_message$) {\n"
341    "  size += com.google.protobuf.CodedOutputStream\n"
342    "    .compute$capitalized_type$Size($number$, $name$_);\n"
343    "}\n");
344}
345
346void ImmutablePrimitiveFieldGenerator::
347GenerateEqualsCode(io::Printer* printer) const {
348  switch (GetJavaType(descriptor_)) {
349    case JAVATYPE_INT:
350    case JAVATYPE_LONG:
351    case JAVATYPE_BOOLEAN:
352      printer->Print(variables_,
353        "result = result && (get$capitalized_name$()\n"
354        "    == other.get$capitalized_name$());\n");
355      break;
356
357    case JAVATYPE_FLOAT:
358      printer->Print(variables_,
359        "result = result && (\n"
360        "    java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
361        "    == java.lang.Float.floatToIntBits(\n"
362        "        other.get$capitalized_name$()));\n");
363      break;
364
365    case JAVATYPE_DOUBLE:
366      printer->Print(variables_,
367        "result = result && (\n"
368        "    java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
369        "    == java.lang.Double.doubleToLongBits(\n"
370        "        other.get$capitalized_name$()));\n");
371      break;
372
373    case JAVATYPE_STRING:
374    case JAVATYPE_BYTES:
375      printer->Print(variables_,
376        "result = result && get$capitalized_name$()\n"
377        "    .equals(other.get$capitalized_name$());\n");
378      break;
379
380    case JAVATYPE_ENUM:
381    case JAVATYPE_MESSAGE:
382    default:
383      GOOGLE_LOG(FATAL) << "Can't get here.";
384      break;
385  }
386}
387
388void ImmutablePrimitiveFieldGenerator::
389GenerateHashCode(io::Printer* printer) const {
390  printer->Print(variables_,
391    "hash = (37 * hash) + $constant_name$;\n");
392  switch (GetJavaType(descriptor_)) {
393    case JAVATYPE_INT:
394      printer->Print(variables_,
395        "hash = (53 * hash) + get$capitalized_name$();\n");
396      break;
397
398    case JAVATYPE_LONG:
399      printer->Print(variables_,
400        "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
401        "    get$capitalized_name$());\n");
402      break;
403
404    case JAVATYPE_BOOLEAN:
405      printer->Print(variables_,
406        "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
407        "    get$capitalized_name$());\n");
408      break;
409
410    case JAVATYPE_FLOAT:
411      printer->Print(variables_,
412        "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
413        "    get$capitalized_name$());\n");
414      break;
415
416    case JAVATYPE_DOUBLE:
417      printer->Print(variables_,
418        "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
419        "    java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
420      break;
421
422    case JAVATYPE_STRING:
423    case JAVATYPE_BYTES:
424      printer->Print(variables_,
425        "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
426      break;
427
428    case JAVATYPE_ENUM:
429    case JAVATYPE_MESSAGE:
430    default:
431      GOOGLE_LOG(FATAL) << "Can't get here.";
432      break;
433  }
434}
435
436string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
437  return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
438}
439
440// ===================================================================
441
442ImmutablePrimitiveOneofFieldGenerator::
443ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
444                                 int messageBitIndex,
445                                 int builderBitIndex,
446                                 Context* context)
447    : ImmutablePrimitiveFieldGenerator(
448          descriptor, messageBitIndex, builderBitIndex, context) {
449  const OneofGeneratorInfo* info =
450      context->GetOneofGeneratorInfo(descriptor->containing_oneof());
451  SetCommonOneofVariables(descriptor, info, &variables_);
452}
453
454ImmutablePrimitiveOneofFieldGenerator::
455~ImmutablePrimitiveOneofFieldGenerator() {}
456
457void ImmutablePrimitiveOneofFieldGenerator::
458GenerateMembers(io::Printer* printer) const {
459  PrintExtraFieldInfo(variables_, printer);
460  if (SupportFieldPresence(descriptor_->file())) {
461    WriteFieldDocComment(printer, descriptor_);
462    printer->Print(variables_,
463      "$deprecation$public boolean has$capitalized_name$() {\n"
464      "  return $has_oneof_case_message$;\n"
465      "}\n");
466  }
467
468  WriteFieldDocComment(printer, descriptor_);
469  printer->Print(variables_,
470    "$deprecation$public $type$ get$capitalized_name$() {\n"
471    "  if ($has_oneof_case_message$) {\n"
472    "    return ($boxed_type$) $oneof_name$_;\n"
473    "  }\n"
474    "  return $default$;\n"
475    "}\n");
476}
477
478
479void ImmutablePrimitiveOneofFieldGenerator::
480GenerateBuilderMembers(io::Printer* printer) const {
481  if (SupportFieldPresence(descriptor_->file())) {
482    WriteFieldDocComment(printer, descriptor_);
483    printer->Print(variables_,
484      "$deprecation$public boolean has$capitalized_name$() {\n"
485      "  return $has_oneof_case_message$;\n"
486      "}\n");
487  }
488
489  WriteFieldDocComment(printer, descriptor_);
490  printer->Print(variables_,
491    "$deprecation$public $type$ get$capitalized_name$() {\n"
492    "  if ($has_oneof_case_message$) {\n"
493    "    return ($boxed_type$) $oneof_name$_;\n"
494    "  }\n"
495    "  return $default$;\n"
496    "}\n");
497
498  WriteFieldDocComment(printer, descriptor_);
499  printer->Print(variables_,
500    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
501    "$null_check$"
502    "  $set_oneof_case_message$;\n"
503    "  $oneof_name$_ = value;\n"
504    "  $on_changed$\n"
505    "  return this;\n"
506    "}\n");
507
508  WriteFieldDocComment(printer, descriptor_);
509  printer->Print(variables_,
510    "$deprecation$public Builder clear$capitalized_name$() {\n"
511    "  if ($has_oneof_case_message$) {\n"
512    "    $clear_oneof_case_message$;\n"
513    "    $oneof_name$_ = null;\n"
514    "    $on_changed$\n"
515    "  }\n"
516    "  return this;\n"
517    "}\n");
518}
519
520void ImmutablePrimitiveOneofFieldGenerator::
521GenerateBuildingCode(io::Printer* printer) const {
522  printer->Print(variables_,
523    "if ($has_oneof_case_message$) {\n"
524    "  result.$oneof_name$_ = $oneof_name$_;\n"
525    "}\n");
526}
527
528void ImmutablePrimitiveOneofFieldGenerator::
529GenerateMergingCode(io::Printer* printer) const {
530  printer->Print(variables_,
531    "set$capitalized_name$(other.get$capitalized_name$());\n");
532}
533
534void ImmutablePrimitiveOneofFieldGenerator::
535GenerateParsingCode(io::Printer* printer) const {
536  printer->Print(variables_,
537    "$set_oneof_case_message$;\n"
538    "$oneof_name$_ = input.read$capitalized_type$();\n");
539}
540
541void ImmutablePrimitiveOneofFieldGenerator::
542GenerateSerializationCode(io::Printer* printer) const {
543  printer->Print(variables_,
544    "if ($has_oneof_case_message$) {\n"
545    "  output.write$capitalized_type$(\n"
546    "      $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
547    "}\n");
548}
549
550void ImmutablePrimitiveOneofFieldGenerator::
551GenerateSerializedSizeCode(io::Printer* printer) const {
552  printer->Print(variables_,
553    "if ($has_oneof_case_message$) {\n"
554    "  size += com.google.protobuf.CodedOutputStream\n"
555    "    .compute$capitalized_type$Size(\n"
556    "        $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
557    "}\n");
558}
559
560// ===================================================================
561
562RepeatedImmutablePrimitiveFieldGenerator::
563RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
564                                         int messageBitIndex,
565                                         int builderBitIndex,
566                                         Context* context)
567  : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
568    builderBitIndex_(builderBitIndex), context_(context),
569    name_resolver_(context->GetNameResolver()) {
570  SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
571                        context->GetFieldGeneratorInfo(descriptor),
572                        name_resolver_, &variables_);
573}
574
575RepeatedImmutablePrimitiveFieldGenerator::
576~RepeatedImmutablePrimitiveFieldGenerator() {}
577
578int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
579  return 0;
580}
581
582int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
583  return 1;
584}
585
586void RepeatedImmutablePrimitiveFieldGenerator::
587GenerateInterfaceMembers(io::Printer* printer) const {
588  WriteFieldDocComment(printer, descriptor_);
589  printer->Print(variables_,
590    "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
591  WriteFieldDocComment(printer, descriptor_);
592  printer->Print(variables_,
593    "$deprecation$int get$capitalized_name$Count();\n");
594  WriteFieldDocComment(printer, descriptor_);
595  printer->Print(variables_,
596    "$deprecation$$type$ get$capitalized_name$(int index);\n");
597}
598
599
600void RepeatedImmutablePrimitiveFieldGenerator::
601GenerateMembers(io::Printer* printer) const {
602  printer->Print(variables_,
603    "private $field_list_type$ $name$_;\n");
604  PrintExtraFieldInfo(variables_, printer);
605  WriteFieldDocComment(printer, descriptor_);
606  printer->Print(variables_,
607    "$deprecation$public java.util.List<$boxed_type$>\n"
608    "    get$capitalized_name$List() {\n"
609    "  return $name$_;\n"   // note:  unmodifiable list
610    "}\n");
611  WriteFieldDocComment(printer, descriptor_);
612  printer->Print(variables_,
613    "$deprecation$public int get$capitalized_name$Count() {\n"
614    "  return $name$_.size();\n"
615    "}\n");
616  WriteFieldDocComment(printer, descriptor_);
617  printer->Print(variables_,
618    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
619    "  return $name$_.get(index);\n"
620    "}\n");
621
622  if (descriptor_->options().packed() &&
623      HasGeneratedMethods(descriptor_->containing_type())) {
624    printer->Print(variables_,
625      "private int $name$MemoizedSerializedSize = -1;\n");
626  }
627}
628
629void RepeatedImmutablePrimitiveFieldGenerator::
630GenerateBuilderMembers(io::Printer* printer) const {
631  // One field is the list and the bit field keeps track of whether the
632  // list is immutable. If it's immutable, the invariant is that it must
633  // either an instance of Collections.emptyList() or it's an ArrayList
634  // wrapped in a Collections.unmodifiableList() wrapper and nobody else has
635  // a refererence to the underlying ArrayList. This invariant allows us to
636  // share instances of lists between protocol buffers avoiding expensive
637  // memory allocations. Note, immutable is a strong guarantee here -- not
638  // just that the list cannot be modified via the reference but that the
639  // list can never be modified.
640  printer->Print(variables_,
641    "private $field_list_type$ $name$_ = $empty_list$;\n");
642
643  printer->Print(variables_,
644    "private void ensure$capitalized_name$IsMutable() {\n"
645    "  if (!$get_mutable_bit_builder$) {\n"
646    "    $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n"
647    "    $set_mutable_bit_builder$;\n"
648    "   }\n"
649    "}\n");
650
651    // Note:  We return an unmodifiable list because otherwise the caller
652    //   could hold on to the returned list and modify it after the message
653    //   has been built, thus mutating the message which is supposed to be
654    //   immutable.
655  WriteFieldDocComment(printer, descriptor_);
656  printer->Print(variables_,
657    "$deprecation$public java.util.List<$boxed_type$>\n"
658    "    get$capitalized_name$List() {\n"
659    "  return java.util.Collections.unmodifiableList($name$_);\n"
660    "}\n");
661  WriteFieldDocComment(printer, descriptor_);
662  printer->Print(variables_,
663    "$deprecation$public int get$capitalized_name$Count() {\n"
664    "  return $name$_.size();\n"
665    "}\n");
666  WriteFieldDocComment(printer, descriptor_);
667  printer->Print(variables_,
668    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
669    "  return $name$_.get(index);\n"
670    "}\n");
671  WriteFieldDocComment(printer, descriptor_);
672  printer->Print(variables_,
673    "$deprecation$public Builder set$capitalized_name$(\n"
674    "    int index, $type$ value) {\n"
675    "$null_check$"
676    "  ensure$capitalized_name$IsMutable();\n"
677    "  $name$_.set(index, value);\n"
678    "  $on_changed$\n"
679    "  return this;\n"
680    "}\n");
681  WriteFieldDocComment(printer, descriptor_);
682  printer->Print(variables_,
683    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
684    "$null_check$"
685    "  ensure$capitalized_name$IsMutable();\n"
686    "  $name$_.add(value);\n"
687    "  $on_changed$\n"
688    "  return this;\n"
689    "}\n");
690  WriteFieldDocComment(printer, descriptor_);
691  printer->Print(variables_,
692    "$deprecation$public Builder addAll$capitalized_name$(\n"
693    "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
694    "  ensure$capitalized_name$IsMutable();\n"
695    "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
696    "      values, $name$_);\n"
697    "  $on_changed$\n"
698    "  return this;\n"
699    "}\n");
700  WriteFieldDocComment(printer, descriptor_);
701  printer->Print(variables_,
702    "$deprecation$public Builder clear$capitalized_name$() {\n"
703    "  $name$_ = $empty_list$;\n"
704    "  $clear_mutable_bit_builder$;\n"
705    "  $on_changed$\n"
706    "  return this;\n"
707    "}\n");
708}
709
710void RepeatedImmutablePrimitiveFieldGenerator::
711GenerateFieldBuilderInitializationCode(io::Printer* printer)  const {
712  // noop for primitives
713}
714
715void RepeatedImmutablePrimitiveFieldGenerator::
716GenerateInitializationCode(io::Printer* printer) const {
717  printer->Print(variables_, "$name$_ = $empty_list$;\n");
718}
719
720void RepeatedImmutablePrimitiveFieldGenerator::
721GenerateBuilderClearCode(io::Printer* printer) const {
722  printer->Print(variables_,
723    "$name$_ = $empty_list$;\n"
724    "$clear_mutable_bit_builder$;\n");
725}
726
727void RepeatedImmutablePrimitiveFieldGenerator::
728GenerateMergingCode(io::Printer* printer) const {
729  // The code below does two optimizations:
730  //   1. If the other list is empty, there's nothing to do. This ensures we
731  //      don't allocate a new array if we already have an immutable one.
732  //   2. If the other list is non-empty and our current list is empty, we can
733  //      reuse the other list which is guaranteed to be immutable.
734  printer->Print(variables_,
735    "if (!other.$name$_.isEmpty()) {\n"
736    "  if ($name$_.isEmpty()) {\n"
737    "    $name$_ = other.$name$_;\n"
738    "    $clear_mutable_bit_builder$;\n"
739    "  } else {\n"
740    "    ensure$capitalized_name$IsMutable();\n"
741    "    $name$_.addAll(other.$name$_);\n"
742    "  }\n"
743    "  $on_changed$\n"
744    "}\n");
745}
746
747void RepeatedImmutablePrimitiveFieldGenerator::
748GenerateBuildingCode(io::Printer* printer) const {
749  // The code below ensures that the result has an immutable list. If our
750  // list is immutable, we can just reuse it. If not, we make it immutable.
751  printer->Print(variables_,
752    "if ($get_mutable_bit_builder$) {\n"
753    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
754    "  $clear_mutable_bit_builder$;\n"
755    "}\n"
756    "result.$name$_ = $name$_;\n");
757}
758
759void RepeatedImmutablePrimitiveFieldGenerator::
760GenerateParsingCode(io::Printer* printer) const {
761  printer->Print(variables_,
762    "if (!$get_mutable_bit_parser$) {\n"
763    "  $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
764    "  $set_mutable_bit_parser$;\n"
765    "}\n"
766    "$name$_.add(input.read$capitalized_type$());\n");
767}
768
769void RepeatedImmutablePrimitiveFieldGenerator::
770GenerateParsingCodeFromPacked(io::Printer* printer) const {
771  printer->Print(variables_,
772    "int length = input.readRawVarint32();\n"
773    "int limit = input.pushLimit(length);\n"
774    "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n"
775    "  $name$_ = new java.util.ArrayList<$boxed_type$>();\n"
776    "  $set_mutable_bit_parser$;\n"
777    "}\n"
778    "while (input.getBytesUntilLimit() > 0) {\n"
779    "  $name$_.add(input.read$capitalized_type$());\n"
780    "}\n"
781    "input.popLimit(limit);\n");
782}
783
784void RepeatedImmutablePrimitiveFieldGenerator::
785GenerateParsingDoneCode(io::Printer* printer) const {
786  printer->Print(variables_,
787    "if ($get_mutable_bit_parser$) {\n"
788    "  $name$_ = java.util.Collections.unmodifiableList($name$_);\n"
789    "}\n");
790}
791
792void RepeatedImmutablePrimitiveFieldGenerator::
793GenerateSerializationCode(io::Printer* printer) const {
794  if (descriptor_->options().packed()) {
795    printer->Print(variables_,
796      "if (get$capitalized_name$List().size() > 0) {\n"
797      "  output.writeRawVarint32($tag$);\n"
798      "  output.writeRawVarint32($name$MemoizedSerializedSize);\n"
799      "}\n"
800      "for (int i = 0; i < $name$_.size(); i++) {\n"
801      "  output.write$capitalized_type$NoTag($name$_.get(i));\n"
802      "}\n");
803  } else {
804    printer->Print(variables_,
805      "for (int i = 0; i < $name$_.size(); i++) {\n"
806      "  output.write$capitalized_type$($number$, $name$_.get(i));\n"
807      "}\n");
808  }
809}
810
811void RepeatedImmutablePrimitiveFieldGenerator::
812GenerateSerializedSizeCode(io::Printer* printer) const {
813  printer->Print(variables_,
814    "{\n"
815    "  int dataSize = 0;\n");
816  printer->Indent();
817
818  if (FixedSize(GetType(descriptor_)) == -1) {
819    printer->Print(variables_,
820      "for (int i = 0; i < $name$_.size(); i++) {\n"
821      "  dataSize += com.google.protobuf.CodedOutputStream\n"
822      "    .compute$capitalized_type$SizeNoTag($name$_.get(i));\n"
823      "}\n");
824  } else {
825    printer->Print(variables_,
826      "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
827  }
828
829  printer->Print(
830      "size += dataSize;\n");
831
832  if (descriptor_->options().packed()) {
833    printer->Print(variables_,
834      "if (!get$capitalized_name$List().isEmpty()) {\n"
835      "  size += $tag_size$;\n"
836      "  size += com.google.protobuf.CodedOutputStream\n"
837      "      .computeInt32SizeNoTag(dataSize);\n"
838      "}\n");
839  } else {
840    printer->Print(variables_,
841      "size += $tag_size$ * get$capitalized_name$List().size();\n");
842  }
843
844  // cache the data size for packed fields.
845  if (descriptor_->options().packed()) {
846    printer->Print(variables_,
847      "$name$MemoizedSerializedSize = dataSize;\n");
848  }
849
850  printer->Outdent();
851  printer->Print("}\n");
852}
853
854void RepeatedImmutablePrimitiveFieldGenerator::
855GenerateEqualsCode(io::Printer* printer) const {
856  printer->Print(variables_,
857    "result = result && get$capitalized_name$List()\n"
858    "    .equals(other.get$capitalized_name$List());\n");
859}
860
861void RepeatedImmutablePrimitiveFieldGenerator::
862GenerateHashCode(io::Printer* printer) const {
863  printer->Print(variables_,
864    "if (get$capitalized_name$Count() > 0) {\n"
865    "  hash = (37 * hash) + $constant_name$;\n"
866    "  hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
867    "}\n");
868}
869
870string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const {
871  return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
872}
873
874}  // namespace java
875}  // namespace compiler
876}  // namespace protobuf
877}  // namespace google
878