• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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: dweis@google.com (Daniel Weis)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/compiler/java/java_message_builder.h>
36 
37 #include <algorithm>
38 #include <google/protobuf/stubs/hash.h>
39 #include <map>
40 #include <memory>
41 #ifndef _SHARED_PTR_H
42 #include <google/protobuf/stubs/shared_ptr.h>
43 #endif
44 #include <vector>
45 
46 #include <google/protobuf/compiler/java/java_context.h>
47 #include <google/protobuf/compiler/java/java_doc_comment.h>
48 #include <google/protobuf/compiler/java/java_enum.h>
49 #include <google/protobuf/compiler/java/java_extension.h>
50 #include <google/protobuf/compiler/java/java_generator_factory.h>
51 #include <google/protobuf/compiler/java/java_helpers.h>
52 #include <google/protobuf/compiler/java/java_name_resolver.h>
53 #include <google/protobuf/io/coded_stream.h>
54 #include <google/protobuf/io/printer.h>
55 #include <google/protobuf/descriptor.pb.h>
56 #include <google/protobuf/wire_format.h>
57 #include <google/protobuf/stubs/strutil.h>
58 #include <google/protobuf/stubs/substitute.h>
59 
60 namespace google {
61 namespace protobuf {
62 namespace compiler {
63 namespace java {
64 
65 namespace {
GenerateHasBits(const Descriptor * descriptor)66 bool GenerateHasBits(const Descriptor* descriptor) {
67   return SupportFieldPresence(descriptor->file()) ||
68       HasRepeatedFields(descriptor);
69 }
70 
MapValueImmutableClassdName(const Descriptor * descriptor,ClassNameResolver * name_resolver)71 string MapValueImmutableClassdName(const Descriptor* descriptor,
72                                    ClassNameResolver* name_resolver) {
73   const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
74   GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
75   return name_resolver->GetImmutableClassName(value_field->message_type());
76 }
77 }  // namespace
78 
MessageBuilderGenerator(const Descriptor * descriptor,Context * context)79 MessageBuilderGenerator::MessageBuilderGenerator(
80     const Descriptor* descriptor, Context* context)
81   : descriptor_(descriptor), context_(context),
82     name_resolver_(context->GetNameResolver()),
83     field_generators_(descriptor, context_) {
84   GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
85       << "Generator factory error: A non-lite message generator is used to "
86          "generate lite messages.";
87 }
88 
~MessageBuilderGenerator()89 MessageBuilderGenerator::~MessageBuilderGenerator() {}
90 
91 void MessageBuilderGenerator::
Generate(io::Printer * printer)92 Generate(io::Printer* printer) {
93   WriteMessageDocComment(printer, descriptor_);
94   if (descriptor_->extension_range_count() > 0) {
95     printer->Print(
96       "public static final class Builder extends\n"
97       "    com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
98       "      $classname$, Builder> implements\n"
99       "    $extra_interfaces$\n"
100       "    $classname$OrBuilder {\n",
101       "classname", name_resolver_->GetImmutableClassName(descriptor_),
102       "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
103   } else {
104     printer->Print(
105       "public static final class Builder extends\n"
106       "    com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
107       "    $extra_interfaces$\n"
108       "    $classname$OrBuilder {\n",
109       "classname", name_resolver_->GetImmutableClassName(descriptor_),
110       "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
111   }
112   printer->Indent();
113 
114   GenerateDescriptorMethods(printer);
115   GenerateCommonBuilderMethods(printer);
116 
117   if (context_->HasGeneratedMethods(descriptor_)) {
118     GenerateIsInitialized(printer);
119     GenerateBuilderParsingMethods(printer);
120   }
121 
122   // oneof
123   map<string, string> vars;
124   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
125     vars["oneof_name"] = context_->GetOneofGeneratorInfo(
126         descriptor_->oneof_decl(i))->name;
127     vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
128         descriptor_->oneof_decl(i))->capitalized_name;
129     vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
130     // oneofCase_ and oneof_
131     printer->Print(vars,
132       "private int $oneof_name$Case_ = 0;\n"
133       "private java.lang.Object $oneof_name$_;\n");
134     // oneofCase() and clearOneof()
135     printer->Print(vars,
136       "public $oneof_capitalized_name$Case\n"
137       "    get$oneof_capitalized_name$Case() {\n"
138       "  return $oneof_capitalized_name$Case.forNumber(\n"
139       "      $oneof_name$Case_);\n"
140       "}\n"
141       "\n"
142       "public Builder clear$oneof_capitalized_name$() {\n"
143       "  $oneof_name$Case_ = 0;\n"
144       "  $oneof_name$_ = null;\n");
145     printer->Print("  onChanged();\n");
146     printer->Print(
147       "  return this;\n"
148       "}\n"
149       "\n");
150   }
151 
152   if (GenerateHasBits(descriptor_)) {
153     // Integers for bit fields.
154     int totalBits = 0;
155     for (int i = 0; i < descriptor_->field_count(); i++) {
156       totalBits += field_generators_.get(descriptor_->field(i))
157           .GetNumBitsForBuilder();
158     }
159     int totalInts = (totalBits + 31) / 32;
160     for (int i = 0; i < totalInts; i++) {
161       printer->Print("private int $bit_field_name$;\n",
162         "bit_field_name", GetBitFieldName(i));
163     }
164   }
165 
166   for (int i = 0; i < descriptor_->field_count(); i++) {
167     printer->Print("\n");
168     field_generators_.get(descriptor_->field(i))
169                      .GenerateBuilderMembers(printer);
170   }
171 
172   if (!PreserveUnknownFields(descriptor_)) {
173     printer->Print(
174       "public final Builder setUnknownFields(\n"
175       "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
176       "  return this;\n"
177       "}\n"
178       "\n"
179       "public final Builder mergeUnknownFields(\n"
180       "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
181       "  return this;\n"
182       "}\n"
183       "\n");
184   }
185 
186   printer->Print(
187     "\n"
188     "// @@protoc_insertion_point(builder_scope:$full_name$)\n",
189     "full_name", descriptor_->full_name());
190 
191   printer->Outdent();
192   printer->Print("}\n");
193 }
194 
195 // ===================================================================
196 
197 void MessageBuilderGenerator::
GenerateDescriptorMethods(io::Printer * printer)198 GenerateDescriptorMethods(io::Printer* printer) {
199   if (!descriptor_->options().no_standard_descriptor_accessor()) {
200     printer->Print(
201       "public static final com.google.protobuf.Descriptors.Descriptor\n"
202       "    getDescriptor() {\n"
203       "  return $fileclass$.internal_$identifier$_descriptor;\n"
204       "}\n"
205       "\n",
206       "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
207       "identifier", UniqueFileScopeIdentifier(descriptor_));
208   }
209   vector<const FieldDescriptor*> map_fields;
210   for (int i = 0; i < descriptor_->field_count(); i++) {
211     const FieldDescriptor* field = descriptor_->field(i);
212     if (GetJavaType(field) == JAVATYPE_MESSAGE &&
213         IsMapEntry(field->message_type())) {
214       map_fields.push_back(field);
215     }
216   }
217   if (!map_fields.empty()) {
218     printer->Print(
219       "@SuppressWarnings({\"rawtypes\"})\n"
220       "protected com.google.protobuf.MapField internalGetMapField(\n"
221       "    int number) {\n"
222       "  switch (number) {\n");
223     printer->Indent();
224     printer->Indent();
225     for (int i = 0; i < map_fields.size(); ++i) {
226       const FieldDescriptor* field = map_fields[i];
227       const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
228       printer->Print(
229         "case $number$:\n"
230         "  return internalGet$capitalized_name$();\n",
231         "number", SimpleItoa(field->number()),
232         "capitalized_name", info->capitalized_name);
233     }
234     printer->Print(
235         "default:\n"
236         "  throw new RuntimeException(\n"
237         "      \"Invalid map field number: \" + number);\n");
238     printer->Outdent();
239     printer->Outdent();
240     printer->Print(
241         "  }\n"
242         "}\n");
243     printer->Print(
244       "@SuppressWarnings({\"rawtypes\"})\n"
245       "protected com.google.protobuf.MapField internalGetMutableMapField(\n"
246       "    int number) {\n"
247       "  switch (number) {\n");
248     printer->Indent();
249     printer->Indent();
250     for (int i = 0; i < map_fields.size(); ++i) {
251       const FieldDescriptor* field = map_fields[i];
252       const FieldGeneratorInfo* info =
253           context_->GetFieldGeneratorInfo(field);
254       printer->Print(
255         "case $number$:\n"
256         "  return internalGetMutable$capitalized_name$();\n",
257         "number", SimpleItoa(field->number()),
258         "capitalized_name", info->capitalized_name);
259     }
260     printer->Print(
261         "default:\n"
262         "  throw new RuntimeException(\n"
263         "      \"Invalid map field number: \" + number);\n");
264     printer->Outdent();
265     printer->Outdent();
266     printer->Print(
267         "  }\n"
268         "}\n");
269   }
270   printer->Print(
271     "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
272     "    internalGetFieldAccessorTable() {\n"
273     "  return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
274     "      .ensureFieldAccessorsInitialized(\n"
275     "          $classname$.class, $classname$.Builder.class);\n"
276     "}\n"
277     "\n",
278     "classname", name_resolver_->GetImmutableClassName(descriptor_),
279     "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
280     "identifier", UniqueFileScopeIdentifier(descriptor_));
281 }
282 
283 // ===================================================================
284 
285 void MessageBuilderGenerator::
GenerateCommonBuilderMethods(io::Printer * printer)286 GenerateCommonBuilderMethods(io::Printer* printer) {
287   printer->Print(
288       "// Construct using $classname$.newBuilder()\n"
289       "private Builder() {\n"
290       "  maybeForceBuilderInitialization();\n"
291       "}\n"
292       "\n",
293       "classname", name_resolver_->GetImmutableClassName(descriptor_));
294 
295   printer->Print(
296     "private Builder(\n"
297     "    com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
298     "  super(parent);\n"
299     "  maybeForceBuilderInitialization();\n"
300     "}\n",
301     "classname", name_resolver_->GetImmutableClassName(descriptor_));
302 
303   printer->Print(
304     "private void maybeForceBuilderInitialization() {\n"
305     "  if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
306 
307   printer->Indent();
308   printer->Indent();
309   for (int i = 0; i < descriptor_->field_count(); i++) {
310     if (!descriptor_->field(i)->containing_oneof()) {
311       field_generators_.get(descriptor_->field(i))
312           .GenerateFieldBuilderInitializationCode(printer);
313     }
314   }
315   printer->Outdent();
316   printer->Outdent();
317 
318   printer->Print(
319     "  }\n"
320     "}\n");
321 
322   printer->Print(
323     "public Builder clear() {\n"
324     "  super.clear();\n");
325 
326   printer->Indent();
327 
328   for (int i = 0; i < descriptor_->field_count(); i++) {
329     if (!descriptor_->field(i)->containing_oneof()) {
330       field_generators_.get(descriptor_->field(i))
331           .GenerateBuilderClearCode(printer);
332     }
333   }
334 
335   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
336     printer->Print(
337       "$oneof_name$Case_ = 0;\n"
338       "$oneof_name$_ = null;\n",
339       "oneof_name", context_->GetOneofGeneratorInfo(
340           descriptor_->oneof_decl(i))->name);
341   }
342 
343   printer->Outdent();
344 
345   printer->Print(
346     "  return this;\n"
347     "}\n"
348     "\n");
349 
350   printer->Print(
351     "public com.google.protobuf.Descriptors.Descriptor\n"
352     "    getDescriptorForType() {\n"
353     "  return $fileclass$.internal_$identifier$_descriptor;\n"
354     "}\n"
355     "\n",
356     "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
357     "identifier", UniqueFileScopeIdentifier(descriptor_));
358 
359   // LITE runtime implements this in GeneratedMessageLite.
360   printer->Print(
361     "public $classname$ getDefaultInstanceForType() {\n"
362     "  return $classname$.getDefaultInstance();\n"
363     "}\n"
364     "\n",
365     "classname", name_resolver_->GetImmutableClassName(descriptor_));
366 
367   printer->Print(
368     "public $classname$ build() {\n"
369     "  $classname$ result = buildPartial();\n"
370     "  if (!result.isInitialized()) {\n"
371     "    throw newUninitializedMessageException(result);\n"
372     "  }\n"
373     "  return result;\n"
374     "}\n"
375     "\n",
376     "classname", name_resolver_->GetImmutableClassName(descriptor_));
377 
378   printer->Print(
379     "public $classname$ buildPartial() {\n"
380     "  $classname$ result = new $classname$(this);\n",
381     "classname", name_resolver_->GetImmutableClassName(descriptor_));
382 
383   printer->Indent();
384 
385   int totalBuilderBits = 0;
386   int totalMessageBits = 0;
387   for (int i = 0; i < descriptor_->field_count(); i++) {
388     const ImmutableFieldGenerator& field =
389         field_generators_.get(descriptor_->field(i));
390     totalBuilderBits += field.GetNumBitsForBuilder();
391     totalMessageBits += field.GetNumBitsForMessage();
392   }
393   int totalBuilderInts = (totalBuilderBits + 31) / 32;
394   int totalMessageInts = (totalMessageBits + 31) / 32;
395 
396   if (GenerateHasBits(descriptor_)) {
397     // Local vars for from and to bit fields to avoid accessing the builder and
398     // message over and over for these fields. Seems to provide a slight
399     // perforamance improvement in micro benchmark and this is also what proto1
400     // code does.
401     for (int i = 0; i < totalBuilderInts; i++) {
402       printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
403         "bit_field_name", GetBitFieldName(i));
404     }
405     for (int i = 0; i < totalMessageInts; i++) {
406       printer->Print("int to_$bit_field_name$ = 0;\n",
407         "bit_field_name", GetBitFieldName(i));
408     }
409   }
410 
411   // Output generation code for each field.
412   for (int i = 0; i < descriptor_->field_count(); i++) {
413     field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
414   }
415 
416   if (GenerateHasBits(descriptor_)) {
417     // Copy the bit field results to the generated message
418     for (int i = 0; i < totalMessageInts; i++) {
419       printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
420         "bit_field_name", GetBitFieldName(i));
421     }
422   }
423 
424   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
425     printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n",
426                    "oneof_name", context_->GetOneofGeneratorInfo(
427                        descriptor_->oneof_decl(i))->name);
428   }
429 
430   printer->Outdent();
431 
432   printer->Print(
433     "  onBuilt();\n");
434 
435   printer->Print(
436     "  return result;\n"
437     "}\n"
438     "\n",
439     "classname", name_resolver_->GetImmutableClassName(descriptor_));
440 
441   // -----------------------------------------------------------------
442 
443   if (context_->HasGeneratedMethods(descriptor_)) {
444     printer->Print(
445       "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
446       "  if (other instanceof $classname$) {\n"
447       "    return mergeFrom(($classname$)other);\n"
448       "  } else {\n"
449       "    super.mergeFrom(other);\n"
450       "    return this;\n"
451       "  }\n"
452       "}\n"
453       "\n",
454       "classname", name_resolver_->GetImmutableClassName(descriptor_));
455 
456     printer->Print(
457       "public Builder mergeFrom($classname$ other) {\n"
458       // Optimization:  If other is the default instance, we know none of its
459       //   fields are set so we can skip the merge.
460       "  if (other == $classname$.getDefaultInstance()) return this;\n",
461       "classname", name_resolver_->GetImmutableClassName(descriptor_));
462     printer->Indent();
463 
464     for (int i = 0; i < descriptor_->field_count(); i++) {
465       if (!descriptor_->field(i)->containing_oneof()) {
466         field_generators_.get(
467             descriptor_->field(i)).GenerateMergingCode(printer);
468       }
469     }
470 
471     // Merge oneof fields.
472     for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
473       printer->Print(
474         "switch (other.get$oneof_capitalized_name$Case()) {\n",
475         "oneof_capitalized_name",
476         context_->GetOneofGeneratorInfo(
477             descriptor_->oneof_decl(i))->capitalized_name);
478       printer->Indent();
479       for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
480         const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
481         printer->Print(
482           "case $field_name$: {\n",
483           "field_name",
484           ToUpper(field->name()));
485         printer->Indent();
486         field_generators_.get(field).GenerateMergingCode(printer);
487         printer->Print(
488             "break;\n");
489         printer->Outdent();
490         printer->Print(
491             "}\n");
492       }
493       printer->Print(
494         "case $cap_oneof_name$_NOT_SET: {\n"
495         "  break;\n"
496         "}\n",
497         "cap_oneof_name",
498         ToUpper(context_->GetOneofGeneratorInfo(
499             descriptor_->oneof_decl(i))->name));
500       printer->Outdent();
501       printer->Print(
502           "}\n");
503     }
504 
505     printer->Outdent();
506 
507     // if message type has extensions
508     if (descriptor_->extension_range_count() > 0) {
509       printer->Print(
510         "  this.mergeExtensionFields(other);\n");
511     }
512 
513     if (PreserveUnknownFields(descriptor_)) {
514       printer->Print(
515         "  this.mergeUnknownFields(other.unknownFields);\n");
516     }
517 
518     printer->Print(
519       "  onChanged();\n");
520 
521     printer->Print(
522       "  return this;\n"
523       "}\n"
524       "\n");
525   }
526 }
527 
528 // ===================================================================
529 
530 void MessageBuilderGenerator::
GenerateBuilderParsingMethods(io::Printer * printer)531 GenerateBuilderParsingMethods(io::Printer* printer) {
532   printer->Print(
533     "public Builder mergeFrom(\n"
534     "    com.google.protobuf.CodedInputStream input,\n"
535     "    com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
536     "    throws java.io.IOException {\n"
537     "  $classname$ parsedMessage = null;\n"
538     "  try {\n"
539     "    parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
540     "  } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
541     "    parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
542     "    throw e.unwrapIOException();\n"
543     "  } finally {\n"
544     "    if (parsedMessage != null) {\n"
545     "      mergeFrom(parsedMessage);\n"
546     "    }\n"
547     "  }\n"
548     "  return this;\n"
549     "}\n",
550     "classname", name_resolver_->GetImmutableClassName(descriptor_));
551 }
552 
553 // ===================================================================
554 
GenerateIsInitialized(io::Printer * printer)555 void MessageBuilderGenerator::GenerateIsInitialized(
556     io::Printer* printer) {
557   printer->Print(
558     "public final boolean isInitialized() {\n");
559   printer->Indent();
560 
561   // Check that all required fields in this message are set.
562   // TODO(kenton):  We can optimize this when we switch to putting all the
563   //   "has" fields into a single bitfield.
564   for (int i = 0; i < descriptor_->field_count(); i++) {
565     const FieldDescriptor* field = descriptor_->field(i);
566     const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
567 
568     if (field->is_required()) {
569       printer->Print(
570         "if (!has$name$()) {\n"
571         "  return false;\n"
572         "}\n",
573         "name", info->capitalized_name);
574     }
575   }
576 
577   // Now check that all embedded messages are initialized.
578   for (int i = 0; i < descriptor_->field_count(); i++) {
579     const FieldDescriptor* field = descriptor_->field(i);
580     const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
581     if (GetJavaType(field) == JAVATYPE_MESSAGE &&
582         HasRequiredFields(field->message_type())) {
583       switch (field->label()) {
584         case FieldDescriptor::LABEL_REQUIRED:
585           printer->Print(
586             "if (!get$name$().isInitialized()) {\n"
587              "  return false;\n"
588              "}\n",
589             "type", name_resolver_->GetImmutableClassName(
590                 field->message_type()),
591             "name", info->capitalized_name);
592           break;
593         case FieldDescriptor::LABEL_OPTIONAL:
594           if (!SupportFieldPresence(descriptor_->file()) &&
595               field->containing_oneof() != NULL) {
596             const OneofDescriptor* oneof = field->containing_oneof();
597             const OneofGeneratorInfo* oneof_info =
598                 context_->GetOneofGeneratorInfo(oneof);
599             printer->Print(
600               "if ($oneof_name$Case_ == $field_number$) {\n",
601               "oneof_name", oneof_info->name,
602               "field_number", SimpleItoa(field->number()));
603           } else {
604             printer->Print(
605               "if (has$name$()) {\n",
606               "name", info->capitalized_name);
607           }
608           printer->Print(
609             "  if (!get$name$().isInitialized()) {\n"
610             "    return false;\n"
611             "  }\n"
612             "}\n",
613             "name", info->capitalized_name);
614           break;
615         case FieldDescriptor::LABEL_REPEATED:
616           if (IsMapEntry(field->message_type())) {
617             printer->Print(
618               "for ($type$ item : get$name$().values()) {\n"
619               "  if (!item.isInitialized()) {\n"
620               "    return false;\n"
621               "  }\n"
622               "}\n",
623               "type", MapValueImmutableClassdName(field->message_type(),
624                                                   name_resolver_),
625               "name", info->capitalized_name);
626           } else {
627             printer->Print(
628               "for (int i = 0; i < get$name$Count(); i++) {\n"
629               "  if (!get$name$(i).isInitialized()) {\n"
630               "    return false;\n"
631               "  }\n"
632               "}\n",
633               "type", name_resolver_->GetImmutableClassName(
634                   field->message_type()),
635               "name", info->capitalized_name);
636           }
637           break;
638       }
639     }
640   }
641 
642   if (descriptor_->extension_range_count() > 0) {
643     printer->Print(
644       "if (!extensionsAreInitialized()) {\n"
645       "  return false;\n"
646       "}\n");
647   }
648 
649   printer->Outdent();
650 
651   printer->Print(
652     "  return true;\n"
653     "}\n"
654     "\n");
655 }
656 
657 // ===================================================================
658 
659 }  // namespace java
660 }  // namespace compiler
661 }  // namespace protobuf
662 }  // namespace google
663