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