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 <google/protobuf/compiler/java/java_message.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_message_builder.h>
49 #include <google/protobuf/compiler/java/java_message_builder_lite.h>
50 #include <google/protobuf/compiler/java/java_name_resolver.h>
51 #include <google/protobuf/descriptor.pb.h>
52 #include <google/protobuf/io/coded_stream.h>
53 #include <google/protobuf/io/printer.h>
54 #include <google/protobuf/descriptor.h>
55 #include <google/protobuf/wire_format.h>
56 #include <google/protobuf/stubs/strutil.h>
57 #include <google/protobuf/stubs/substitute.h>
58
59 namespace google {
60 namespace protobuf {
61 namespace compiler {
62 namespace java {
63
64 using internal::WireFormat;
65 using internal::WireFormatLite;
66
67 namespace {
MapValueImmutableClassdName(const Descriptor * descriptor,ClassNameResolver * name_resolver)68 std::string MapValueImmutableClassdName(const Descriptor* descriptor,
69 ClassNameResolver* name_resolver) {
70 const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
71 GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
72 return name_resolver->GetImmutableClassName(value_field->message_type());
73 }
74 } // namespace
75
76 // ===================================================================
77
MessageGenerator(const Descriptor * descriptor)78 MessageGenerator::MessageGenerator(const Descriptor* descriptor)
79 : descriptor_(descriptor) {
80 for (int i = 0; i < descriptor_->field_count(); i++) {
81 if (IsRealOneof(descriptor_->field(i))) {
82 oneofs_.insert(descriptor_->field(i)->containing_oneof());
83 }
84 }
85 }
86
~MessageGenerator()87 MessageGenerator::~MessageGenerator() {}
88
89 // ===================================================================
ImmutableMessageGenerator(const Descriptor * descriptor,Context * context)90 ImmutableMessageGenerator::ImmutableMessageGenerator(
91 const Descriptor* descriptor, Context* context)
92 : MessageGenerator(descriptor),
93 context_(context),
94 name_resolver_(context->GetNameResolver()),
95 field_generators_(descriptor, context_) {
96 GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite()))
97 << "Generator factory error: A non-lite message generator is used to "
98 "generate lite messages.";
99 }
100
~ImmutableMessageGenerator()101 ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
102
GenerateStaticVariables(io::Printer * printer,int * bytecode_estimate)103 void ImmutableMessageGenerator::GenerateStaticVariables(
104 io::Printer* printer, int* bytecode_estimate) {
105 // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
106 // used in the construction of descriptors, we have a tricky bootstrapping
107 // problem. To help control static initialization order, we make sure all
108 // descriptors and other static data that depends on them are members of
109 // the outermost class in the file. This way, they will be initialized in
110 // a deterministic order.
111
112 std::map<std::string, std::string> vars;
113 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
114 vars["index"] = StrCat(descriptor_->index());
115 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
116 if (descriptor_->containing_type() != NULL) {
117 vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
118 }
119 if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
120 // We can only make these package-private since the classes that use them
121 // are in separate files.
122 vars["private"] = "";
123 } else {
124 vars["private"] = "private ";
125 }
126 if (*bytecode_estimate <= kMaxStaticSize) {
127 vars["final"] = "final ";
128 } else {
129 vars["final"] = "";
130 }
131
132 // The descriptor for this type.
133 printer->Print(
134 vars,
135 // TODO(teboring): final needs to be added back. The way to fix it is to
136 // generate methods that can construct the types, and then still declare
137 // the types, and then init them in clinit with the new method calls.
138 "$private$static $final$com.google.protobuf.Descriptors.Descriptor\n"
139 " internal_$identifier$_descriptor;\n");
140 *bytecode_estimate += 30;
141
142 // And the FieldAccessorTable.
143 GenerateFieldAccessorTable(printer, bytecode_estimate);
144
145 // Generate static members for all nested types.
146 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
147 // TODO(kenton): Reuse MessageGenerator objects?
148 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
149 .GenerateStaticVariables(printer, bytecode_estimate);
150 }
151 }
152
GenerateStaticVariableInitializers(io::Printer * printer)153 int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
154 io::Printer* printer) {
155 int bytecode_estimate = 0;
156 std::map<std::string, std::string> vars;
157 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
158 vars["index"] = StrCat(descriptor_->index());
159 vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
160 if (descriptor_->containing_type() != NULL) {
161 vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
162 }
163
164 // The descriptor for this type.
165 if (descriptor_->containing_type() == NULL) {
166 printer->Print(vars,
167 "internal_$identifier$_descriptor =\n"
168 " getDescriptor().getMessageTypes().get($index$);\n");
169 bytecode_estimate += 30;
170 } else {
171 printer->Print(
172 vars,
173 "internal_$identifier$_descriptor =\n"
174 " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
175 bytecode_estimate += 30;
176 }
177
178 // And the FieldAccessorTable.
179 bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
180
181 // Generate static member initializers for all nested types.
182 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
183 // TODO(kenton): Reuse MessageGenerator objects?
184 bytecode_estimate +=
185 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
186 .GenerateStaticVariableInitializers(printer);
187 }
188 return bytecode_estimate;
189 }
190
GenerateFieldAccessorTable(io::Printer * printer,int * bytecode_estimate)191 void ImmutableMessageGenerator::GenerateFieldAccessorTable(
192 io::Printer* printer, int* bytecode_estimate) {
193 std::map<std::string, std::string> vars;
194 vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
195 if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
196 // We can only make these package-private since the classes that use them
197 // are in separate files.
198 vars["private"] = "";
199 } else {
200 vars["private"] = "private ";
201 }
202 if (*bytecode_estimate <= kMaxStaticSize) {
203 vars["final"] = "final ";
204 } else {
205 vars["final"] = "";
206 }
207 vars["ver"] = GeneratedCodeVersionSuffix();
208 printer->Print(
209 vars,
210 "$private$static $final$\n"
211 " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
212 " internal_$identifier$_fieldAccessorTable;\n");
213
214 // 6 bytes per field and oneof
215 *bytecode_estimate +=
216 10 + 6 * descriptor_->field_count() + 6 * oneofs_.size();
217 }
218
GenerateFieldAccessorTableInitializer(io::Printer * printer)219 int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer(
220 io::Printer* printer) {
221 int bytecode_estimate = 10;
222 printer->Print(
223 "internal_$identifier$_fieldAccessorTable = new\n"
224 " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n"
225 " internal_$identifier$_descriptor,\n"
226 " new java.lang.String[] { ",
227 "identifier", UniqueFileScopeIdentifier(descriptor_), "ver",
228 GeneratedCodeVersionSuffix());
229 for (int i = 0; i < descriptor_->field_count(); i++) {
230 const FieldDescriptor* field = descriptor_->field(i);
231 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
232 bytecode_estimate += 6;
233 printer->Print("\"$field_name$\", ", "field_name", info->capitalized_name);
234 }
235 // We reproduce synthetic oneofs here since proto reflection needs these.
236 for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
237 const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
238 const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof);
239 bytecode_estimate += 6;
240 printer->Print("\"$oneof_name$\", ", "oneof_name", info->capitalized_name);
241 }
242 printer->Print("});\n");
243 return bytecode_estimate;
244 }
245
246 // ===================================================================
247
GenerateInterface(io::Printer * printer)248 void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
249 MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
250 /* immutable = */ true, "OrBuilder");
251 if (descriptor_->extension_range_count() > 0) {
252 printer->Print(
253 "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
254 " $extra_interfaces$\n"
255 " com.google.protobuf.GeneratedMessage$ver$.\n"
256 " ExtendableMessageOrBuilder<$classname$> {\n",
257 "deprecation",
258 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
259 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
260 "classname", descriptor_->name(), "{", "", "}", "", "ver",
261 GeneratedCodeVersionSuffix());
262 } else {
263 printer->Print(
264 "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
265 " $extra_interfaces$\n"
266 " com.google.protobuf.MessageOrBuilder {\n",
267 "deprecation",
268 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
269 "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
270 "classname", descriptor_->name(), "{", "", "}", "");
271 }
272 printer->Annotate("{", "}", descriptor_);
273
274 printer->Indent();
275 for (int i = 0; i < descriptor_->field_count(); i++) {
276 printer->Print("\n");
277 field_generators_.get(descriptor_->field(i))
278 .GenerateInterfaceMembers(printer);
279 }
280 for (auto oneof : oneofs_) {
281 printer->Print(
282 "\n"
283 "public $classname$.$oneof_capitalized_name$Case "
284 "get$oneof_capitalized_name$Case();\n",
285 "oneof_capitalized_name",
286 context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname",
287 context_->GetNameResolver()->GetImmutableClassName(descriptor_));
288 }
289 printer->Outdent();
290
291 printer->Print("}\n");
292 }
293
294 // ===================================================================
295
Generate(io::Printer * printer)296 void ImmutableMessageGenerator::Generate(io::Printer* printer) {
297 bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
298
299 std::map<std::string, std::string> variables;
300 variables["static"] = is_own_file ? "" : "static ";
301 variables["classname"] = descriptor_->name();
302 variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
303 variables["ver"] = GeneratedCodeVersionSuffix();
304 variables["deprecation"] =
305 descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "";
306
307 WriteMessageDocComment(printer, descriptor_);
308 MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
309 /* immutable = */ true);
310
311 // The builder_type stores the super type name of the nested Builder class.
312 std::string builder_type;
313 if (descriptor_->extension_range_count() > 0) {
314 printer->Print(
315 variables,
316 "$deprecation$public $static$final class $classname$ extends\n");
317 printer->Annotate("classname", descriptor_);
318 printer->Print(
319 variables,
320 " com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n"
321 " $classname$> implements\n"
322 " $extra_interfaces$\n"
323 " $classname$OrBuilder {\n");
324 builder_type = strings::Substitute(
325 "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
326 name_resolver_->GetImmutableClassName(descriptor_),
327 GeneratedCodeVersionSuffix());
328 } else {
329 printer->Print(
330 variables,
331 "$deprecation$public $static$final class $classname$ extends\n");
332 printer->Annotate("classname", descriptor_);
333 printer->Print(variables,
334 " com.google.protobuf.GeneratedMessage$ver$ implements\n"
335 " $extra_interfaces$\n"
336 " $classname$OrBuilder {\n");
337 builder_type =
338 strings::Substitute("com.google.protobuf.GeneratedMessage$0.Builder<?>",
339 GeneratedCodeVersionSuffix());
340 }
341 printer->Print("private static final long serialVersionUID = 0L;\n");
342
343 printer->Indent();
344 // Using builder_type, instead of Builder, prevents the Builder class from
345 // being loaded into PermGen space when the default instance is created.
346 // This optimizes the PermGen space usage for clients that do not modify
347 // messages.
348 printer->Print(
349 "// Use $classname$.newBuilder() to construct.\n"
350 "private $classname$($buildertype$ builder) {\n"
351 " super(builder);\n"
352 "}\n",
353 "classname", descriptor_->name(), "buildertype", builder_type);
354 printer->Print("private $classname$() {\n", "classname", descriptor_->name());
355 printer->Indent();
356 GenerateInitializers(printer);
357 printer->Outdent();
358 printer->Print(
359 "}\n"
360 "\n");
361
362 printer->Print(variables,
363 "@java.lang.Override\n"
364 "@SuppressWarnings({\"unused\"})\n"
365 "protected java.lang.Object newInstance(\n"
366 " UnusedPrivateParameter unused) {\n"
367 " return new $classname$();\n"
368 "}\n"
369 "\n");
370
371 // TODO(b/248149118): Remove this superfluous override.
372 printer->Print(
373 "@java.lang.Override\n"
374 "public final com.google.protobuf.UnknownFieldSet\n"
375 "getUnknownFields() {\n"
376 " return this.unknownFields;\n"
377 "}\n");
378
379 GenerateDescriptorMethods(printer);
380
381 // Nested types
382 for (int i = 0; i < descriptor_->enum_type_count(); i++) {
383 EnumGenerator(descriptor_->enum_type(i), true, context_).Generate(printer);
384 }
385
386 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
387 // Don't generate Java classes for map entry messages.
388 if (IsMapEntry(descriptor_->nested_type(i))) continue;
389 ImmutableMessageGenerator messageGenerator(descriptor_->nested_type(i),
390 context_);
391 messageGenerator.GenerateInterface(printer);
392 messageGenerator.Generate(printer);
393 }
394
395 // Integers for bit fields.
396 int totalBits = 0;
397 for (int i = 0; i < descriptor_->field_count(); i++) {
398 totalBits +=
399 field_generators_.get(descriptor_->field(i)).GetNumBitsForMessage();
400 }
401 int totalInts = (totalBits + 31) / 32;
402 for (int i = 0; i < totalInts; i++) {
403 printer->Print("private int $bit_field_name$;\n", "bit_field_name",
404 GetBitFieldName(i));
405 }
406
407 // oneof
408 std::map<std::string, std::string> vars;
409 for (auto oneof : oneofs_) {
410 vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
411 vars["oneof_capitalized_name"] =
412 context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
413 vars["oneof_index"] = StrCat((oneof)->index());
414 // oneofCase_ and oneof_
415 printer->Print(vars,
416 "private int $oneof_name$Case_ = 0;\n"
417 "private java.lang.Object $oneof_name$_;\n");
418 // OneofCase enum
419 printer->Print(
420 vars,
421 "public enum $oneof_capitalized_name$Case\n"
422 // TODO(dweis): Remove EnumLite when we want to break compatibility with
423 // 3.x users
424 " implements com.google.protobuf.Internal.EnumLite,\n"
425 " com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n");
426 printer->Indent();
427 for (int j = 0; j < (oneof)->field_count(); j++) {
428 const FieldDescriptor* field = (oneof)->field(j);
429 printer->Print(
430 "$deprecation$$field_name$($field_number$),\n", "deprecation",
431 field->options().deprecated() ? "@java.lang.Deprecated " : "",
432 "field_name", ToUpper(field->name()), "field_number",
433 StrCat(field->number()));
434 }
435 printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name",
436 ToUpper(vars["oneof_name"]));
437 printer->Print(vars,
438 "private final int value;\n"
439 "private $oneof_capitalized_name$Case(int value) {\n"
440 " this.value = value;\n"
441 "}\n");
442 printer->Print(
443 vars,
444 "/**\n"
445 " * @param value The number of the enum to look for.\n"
446 " * @return The enum associated with the given number.\n"
447 " * @deprecated Use {@link #forNumber(int)} instead.\n"
448 " */\n"
449 "@java.lang.Deprecated\n"
450 "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
451 " return forNumber(value);\n"
452 "}\n"
453 "\n"
454 "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
455 " switch (value) {\n");
456 for (int j = 0; j < (oneof)->field_count(); j++) {
457 const FieldDescriptor* field = (oneof)->field(j);
458 printer->Print(" case $field_number$: return $field_name$;\n",
459 "field_number", StrCat(field->number()),
460 "field_name", ToUpper(field->name()));
461 }
462 printer->Print(
463 " case 0: return $cap_oneof_name$_NOT_SET;\n"
464 " default: return null;\n"
465 " }\n"
466 "}\n"
467 "public int getNumber() {\n"
468 " return this.value;\n"
469 "}\n",
470 "cap_oneof_name", ToUpper(vars["oneof_name"]));
471 printer->Outdent();
472 printer->Print("};\n\n");
473 // oneofCase()
474 printer->Print(vars,
475 "public $oneof_capitalized_name$Case\n"
476 "get$oneof_capitalized_name$Case() {\n"
477 " return $oneof_capitalized_name$Case.forNumber(\n"
478 " $oneof_name$Case_);\n"
479 "}\n"
480 "\n");
481 }
482
483 if (IsAnyMessage(descriptor_)) {
484 GenerateAnyMethods(printer);
485 }
486
487 // Fields
488 for (int i = 0; i < descriptor_->field_count(); i++) {
489 printer->Print("public static final int $constant_name$ = $number$;\n",
490 "constant_name", FieldConstantName(descriptor_->field(i)),
491 "number", StrCat(descriptor_->field(i)->number()));
492 field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
493 printer->Print("\n");
494 }
495
496 if (context_->HasGeneratedMethods(descriptor_)) {
497 GenerateIsInitialized(printer);
498 GenerateMessageSerializationMethods(printer);
499 GenerateEqualsAndHashCode(printer);
500 }
501
502
503 GenerateParseFromMethods(printer);
504 GenerateBuilder(printer);
505
506 printer->Print(
507 "\n"
508 "// @@protoc_insertion_point(class_scope:$full_name$)\n",
509 "full_name", descriptor_->full_name());
510
511 // Carefully initialize the default instance in such a way that it doesn't
512 // conflict with other initialization.
513 printer->Print("private static final $classname$ DEFAULT_INSTANCE;\n",
514 "classname",
515 name_resolver_->GetImmutableClassName(descriptor_));
516 printer->Print(
517 "static {\n"
518 " DEFAULT_INSTANCE = new $classname$();\n"
519 "}\n"
520 "\n",
521 "classname", name_resolver_->GetImmutableClassName(descriptor_));
522
523 printer->Print(
524 "public static $classname$ getDefaultInstance() {\n"
525 " return DEFAULT_INSTANCE;\n"
526 "}\n"
527 "\n",
528 "classname", name_resolver_->GetImmutableClassName(descriptor_));
529
530 // 'of' method for Wrappers
531 if (IsWrappersProtoFile(descriptor_->file())) {
532 printer->Print(
533 "public static $classname$ of($field_type$ value) {\n"
534 " return newBuilder().setValue(value).build();\n"
535 "}\n"
536 "\n",
537 "classname", name_resolver_->GetImmutableClassName(descriptor_),
538 "field_type", PrimitiveTypeName(GetJavaType(descriptor_->field(0))));
539 }
540
541 GenerateParser(printer);
542
543 printer->Print(
544 "@java.lang.Override\n"
545 "public $classname$ getDefaultInstanceForType() {\n"
546 " return DEFAULT_INSTANCE;\n"
547 "}\n"
548 "\n",
549 "classname", name_resolver_->GetImmutableClassName(descriptor_));
550
551 // Extensions must be declared after the DEFAULT_INSTANCE is initialized
552 // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
553 // the outer class's FileDescriptor.
554 for (int i = 0; i < descriptor_->extension_count(); i++) {
555 ImmutableExtensionGenerator(descriptor_->extension(i), context_)
556 .Generate(printer);
557 }
558
559 printer->Outdent();
560 printer->Print("}\n\n");
561 }
562
563 // ===================================================================
564
GenerateMessageSerializationMethods(io::Printer * printer)565 void ImmutableMessageGenerator::GenerateMessageSerializationMethods(
566 io::Printer* printer) {
567 std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
568 SortFieldsByNumber(descriptor_));
569
570 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
571 for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
572 sorted_extensions.push_back(descriptor_->extension_range(i));
573 }
574 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
575 ExtensionRangeOrdering());
576 printer->Print(
577 "@java.lang.Override\n"
578 "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
579 " throws java.io.IOException {\n");
580 printer->Indent();
581
582 if (HasPackedFields(descriptor_)) {
583 // writeTo(CodedOutputStream output) might be invoked without
584 // getSerializedSize() ever being called, but we need the memoized
585 // sizes in case this message has packed fields. Rather than emit checks
586 // for each packed field, just call getSerializedSize() up front. In most
587 // cases, getSerializedSize() will have already been called anyway by one
588 // of the wrapper writeTo() methods, making this call cheap.
589 printer->Print("getSerializedSize();\n");
590 }
591
592 if (descriptor_->extension_range_count() > 0) {
593 if (descriptor_->options().message_set_wire_format()) {
594 printer->Print(
595 "com.google.protobuf.GeneratedMessage$ver$\n"
596 " .ExtendableMessage<$classname$>.ExtensionWriter\n"
597 " extensionWriter = newMessageSetExtensionWriter();\n",
598 "classname", name_resolver_->GetImmutableClassName(descriptor_),
599 "ver", GeneratedCodeVersionSuffix());
600 } else {
601 printer->Print(
602 "com.google.protobuf.GeneratedMessage$ver$\n"
603 " .ExtendableMessage<$classname$>.ExtensionWriter\n"
604 " extensionWriter = newExtensionWriter();\n",
605 "classname", name_resolver_->GetImmutableClassName(descriptor_),
606 "ver", GeneratedCodeVersionSuffix());
607 }
608 }
609
610 // Merge the fields and the extension ranges, both sorted by field number.
611 for (int i = 0, j = 0;
612 i < descriptor_->field_count() || j < sorted_extensions.size();) {
613 if (i == descriptor_->field_count()) {
614 GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
615 } else if (j == sorted_extensions.size()) {
616 GenerateSerializeOneField(printer, sorted_fields[i++]);
617 } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
618 GenerateSerializeOneField(printer, sorted_fields[i++]);
619 } else {
620 GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
621 }
622 }
623
624 if (descriptor_->options().message_set_wire_format()) {
625 printer->Print("getUnknownFields().writeAsMessageSetTo(output);\n");
626 } else {
627 printer->Print("getUnknownFields().writeTo(output);\n");
628 }
629
630 printer->Outdent();
631 printer->Print(
632 "}\n"
633 "\n"
634 "@java.lang.Override\n"
635 "public int getSerializedSize() {\n"
636 " int size = memoizedSize;\n"
637 " if (size != -1) return size;\n"
638 "\n");
639 printer->Indent();
640
641 printer->Print("size = 0;\n");
642
643 for (int i = 0; i < descriptor_->field_count(); i++) {
644 field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
645 }
646
647 if (descriptor_->extension_range_count() > 0) {
648 if (descriptor_->options().message_set_wire_format()) {
649 printer->Print("size += extensionsSerializedSizeAsMessageSet();\n");
650 } else {
651 printer->Print("size += extensionsSerializedSize();\n");
652 }
653 }
654
655 if (descriptor_->options().message_set_wire_format()) {
656 printer->Print(
657 "size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
658 } else {
659 printer->Print("size += getUnknownFields().getSerializedSize();\n");
660 }
661
662 printer->Print(
663 "memoizedSize = size;\n"
664 "return size;\n");
665
666 printer->Outdent();
667 printer->Print(
668 "}\n"
669 "\n");
670 }
671
GenerateParseFromMethods(io::Printer * printer)672 void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) {
673 // Note: These are separate from GenerateMessageSerializationMethods()
674 // because they need to be generated even for messages that are optimized
675 // for code size.
676 printer->Print(
677 "public static $classname$ parseFrom(\n"
678 " java.nio.ByteBuffer data)\n"
679 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
680 " return PARSER.parseFrom(data);\n"
681 "}\n"
682 "public static $classname$ parseFrom(\n"
683 " java.nio.ByteBuffer data,\n"
684 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
685 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
686 " return PARSER.parseFrom(data, extensionRegistry);\n"
687 "}\n"
688 "public static $classname$ parseFrom(\n"
689 " com.google.protobuf.ByteString data)\n"
690 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
691 " return PARSER.parseFrom(data);\n"
692 "}\n"
693 "public static $classname$ parseFrom(\n"
694 " com.google.protobuf.ByteString data,\n"
695 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
696 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
697 " return PARSER.parseFrom(data, extensionRegistry);\n"
698 "}\n"
699 "public static $classname$ parseFrom(byte[] data)\n"
700 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
701 " return PARSER.parseFrom(data);\n"
702 "}\n"
703 "public static $classname$ parseFrom(\n"
704 " byte[] data,\n"
705 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
706 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
707 " return PARSER.parseFrom(data, extensionRegistry);\n"
708 "}\n"
709 "public static $classname$ parseFrom(java.io.InputStream input)\n"
710 " throws java.io.IOException {\n"
711 " return com.google.protobuf.GeneratedMessage$ver$\n"
712 " .parseWithIOException(PARSER, input);\n"
713 "}\n"
714 "public static $classname$ parseFrom(\n"
715 " java.io.InputStream input,\n"
716 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
717 " throws java.io.IOException {\n"
718 " return com.google.protobuf.GeneratedMessage$ver$\n"
719 " .parseWithIOException(PARSER, input, extensionRegistry);\n"
720 "}\n"
721 "public static $classname$ parseDelimitedFrom(java.io.InputStream "
722 "input)\n"
723 " throws java.io.IOException {\n"
724 " return com.google.protobuf.GeneratedMessage$ver$\n"
725 " .parseDelimitedWithIOException(PARSER, input);\n"
726 "}\n"
727 "public static $classname$ parseDelimitedFrom(\n"
728 " java.io.InputStream input,\n"
729 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
730 " throws java.io.IOException {\n"
731 " return com.google.protobuf.GeneratedMessage$ver$\n"
732 " .parseDelimitedWithIOException(PARSER, input, "
733 "extensionRegistry);\n"
734 "}\n"
735 "public static $classname$ parseFrom(\n"
736 " com.google.protobuf.CodedInputStream input)\n"
737 " throws java.io.IOException {\n"
738 " return com.google.protobuf.GeneratedMessage$ver$\n"
739 " .parseWithIOException(PARSER, input);\n"
740 "}\n"
741 "public static $classname$ parseFrom(\n"
742 " com.google.protobuf.CodedInputStream input,\n"
743 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
744 " throws java.io.IOException {\n"
745 " return com.google.protobuf.GeneratedMessage$ver$\n"
746 " .parseWithIOException(PARSER, input, extensionRegistry);\n"
747 "}\n"
748 "\n",
749 "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver",
750 GeneratedCodeVersionSuffix());
751 }
752
GenerateSerializeOneField(io::Printer * printer,const FieldDescriptor * field)753 void ImmutableMessageGenerator::GenerateSerializeOneField(
754 io::Printer* printer, const FieldDescriptor* field) {
755 field_generators_.get(field).GenerateSerializationCode(printer);
756 }
757
GenerateSerializeOneExtensionRange(io::Printer * printer,const Descriptor::ExtensionRange * range)758 void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
759 io::Printer* printer, const Descriptor::ExtensionRange* range) {
760 printer->Print("extensionWriter.writeUntil($end$, output);\n", "end",
761 StrCat(range->end));
762 }
763
764 // ===================================================================
765
GenerateBuilder(io::Printer * printer)766 void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
767 // LITE_RUNTIME implements this at the GeneratedMessageLite level.
768 printer->Print(
769 "@java.lang.Override\n"
770 "public Builder newBuilderForType() { return newBuilder(); }\n");
771
772 printer->Print(
773 "public static Builder newBuilder() {\n"
774 " return DEFAULT_INSTANCE.toBuilder();\n"
775 "}\n"
776 "public static Builder newBuilder($classname$ prototype) {\n"
777 " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
778 "}\n"
779 "@java.lang.Override\n"
780 "public Builder toBuilder() {\n"
781 " return this == DEFAULT_INSTANCE\n"
782 " ? new Builder() : new Builder().mergeFrom(this);\n"
783 "}\n"
784 "\n",
785 "classname", name_resolver_->GetImmutableClassName(descriptor_));
786
787 printer->Print(
788 "@java.lang.Override\n"
789 "protected Builder newBuilderForType(\n"
790 " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n"
791 " Builder builder = new Builder(parent);\n"
792 " return builder;\n"
793 "}\n",
794 "ver", GeneratedCodeVersionSuffix());
795
796 MessageBuilderGenerator builderGenerator(descriptor_, context_);
797 builderGenerator.Generate(printer);
798 }
799
GenerateDescriptorMethods(io::Printer * printer)800 void ImmutableMessageGenerator::GenerateDescriptorMethods(
801 io::Printer* printer) {
802 if (!descriptor_->options().no_standard_descriptor_accessor()) {
803 printer->Print(
804 "public static final com.google.protobuf.Descriptors.Descriptor\n"
805 " getDescriptor() {\n"
806 " return $fileclass$.internal_$identifier$_descriptor;\n"
807 "}\n"
808 "\n",
809 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
810 "identifier", UniqueFileScopeIdentifier(descriptor_));
811 }
812 std::vector<const FieldDescriptor*> map_fields;
813 for (int i = 0; i < descriptor_->field_count(); i++) {
814 const FieldDescriptor* field = descriptor_->field(i);
815 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
816 IsMapEntry(field->message_type())) {
817 map_fields.push_back(field);
818 }
819 }
820 if (!map_fields.empty()) {
821 printer->Print(
822 "@SuppressWarnings({\"rawtypes\"})\n"
823 "@java.lang.Override\n"
824 "protected com.google.protobuf.MapField internalGetMapField(\n"
825 " int number) {\n"
826 " switch (number) {\n");
827 printer->Indent();
828 printer->Indent();
829 for (int i = 0; i < map_fields.size(); ++i) {
830 const FieldDescriptor* field = map_fields[i];
831 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
832 printer->Print(
833 "case $number$:\n"
834 " return internalGet$capitalized_name$();\n",
835 "number", StrCat(field->number()), "capitalized_name",
836 info->capitalized_name);
837 }
838 printer->Print(
839 "default:\n"
840 " throw new RuntimeException(\n"
841 " \"Invalid map field number: \" + number);\n");
842 printer->Outdent();
843 printer->Outdent();
844 printer->Print(
845 " }\n"
846 "}\n");
847 }
848 printer->Print(
849 "@java.lang.Override\n"
850 "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n"
851 " internalGetFieldAccessorTable() {\n"
852 " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
853 " .ensureFieldAccessorsInitialized(\n"
854 " $classname$.class, $classname$.Builder.class);\n"
855 "}\n"
856 "\n",
857 "classname", name_resolver_->GetImmutableClassName(descriptor_),
858 "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
859 "identifier", UniqueFileScopeIdentifier(descriptor_), "ver",
860 GeneratedCodeVersionSuffix());
861 }
862
863 // ===================================================================
864
GenerateIsInitialized(io::Printer * printer)865 void ImmutableMessageGenerator::GenerateIsInitialized(io::Printer* printer) {
866 // Memoizes whether the protocol buffer is fully initialized (has all
867 // required fields). -1 means not yet computed. 0 means false and 1 means
868 // true.
869 printer->Print("private byte memoizedIsInitialized = -1;\n");
870 printer->Print(
871 "@java.lang.Override\n"
872 "public final boolean isInitialized() {\n");
873 printer->Indent();
874
875 // Don't directly compare to -1 to avoid an Android x86 JIT bug.
876 printer->Print(
877 "byte isInitialized = memoizedIsInitialized;\n"
878 "if (isInitialized == 1) return true;\n"
879 "if (isInitialized == 0) return false;\n"
880 "\n");
881
882 // Check that all required fields in this message are set.
883 // TODO(kenton): We can optimize this when we switch to putting all the
884 // "has" fields into a single bitfield.
885 for (int i = 0; i < descriptor_->field_count(); i++) {
886 const FieldDescriptor* field = descriptor_->field(i);
887 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
888
889 if (field->is_required()) {
890 printer->Print(
891 "if (!has$name$()) {\n"
892 " memoizedIsInitialized = 0;\n"
893 " return false;\n"
894 "}\n",
895 "name", info->capitalized_name);
896 }
897 }
898
899 // Now check that all embedded messages are initialized.
900 for (int i = 0; i < descriptor_->field_count(); i++) {
901 const FieldDescriptor* field = descriptor_->field(i);
902 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
903 if (GetJavaType(field) == JAVATYPE_MESSAGE &&
904 HasRequiredFields(field->message_type())) {
905 switch (field->label()) {
906 case FieldDescriptor::LABEL_REQUIRED:
907 printer->Print(
908 "if (!get$name$().isInitialized()) {\n"
909 " memoizedIsInitialized = 0;\n"
910 " return false;\n"
911 "}\n",
912 "type",
913 name_resolver_->GetImmutableClassName(field->message_type()),
914 "name", info->capitalized_name);
915 break;
916 case FieldDescriptor::LABEL_OPTIONAL:
917 printer->Print(
918 "if (has$name$()) {\n"
919 " if (!get$name$().isInitialized()) {\n"
920 " memoizedIsInitialized = 0;\n"
921 " return false;\n"
922 " }\n"
923 "}\n",
924 "name", info->capitalized_name);
925 break;
926 case FieldDescriptor::LABEL_REPEATED:
927 if (IsMapEntry(field->message_type())) {
928 printer->Print(
929 "for ($type$ item : get$name$Map().values()) {\n"
930 " if (!item.isInitialized()) {\n"
931 " memoizedIsInitialized = 0;\n"
932 " return false;\n"
933 " }\n"
934 "}\n",
935 "type",
936 MapValueImmutableClassdName(field->message_type(),
937 name_resolver_),
938 "name", info->capitalized_name);
939 } else {
940 printer->Print(
941 "for (int i = 0; i < get$name$Count(); i++) {\n"
942 " if (!get$name$(i).isInitialized()) {\n"
943 " memoizedIsInitialized = 0;\n"
944 " return false;\n"
945 " }\n"
946 "}\n",
947 "type",
948 name_resolver_->GetImmutableClassName(field->message_type()),
949 "name", info->capitalized_name);
950 }
951 break;
952 }
953 }
954 }
955
956 if (descriptor_->extension_range_count() > 0) {
957 printer->Print(
958 "if (!extensionsAreInitialized()) {\n"
959 " memoizedIsInitialized = 0;\n"
960 " return false;\n"
961 "}\n");
962 }
963
964 printer->Outdent();
965
966 printer->Print(" memoizedIsInitialized = 1;\n");
967
968 printer->Print(
969 " return true;\n"
970 "}\n"
971 "\n");
972 }
973
974 // ===================================================================
975
976 namespace {
CheckHasBitsForEqualsAndHashCode(const FieldDescriptor * field)977 bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
978 if (field->is_repeated()) {
979 return false;
980 }
981 if (HasHasbit(field)) {
982 return true;
983 }
984 return GetJavaType(field) == JAVATYPE_MESSAGE && !IsRealOneof(field);
985 }
986 } // namespace
987
GenerateEqualsAndHashCode(io::Printer * printer)988 void ImmutableMessageGenerator::GenerateEqualsAndHashCode(
989 io::Printer* printer) {
990 printer->Print(
991 "@java.lang.Override\n"
992 "public boolean equals(");
993 printer->Print("final java.lang.Object obj) {\n");
994 printer->Indent();
995 printer->Print(
996 "if (obj == this) {\n"
997 " return true;\n"
998 "}\n"
999 "if (!(obj instanceof $classname$)) {\n"
1000 " return super.equals(obj);\n"
1001 "}\n"
1002 "$classname$ other = ($classname$) obj;\n"
1003 "\n",
1004 "classname", name_resolver_->GetImmutableClassName(descriptor_));
1005
1006 for (int i = 0; i < descriptor_->field_count(); i++) {
1007 const FieldDescriptor* field = descriptor_->field(i);
1008 if (!IsRealOneof(field)) {
1009 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
1010 bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
1011 if (check_has_bits) {
1012 printer->Print(
1013 "if (has$name$() != other.has$name$()) return false;\n"
1014 "if (has$name$()) {\n",
1015 "name", info->capitalized_name);
1016 printer->Indent();
1017 }
1018 field_generators_.get(field).GenerateEqualsCode(printer);
1019 if (check_has_bits) {
1020 printer->Outdent();
1021 printer->Print("}\n");
1022 }
1023 }
1024 }
1025
1026 // Compare oneofs.
1027 for (auto oneof : oneofs_) {
1028 printer->Print(
1029 "if (!get$oneof_capitalized_name$Case().equals("
1030 "other.get$oneof_capitalized_name$Case())) return false;\n",
1031 "oneof_capitalized_name",
1032 context_->GetOneofGeneratorInfo(oneof)->capitalized_name);
1033 printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name",
1034 context_->GetOneofGeneratorInfo(oneof)->name);
1035 printer->Indent();
1036 for (int j = 0; j < (oneof)->field_count(); j++) {
1037 const FieldDescriptor* field = (oneof)->field(j);
1038 printer->Print("case $field_number$:\n", "field_number",
1039 StrCat(field->number()));
1040 printer->Indent();
1041 field_generators_.get(field).GenerateEqualsCode(printer);
1042 printer->Print("break;\n");
1043 printer->Outdent();
1044 }
1045 printer->Print(
1046 "case 0:\n"
1047 "default:\n");
1048 printer->Outdent();
1049 printer->Print("}\n");
1050 }
1051
1052 // Always consider unknown fields for equality. This will sometimes return
1053 // false for non-canonical ordering when running in LITE_RUNTIME but it's
1054 // the best we can do.
1055 printer->Print(
1056 "if (!getUnknownFields().equals(other.getUnknownFields())) return "
1057 "false;\n");
1058 if (descriptor_->extension_range_count() > 0) {
1059 printer->Print(
1060 "if (!getExtensionFields().equals(other.getExtensionFields()))\n"
1061 " return false;\n");
1062 }
1063 printer->Print("return true;\n");
1064 printer->Outdent();
1065 printer->Print(
1066 "}\n"
1067 "\n");
1068
1069 printer->Print(
1070 "@java.lang.Override\n"
1071 "public int hashCode() {\n");
1072 printer->Indent();
1073 printer->Print("if (memoizedHashCode != 0) {\n");
1074 printer->Indent();
1075 printer->Print("return memoizedHashCode;\n");
1076 printer->Outdent();
1077 printer->Print(
1078 "}\n"
1079 "int hash = 41;\n");
1080
1081 // If we output a getDescriptor() method, use that as it is more efficient.
1082 if (descriptor_->options().no_standard_descriptor_accessor()) {
1083 printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
1084 } else {
1085 printer->Print("hash = (19 * hash) + getDescriptor().hashCode();\n");
1086 }
1087
1088 // hashCode non-oneofs.
1089 for (int i = 0; i < descriptor_->field_count(); i++) {
1090 const FieldDescriptor* field = descriptor_->field(i);
1091 if (!IsRealOneof(field)) {
1092 const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
1093 bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
1094 if (check_has_bits) {
1095 printer->Print("if (has$name$()) {\n", "name", info->capitalized_name);
1096 printer->Indent();
1097 }
1098 field_generators_.get(field).GenerateHashCode(printer);
1099 if (check_has_bits) {
1100 printer->Outdent();
1101 printer->Print("}\n");
1102 }
1103 }
1104 }
1105
1106 // hashCode oneofs.
1107 for (auto oneof : oneofs_) {
1108 printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name",
1109 context_->GetOneofGeneratorInfo(oneof)->name);
1110 printer->Indent();
1111 for (int j = 0; j < (oneof)->field_count(); j++) {
1112 const FieldDescriptor* field = (oneof)->field(j);
1113 printer->Print("case $field_number$:\n", "field_number",
1114 StrCat(field->number()));
1115 printer->Indent();
1116 field_generators_.get(field).GenerateHashCode(printer);
1117 printer->Print("break;\n");
1118 printer->Outdent();
1119 }
1120 printer->Print(
1121 "case 0:\n"
1122 "default:\n");
1123 printer->Outdent();
1124 printer->Print("}\n");
1125 }
1126
1127 if (descriptor_->extension_range_count() > 0) {
1128 printer->Print("hash = hashFields(hash, getExtensionFields());\n");
1129 }
1130
1131 printer->Print("hash = (29 * hash) + getUnknownFields().hashCode();\n");
1132 printer->Print(
1133 "memoizedHashCode = hash;\n"
1134 "return hash;\n");
1135 printer->Outdent();
1136 printer->Print(
1137 "}\n"
1138 "\n");
1139 }
1140
1141 // ===================================================================
1142
GenerateExtensionRegistrationCode(io::Printer * printer)1143 void ImmutableMessageGenerator::GenerateExtensionRegistrationCode(
1144 io::Printer* printer) {
1145 for (int i = 0; i < descriptor_->extension_count(); i++) {
1146 ImmutableExtensionGenerator(descriptor_->extension(i), context_)
1147 .GenerateRegistrationCode(printer);
1148 }
1149
1150 for (int i = 0; i < descriptor_->nested_type_count(); i++) {
1151 ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
1152 .GenerateExtensionRegistrationCode(printer);
1153 }
1154 }
1155
1156 // ===================================================================
GenerateParser(io::Printer * printer)1157 void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
1158 printer->Print(
1159 "$visibility$ static final com.google.protobuf.Parser<$classname$>\n"
1160 " PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n"
1161 " @java.lang.Override\n"
1162 " public $classname$ parsePartialFrom(\n"
1163 " com.google.protobuf.CodedInputStream input,\n"
1164 " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
1165 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
1166 " Builder builder = newBuilder();\n"
1167 " try {\n"
1168 " builder.mergeFrom(input, extensionRegistry);\n"
1169 " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
1170 " throw e.setUnfinishedMessage(builder.buildPartial());\n"
1171 " } catch (com.google.protobuf.UninitializedMessageException e) {\n"
1172 " throw "
1173 "e.asInvalidProtocolBufferException().setUnfinishedMessage(builder."
1174 "buildPartial());\n"
1175 " } catch (java.io.IOException e) {\n"
1176 " throw new com.google.protobuf.InvalidProtocolBufferException(e)\n"
1177 " .setUnfinishedMessage(builder.buildPartial());\n"
1178 " }\n"
1179 " return builder.buildPartial();\n"
1180 " }\n"
1181 "};\n"
1182 "\n"
1183 "public static com.google.protobuf.Parser<$classname$> parser() {\n"
1184 " return PARSER;\n"
1185 "}\n"
1186 "\n"
1187 "@java.lang.Override\n"
1188 "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
1189 " return PARSER;\n"
1190 "}\n"
1191 "\n",
1192 "visibility",
1193 ExposePublicParser(descriptor_->file()) ? "@java.lang.Deprecated public"
1194 : "private",
1195 "classname", descriptor_->name());
1196 }
1197
1198 // ===================================================================
GenerateInitializers(io::Printer * printer)1199 void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
1200 for (int i = 0; i < descriptor_->field_count(); i++) {
1201 if (!IsRealOneof(descriptor_->field(i))) {
1202 field_generators_.get(descriptor_->field(i))
1203 .GenerateInitializationCode(printer);
1204 }
1205 }
1206 }
1207
GenerateAnyMethods(io::Printer * printer)1208 void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
1209 printer->Print(
1210 "private static String getTypeUrl(\n"
1211 " java.lang.String typeUrlPrefix,\n"
1212 " com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
1213 " return typeUrlPrefix.endsWith(\"/\")\n"
1214 " ? typeUrlPrefix + descriptor.getFullName()\n"
1215 " : typeUrlPrefix + \"/\" + descriptor.getFullName();\n"
1216 "}\n"
1217 "\n"
1218 "private static String getTypeNameFromTypeUrl(\n"
1219 " java.lang.String typeUrl) {\n"
1220 " int pos = typeUrl.lastIndexOf('/');\n"
1221 " return pos == -1 ? \"\" : typeUrl.substring(pos + 1);\n"
1222 "}\n"
1223 "\n"
1224 "public static <T extends com.google.protobuf.Message> Any pack(\n"
1225 " T message) {\n"
1226 " return Any.newBuilder()\n"
1227 " .setTypeUrl(getTypeUrl(\"type.googleapis.com\",\n"
1228 " message.getDescriptorForType()))\n"
1229 " .setValue(message.toByteString())\n"
1230 " .build();\n"
1231 "}\n"
1232 "\n"
1233 "/**\n"
1234 " * Packs a message using the given type URL prefix. The type URL will\n"
1235 " * be constructed by concatenating the message type's full name to the\n"
1236 " * prefix with an optional \"/\" separator if the prefix doesn't end\n"
1237 " * with \"/\" already.\n"
1238 " */\n"
1239 "public static <T extends com.google.protobuf.Message> Any pack(\n"
1240 " T message, java.lang.String typeUrlPrefix) {\n"
1241 " return Any.newBuilder()\n"
1242 " .setTypeUrl(getTypeUrl(typeUrlPrefix,\n"
1243 " message.getDescriptorForType()))\n"
1244 " .setValue(message.toByteString())\n"
1245 " .build();\n"
1246 "}\n"
1247 "\n"
1248 "public <T extends com.google.protobuf.Message> boolean is(\n"
1249 " java.lang.Class<T> clazz) {\n"
1250 " T defaultInstance =\n"
1251 " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
1252 " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
1253 " defaultInstance.getDescriptorForType().getFullName());\n"
1254 "}\n"
1255 "\n"
1256 "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
1257 "\n"
1258 "@java.lang.SuppressWarnings(\"unchecked\")\n"
1259 "public <T extends com.google.protobuf.Message> T unpack(\n"
1260 " java.lang.Class<T> clazz)\n"
1261 " throws com.google.protobuf.InvalidProtocolBufferException {\n"
1262 " boolean invalidClazz = false;\n"
1263 " if (cachedUnpackValue != null) {\n"
1264 " if (cachedUnpackValue.getClass() == clazz) {\n"
1265 " return (T) cachedUnpackValue;\n"
1266 " }\n"
1267 " invalidClazz = true;\n"
1268 " }\n"
1269 " if (invalidClazz || !is(clazz)) {\n"
1270 " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
1271 " \"Type of the Any message does not match the given class.\");\n"
1272 " }\n"
1273 " T defaultInstance =\n"
1274 " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
1275 " T result = (T) defaultInstance.getParserForType()\n"
1276 " .parseFrom(getValue());\n"
1277 " cachedUnpackValue = result;\n"
1278 " return result;\n"
1279 "}\n");
1280 }
1281
1282 } // namespace java
1283 } // namespace compiler
1284 } // namespace protobuf
1285 } // namespace google
1286