| 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 | |