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 package com.google.protobuf; 32 33 import com.google.protobuf.Descriptors.Descriptor; 34 import com.google.protobuf.Descriptors.EnumValueDescriptor; 35 import com.google.protobuf.Descriptors.FieldDescriptor; 36 37 import java.io.IOException; 38 import java.lang.reflect.Method; 39 import java.lang.reflect.InvocationTargetException; 40 import java.util.ArrayList; 41 import java.util.Collections; 42 import java.util.Iterator; 43 import java.util.List; 44 import java.util.Map; 45 import java.util.TreeMap; 46 47 /** 48 * All generated protocol message classes extend this class. This class 49 * implements most of the Message and Builder interfaces using Java reflection. 50 * Users can ignore this class and pretend that generated messages implement 51 * the Message interface directly. 52 * 53 * @author kenton@google.com Kenton Varda 54 */ 55 public abstract class GeneratedMessage extends AbstractMessage { GeneratedMessage()56 protected GeneratedMessage() {} 57 58 private UnknownFieldSet unknownFields = UnknownFieldSet.getDefaultInstance(); 59 60 /** 61 * Get the FieldAccessorTable for this type. We can't have the message 62 * class pass this in to the constructor because of bootstrapping trouble 63 * with DescriptorProtos. 64 */ internalGetFieldAccessorTable()65 protected abstract FieldAccessorTable internalGetFieldAccessorTable(); 66 getDescriptorForType()67 public Descriptor getDescriptorForType() { 68 return internalGetFieldAccessorTable().descriptor; 69 } 70 71 /** Internal helper which returns a mutable map. */ getAllFieldsMutable()72 private Map<FieldDescriptor, Object> getAllFieldsMutable() { 73 final TreeMap<FieldDescriptor, Object> result = 74 new TreeMap<FieldDescriptor, Object>(); 75 final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; 76 for (final FieldDescriptor field : descriptor.getFields()) { 77 if (field.isRepeated()) { 78 final List value = (List) getField(field); 79 if (!value.isEmpty()) { 80 result.put(field, value); 81 } 82 } else { 83 if (hasField(field)) { 84 result.put(field, getField(field)); 85 } 86 } 87 } 88 return result; 89 } 90 91 @Override isInitialized()92 public boolean isInitialized() { 93 for (final FieldDescriptor field : getDescriptorForType().getFields()) { 94 // Check that all required fields are present. 95 if (field.isRequired()) { 96 if (!hasField(field)) { 97 return false; 98 } 99 } 100 // Check that embedded messages are initialized. 101 if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { 102 if (field.isRepeated()) { 103 @SuppressWarnings("unchecked") final 104 List<Message> messageList = (List<Message>) getField(field); 105 for (final Message element : messageList) { 106 if (!element.isInitialized()) { 107 return false; 108 } 109 } 110 } else { 111 if (hasField(field) && !((Message) getField(field)).isInitialized()) { 112 return false; 113 } 114 } 115 } 116 } 117 118 return true; 119 } 120 getAllFields()121 public Map<FieldDescriptor, Object> getAllFields() { 122 return Collections.unmodifiableMap(getAllFieldsMutable()); 123 } 124 hasField(final FieldDescriptor field)125 public boolean hasField(final FieldDescriptor field) { 126 return internalGetFieldAccessorTable().getField(field).has(this); 127 } 128 getField(final FieldDescriptor field)129 public Object getField(final FieldDescriptor field) { 130 return internalGetFieldAccessorTable().getField(field).get(this); 131 } 132 getRepeatedFieldCount(final FieldDescriptor field)133 public int getRepeatedFieldCount(final FieldDescriptor field) { 134 return internalGetFieldAccessorTable().getField(field) 135 .getRepeatedCount(this); 136 } 137 getRepeatedField(final FieldDescriptor field, final int index)138 public Object getRepeatedField(final FieldDescriptor field, final int index) { 139 return internalGetFieldAccessorTable().getField(field) 140 .getRepeated(this, index); 141 } 142 getUnknownFields()143 public final UnknownFieldSet getUnknownFields() { 144 return unknownFields; 145 } 146 147 @SuppressWarnings("unchecked") 148 public abstract static class Builder <BuilderType extends Builder> 149 extends AbstractMessage.Builder<BuilderType> { Builder()150 protected Builder() {} 151 152 // This is implemented here only to work around an apparent bug in the 153 // Java compiler and/or build system. See bug #1898463. The mere presence 154 // of this dummy clone() implementation makes it go away. 155 @Override clone()156 public BuilderType clone() { 157 throw new UnsupportedOperationException( 158 "This is supposed to be overridden by subclasses."); 159 } 160 161 /** 162 * Get the message being built. We don't just pass this to the 163 * constructor because it becomes null when build() is called. 164 */ internalGetResult()165 protected abstract GeneratedMessage internalGetResult(); 166 167 /** 168 * Get the FieldAccessorTable for this type. We can't have the message 169 * class pass this in to the constructor because of bootstrapping trouble 170 * with DescriptorProtos. 171 */ internalGetFieldAccessorTable()172 private FieldAccessorTable internalGetFieldAccessorTable() { 173 return internalGetResult().internalGetFieldAccessorTable(); 174 } 175 getDescriptorForType()176 public Descriptor getDescriptorForType() { 177 return internalGetFieldAccessorTable().descriptor; 178 } 179 getAllFields()180 public Map<FieldDescriptor, Object> getAllFields() { 181 return internalGetResult().getAllFields(); 182 } 183 newBuilderForField( final FieldDescriptor field)184 public Message.Builder newBuilderForField( 185 final FieldDescriptor field) { 186 return internalGetFieldAccessorTable().getField(field).newBuilder(); 187 } 188 hasField(final FieldDescriptor field)189 public boolean hasField(final FieldDescriptor field) { 190 return internalGetResult().hasField(field); 191 } 192 getField(final FieldDescriptor field)193 public Object getField(final FieldDescriptor field) { 194 if (field.isRepeated()) { 195 // The underlying list object is still modifiable at this point. 196 // Make sure not to expose the modifiable list to the caller. 197 return Collections.unmodifiableList( 198 (List) internalGetResult().getField(field)); 199 } else { 200 return internalGetResult().getField(field); 201 } 202 } 203 setField(final FieldDescriptor field, final Object value)204 public BuilderType setField(final FieldDescriptor field, 205 final Object value) { 206 internalGetFieldAccessorTable().getField(field).set(this, value); 207 return (BuilderType) this; 208 } 209 clearField(final FieldDescriptor field)210 public BuilderType clearField(final FieldDescriptor field) { 211 internalGetFieldAccessorTable().getField(field).clear(this); 212 return (BuilderType) this; 213 } 214 getRepeatedFieldCount(final FieldDescriptor field)215 public int getRepeatedFieldCount(final FieldDescriptor field) { 216 return internalGetResult().getRepeatedFieldCount(field); 217 } 218 getRepeatedField(final FieldDescriptor field, final int index)219 public Object getRepeatedField(final FieldDescriptor field, 220 final int index) { 221 return internalGetResult().getRepeatedField(field, index); 222 } 223 setRepeatedField(final FieldDescriptor field, final int index, final Object value)224 public BuilderType setRepeatedField(final FieldDescriptor field, 225 final int index, final Object value) { 226 internalGetFieldAccessorTable().getField(field) 227 .setRepeated(this, index, value); 228 return (BuilderType) this; 229 } 230 addRepeatedField(final FieldDescriptor field, final Object value)231 public BuilderType addRepeatedField(final FieldDescriptor field, 232 final Object value) { 233 internalGetFieldAccessorTable().getField(field).addRepeated(this, value); 234 return (BuilderType) this; 235 } 236 getUnknownFields()237 public final UnknownFieldSet getUnknownFields() { 238 return internalGetResult().unknownFields; 239 } 240 setUnknownFields( final UnknownFieldSet unknownFields)241 public final BuilderType setUnknownFields( 242 final UnknownFieldSet unknownFields) { 243 internalGetResult().unknownFields = unknownFields; 244 return (BuilderType) this; 245 } 246 247 @Override mergeUnknownFields( final UnknownFieldSet unknownFields)248 public final BuilderType mergeUnknownFields( 249 final UnknownFieldSet unknownFields) { 250 final GeneratedMessage result = internalGetResult(); 251 result.unknownFields = 252 UnknownFieldSet.newBuilder(result.unknownFields) 253 .mergeFrom(unknownFields) 254 .build(); 255 return (BuilderType) this; 256 } 257 isInitialized()258 public boolean isInitialized() { 259 return internalGetResult().isInitialized(); 260 } 261 262 /** 263 * Called by subclasses to parse an unknown field. 264 * @return {@code true} unless the tag is an end-group tag. 265 */ parseUnknownField( final CodedInputStream input, final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, final int tag)266 protected boolean parseUnknownField( 267 final CodedInputStream input, 268 final UnknownFieldSet.Builder unknownFields, 269 final ExtensionRegistryLite extensionRegistry, 270 final int tag) throws IOException { 271 return unknownFields.mergeFieldFrom(tag, input); 272 } 273 } 274 275 // ================================================================= 276 // Extensions-related stuff 277 278 /** 279 * Generated message classes for message types that contain extension ranges 280 * subclass this. 281 * 282 * <p>This class implements type-safe accessors for extensions. They 283 * implement all the same operations that you can do with normal fields -- 284 * e.g. "has", "get", and "getCount" -- but for extensions. The extensions 285 * are identified using instances of the class {@link GeneratedExtension}; 286 * the protocol compiler generates a static instance of this class for every 287 * extension in its input. Through the magic of generics, all is made 288 * type-safe. 289 * 290 * <p>For example, imagine you have the {@code .proto} file: 291 * 292 * <pre> 293 * option java_class = "MyProto"; 294 * 295 * message Foo { 296 * extensions 1000 to max; 297 * } 298 * 299 * extend Foo { 300 * optional int32 bar; 301 * } 302 * </pre> 303 * 304 * <p>Then you might write code like: 305 * 306 * <pre> 307 * MyProto.Foo foo = getFoo(); 308 * int i = foo.getExtension(MyProto.bar); 309 * </pre> 310 * 311 * <p>See also {@link ExtendableBuilder}. 312 */ 313 public abstract static class ExtendableMessage< 314 MessageType extends ExtendableMessage> 315 extends GeneratedMessage { ExtendableMessage()316 protected ExtendableMessage() {} 317 private final FieldSet<FieldDescriptor> extensions = FieldSet.newFieldSet(); 318 verifyExtensionContainingType( final GeneratedExtension<MessageType, ?> extension)319 private void verifyExtensionContainingType( 320 final GeneratedExtension<MessageType, ?> extension) { 321 if (extension.getDescriptor().getContainingType() != 322 getDescriptorForType()) { 323 // This can only happen if someone uses unchecked operations. 324 throw new IllegalArgumentException( 325 "Extension is for type \"" + 326 extension.getDescriptor().getContainingType().getFullName() + 327 "\" which does not match message type \"" + 328 getDescriptorForType().getFullName() + "\"."); 329 } 330 } 331 332 /** Check if a singular extension is present. */ hasExtension( final GeneratedExtension<MessageType, ?> extension)333 public final boolean hasExtension( 334 final GeneratedExtension<MessageType, ?> extension) { 335 verifyExtensionContainingType(extension); 336 return extensions.hasField(extension.getDescriptor()); 337 } 338 339 /** Get the number of elements in a repeated extension. */ getExtensionCount( final GeneratedExtension<MessageType, List<Type>> extension)340 public final <Type> int getExtensionCount( 341 final GeneratedExtension<MessageType, List<Type>> extension) { 342 verifyExtensionContainingType(extension); 343 final FieldDescriptor descriptor = extension.getDescriptor(); 344 return extensions.getRepeatedFieldCount(descriptor); 345 } 346 347 /** Get the value of an extension. */ 348 @SuppressWarnings("unchecked") getExtension( final GeneratedExtension<MessageType, Type> extension)349 public final <Type> Type getExtension( 350 final GeneratedExtension<MessageType, Type> extension) { 351 verifyExtensionContainingType(extension); 352 FieldDescriptor descriptor = extension.getDescriptor(); 353 final Object value = extensions.getField(descriptor); 354 if (value == null) { 355 if (descriptor.isRepeated()) { 356 return (Type) Collections.emptyList(); 357 } else if (descriptor.getJavaType() == 358 FieldDescriptor.JavaType.MESSAGE) { 359 return (Type) extension.getMessageDefaultInstance(); 360 } else { 361 return (Type) extension.fromReflectionType( 362 descriptor.getDefaultValue()); 363 } 364 } else { 365 return (Type) extension.fromReflectionType(value); 366 } 367 } 368 369 /** Get one element of a repeated extension. */ 370 @SuppressWarnings("unchecked") getExtension( final GeneratedExtension<MessageType, List<Type>> extension, final int index)371 public final <Type> Type getExtension( 372 final GeneratedExtension<MessageType, List<Type>> extension, 373 final int index) { 374 verifyExtensionContainingType(extension); 375 FieldDescriptor descriptor = extension.getDescriptor(); 376 return (Type) extension.singularFromReflectionType( 377 extensions.getRepeatedField(descriptor, index)); 378 } 379 380 /** Called by subclasses to check if all extensions are initialized. */ extensionsAreInitialized()381 protected boolean extensionsAreInitialized() { 382 return extensions.isInitialized(); 383 } 384 385 @Override isInitialized()386 public boolean isInitialized() { 387 return super.isInitialized() && extensionsAreInitialized(); 388 } 389 390 /** 391 * Used by subclasses to serialize extensions. Extension ranges may be 392 * interleaved with field numbers, but we must write them in canonical 393 * (sorted by field number) order. ExtensionWriter helps us write 394 * individual ranges of extensions at once. 395 */ 396 protected class ExtensionWriter { 397 // Imagine how much simpler this code would be if Java iterators had 398 // a way to get the next element without advancing the iterator. 399 400 private final Iterator<Map.Entry<FieldDescriptor, Object>> iter = 401 extensions.iterator(); 402 private Map.Entry<FieldDescriptor, Object> next; 403 private final boolean messageSetWireFormat; 404 ExtensionWriter(final boolean messageSetWireFormat)405 private ExtensionWriter(final boolean messageSetWireFormat) { 406 if (iter.hasNext()) { 407 next = iter.next(); 408 } 409 this.messageSetWireFormat = messageSetWireFormat; 410 } 411 writeUntil(final int end, final CodedOutputStream output)412 public void writeUntil(final int end, final CodedOutputStream output) 413 throws IOException { 414 while (next != null && next.getKey().getNumber() < end) { 415 FieldDescriptor descriptor = next.getKey(); 416 if (messageSetWireFormat && descriptor.getLiteJavaType() == 417 WireFormat.JavaType.MESSAGE && 418 !descriptor.isRepeated()) { 419 output.writeMessageSetExtension(descriptor.getNumber(), 420 (Message) next.getValue()); 421 } else { 422 FieldSet.writeField(descriptor, next.getValue(), output); 423 } 424 if (iter.hasNext()) { 425 next = iter.next(); 426 } else { 427 next = null; 428 } 429 } 430 } 431 } 432 newExtensionWriter()433 protected ExtensionWriter newExtensionWriter() { 434 return new ExtensionWriter(false); 435 } newMessageSetExtensionWriter()436 protected ExtensionWriter newMessageSetExtensionWriter() { 437 return new ExtensionWriter(true); 438 } 439 440 /** Called by subclasses to compute the size of extensions. */ extensionsSerializedSize()441 protected int extensionsSerializedSize() { 442 return extensions.getSerializedSize(); 443 } extensionsSerializedSizeAsMessageSet()444 protected int extensionsSerializedSizeAsMessageSet() { 445 return extensions.getMessageSetSerializedSize(); 446 } 447 448 // --------------------------------------------------------------- 449 // Reflection 450 451 @Override getAllFields()452 public Map<FieldDescriptor, Object> getAllFields() { 453 final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable(); 454 result.putAll(extensions.getAllFields()); 455 return Collections.unmodifiableMap(result); 456 } 457 458 @Override hasField(final FieldDescriptor field)459 public boolean hasField(final FieldDescriptor field) { 460 if (field.isExtension()) { 461 verifyContainingType(field); 462 return extensions.hasField(field); 463 } else { 464 return super.hasField(field); 465 } 466 } 467 468 @Override getField(final FieldDescriptor field)469 public Object getField(final FieldDescriptor field) { 470 if (field.isExtension()) { 471 verifyContainingType(field); 472 final Object value = extensions.getField(field); 473 if (value == null) { 474 if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { 475 // Lacking an ExtensionRegistry, we have no way to determine the 476 // extension's real type, so we return a DynamicMessage. 477 return DynamicMessage.getDefaultInstance(field.getMessageType()); 478 } else { 479 return field.getDefaultValue(); 480 } 481 } else { 482 return value; 483 } 484 } else { 485 return super.getField(field); 486 } 487 } 488 489 @Override getRepeatedFieldCount(final FieldDescriptor field)490 public int getRepeatedFieldCount(final FieldDescriptor field) { 491 if (field.isExtension()) { 492 verifyContainingType(field); 493 return extensions.getRepeatedFieldCount(field); 494 } else { 495 return super.getRepeatedFieldCount(field); 496 } 497 } 498 499 @Override getRepeatedField(final FieldDescriptor field, final int index)500 public Object getRepeatedField(final FieldDescriptor field, 501 final int index) { 502 if (field.isExtension()) { 503 verifyContainingType(field); 504 return extensions.getRepeatedField(field, index); 505 } else { 506 return super.getRepeatedField(field, index); 507 } 508 } 509 verifyContainingType(final FieldDescriptor field)510 private void verifyContainingType(final FieldDescriptor field) { 511 if (field.getContainingType() != getDescriptorForType()) { 512 throw new IllegalArgumentException( 513 "FieldDescriptor does not match message type."); 514 } 515 } 516 } 517 518 /** 519 * Generated message builders for message types that contain extension ranges 520 * subclass this. 521 * 522 * <p>This class implements type-safe accessors for extensions. They 523 * implement all the same operations that you can do with normal fields -- 524 * e.g. "get", "set", and "add" -- but for extensions. The extensions are 525 * identified using instances of the class {@link GeneratedExtension}; the 526 * protocol compiler generates a static instance of this class for every 527 * extension in its input. Through the magic of generics, all is made 528 * type-safe. 529 * 530 * <p>For example, imagine you have the {@code .proto} file: 531 * 532 * <pre> 533 * option java_class = "MyProto"; 534 * 535 * message Foo { 536 * extensions 1000 to max; 537 * } 538 * 539 * extend Foo { 540 * optional int32 bar; 541 * } 542 * </pre> 543 * 544 * <p>Then you might write code like: 545 * 546 * <pre> 547 * MyProto.Foo foo = 548 * MyProto.Foo.newBuilder() 549 * .setExtension(MyProto.bar, 123) 550 * .build(); 551 * </pre> 552 * 553 * <p>See also {@link ExtendableMessage}. 554 */ 555 @SuppressWarnings("unchecked") 556 public abstract static class ExtendableBuilder< 557 MessageType extends ExtendableMessage, 558 BuilderType extends ExtendableBuilder> 559 extends Builder<BuilderType> { ExtendableBuilder()560 protected ExtendableBuilder() {} 561 562 // This is implemented here only to work around an apparent bug in the 563 // Java compiler and/or build system. See bug #1898463. The mere presence 564 // of this dummy clone() implementation makes it go away. 565 @Override clone()566 public BuilderType clone() { 567 throw new UnsupportedOperationException( 568 "This is supposed to be overridden by subclasses."); 569 } 570 571 @Override internalGetResult()572 protected abstract ExtendableMessage<MessageType> internalGetResult(); 573 574 /** Check if a singular extension is present. */ hasExtension( final GeneratedExtension<MessageType, ?> extension)575 public final boolean hasExtension( 576 final GeneratedExtension<MessageType, ?> extension) { 577 return internalGetResult().hasExtension(extension); 578 } 579 580 /** Get the number of elements in a repeated extension. */ getExtensionCount( final GeneratedExtension<MessageType, List<Type>> extension)581 public final <Type> int getExtensionCount( 582 final GeneratedExtension<MessageType, List<Type>> extension) { 583 return internalGetResult().getExtensionCount(extension); 584 } 585 586 /** Get the value of an extension. */ getExtension( final GeneratedExtension<MessageType, Type> extension)587 public final <Type> Type getExtension( 588 final GeneratedExtension<MessageType, Type> extension) { 589 return internalGetResult().getExtension(extension); 590 } 591 592 /** Get one element of a repeated extension. */ getExtension( final GeneratedExtension<MessageType, List<Type>> extension, final int index)593 public final <Type> Type getExtension( 594 final GeneratedExtension<MessageType, List<Type>> extension, 595 final int index) { 596 return internalGetResult().getExtension(extension, index); 597 } 598 599 /** Set the value of an extension. */ setExtension( final GeneratedExtension<MessageType, Type> extension, final Type value)600 public final <Type> BuilderType setExtension( 601 final GeneratedExtension<MessageType, Type> extension, 602 final Type value) { 603 final ExtendableMessage<MessageType> message = internalGetResult(); 604 message.verifyExtensionContainingType(extension); 605 final FieldDescriptor descriptor = extension.getDescriptor(); 606 message.extensions.setField(descriptor, 607 extension.toReflectionType(value)); 608 return (BuilderType) this; 609 } 610 611 /** Set the value of one element of a repeated extension. */ setExtension( final GeneratedExtension<MessageType, List<Type>> extension, final int index, final Type value)612 public final <Type> BuilderType setExtension( 613 final GeneratedExtension<MessageType, List<Type>> extension, 614 final int index, final Type value) { 615 final ExtendableMessage<MessageType> message = internalGetResult(); 616 message.verifyExtensionContainingType(extension); 617 final FieldDescriptor descriptor = extension.getDescriptor(); 618 message.extensions.setRepeatedField( 619 descriptor, index, 620 extension.singularToReflectionType(value)); 621 return (BuilderType) this; 622 } 623 624 /** Append a value to a repeated extension. */ addExtension( final GeneratedExtension<MessageType, List<Type>> extension, final Type value)625 public final <Type> BuilderType addExtension( 626 final GeneratedExtension<MessageType, List<Type>> extension, 627 final Type value) { 628 final ExtendableMessage<MessageType> message = internalGetResult(); 629 message.verifyExtensionContainingType(extension); 630 final FieldDescriptor descriptor = extension.getDescriptor(); 631 message.extensions.addRepeatedField( 632 descriptor, extension.singularToReflectionType(value)); 633 return (BuilderType) this; 634 } 635 636 /** Clear an extension. */ clearExtension( final GeneratedExtension<MessageType, ?> extension)637 public final <Type> BuilderType clearExtension( 638 final GeneratedExtension<MessageType, ?> extension) { 639 final ExtendableMessage<MessageType> message = internalGetResult(); 640 message.verifyExtensionContainingType(extension); 641 message.extensions.clearField(extension.getDescriptor()); 642 return (BuilderType) this; 643 } 644 645 /** 646 * Called by subclasses to parse an unknown field or an extension. 647 * @return {@code true} unless the tag is an end-group tag. 648 */ 649 @Override parseUnknownField( final CodedInputStream input, final UnknownFieldSet.Builder unknownFields, final ExtensionRegistryLite extensionRegistry, final int tag)650 protected boolean parseUnknownField( 651 final CodedInputStream input, 652 final UnknownFieldSet.Builder unknownFields, 653 final ExtensionRegistryLite extensionRegistry, 654 final int tag) throws IOException { 655 final ExtendableMessage<MessageType> message = internalGetResult(); 656 return AbstractMessage.Builder.mergeFieldFrom( 657 input, unknownFields, extensionRegistry, this, tag); 658 } 659 660 // --------------------------------------------------------------- 661 // Reflection 662 663 // We don't have to override the get*() methods here because they already 664 // just forward to the underlying message. 665 666 @Override setField(final FieldDescriptor field, final Object value)667 public BuilderType setField(final FieldDescriptor field, 668 final Object value) { 669 if (field.isExtension()) { 670 final ExtendableMessage<MessageType> message = internalGetResult(); 671 message.verifyContainingType(field); 672 message.extensions.setField(field, value); 673 return (BuilderType) this; 674 } else { 675 return super.setField(field, value); 676 } 677 } 678 679 @Override clearField(final FieldDescriptor field)680 public BuilderType clearField(final FieldDescriptor field) { 681 if (field.isExtension()) { 682 final ExtendableMessage<MessageType> message = internalGetResult(); 683 message.verifyContainingType(field); 684 message.extensions.clearField(field); 685 return (BuilderType) this; 686 } else { 687 return super.clearField(field); 688 } 689 } 690 691 @Override setRepeatedField(final FieldDescriptor field, final int index, final Object value)692 public BuilderType setRepeatedField(final FieldDescriptor field, 693 final int index, final Object value) { 694 if (field.isExtension()) { 695 final ExtendableMessage<MessageType> message = internalGetResult(); 696 message.verifyContainingType(field); 697 message.extensions.setRepeatedField(field, index, value); 698 return (BuilderType) this; 699 } else { 700 return super.setRepeatedField(field, index, value); 701 } 702 } 703 704 @Override addRepeatedField(final FieldDescriptor field, final Object value)705 public BuilderType addRepeatedField(final FieldDescriptor field, 706 final Object value) { 707 if (field.isExtension()) { 708 final ExtendableMessage<MessageType> message = internalGetResult(); 709 message.verifyContainingType(field); 710 message.extensions.addRepeatedField(field, value); 711 return (BuilderType) this; 712 } else { 713 return super.addRepeatedField(field, value); 714 } 715 } 716 mergeExtensionFields(final ExtendableMessage other)717 protected final void mergeExtensionFields(final ExtendableMessage other) { 718 internalGetResult().extensions.mergeFrom(other.extensions); 719 } 720 } 721 722 // ----------------------------------------------------------------- 723 724 /** For use by generated code only. */ 725 public static <ContainingType extends Message, Type> 726 GeneratedExtension<ContainingType, Type> newGeneratedExtension()727 newGeneratedExtension() { 728 return new GeneratedExtension<ContainingType, Type>(); 729 } 730 731 /** 732 * Type used to represent generated extensions. The protocol compiler 733 * generates a static singleton instance of this class for each extension. 734 * 735 * <p>For example, imagine you have the {@code .proto} file: 736 * 737 * <pre> 738 * option java_class = "MyProto"; 739 * 740 * message Foo { 741 * extensions 1000 to max; 742 * } 743 * 744 * extend Foo { 745 * optional int32 bar; 746 * } 747 * </pre> 748 * 749 * <p>Then, {@code MyProto.Foo.bar} has type 750 * {@code GeneratedExtension<MyProto.Foo, Integer>}. 751 * 752 * <p>In general, users should ignore the details of this type, and simply use 753 * these static singletons as parameters to the extension accessors defined 754 * in {@link ExtendableMessage} and {@link ExtendableBuilder}. 755 */ 756 public static final class GeneratedExtension< 757 ContainingType extends Message, Type> { 758 // TODO(kenton): Find ways to avoid using Java reflection within this 759 // class. Also try to avoid suppressing unchecked warnings. 760 761 // We can't always initialize a GeneratedExtension when we first construct 762 // it due to initialization order difficulties (namely, the descriptor may 763 // not have been constructed yet, since it is often constructed by the 764 // initializer of a separate module). So, we construct an uninitialized 765 // GeneratedExtension once, then call internalInit() on it later. Generated 766 // code will always call internalInit() on all extensions as part of the 767 // static initialization code, and internalInit() throws an exception if 768 // called more than once, so this method is useless to users. GeneratedExtension()769 private GeneratedExtension() {} 770 771 /** For use by generated code only. */ internalInit(final FieldDescriptor descriptor, final Class type)772 public void internalInit(final FieldDescriptor descriptor, 773 final Class type) { 774 if (this.descriptor != null) { 775 throw new IllegalStateException("Already initialized."); 776 } 777 778 if (!descriptor.isExtension()) { 779 throw new IllegalArgumentException( 780 "GeneratedExtension given a regular (non-extension) field."); 781 } 782 783 this.descriptor = descriptor; 784 this.type = type; 785 786 switch (descriptor.getJavaType()) { 787 case MESSAGE: 788 enumValueOf = null; 789 enumGetValueDescriptor = null; 790 messageDefaultInstance = 791 (Message) invokeOrDie(getMethodOrDie(type, "getDefaultInstance"), 792 null); 793 if (messageDefaultInstance == null) { 794 throw new IllegalStateException( 795 type.getName() + ".getDefaultInstance() returned null."); 796 } 797 break; 798 case ENUM: 799 enumValueOf = getMethodOrDie(type, "valueOf", 800 EnumValueDescriptor.class); 801 enumGetValueDescriptor = getMethodOrDie(type, "getValueDescriptor"); 802 messageDefaultInstance = null; 803 break; 804 default: 805 enumValueOf = null; 806 enumGetValueDescriptor = null; 807 messageDefaultInstance = null; 808 break; 809 } 810 } 811 812 private FieldDescriptor descriptor; 813 private Class type; 814 private Method enumValueOf; 815 private Method enumGetValueDescriptor; 816 private Message messageDefaultInstance; 817 getDescriptor()818 public FieldDescriptor getDescriptor() { return descriptor; } 819 820 /** 821 * If the extension is an embedded message or group, returns the default 822 * instance of the message. 823 */ 824 @SuppressWarnings("unchecked") getMessageDefaultInstance()825 public Message getMessageDefaultInstance() { 826 return messageDefaultInstance; 827 } 828 829 /** 830 * Convert from the type used by the reflection accessors to the type used 831 * by native accessors. E.g., for enums, the reflection accessors use 832 * EnumValueDescriptors but the native accessors use the generated enum 833 * type. 834 */ 835 @SuppressWarnings("unchecked") fromReflectionType(final Object value)836 private Object fromReflectionType(final Object value) { 837 if (descriptor.isRepeated()) { 838 if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE || 839 descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { 840 // Must convert the whole list. 841 final List result = new ArrayList(); 842 for (final Object element : (List) value) { 843 result.add(singularFromReflectionType(element)); 844 } 845 return result; 846 } else { 847 return value; 848 } 849 } else { 850 return singularFromReflectionType(value); 851 } 852 } 853 854 /** 855 * Like {@link #fromReflectionType(Object)}, but if the type is a repeated 856 * type, this converts a single element. 857 */ singularFromReflectionType(final Object value)858 private Object singularFromReflectionType(final Object value) { 859 switch (descriptor.getJavaType()) { 860 case MESSAGE: 861 if (type.isInstance(value)) { 862 return value; 863 } else { 864 // It seems the copy of the embedded message stored inside the 865 // extended message is not of the exact type the user was 866 // expecting. This can happen if a user defines a 867 // GeneratedExtension manually and gives it a different type. 868 // This should not happen in normal use. But, to be nice, we'll 869 // copy the message to whatever type the caller was expecting. 870 return messageDefaultInstance.newBuilderForType() 871 .mergeFrom((Message) value).build(); 872 } 873 case ENUM: 874 return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value); 875 default: 876 return value; 877 } 878 } 879 880 /** 881 * Convert from the type used by the native accessors to the type used 882 * by reflection accessors. E.g., for enums, the reflection accessors use 883 * EnumValueDescriptors but the native accessors use the generated enum 884 * type. 885 */ 886 @SuppressWarnings("unchecked") toReflectionType(final Object value)887 private Object toReflectionType(final Object value) { 888 if (descriptor.isRepeated()) { 889 if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { 890 // Must convert the whole list. 891 final List result = new ArrayList(); 892 for (final Object element : (List) value) { 893 result.add(singularToReflectionType(element)); 894 } 895 return result; 896 } else { 897 return value; 898 } 899 } else { 900 return singularToReflectionType(value); 901 } 902 } 903 904 /** 905 * Like {@link #toReflectionType(Object)}, but if the type is a repeated 906 * type, this converts a single element. 907 */ singularToReflectionType(final Object value)908 private Object singularToReflectionType(final Object value) { 909 switch (descriptor.getJavaType()) { 910 case ENUM: 911 return invokeOrDie(enumGetValueDescriptor, value); 912 default: 913 return value; 914 } 915 } 916 } 917 918 // ================================================================= 919 920 /** Calls Class.getMethod and throws a RuntimeException if it fails. */ 921 @SuppressWarnings("unchecked") getMethodOrDie( final Class clazz, final String name, final Class... params)922 private static Method getMethodOrDie( 923 final Class clazz, final String name, final Class... params) { 924 try { 925 return clazz.getMethod(name, params); 926 } catch (NoSuchMethodException e) { 927 throw new RuntimeException( 928 "Generated message class \"" + clazz.getName() + 929 "\" missing method \"" + name + "\".", e); 930 } 931 } 932 933 /** Calls invoke and throws a RuntimeException if it fails. */ invokeOrDie( final Method method, final Object object, final Object... params)934 private static Object invokeOrDie( 935 final Method method, final Object object, final Object... params) { 936 try { 937 return method.invoke(object, params); 938 } catch (IllegalAccessException e) { 939 throw new RuntimeException( 940 "Couldn't use Java reflection to implement protocol message " + 941 "reflection.", e); 942 } catch (InvocationTargetException e) { 943 final Throwable cause = e.getCause(); 944 if (cause instanceof RuntimeException) { 945 throw (RuntimeException) cause; 946 } else if (cause instanceof Error) { 947 throw (Error) cause; 948 } else { 949 throw new RuntimeException( 950 "Unexpected exception thrown by generated accessor method.", cause); 951 } 952 } 953 } 954 955 /** 956 * Users should ignore this class. This class provides the implementation 957 * with access to the fields of a message object using Java reflection. 958 */ 959 public static final class FieldAccessorTable { 960 961 /** 962 * Construct a FieldAccessorTable for a particular message class. Only 963 * one FieldAccessorTable should ever be constructed per class. 964 * 965 * @param descriptor The type's descriptor. 966 * @param camelCaseNames The camelcase names of all fields in the message. 967 * These are used to derive the accessor method names. 968 * @param messageClass The message type. 969 * @param builderClass The builder type. 970 */ FieldAccessorTable( final Descriptor descriptor, final String[] camelCaseNames, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder> builderClass)971 public FieldAccessorTable( 972 final Descriptor descriptor, 973 final String[] camelCaseNames, 974 final Class<? extends GeneratedMessage> messageClass, 975 final Class<? extends Builder> builderClass) { 976 this.descriptor = descriptor; 977 fields = new FieldAccessor[descriptor.getFields().size()]; 978 979 for (int i = 0; i < fields.length; i++) { 980 final FieldDescriptor field = descriptor.getFields().get(i); 981 if (field.isRepeated()) { 982 if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { 983 fields[i] = new RepeatedMessageFieldAccessor( 984 field, camelCaseNames[i], messageClass, builderClass); 985 } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { 986 fields[i] = new RepeatedEnumFieldAccessor( 987 field, camelCaseNames[i], messageClass, builderClass); 988 } else { 989 fields[i] = new RepeatedFieldAccessor( 990 field, camelCaseNames[i], messageClass, builderClass); 991 } 992 } else { 993 if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { 994 fields[i] = new SingularMessageFieldAccessor( 995 field, camelCaseNames[i], messageClass, builderClass); 996 } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { 997 fields[i] = new SingularEnumFieldAccessor( 998 field, camelCaseNames[i], messageClass, builderClass); 999 } else { 1000 fields[i] = new SingularFieldAccessor( 1001 field, camelCaseNames[i], messageClass, builderClass); 1002 } 1003 } 1004 } 1005 } 1006 1007 private final Descriptor descriptor; 1008 private final FieldAccessor[] fields; 1009 1010 /** Get the FieldAccessor for a particular field. */ getField(final FieldDescriptor field)1011 private FieldAccessor getField(final FieldDescriptor field) { 1012 if (field.getContainingType() != descriptor) { 1013 throw new IllegalArgumentException( 1014 "FieldDescriptor does not match message type."); 1015 } else if (field.isExtension()) { 1016 // If this type had extensions, it would subclass ExtendableMessage, 1017 // which overrides the reflection interface to handle extensions. 1018 throw new IllegalArgumentException( 1019 "This type does not have extensions."); 1020 } 1021 return fields[field.getIndex()]; 1022 } 1023 1024 /** 1025 * Abstract interface that provides access to a single field. This is 1026 * implemented differently depending on the field type and cardinality. 1027 */ 1028 private interface FieldAccessor { get(GeneratedMessage message)1029 Object get(GeneratedMessage message); set(Builder builder, Object value)1030 void set(Builder builder, Object value); getRepeated(GeneratedMessage message, int index)1031 Object getRepeated(GeneratedMessage message, int index); setRepeated(Builder builder, int index, Object value)1032 void setRepeated(Builder builder, 1033 int index, Object value); addRepeated(Builder builder, Object value)1034 void addRepeated(Builder builder, Object value); has(GeneratedMessage message)1035 boolean has(GeneratedMessage message); getRepeatedCount(GeneratedMessage message)1036 int getRepeatedCount(GeneratedMessage message); clear(Builder builder)1037 void clear(Builder builder); newBuilder()1038 Message.Builder newBuilder(); 1039 } 1040 1041 // --------------------------------------------------------------- 1042 1043 private static class SingularFieldAccessor implements FieldAccessor { SingularFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder> builderClass)1044 SingularFieldAccessor( 1045 final FieldDescriptor descriptor, final String camelCaseName, 1046 final Class<? extends GeneratedMessage> messageClass, 1047 final Class<? extends Builder> builderClass) { 1048 getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); 1049 type = getMethod.getReturnType(); 1050 setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); 1051 hasMethod = 1052 getMethodOrDie(messageClass, "has" + camelCaseName); 1053 clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); 1054 } 1055 1056 // Note: We use Java reflection to call public methods rather than 1057 // access private fields directly as this avoids runtime security 1058 // checks. 1059 protected final Class type; 1060 protected final Method getMethod; 1061 protected final Method setMethod; 1062 protected final Method hasMethod; 1063 protected final Method clearMethod; 1064 get(final GeneratedMessage message)1065 public Object get(final GeneratedMessage message) { 1066 return invokeOrDie(getMethod, message); 1067 } set(final Builder builder, final Object value)1068 public void set(final Builder builder, final Object value) { 1069 invokeOrDie(setMethod, builder, value); 1070 } getRepeated(final GeneratedMessage message, final int index)1071 public Object getRepeated(final GeneratedMessage message, 1072 final int index) { 1073 throw new UnsupportedOperationException( 1074 "getRepeatedField() called on a singular field."); 1075 } setRepeated(final Builder builder, final int index, final Object value)1076 public void setRepeated(final Builder builder, 1077 final int index, final Object value) { 1078 throw new UnsupportedOperationException( 1079 "setRepeatedField() called on a singular field."); 1080 } addRepeated(final Builder builder, final Object value)1081 public void addRepeated(final Builder builder, final Object value) { 1082 throw new UnsupportedOperationException( 1083 "addRepeatedField() called on a singular field."); 1084 } has(final GeneratedMessage message)1085 public boolean has(final GeneratedMessage message) { 1086 return (Boolean) invokeOrDie(hasMethod, message); 1087 } getRepeatedCount(final GeneratedMessage message)1088 public int getRepeatedCount(final GeneratedMessage message) { 1089 throw new UnsupportedOperationException( 1090 "getRepeatedFieldSize() called on a singular field."); 1091 } clear(final Builder builder)1092 public void clear(final Builder builder) { 1093 invokeOrDie(clearMethod, builder); 1094 } newBuilder()1095 public Message.Builder newBuilder() { 1096 throw new UnsupportedOperationException( 1097 "newBuilderForField() called on a non-Message type."); 1098 } 1099 } 1100 1101 private static class RepeatedFieldAccessor implements FieldAccessor { RepeatedFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder> builderClass)1102 RepeatedFieldAccessor( 1103 final FieldDescriptor descriptor, final String camelCaseName, 1104 final Class<? extends GeneratedMessage> messageClass, 1105 final Class<? extends Builder> builderClass) { 1106 getMethod = getMethodOrDie(messageClass, 1107 "get" + camelCaseName + "List"); 1108 1109 getRepeatedMethod = 1110 getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); 1111 type = getRepeatedMethod.getReturnType(); 1112 setRepeatedMethod = 1113 getMethodOrDie(builderClass, "set" + camelCaseName, 1114 Integer.TYPE, type); 1115 addRepeatedMethod = 1116 getMethodOrDie(builderClass, "add" + camelCaseName, type); 1117 getCountMethod = 1118 getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); 1119 1120 clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); 1121 } 1122 1123 protected final Class type; 1124 protected final Method getMethod; 1125 protected final Method getRepeatedMethod; 1126 protected final Method setRepeatedMethod; 1127 protected final Method addRepeatedMethod; 1128 protected final Method getCountMethod; 1129 protected final Method clearMethod; 1130 get(final GeneratedMessage message)1131 public Object get(final GeneratedMessage message) { 1132 return invokeOrDie(getMethod, message); 1133 } set(final Builder builder, final Object value)1134 public void set(final Builder builder, final Object value) { 1135 // Add all the elements individually. This serves two purposes: 1136 // 1) Verifies that each element has the correct type. 1137 // 2) Insures that the caller cannot modify the list later on and 1138 // have the modifications be reflected in the message. 1139 clear(builder); 1140 for (final Object element : (List) value) { 1141 addRepeated(builder, element); 1142 } 1143 } getRepeated(final GeneratedMessage message, final int index)1144 public Object getRepeated(final GeneratedMessage message, 1145 final int index) { 1146 return invokeOrDie(getRepeatedMethod, message, index); 1147 } setRepeated(final Builder builder, final int index, final Object value)1148 public void setRepeated(final Builder builder, 1149 final int index, final Object value) { 1150 invokeOrDie(setRepeatedMethod, builder, index, value); 1151 } addRepeated(final Builder builder, final Object value)1152 public void addRepeated(final Builder builder, final Object value) { 1153 invokeOrDie(addRepeatedMethod, builder, value); 1154 } has(final GeneratedMessage message)1155 public boolean has(final GeneratedMessage message) { 1156 throw new UnsupportedOperationException( 1157 "hasField() called on a singular field."); 1158 } getRepeatedCount(final GeneratedMessage message)1159 public int getRepeatedCount(final GeneratedMessage message) { 1160 return (Integer) invokeOrDie(getCountMethod, message); 1161 } clear(final Builder builder)1162 public void clear(final Builder builder) { 1163 invokeOrDie(clearMethod, builder); 1164 } newBuilder()1165 public Message.Builder newBuilder() { 1166 throw new UnsupportedOperationException( 1167 "newBuilderForField() called on a non-Message type."); 1168 } 1169 } 1170 1171 // --------------------------------------------------------------- 1172 1173 private static final class SingularEnumFieldAccessor 1174 extends SingularFieldAccessor { SingularEnumFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder> builderClass)1175 SingularEnumFieldAccessor( 1176 final FieldDescriptor descriptor, final String camelCaseName, 1177 final Class<? extends GeneratedMessage> messageClass, 1178 final Class<? extends Builder> builderClass) { 1179 super(descriptor, camelCaseName, messageClass, builderClass); 1180 1181 valueOfMethod = getMethodOrDie(type, "valueOf", 1182 EnumValueDescriptor.class); 1183 getValueDescriptorMethod = 1184 getMethodOrDie(type, "getValueDescriptor"); 1185 } 1186 1187 private Method valueOfMethod; 1188 private Method getValueDescriptorMethod; 1189 1190 @Override get(final GeneratedMessage message)1191 public Object get(final GeneratedMessage message) { 1192 return invokeOrDie(getValueDescriptorMethod, super.get(message)); 1193 } 1194 @Override set(final Builder builder, final Object value)1195 public void set(final Builder builder, final Object value) { 1196 super.set(builder, invokeOrDie(valueOfMethod, null, value)); 1197 } 1198 } 1199 1200 private static final class RepeatedEnumFieldAccessor 1201 extends RepeatedFieldAccessor { RepeatedEnumFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder> builderClass)1202 RepeatedEnumFieldAccessor( 1203 final FieldDescriptor descriptor, final String camelCaseName, 1204 final Class<? extends GeneratedMessage> messageClass, 1205 final Class<? extends Builder> builderClass) { 1206 super(descriptor, camelCaseName, messageClass, builderClass); 1207 1208 valueOfMethod = getMethodOrDie(type, "valueOf", 1209 EnumValueDescriptor.class); 1210 getValueDescriptorMethod = 1211 getMethodOrDie(type, "getValueDescriptor"); 1212 } 1213 1214 private final Method valueOfMethod; 1215 private final Method getValueDescriptorMethod; 1216 1217 @Override 1218 @SuppressWarnings("unchecked") get(final GeneratedMessage message)1219 public Object get(final GeneratedMessage message) { 1220 final List newList = new ArrayList(); 1221 for (final Object element : (List) super.get(message)) { 1222 newList.add(invokeOrDie(getValueDescriptorMethod, element)); 1223 } 1224 return Collections.unmodifiableList(newList); 1225 } 1226 @Override getRepeated(final GeneratedMessage message, final int index)1227 public Object getRepeated(final GeneratedMessage message, 1228 final int index) { 1229 return invokeOrDie(getValueDescriptorMethod, 1230 super.getRepeated(message, index)); 1231 } 1232 @Override setRepeated(final Builder builder, final int index, final Object value)1233 public void setRepeated(final Builder builder, 1234 final int index, final Object value) { 1235 super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, 1236 value)); 1237 } 1238 @Override addRepeated(final Builder builder, final Object value)1239 public void addRepeated(final Builder builder, final Object value) { 1240 super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value)); 1241 } 1242 } 1243 1244 // --------------------------------------------------------------- 1245 1246 private static final class SingularMessageFieldAccessor 1247 extends SingularFieldAccessor { SingularMessageFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder> builderClass)1248 SingularMessageFieldAccessor( 1249 final FieldDescriptor descriptor, final String camelCaseName, 1250 final Class<? extends GeneratedMessage> messageClass, 1251 final Class<? extends Builder> builderClass) { 1252 super(descriptor, camelCaseName, messageClass, builderClass); 1253 1254 newBuilderMethod = getMethodOrDie(type, "newBuilder"); 1255 } 1256 1257 private final Method newBuilderMethod; 1258 coerceType(final Object value)1259 private Object coerceType(final Object value) { 1260 if (type.isInstance(value)) { 1261 return value; 1262 } else { 1263 // The value is not the exact right message type. However, if it 1264 // is an alternative implementation of the same type -- e.g. a 1265 // DynamicMessage -- we should accept it. In this case we can make 1266 // a copy of the message. 1267 return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) 1268 .mergeFrom((Message) value).build(); 1269 } 1270 } 1271 1272 @Override set(final Builder builder, final Object value)1273 public void set(final Builder builder, final Object value) { 1274 super.set(builder, coerceType(value)); 1275 } 1276 @Override newBuilder()1277 public Message.Builder newBuilder() { 1278 return (Message.Builder) invokeOrDie(newBuilderMethod, null); 1279 } 1280 } 1281 1282 private static final class RepeatedMessageFieldAccessor 1283 extends RepeatedFieldAccessor { RepeatedMessageFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class<? extends GeneratedMessage> messageClass, final Class<? extends Builder> builderClass)1284 RepeatedMessageFieldAccessor( 1285 final FieldDescriptor descriptor, final String camelCaseName, 1286 final Class<? extends GeneratedMessage> messageClass, 1287 final Class<? extends Builder> builderClass) { 1288 super(descriptor, camelCaseName, messageClass, builderClass); 1289 1290 newBuilderMethod = getMethodOrDie(type, "newBuilder"); 1291 } 1292 1293 private final Method newBuilderMethod; 1294 coerceType(final Object value)1295 private Object coerceType(final Object value) { 1296 if (type.isInstance(value)) { 1297 return value; 1298 } else { 1299 // The value is not the exact right message type. However, if it 1300 // is an alternative implementation of the same type -- e.g. a 1301 // DynamicMessage -- we should accept it. In this case we can make 1302 // a copy of the message. 1303 return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) 1304 .mergeFrom((Message) value).build(); 1305 } 1306 } 1307 1308 @Override setRepeated(final Builder builder, final int index, final Object value)1309 public void setRepeated(final Builder builder, 1310 final int index, final Object value) { 1311 super.setRepeated(builder, index, coerceType(value)); 1312 } 1313 @Override addRepeated(final Builder builder, final Object value)1314 public void addRepeated(final Builder builder, final Object value) { 1315 super.addRepeated(builder, coerceType(value)); 1316 } 1317 @Override newBuilder()1318 public Message.Builder newBuilder() { 1319 return (Message.Builder) invokeOrDie(newBuilderMethod, null); 1320 } 1321 } 1322 } 1323 } 1324