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 <map> 36#include <string> 37 38#include <google/protobuf/stubs/logging.h> 39#include <google/protobuf/stubs/common.h> 40#include <google/protobuf/compiler/java/java_context.h> 41#include <google/protobuf/compiler/java/java_doc_comment.h> 42#include <google/protobuf/compiler/java/java_enum_field.h> 43#include <google/protobuf/compiler/java/java_helpers.h> 44#include <google/protobuf/compiler/java/java_name_resolver.h> 45#include <google/protobuf/io/printer.h> 46#include <google/protobuf/wire_format.h> 47#include <google/protobuf/stubs/strutil.h> 48 49namespace google { 50namespace protobuf { 51namespace compiler { 52namespace java { 53 54namespace { 55 56void SetEnumVariables(const FieldDescriptor* descriptor, 57 int messageBitIndex, 58 int builderBitIndex, 59 const FieldGeneratorInfo* info, 60 ClassNameResolver* name_resolver, 61 map<string, string>* variables) { 62 SetCommonFieldVariables(descriptor, info, variables); 63 64 (*variables)["type"] = 65 name_resolver->GetImmutableClassName(descriptor->enum_type()); 66 (*variables)["mutable_type"] = 67 name_resolver->GetMutableClassName(descriptor->enum_type()); 68 (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); 69 (*variables)["default_number"] = SimpleItoa( 70 descriptor->default_value_enum()->number()); 71 (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); 72 (*variables)["tag_size"] = SimpleItoa( 73 internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); 74 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported 75 // by the proto compiler 76 (*variables)["deprecation"] = descriptor->options().deprecated() 77 ? "@java.lang.Deprecated " : ""; 78 (*variables)["on_changed"] = "onChanged();"; 79 80 if (SupportFieldPresence(descriptor->file())) { 81 // For singular messages and builders, one bit is used for the hasField bit. 82 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); 83 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); 84 85 // Note that these have a trailing ";". 86 (*variables)["set_has_field_bit_message"] = 87 GenerateSetBit(messageBitIndex) + ";"; 88 (*variables)["set_has_field_bit_builder"] = 89 GenerateSetBit(builderBitIndex) + ";"; 90 (*variables)["clear_has_field_bit_builder"] = 91 GenerateClearBit(builderBitIndex) + ";"; 92 93 (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); 94 } else { 95 (*variables)["set_has_field_bit_message"] = ""; 96 (*variables)["set_has_field_bit_builder"] = ""; 97 (*variables)["clear_has_field_bit_builder"] = ""; 98 99 (*variables)["is_field_present_message"] = 100 (*variables)["name"] + "_ != " + 101 (*variables)["default"] + ".getNumber()"; 102 } 103 104 // For repated builders, one bit is used for whether the array is immutable. 105 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); 106 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); 107 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); 108 109 // For repeated fields, one bit is used for whether the array is immutable 110 // in the parsing constructor. 111 (*variables)["get_mutable_bit_parser"] = 112 GenerateGetBitMutableLocal(builderBitIndex); 113 (*variables)["set_mutable_bit_parser"] = 114 GenerateSetBitMutableLocal(builderBitIndex); 115 116 (*variables)["get_has_field_bit_from_local"] = 117 GenerateGetBitFromLocal(builderBitIndex); 118 (*variables)["set_has_field_bit_to_local"] = 119 GenerateSetBitToLocal(messageBitIndex); 120 121 if (SupportUnknownEnumValue(descriptor->file())) { 122 (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED"; 123 } else { 124 (*variables)["unknown"] = (*variables)["default"]; 125 } 126} 127 128} // namespace 129 130// =================================================================== 131 132ImmutableEnumFieldGenerator:: 133ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, 134 int messageBitIndex, 135 int builderBitIndex, 136 Context* context) 137 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 138 builderBitIndex_(builderBitIndex), 139 name_resolver_(context->GetNameResolver()) { 140 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, 141 context->GetFieldGeneratorInfo(descriptor), 142 name_resolver_, &variables_); 143} 144 145ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {} 146 147int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const { 148 return 1; 149} 150 151int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { 152 return 1; 153} 154 155void ImmutableEnumFieldGenerator:: 156GenerateInterfaceMembers(io::Printer* printer) const { 157 if (SupportFieldPresence(descriptor_->file())) { 158 WriteFieldDocComment(printer, descriptor_); 159 printer->Print(variables_, 160 "$deprecation$boolean has$capitalized_name$();\n"); 161 } 162 if (SupportUnknownEnumValue(descriptor_->file())) { 163 WriteFieldDocComment(printer, descriptor_); 164 printer->Print(variables_, 165 "$deprecation$int get$capitalized_name$Value();\n"); 166 } 167 WriteFieldDocComment(printer, descriptor_); 168 printer->Print(variables_, 169 "$deprecation$$type$ get$capitalized_name$();\n"); 170} 171 172void ImmutableEnumFieldGenerator:: 173GenerateMembers(io::Printer* printer) const { 174 printer->Print(variables_, 175 "private int $name$_;\n"); 176 PrintExtraFieldInfo(variables_, printer); 177 if (SupportFieldPresence(descriptor_->file())) { 178 WriteFieldDocComment(printer, descriptor_); 179 printer->Print(variables_, 180 "$deprecation$public boolean has$capitalized_name$() {\n" 181 " return $get_has_field_bit_message$;\n" 182 "}\n"); 183 } 184 if (SupportUnknownEnumValue(descriptor_->file())) { 185 WriteFieldDocComment(printer, descriptor_); 186 printer->Print(variables_, 187 "$deprecation$public int get$capitalized_name$Value() {\n" 188 " return $name$_;\n" 189 "}\n"); 190 } 191 WriteFieldDocComment(printer, descriptor_); 192 printer->Print(variables_, 193 "$deprecation$public $type$ get$capitalized_name$() {\n" 194 " $type$ result = $type$.forNumber($name$_);\n" 195 " return result == null ? $unknown$ : result;\n" 196 "}\n"); 197} 198 199void ImmutableEnumFieldGenerator:: 200GenerateBuilderMembers(io::Printer* printer) const { 201 printer->Print(variables_, 202 "private int $name$_ = $default_number$;\n"); 203 if (SupportFieldPresence(descriptor_->file())) { 204 WriteFieldDocComment(printer, descriptor_); 205 printer->Print(variables_, 206 "$deprecation$public boolean has$capitalized_name$() {\n" 207 " return $get_has_field_bit_builder$;\n" 208 "}\n"); 209 } 210 if (SupportUnknownEnumValue(descriptor_->file())) { 211 WriteFieldDocComment(printer, descriptor_); 212 printer->Print(variables_, 213 "$deprecation$public int get$capitalized_name$Value() {\n" 214 " return $name$_;\n" 215 "}\n"); 216 WriteFieldDocComment(printer, descriptor_); 217 printer->Print(variables_, 218 "$deprecation$public Builder set$capitalized_name$Value(int value) {\n" 219 " $name$_ = value;\n" 220 " $on_changed$\n" 221 " return this;\n" 222 "}\n"); 223 } 224 WriteFieldDocComment(printer, descriptor_); 225 printer->Print(variables_, 226 "$deprecation$public $type$ get$capitalized_name$() {\n" 227 " $type$ result = $type$.forNumber($name$_);\n" 228 " return result == null ? $unknown$ : result;\n" 229 "}\n"); 230 WriteFieldDocComment(printer, descriptor_); 231 printer->Print(variables_, 232 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" 233 " if (value == null) {\n" 234 " throw new NullPointerException();\n" 235 " }\n" 236 " $set_has_field_bit_builder$\n" 237 " $name$_ = value.getNumber();\n" 238 " $on_changed$\n" 239 " return this;\n" 240 "}\n"); 241 WriteFieldDocComment(printer, descriptor_); 242 printer->Print(variables_, 243 "$deprecation$public Builder clear$capitalized_name$() {\n" 244 " $clear_has_field_bit_builder$\n" 245 " $name$_ = $default_number$;\n" 246 " $on_changed$\n" 247 " return this;\n" 248 "}\n"); 249} 250 251void ImmutableEnumFieldGenerator:: 252GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 253 // noop for enums 254} 255 256void ImmutableEnumFieldGenerator:: 257GenerateInitializationCode(io::Printer* printer) const { 258 printer->Print(variables_, "$name$_ = $default_number$;\n"); 259} 260 261void ImmutableEnumFieldGenerator:: 262GenerateBuilderClearCode(io::Printer* printer) const { 263 printer->Print(variables_, 264 "$name$_ = $default_number$;\n" 265 "$clear_has_field_bit_builder$\n"); 266} 267 268void ImmutableEnumFieldGenerator:: 269GenerateMergingCode(io::Printer* printer) const { 270 if (SupportFieldPresence(descriptor_->file())) { 271 printer->Print(variables_, 272 "if (other.has$capitalized_name$()) {\n" 273 " set$capitalized_name$(other.get$capitalized_name$());\n" 274 "}\n"); 275 } else if (SupportUnknownEnumValue(descriptor_->file())) { 276 printer->Print(variables_, 277 "if (other.$name$_ != $default_number$) {\n" 278 " set$capitalized_name$Value(other.get$capitalized_name$Value());\n" 279 "}\n"); 280 } else { 281 GOOGLE_LOG(FATAL) << "Can't reach here."; 282 } 283} 284 285void ImmutableEnumFieldGenerator:: 286GenerateBuildingCode(io::Printer* printer) const { 287 if (SupportFieldPresence(descriptor_->file())) { 288 printer->Print(variables_, 289 "if ($get_has_field_bit_from_local$) {\n" 290 " $set_has_field_bit_to_local$;\n" 291 "}\n"); 292 } 293 printer->Print(variables_, 294 "result.$name$_ = $name$_;\n"); 295} 296 297void ImmutableEnumFieldGenerator:: 298GenerateParsingCode(io::Printer* printer) const { 299 if (SupportUnknownEnumValue(descriptor_->file())) { 300 printer->Print(variables_, 301 "int rawValue = input.readEnum();\n" 302 "$set_has_field_bit_message$\n" 303 "$name$_ = rawValue;\n"); 304 } else { 305 printer->Print(variables_, 306 "int rawValue = input.readEnum();\n" 307 "$type$ value = $type$.forNumber(rawValue);\n" 308 "if (value == null) {\n"); 309 if (PreserveUnknownFields(descriptor_->containing_type())) { 310 printer->Print(variables_, 311 " unknownFields.mergeVarintField($number$, rawValue);\n"); 312 } 313 printer->Print(variables_, 314 "} else {\n" 315 " $set_has_field_bit_message$\n" 316 " $name$_ = rawValue;\n" 317 "}\n"); 318 } 319} 320 321void ImmutableEnumFieldGenerator:: 322GenerateParsingDoneCode(io::Printer* printer) const { 323 // noop for enums 324} 325 326void ImmutableEnumFieldGenerator:: 327GenerateSerializationCode(io::Printer* printer) const { 328 printer->Print(variables_, 329 "if ($is_field_present_message$) {\n" 330 " output.writeEnum($number$, $name$_);\n" 331 "}\n"); 332} 333 334void ImmutableEnumFieldGenerator:: 335GenerateSerializedSizeCode(io::Printer* printer) const { 336 printer->Print(variables_, 337 "if ($is_field_present_message$) {\n" 338 " size += com.google.protobuf.CodedOutputStream\n" 339 " .computeEnumSize($number$, $name$_);\n" 340 "}\n"); 341} 342 343void ImmutableEnumFieldGenerator:: 344GenerateEqualsCode(io::Printer* printer) const { 345 printer->Print(variables_, 346 "result = result && $name$_ == other.$name$_;\n"); 347} 348 349void ImmutableEnumFieldGenerator:: 350GenerateHashCode(io::Printer* printer) const { 351 printer->Print(variables_, 352 "hash = (37 * hash) + $constant_name$;\n" 353 "hash = (53 * hash) + $name$_;\n"); 354} 355 356string ImmutableEnumFieldGenerator::GetBoxedType() const { 357 return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); 358} 359 360// =================================================================== 361 362ImmutableEnumOneofFieldGenerator:: 363ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor, 364 int messageBitIndex, 365 int builderBitIndex, 366 Context* context) 367 : ImmutableEnumFieldGenerator( 368 descriptor, messageBitIndex, builderBitIndex, context) { 369 const OneofGeneratorInfo* info = 370 context->GetOneofGeneratorInfo(descriptor->containing_oneof()); 371 SetCommonOneofVariables(descriptor, info, &variables_); 372} 373 374ImmutableEnumOneofFieldGenerator:: 375~ImmutableEnumOneofFieldGenerator() {} 376 377void ImmutableEnumOneofFieldGenerator:: 378GenerateMembers(io::Printer* printer) const { 379 PrintExtraFieldInfo(variables_, printer); 380 if (SupportFieldPresence(descriptor_->file())) { 381 WriteFieldDocComment(printer, descriptor_); 382 printer->Print(variables_, 383 "$deprecation$public boolean has$capitalized_name$() {\n" 384 " return $has_oneof_case_message$;\n" 385 "}\n"); 386 } 387 if (SupportUnknownEnumValue(descriptor_->file())) { 388 WriteFieldDocComment(printer, descriptor_); 389 printer->Print(variables_, 390 "$deprecation$public int get$capitalized_name$Value() {\n" 391 " if ($has_oneof_case_message$) {\n" 392 " return (java.lang.Integer) $oneof_name$_;\n" 393 " }\n" 394 " return $default_number$;\n" 395 "}\n"); 396 } 397 WriteFieldDocComment(printer, descriptor_); 398 printer->Print(variables_, 399 "$deprecation$public $type$ get$capitalized_name$() {\n" 400 " if ($has_oneof_case_message$) {\n" 401 " $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n" 402 " return result == null ? $unknown$ : result;\n" 403 " }\n" 404 " return $default$;\n" 405 "}\n"); 406} 407 408void ImmutableEnumOneofFieldGenerator:: 409GenerateBuilderMembers(io::Printer* printer) const { 410 if (SupportFieldPresence(descriptor_->file())) { 411 WriteFieldDocComment(printer, descriptor_); 412 printer->Print(variables_, 413 "$deprecation$public boolean has$capitalized_name$() {\n" 414 " return $has_oneof_case_message$;\n" 415 "}\n"); 416 } 417 if (SupportUnknownEnumValue(descriptor_->file())) { 418 WriteFieldDocComment(printer, descriptor_); 419 printer->Print(variables_, 420 "$deprecation$public int get$capitalized_name$Value() {\n" 421 " if ($has_oneof_case_message$) {\n" 422 " return ((java.lang.Integer) $oneof_name$_).intValue();\n" 423 " }\n" 424 " return $default_number$;\n" 425 "}\n"); 426 WriteFieldDocComment(printer, descriptor_); 427 printer->Print(variables_, 428 "$deprecation$public Builder set$capitalized_name$Value(int value) {\n" 429 " $set_oneof_case_message$;\n" 430 " $oneof_name$_ = value;\n" 431 " $on_changed$\n" 432 " return this;\n" 433 "}\n"); 434 } 435 WriteFieldDocComment(printer, descriptor_); 436 printer->Print(variables_, 437 "$deprecation$public $type$ get$capitalized_name$() {\n" 438 " if ($has_oneof_case_message$) {\n" 439 " $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n" 440 " return result == null ? $unknown$ : result;\n" 441 " }\n" 442 " return $default$;\n" 443 "}\n"); 444 WriteFieldDocComment(printer, descriptor_); 445 printer->Print(variables_, 446 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" 447 " if (value == null) {\n" 448 " throw new NullPointerException();\n" 449 " }\n" 450 " $set_oneof_case_message$;\n" 451 " $oneof_name$_ = value.getNumber();\n" 452 " $on_changed$\n" 453 " return this;\n" 454 "}\n"); 455 WriteFieldDocComment(printer, descriptor_); 456 printer->Print(variables_, 457 "$deprecation$public Builder clear$capitalized_name$() {\n" 458 " if ($has_oneof_case_message$) {\n" 459 " $clear_oneof_case_message$;\n" 460 " $oneof_name$_ = null;\n" 461 " $on_changed$\n" 462 " }\n" 463 " return this;\n" 464 "}\n"); 465} 466 467void ImmutableEnumOneofFieldGenerator:: 468GenerateBuildingCode(io::Printer* printer) const { 469 printer->Print(variables_, 470 "if ($has_oneof_case_message$) {\n" 471 " result.$oneof_name$_ = $oneof_name$_;\n" 472 "}\n"); 473} 474 475void ImmutableEnumOneofFieldGenerator:: 476GenerateMergingCode(io::Printer* printer) const { 477 if (SupportUnknownEnumValue(descriptor_->file())) { 478 printer->Print(variables_, 479 "set$capitalized_name$Value(other.get$capitalized_name$Value());\n"); 480 } else { 481 printer->Print(variables_, 482 "set$capitalized_name$(other.get$capitalized_name$());\n"); 483 } 484} 485 486void ImmutableEnumOneofFieldGenerator:: 487GenerateParsingCode(io::Printer* printer) const { 488 if (SupportUnknownEnumValue(descriptor_->file())) { 489 printer->Print(variables_, 490 "int rawValue = input.readEnum();\n" 491 "$set_oneof_case_message$;\n" 492 "$oneof_name$_ = rawValue;\n"); 493 } else { 494 printer->Print(variables_, 495 "int rawValue = input.readEnum();\n" 496 "$type$ value = $type$.forNumber(rawValue);\n" 497 "if (value == null) {\n"); 498 if (PreserveUnknownFields(descriptor_->containing_type())) { 499 printer->Print(variables_, 500 " unknownFields.mergeVarintField($number$, rawValue);\n"); 501 } 502 printer->Print(variables_, 503 "} else {\n" 504 " $set_oneof_case_message$;\n" 505 " $oneof_name$_ = rawValue;\n" 506 "}\n"); 507 } 508} 509 510void ImmutableEnumOneofFieldGenerator:: 511GenerateSerializationCode(io::Printer* printer) const { 512 printer->Print(variables_, 513 "if ($has_oneof_case_message$) {\n" 514 " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n" 515 "}\n"); 516} 517 518void ImmutableEnumOneofFieldGenerator:: 519GenerateSerializedSizeCode(io::Printer* printer) const { 520 printer->Print(variables_, 521 "if ($has_oneof_case_message$) {\n" 522 " size += com.google.protobuf.CodedOutputStream\n" 523 " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n" 524 "}\n"); 525} 526 527void ImmutableEnumOneofFieldGenerator:: 528GenerateEqualsCode(io::Printer* printer) const { 529 if (SupportUnknownEnumValue(descriptor_->file())) { 530 printer->Print(variables_, 531 "result = result && get$capitalized_name$Value()\n" 532 " == other.get$capitalized_name$Value();\n"); 533 } else { 534 printer->Print(variables_, 535 "result = result && get$capitalized_name$()\n" 536 " .equals(other.get$capitalized_name$());\n"); 537 } 538} 539 540void ImmutableEnumOneofFieldGenerator:: 541GenerateHashCode(io::Printer* printer) const { 542 if (SupportUnknownEnumValue(descriptor_->file())) { 543 printer->Print(variables_, 544 "hash = (37 * hash) + $constant_name$;\n" 545 "hash = (53 * hash) + get$capitalized_name$Value();\n"); 546 } else { 547 printer->Print(variables_, 548 "hash = (37 * hash) + $constant_name$;\n" 549 "hash = (53 * hash) + get$capitalized_name$().getNumber();\n"); 550 } 551} 552 553// =================================================================== 554 555RepeatedImmutableEnumFieldGenerator:: 556RepeatedImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, 557 int messageBitIndex, 558 int builderBitIndex, 559 Context* context) 560 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 561 builderBitIndex_(builderBitIndex), context_(context), 562 name_resolver_(context->GetNameResolver()) { 563 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, 564 context->GetFieldGeneratorInfo(descriptor), 565 name_resolver_, &variables_); 566} 567 568RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {} 569 570int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const { 571 return 0; 572} 573 574int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { 575 return 1; 576} 577 578void RepeatedImmutableEnumFieldGenerator:: 579GenerateInterfaceMembers(io::Printer* printer) const { 580 WriteFieldDocComment(printer, descriptor_); 581 printer->Print(variables_, 582 "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); 583 WriteFieldDocComment(printer, descriptor_); 584 printer->Print(variables_, 585 "$deprecation$int get$capitalized_name$Count();\n"); 586 WriteFieldDocComment(printer, descriptor_); 587 printer->Print(variables_, 588 "$deprecation$$type$ get$capitalized_name$(int index);\n"); 589 if (SupportUnknownEnumValue(descriptor_->file())) { 590 WriteFieldDocComment(printer, descriptor_); 591 printer->Print(variables_, 592 "$deprecation$java.util.List<java.lang.Integer>\n" 593 "get$capitalized_name$ValueList();\n"); 594 WriteFieldDocComment(printer, descriptor_); 595 printer->Print(variables_, 596 "$deprecation$int get$capitalized_name$Value(int index);\n"); 597 } 598} 599 600void RepeatedImmutableEnumFieldGenerator:: 601GenerateMembers(io::Printer* printer) const { 602 printer->Print(variables_, 603 "private java.util.List<java.lang.Integer> $name$_;\n" 604 "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n" 605 " java.lang.Integer, $type$> $name$_converter_ =\n" 606 " new com.google.protobuf.Internal.ListAdapter.Converter<\n" 607 " java.lang.Integer, $type$>() {\n" 608 " public $type$ convert(java.lang.Integer from) {\n" 609 " $type$ result = $type$.forNumber(from);\n" 610 " return result == null ? $unknown$ : result;\n" 611 " }\n" 612 " };\n"); 613 PrintExtraFieldInfo(variables_, printer); 614 WriteFieldDocComment(printer, descriptor_); 615 printer->Print(variables_, 616 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" 617 " return new com.google.protobuf.Internal.ListAdapter<\n" 618 " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" 619 "}\n"); 620 WriteFieldDocComment(printer, descriptor_); 621 printer->Print(variables_, 622 "$deprecation$public int get$capitalized_name$Count() {\n" 623 " return $name$_.size();\n" 624 "}\n"); 625 WriteFieldDocComment(printer, descriptor_); 626 printer->Print(variables_, 627 "$deprecation$public $type$ get$capitalized_name$(int index) {\n" 628 " return $name$_converter_.convert($name$_.get(index));\n" 629 "}\n"); 630 if (SupportUnknownEnumValue(descriptor_->file())) { 631 WriteFieldDocComment(printer, descriptor_); 632 printer->Print(variables_, 633 "$deprecation$public java.util.List<java.lang.Integer>\n" 634 "get$capitalized_name$ValueList() {\n" 635 " return $name$_;\n" 636 "}\n"); 637 WriteFieldDocComment(printer, descriptor_); 638 printer->Print(variables_, 639 "$deprecation$public int get$capitalized_name$Value(int index) {\n" 640 " return $name$_.get(index);\n" 641 "}\n"); 642 } 643 644 if (descriptor_->is_packed() && 645 context_->HasGeneratedMethods(descriptor_->containing_type())) { 646 printer->Print(variables_, 647 "private int $name$MemoizedSerializedSize;\n"); 648 } 649} 650 651void RepeatedImmutableEnumFieldGenerator:: 652GenerateBuilderMembers(io::Printer* printer) const { 653 printer->Print(variables_, 654 // One field is the list and the other field keeps track of whether the 655 // list is immutable. If it's immutable, the invariant is that it must 656 // either an instance of Collections.emptyList() or it's an ArrayList 657 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has 658 // a refererence to the underlying ArrayList. This invariant allows us to 659 // share instances of lists between protocol buffers avoiding expensive 660 // memory allocations. Note, immutable is a strong guarantee here -- not 661 // just that the list cannot be modified via the reference but that the 662 // list can never be modified. 663 "private java.util.List<java.lang.Integer> $name$_ =\n" 664 " java.util.Collections.emptyList();\n" 665 666 "private void ensure$capitalized_name$IsMutable() {\n" 667 " if (!$get_mutable_bit_builder$) {\n" 668 " $name$_ = new java.util.ArrayList<java.lang.Integer>($name$_);\n" 669 " $set_mutable_bit_builder$;\n" 670 " }\n" 671 "}\n"); 672 673 WriteFieldDocComment(printer, descriptor_); 674 printer->Print(variables_, 675 // Note: We return an unmodifiable list because otherwise the caller 676 // could hold on to the returned list and modify it after the message 677 // has been built, thus mutating the message which is supposed to be 678 // immutable. 679 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" 680 " return new com.google.protobuf.Internal.ListAdapter<\n" 681 " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" 682 "}\n"); 683 WriteFieldDocComment(printer, descriptor_); 684 printer->Print(variables_, 685 "$deprecation$public int get$capitalized_name$Count() {\n" 686 " return $name$_.size();\n" 687 "}\n"); 688 WriteFieldDocComment(printer, descriptor_); 689 printer->Print(variables_, 690 "$deprecation$public $type$ get$capitalized_name$(int index) {\n" 691 " return $name$_converter_.convert($name$_.get(index));\n" 692 "}\n"); 693 WriteFieldDocComment(printer, descriptor_); 694 printer->Print(variables_, 695 "$deprecation$public Builder set$capitalized_name$(\n" 696 " int index, $type$ value) {\n" 697 " if (value == null) {\n" 698 " throw new NullPointerException();\n" 699 " }\n" 700 " ensure$capitalized_name$IsMutable();\n" 701 " $name$_.set(index, value.getNumber());\n" 702 " $on_changed$\n" 703 " return this;\n" 704 "}\n"); 705 WriteFieldDocComment(printer, descriptor_); 706 printer->Print(variables_, 707 "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" 708 " if (value == null) {\n" 709 " throw new NullPointerException();\n" 710 " }\n" 711 " ensure$capitalized_name$IsMutable();\n" 712 " $name$_.add(value.getNumber());\n" 713 " $on_changed$\n" 714 " return this;\n" 715 "}\n"); 716 WriteFieldDocComment(printer, descriptor_); 717 printer->Print(variables_, 718 "$deprecation$public Builder addAll$capitalized_name$(\n" 719 " java.lang.Iterable<? extends $type$> values) {\n" 720 " ensure$capitalized_name$IsMutable();\n" 721 " for ($type$ value : values) {\n" 722 " $name$_.add(value.getNumber());\n" 723 " }\n" 724 " $on_changed$\n" 725 " return this;\n" 726 "}\n"); 727 WriteFieldDocComment(printer, descriptor_); 728 printer->Print(variables_, 729 "$deprecation$public Builder clear$capitalized_name$() {\n" 730 " $name$_ = java.util.Collections.emptyList();\n" 731 " $clear_mutable_bit_builder$;\n" 732 " $on_changed$\n" 733 " return this;\n" 734 "}\n"); 735 736 if (SupportUnknownEnumValue(descriptor_->file())) { 737 WriteFieldDocComment(printer, descriptor_); 738 printer->Print(variables_, 739 "$deprecation$public java.util.List<java.lang.Integer>\n" 740 "get$capitalized_name$ValueList() {\n" 741 " return java.util.Collections.unmodifiableList($name$_);\n" 742 "}\n"); 743 WriteFieldDocComment(printer, descriptor_); 744 printer->Print(variables_, 745 "$deprecation$public int get$capitalized_name$Value(int index) {\n" 746 " return $name$_.get(index);\n" 747 "}\n"); 748 WriteFieldDocComment(printer, descriptor_); 749 printer->Print(variables_, 750 "$deprecation$public Builder set$capitalized_name$Value(\n" 751 " int index, int value) {\n" 752 " ensure$capitalized_name$IsMutable();\n" 753 " $name$_.set(index, value);\n" 754 " $on_changed$\n" 755 " return this;\n" 756 "}\n"); 757 WriteFieldDocComment(printer, descriptor_); 758 printer->Print(variables_, 759 "$deprecation$public Builder add$capitalized_name$Value(int value) {\n" 760 " ensure$capitalized_name$IsMutable();\n" 761 " $name$_.add(value);\n" 762 " $on_changed$\n" 763 " return this;\n" 764 "}\n"); 765 WriteFieldDocComment(printer, descriptor_); 766 printer->Print(variables_, 767 "$deprecation$public Builder addAll$capitalized_name$Value(\n" 768 " java.lang.Iterable<java.lang.Integer> values) {\n" 769 " ensure$capitalized_name$IsMutable();\n" 770 " for (int value : values) {\n" 771 " $name$_.add(value);\n" 772 " }\n" 773 " $on_changed$\n" 774 " return this;\n" 775 "}\n"); 776 } 777} 778 779void RepeatedImmutableEnumFieldGenerator:: 780GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 781 // noop for enums 782} 783 784void RepeatedImmutableEnumFieldGenerator:: 785GenerateInitializationCode(io::Printer* printer) const { 786 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); 787} 788 789void RepeatedImmutableEnumFieldGenerator:: 790GenerateBuilderClearCode(io::Printer* printer) const { 791 printer->Print(variables_, 792 "$name$_ = java.util.Collections.emptyList();\n" 793 "$clear_mutable_bit_builder$;\n"); 794} 795 796void RepeatedImmutableEnumFieldGenerator:: 797GenerateMergingCode(io::Printer* printer) const { 798 // The code below does two optimizations: 799 // 1. If the other list is empty, there's nothing to do. This ensures we 800 // don't allocate a new array if we already have an immutable one. 801 // 2. If the other list is non-empty and our current list is empty, we can 802 // reuse the other list which is guaranteed to be immutable. 803 printer->Print(variables_, 804 "if (!other.$name$_.isEmpty()) {\n" 805 " if ($name$_.isEmpty()) {\n" 806 " $name$_ = other.$name$_;\n" 807 " $clear_mutable_bit_builder$;\n" 808 " } else {\n" 809 " ensure$capitalized_name$IsMutable();\n" 810 " $name$_.addAll(other.$name$_);\n" 811 " }\n" 812 " $on_changed$\n" 813 "}\n"); 814} 815 816void RepeatedImmutableEnumFieldGenerator:: 817GenerateBuildingCode(io::Printer* printer) const { 818 // The code below ensures that the result has an immutable list. If our 819 // list is immutable, we can just reuse it. If not, we make it immutable. 820 printer->Print(variables_, 821 "if ($get_mutable_bit_builder$) {\n" 822 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" 823 " $clear_mutable_bit_builder$;\n" 824 "}\n" 825 "result.$name$_ = $name$_;\n"); 826} 827 828void RepeatedImmutableEnumFieldGenerator:: 829GenerateParsingCode(io::Printer* printer) const { 830 // Read and store the enum 831 if (SupportUnknownEnumValue(descriptor_->file())) { 832 printer->Print(variables_, 833 "int rawValue = input.readEnum();\n" 834 "if (!$get_mutable_bit_parser$) {\n" 835 " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n" 836 " $set_mutable_bit_parser$;\n" 837 "}\n" 838 "$name$_.add(rawValue);\n"); 839 } else { 840 printer->Print(variables_, 841 "int rawValue = input.readEnum();\n" 842 "$type$ value = $type$.forNumber(rawValue);\n" 843 "if (value == null) {\n"); 844 if (PreserveUnknownFields(descriptor_->containing_type())) { 845 printer->Print(variables_, 846 " unknownFields.mergeVarintField($number$, rawValue);\n"); 847 } 848 printer->Print(variables_, 849 "} else {\n" 850 " if (!$get_mutable_bit_parser$) {\n" 851 " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n" 852 " $set_mutable_bit_parser$;\n" 853 " }\n" 854 " $name$_.add(rawValue);\n" 855 "}\n"); 856 } 857} 858 859void RepeatedImmutableEnumFieldGenerator:: 860GenerateParsingCodeFromPacked(io::Printer* printer) const { 861 // Wrap GenerateParsingCode's contents with a while loop. 862 863 printer->Print(variables_, 864 "int length = input.readRawVarint32();\n" 865 "int oldLimit = input.pushLimit(length);\n" 866 "while(input.getBytesUntilLimit() > 0) {\n"); 867 printer->Indent(); 868 869 GenerateParsingCode(printer); 870 871 printer->Outdent(); 872 printer->Print(variables_, 873 "}\n" 874 "input.popLimit(oldLimit);\n"); 875} 876 877void RepeatedImmutableEnumFieldGenerator:: 878GenerateParsingDoneCode(io::Printer* printer) const { 879 printer->Print(variables_, 880 "if ($get_mutable_bit_parser$) {\n" 881 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" 882 "}\n"); 883} 884 885void RepeatedImmutableEnumFieldGenerator:: 886GenerateSerializationCode(io::Printer* printer) const { 887 if (descriptor_->is_packed()) { 888 printer->Print(variables_, 889 "if (get$capitalized_name$List().size() > 0) {\n" 890 " output.writeRawVarint32($tag$);\n" 891 " output.writeRawVarint32($name$MemoizedSerializedSize);\n" 892 "}\n" 893 "for (int i = 0; i < $name$_.size(); i++) {\n" 894 " output.writeEnumNoTag($name$_.get(i));\n" 895 "}\n"); 896 } else { 897 printer->Print(variables_, 898 "for (int i = 0; i < $name$_.size(); i++) {\n" 899 " output.writeEnum($number$, $name$_.get(i));\n" 900 "}\n"); 901 } 902} 903 904void RepeatedImmutableEnumFieldGenerator:: 905GenerateSerializedSizeCode(io::Printer* printer) const { 906 printer->Print(variables_, 907 "{\n" 908 " int dataSize = 0;\n"); 909 printer->Indent(); 910 911 printer->Print(variables_, 912 "for (int i = 0; i < $name$_.size(); i++) {\n" 913 " dataSize += com.google.protobuf.CodedOutputStream\n" 914 " .computeEnumSizeNoTag($name$_.get(i));\n" 915 "}\n"); 916 printer->Print( 917 "size += dataSize;\n"); 918 if (descriptor_->is_packed()) { 919 printer->Print(variables_, 920 "if (!get$capitalized_name$List().isEmpty()) {" 921 " size += $tag_size$;\n" 922 " size += com.google.protobuf.CodedOutputStream\n" 923 " .computeRawVarint32Size(dataSize);\n" 924 "}"); 925 } else { 926 printer->Print(variables_, 927 "size += $tag_size$ * $name$_.size();\n"); 928 } 929 930 // cache the data size for packed fields. 931 if (descriptor_->is_packed()) { 932 printer->Print(variables_, 933 "$name$MemoizedSerializedSize = dataSize;\n"); 934 } 935 936 printer->Outdent(); 937 printer->Print("}\n"); 938} 939 940void RepeatedImmutableEnumFieldGenerator:: 941GenerateEqualsCode(io::Printer* printer) const { 942 printer->Print(variables_, 943 "result = result && $name$_.equals(other.$name$_);\n"); 944} 945 946void RepeatedImmutableEnumFieldGenerator:: 947GenerateHashCode(io::Printer* printer) const { 948 printer->Print(variables_, 949 "if (get$capitalized_name$Count() > 0) {\n" 950 " hash = (37 * hash) + $constant_name$;\n" 951 " hash = (53 * hash) + $name$_.hashCode();\n" 952 "}\n"); 953} 954 955string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const { 956 return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); 957} 958 959} // namespace java 960} // namespace compiler 961} // namespace protobuf 962} // namespace google 963