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