1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 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/compiler/java/java_enum_field.h> 39#include <google/protobuf/compiler/java/java_doc_comment.h> 40#include <google/protobuf/stubs/common.h> 41#include <google/protobuf/compiler/java/java_helpers.h> 42#include <google/protobuf/io/printer.h> 43#include <google/protobuf/wire_format.h> 44#include <google/protobuf/stubs/strutil.h> 45 46namespace google { 47namespace protobuf { 48namespace compiler { 49namespace java { 50 51namespace { 52 53// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of 54// repeat code between this and the other field types. 55void SetEnumVariables(const FieldDescriptor* descriptor, 56 int messageBitIndex, 57 int builderBitIndex, 58 map<string, string>* variables) { 59 (*variables)["name"] = 60 UnderscoresToCamelCase(descriptor); 61 (*variables)["capitalized_name"] = 62 UnderscoresToCapitalizedCamelCase(descriptor); 63 (*variables)["constant_name"] = FieldConstantName(descriptor); 64 (*variables)["number"] = SimpleItoa(descriptor->number()); 65 (*variables)["type"] = ClassName(descriptor->enum_type()); 66 (*variables)["default"] = DefaultValue(descriptor); 67 (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); 68 (*variables)["tag_size"] = SimpleItoa( 69 internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); 70 // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported 71 // by the proto compiler 72 (*variables)["deprecation"] = descriptor->options().deprecated() 73 ? "@java.lang.Deprecated " : ""; 74 (*variables)["on_changed"] = 75 HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; 76 77 // For singular messages and builders, one bit is used for the hasField bit. 78 (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); 79 (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); 80 81 (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); 82 (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); 83 (*variables)["clear_has_field_bit_builder"] = 84 GenerateClearBit(builderBitIndex); 85 86 // For repated builders, one bit is used for whether the array is immutable. 87 (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); 88 (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); 89 (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); 90 91 // For repeated fields, one bit is used for whether the array is immutable 92 // in the parsing constructor. 93 (*variables)["get_mutable_bit_parser"] = 94 GenerateGetBitMutableLocal(builderBitIndex); 95 (*variables)["set_mutable_bit_parser"] = 96 GenerateSetBitMutableLocal(builderBitIndex); 97 98 (*variables)["get_has_field_bit_from_local"] = 99 GenerateGetBitFromLocal(builderBitIndex); 100 (*variables)["set_has_field_bit_to_local"] = 101 GenerateSetBitToLocal(messageBitIndex); 102} 103 104} // namespace 105 106// =================================================================== 107 108EnumFieldGenerator:: 109EnumFieldGenerator(const FieldDescriptor* descriptor, 110 int messageBitIndex, 111 int builderBitIndex) 112 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 113 builderBitIndex_(builderBitIndex) { 114 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_); 115} 116 117EnumFieldGenerator::~EnumFieldGenerator() {} 118 119int EnumFieldGenerator::GetNumBitsForMessage() const { 120 return 1; 121} 122 123int EnumFieldGenerator::GetNumBitsForBuilder() const { 124 return 1; 125} 126 127void EnumFieldGenerator:: 128GenerateInterfaceMembers(io::Printer* printer) const { 129 WriteFieldDocComment(printer, descriptor_); 130 printer->Print(variables_, 131 "$deprecation$boolean has$capitalized_name$();\n"); 132 WriteFieldDocComment(printer, descriptor_); 133 printer->Print(variables_, 134 "$deprecation$$type$ get$capitalized_name$();\n"); 135} 136 137void EnumFieldGenerator:: 138GenerateMembers(io::Printer* printer) const { 139 printer->Print(variables_, 140 "private $type$ $name$_;\n"); 141 WriteFieldDocComment(printer, descriptor_); 142 printer->Print(variables_, 143 "$deprecation$public boolean has$capitalized_name$() {\n" 144 " return $get_has_field_bit_message$;\n" 145 "}\n"); 146 WriteFieldDocComment(printer, descriptor_); 147 printer->Print(variables_, 148 "$deprecation$public $type$ get$capitalized_name$() {\n" 149 " return $name$_;\n" 150 "}\n"); 151} 152 153void EnumFieldGenerator:: 154GenerateBuilderMembers(io::Printer* printer) const { 155 printer->Print(variables_, 156 "private $type$ $name$_ = $default$;\n"); 157 WriteFieldDocComment(printer, descriptor_); 158 printer->Print(variables_, 159 "$deprecation$public boolean has$capitalized_name$() {\n" 160 " return $get_has_field_bit_builder$;\n" 161 "}\n"); 162 WriteFieldDocComment(printer, descriptor_); 163 printer->Print(variables_, 164 "$deprecation$public $type$ get$capitalized_name$() {\n" 165 " return $name$_;\n" 166 "}\n"); 167 WriteFieldDocComment(printer, descriptor_); 168 printer->Print(variables_, 169 "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" 170 " if (value == null) {\n" 171 " throw new NullPointerException();\n" 172 " }\n" 173 " $set_has_field_bit_builder$;\n" 174 " $name$_ = value;\n" 175 " $on_changed$\n" 176 " return this;\n" 177 "}\n"); 178 WriteFieldDocComment(printer, descriptor_); 179 printer->Print(variables_, 180 "$deprecation$public Builder clear$capitalized_name$() {\n" 181 " $clear_has_field_bit_builder$;\n" 182 " $name$_ = $default$;\n" 183 " $on_changed$\n" 184 " return this;\n" 185 "}\n"); 186} 187 188void EnumFieldGenerator:: 189GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 190 // noop for enums 191} 192 193void EnumFieldGenerator:: 194GenerateInitializationCode(io::Printer* printer) const { 195 printer->Print(variables_, "$name$_ = $default$;\n"); 196} 197 198void EnumFieldGenerator:: 199GenerateBuilderClearCode(io::Printer* printer) const { 200 printer->Print(variables_, 201 "$name$_ = $default$;\n" 202 "$clear_has_field_bit_builder$;\n"); 203} 204 205void EnumFieldGenerator:: 206GenerateMergingCode(io::Printer* printer) const { 207 printer->Print(variables_, 208 "if (other.has$capitalized_name$()) {\n" 209 " set$capitalized_name$(other.get$capitalized_name$());\n" 210 "}\n"); 211} 212 213void EnumFieldGenerator:: 214GenerateBuildingCode(io::Printer* printer) const { 215 printer->Print(variables_, 216 "if ($get_has_field_bit_from_local$) {\n" 217 " $set_has_field_bit_to_local$;\n" 218 "}\n" 219 "result.$name$_ = $name$_;\n"); 220} 221 222void EnumFieldGenerator:: 223GenerateParsingCode(io::Printer* printer) const { 224 printer->Print(variables_, 225 "int rawValue = input.readEnum();\n" 226 "$type$ value = $type$.valueOf(rawValue);\n"); 227 if (HasUnknownFields(descriptor_->containing_type())) { 228 printer->Print(variables_, 229 "if (value == null) {\n" 230 " unknownFields.mergeVarintField($number$, rawValue);\n" 231 "} else {\n"); 232 } else { 233 printer->Print(variables_, 234 "if (value != null) {\n"); 235 } 236 printer->Print(variables_, 237 " $set_has_field_bit_message$;\n" 238 " $name$_ = value;\n" 239 "}\n"); 240} 241 242void EnumFieldGenerator:: 243GenerateParsingDoneCode(io::Printer* printer) const { 244 // noop for enums 245} 246 247void EnumFieldGenerator:: 248GenerateSerializationCode(io::Printer* printer) const { 249 printer->Print(variables_, 250 "if ($get_has_field_bit_message$) {\n" 251 " output.writeEnum($number$, $name$_.getNumber());\n" 252 "}\n"); 253} 254 255void EnumFieldGenerator:: 256GenerateSerializedSizeCode(io::Printer* printer) const { 257 printer->Print(variables_, 258 "if ($get_has_field_bit_message$) {\n" 259 " size += com.google.protobuf.CodedOutputStream\n" 260 " .computeEnumSize($number$, $name$_.getNumber());\n" 261 "}\n"); 262} 263 264void EnumFieldGenerator:: 265GenerateEqualsCode(io::Printer* printer) const { 266 printer->Print(variables_, 267 "result = result &&\n" 268 " (get$capitalized_name$() == other.get$capitalized_name$());\n"); 269} 270 271void EnumFieldGenerator:: 272GenerateHashCode(io::Printer* printer) const { 273 printer->Print(variables_, 274 "hash = (37 * hash) + $constant_name$;\n" 275 "hash = (53 * hash) + hashEnum(get$capitalized_name$());\n"); 276} 277 278string EnumFieldGenerator::GetBoxedType() const { 279 return ClassName(descriptor_->enum_type()); 280} 281 282// =================================================================== 283 284RepeatedEnumFieldGenerator:: 285RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, 286 int messageBitIndex, 287 int builderBitIndex) 288 : descriptor_(descriptor), messageBitIndex_(messageBitIndex), 289 builderBitIndex_(builderBitIndex) { 290 SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_); 291} 292 293RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} 294 295int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const { 296 return 0; 297} 298 299int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const { 300 return 1; 301} 302 303void RepeatedEnumFieldGenerator:: 304GenerateInterfaceMembers(io::Printer* printer) const { 305 WriteFieldDocComment(printer, descriptor_); 306 printer->Print(variables_, 307 "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); 308 WriteFieldDocComment(printer, descriptor_); 309 printer->Print(variables_, 310 "$deprecation$int get$capitalized_name$Count();\n"); 311 WriteFieldDocComment(printer, descriptor_); 312 printer->Print(variables_, 313 "$deprecation$$type$ get$capitalized_name$(int index);\n"); 314} 315 316void RepeatedEnumFieldGenerator:: 317GenerateMembers(io::Printer* printer) const { 318 printer->Print(variables_, 319 "private java.util.List<$type$> $name$_;\n"); 320 WriteFieldDocComment(printer, descriptor_); 321 printer->Print(variables_, 322 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" 323 " return $name$_;\n" // note: unmodifiable list 324 "}\n"); 325 WriteFieldDocComment(printer, descriptor_); 326 printer->Print(variables_, 327 "$deprecation$public int get$capitalized_name$Count() {\n" 328 " return $name$_.size();\n" 329 "}\n"); 330 WriteFieldDocComment(printer, descriptor_); 331 printer->Print(variables_, 332 "$deprecation$public $type$ get$capitalized_name$(int index) {\n" 333 " return $name$_.get(index);\n" 334 "}\n"); 335 336 if (descriptor_->options().packed() && 337 HasGeneratedMethods(descriptor_->containing_type())) { 338 printer->Print(variables_, 339 "private int $name$MemoizedSerializedSize;\n"); 340 } 341} 342 343void RepeatedEnumFieldGenerator:: 344GenerateBuilderMembers(io::Printer* printer) const { 345 printer->Print(variables_, 346 // One field is the list and the other field keeps track of whether the 347 // list is immutable. If it's immutable, the invariant is that it must 348 // either an instance of Collections.emptyList() or it's an ArrayList 349 // wrapped in a Collections.unmodifiableList() wrapper and nobody else has 350 // a refererence to the underlying ArrayList. This invariant allows us to 351 // share instances of lists between protocol buffers avoiding expensive 352 // memory allocations. Note, immutable is a strong guarantee here -- not 353 // just that the list cannot be modified via the reference but that the 354 // list can never be modified. 355 "private java.util.List<$type$> $name$_ =\n" 356 " java.util.Collections.emptyList();\n" 357 358 "private void ensure$capitalized_name$IsMutable() {\n" 359 " if (!$get_mutable_bit_builder$) {\n" 360 " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" 361 " $set_mutable_bit_builder$;\n" 362 " }\n" 363 "}\n"); 364 365 WriteFieldDocComment(printer, descriptor_); 366 printer->Print(variables_, 367 // Note: We return an unmodifiable list because otherwise the caller 368 // could hold on to the returned list and modify it after the message 369 // has been built, thus mutating the message which is supposed to be 370 // immutable. 371 "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" 372 " return java.util.Collections.unmodifiableList($name$_);\n" 373 "}\n"); 374 WriteFieldDocComment(printer, descriptor_); 375 printer->Print(variables_, 376 "$deprecation$public int get$capitalized_name$Count() {\n" 377 " return $name$_.size();\n" 378 "}\n"); 379 WriteFieldDocComment(printer, descriptor_); 380 printer->Print(variables_, 381 "$deprecation$public $type$ get$capitalized_name$(int index) {\n" 382 " return $name$_.get(index);\n" 383 "}\n"); 384 WriteFieldDocComment(printer, descriptor_); 385 printer->Print(variables_, 386 "$deprecation$public Builder set$capitalized_name$(\n" 387 " int index, $type$ value) {\n" 388 " if (value == null) {\n" 389 " throw new NullPointerException();\n" 390 " }\n" 391 " ensure$capitalized_name$IsMutable();\n" 392 " $name$_.set(index, value);\n" 393 " $on_changed$\n" 394 " return this;\n" 395 "}\n"); 396 WriteFieldDocComment(printer, descriptor_); 397 printer->Print(variables_, 398 "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" 399 " if (value == null) {\n" 400 " throw new NullPointerException();\n" 401 " }\n" 402 " ensure$capitalized_name$IsMutable();\n" 403 " $name$_.add(value);\n" 404 " $on_changed$\n" 405 " return this;\n" 406 "}\n"); 407 WriteFieldDocComment(printer, descriptor_); 408 printer->Print(variables_, 409 "$deprecation$public Builder addAll$capitalized_name$(\n" 410 " java.lang.Iterable<? extends $type$> values) {\n" 411 " ensure$capitalized_name$IsMutable();\n" 412 " super.addAll(values, $name$_);\n" 413 " $on_changed$\n" 414 " return this;\n" 415 "}\n"); 416 WriteFieldDocComment(printer, descriptor_); 417 printer->Print(variables_, 418 "$deprecation$public Builder clear$capitalized_name$() {\n" 419 " $name$_ = java.util.Collections.emptyList();\n" 420 " $clear_mutable_bit_builder$;\n" 421 " $on_changed$\n" 422 " return this;\n" 423 "}\n"); 424} 425 426void RepeatedEnumFieldGenerator:: 427GenerateFieldBuilderInitializationCode(io::Printer* printer) const { 428 // noop for enums 429} 430 431void RepeatedEnumFieldGenerator:: 432GenerateInitializationCode(io::Printer* printer) const { 433 printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); 434} 435 436void RepeatedEnumFieldGenerator:: 437GenerateBuilderClearCode(io::Printer* printer) const { 438 printer->Print(variables_, 439 "$name$_ = java.util.Collections.emptyList();\n" 440 "$clear_mutable_bit_builder$;\n"); 441} 442 443void RepeatedEnumFieldGenerator:: 444GenerateMergingCode(io::Printer* printer) const { 445 // The code below does two optimizations: 446 // 1. If the other list is empty, there's nothing to do. This ensures we 447 // don't allocate a new array if we already have an immutable one. 448 // 2. If the other list is non-empty and our current list is empty, we can 449 // reuse the other list which is guaranteed to be immutable. 450 printer->Print(variables_, 451 "if (!other.$name$_.isEmpty()) {\n" 452 " if ($name$_.isEmpty()) {\n" 453 " $name$_ = other.$name$_;\n" 454 " $clear_mutable_bit_builder$;\n" 455 " } else {\n" 456 " ensure$capitalized_name$IsMutable();\n" 457 " $name$_.addAll(other.$name$_);\n" 458 " }\n" 459 " $on_changed$\n" 460 "}\n"); 461} 462 463void RepeatedEnumFieldGenerator:: 464GenerateBuildingCode(io::Printer* printer) const { 465 // The code below ensures that the result has an immutable list. If our 466 // list is immutable, we can just reuse it. If not, we make it immutable. 467 printer->Print(variables_, 468 "if ($get_mutable_bit_builder$) {\n" 469 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" 470 " $clear_mutable_bit_builder$;\n" 471 "}\n" 472 "result.$name$_ = $name$_;\n"); 473} 474 475void RepeatedEnumFieldGenerator:: 476GenerateParsingCode(io::Printer* printer) const { 477 // Read and store the enum 478 printer->Print(variables_, 479 "int rawValue = input.readEnum();\n" 480 "$type$ value = $type$.valueOf(rawValue);\n"); 481 if (HasUnknownFields(descriptor_->containing_type())) { 482 printer->Print(variables_, 483 "if (value == null) {\n" 484 " unknownFields.mergeVarintField($number$, rawValue);\n" 485 "} else {\n"); 486 } else { 487 printer->Print(variables_, 488 "if (value != null) {\n"); 489 } 490 printer->Print(variables_, 491 " if (!$get_mutable_bit_parser$) {\n" 492 " $name$_ = new java.util.ArrayList<$type$>();\n" 493 " $set_mutable_bit_parser$;\n" 494 " }\n" 495 " $name$_.add(value);\n" 496 "}\n"); 497} 498 499void RepeatedEnumFieldGenerator:: 500GenerateParsingCodeFromPacked(io::Printer* printer) const { 501 // Wrap GenerateParsingCode's contents with a while loop. 502 503 printer->Print(variables_, 504 "int length = input.readRawVarint32();\n" 505 "int oldLimit = input.pushLimit(length);\n" 506 "while(input.getBytesUntilLimit() > 0) {\n"); 507 printer->Indent(); 508 509 GenerateParsingCode(printer); 510 511 printer->Outdent(); 512 printer->Print(variables_, 513 "}\n" 514 "input.popLimit(oldLimit);\n"); 515} 516 517void RepeatedEnumFieldGenerator:: 518GenerateParsingDoneCode(io::Printer* printer) const { 519 printer->Print(variables_, 520 "if ($get_mutable_bit_parser$) {\n" 521 " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" 522 "}\n"); 523} 524 525void RepeatedEnumFieldGenerator:: 526GenerateSerializationCode(io::Printer* printer) const { 527 if (descriptor_->options().packed()) { 528 printer->Print(variables_, 529 "if (get$capitalized_name$List().size() > 0) {\n" 530 " output.writeRawVarint32($tag$);\n" 531 " output.writeRawVarint32($name$MemoizedSerializedSize);\n" 532 "}\n" 533 "for (int i = 0; i < $name$_.size(); i++) {\n" 534 " output.writeEnumNoTag($name$_.get(i).getNumber());\n" 535 "}\n"); 536 } else { 537 printer->Print(variables_, 538 "for (int i = 0; i < $name$_.size(); i++) {\n" 539 " output.writeEnum($number$, $name$_.get(i).getNumber());\n" 540 "}\n"); 541 } 542} 543 544void RepeatedEnumFieldGenerator:: 545GenerateSerializedSizeCode(io::Printer* printer) const { 546 printer->Print(variables_, 547 "{\n" 548 " int dataSize = 0;\n"); 549 printer->Indent(); 550 551 printer->Print(variables_, 552 "for (int i = 0; i < $name$_.size(); i++) {\n" 553 " dataSize += com.google.protobuf.CodedOutputStream\n" 554 " .computeEnumSizeNoTag($name$_.get(i).getNumber());\n" 555 "}\n"); 556 printer->Print( 557 "size += dataSize;\n"); 558 if (descriptor_->options().packed()) { 559 printer->Print(variables_, 560 "if (!get$capitalized_name$List().isEmpty()) {" 561 " size += $tag_size$;\n" 562 " size += com.google.protobuf.CodedOutputStream\n" 563 " .computeRawVarint32Size(dataSize);\n" 564 "}"); 565 } else { 566 printer->Print(variables_, 567 "size += $tag_size$ * $name$_.size();\n"); 568 } 569 570 // cache the data size for packed fields. 571 if (descriptor_->options().packed()) { 572 printer->Print(variables_, 573 "$name$MemoizedSerializedSize = dataSize;\n"); 574 } 575 576 printer->Outdent(); 577 printer->Print("}\n"); 578} 579 580void RepeatedEnumFieldGenerator:: 581GenerateEqualsCode(io::Printer* printer) const { 582 printer->Print(variables_, 583 "result = result && get$capitalized_name$List()\n" 584 " .equals(other.get$capitalized_name$List());\n"); 585} 586 587void RepeatedEnumFieldGenerator:: 588GenerateHashCode(io::Printer* printer) const { 589 printer->Print(variables_, 590 "if (get$capitalized_name$Count() > 0) {\n" 591 " hash = (37 * hash) + $constant_name$;\n" 592 " hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n" 593 "}\n"); 594} 595 596string RepeatedEnumFieldGenerator::GetBoxedType() const { 597 return ClassName(descriptor_->enum_type()); 598} 599 600} // namespace java 601} // namespace compiler 602} // namespace protobuf 603} // namespace google 604