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