• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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