Index: third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java |
diff --git a/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d84fa75c5110f72d4223d6f39a762d60bf525b39 |
--- /dev/null |
+++ b/third_party/protobuf/java/src/main/java/com/google/protobuf/GeneratedMessage.java |
@@ -0,0 +1,2778 @@ |
+// Protocol Buffers - Google's data interchange format |
+// Copyright 2008 Google Inc. All rights reserved. |
+// https://developers.google.com/protocol-buffers/ |
+// |
+// Redistribution and use in source and binary forms, with or without |
+// modification, are permitted provided that the following conditions are |
+// met: |
+// |
+// * Redistributions of source code must retain the above copyright |
+// notice, this list of conditions and the following disclaimer. |
+// * Redistributions in binary form must reproduce the above |
+// copyright notice, this list of conditions and the following disclaimer |
+// in the documentation and/or other materials provided with the |
+// distribution. |
+// * Neither the name of Google Inc. nor the names of its |
+// contributors may be used to endorse or promote products derived from |
+// this software without specific prior written permission. |
+// |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+package com.google.protobuf; |
+ |
+import com.google.protobuf.Descriptors.Descriptor; |
+import com.google.protobuf.Descriptors.EnumDescriptor; |
+import com.google.protobuf.Descriptors.EnumValueDescriptor; |
+import com.google.protobuf.Descriptors.FieldDescriptor; |
+import com.google.protobuf.Descriptors.FileDescriptor; |
+import com.google.protobuf.Descriptors.OneofDescriptor; |
+import com.google.protobuf.GeneratedMessageLite.ExtendableMessage; |
+import com.google.protobuf.GeneratedMessageLite.GeneratedExtension; |
+ |
+import java.io.IOException; |
+import java.io.ObjectStreamException; |
+import java.io.Serializable; |
+import java.lang.reflect.InvocationTargetException; |
+import java.lang.reflect.Method; |
+import java.lang.reflect.Type; |
+import java.util.ArrayList; |
+import java.util.Collections; |
+import java.util.Iterator; |
+import java.util.List; |
+import java.util.Map; |
+import java.util.TreeMap; |
+ |
+/** |
+ * All generated protocol message classes extend this class. This class |
+ * implements most of the Message and Builder interfaces using Java reflection. |
+ * Users can ignore this class and pretend that generated messages implement |
+ * the Message interface directly. |
+ * |
+ * @author kenton@google.com Kenton Varda |
+ */ |
+public abstract class GeneratedMessage extends AbstractMessage |
+ implements Serializable { |
+ private static final long serialVersionUID = 1L; |
+ |
+ /** |
+ * For testing. Allows a test to disable the optimization that avoids using |
+ * field builders for nested messages until they are requested. By disabling |
+ * this optimization, existing tests can be reused to test the field builders. |
+ */ |
+ protected static boolean alwaysUseFieldBuilders = false; |
+ |
+ /** For use by generated code only. */ |
+ protected UnknownFieldSet unknownFields; |
+ |
+ protected GeneratedMessage() { |
+ unknownFields = UnknownFieldSet.getDefaultInstance(); |
+ } |
+ |
+ protected GeneratedMessage(Builder<?> builder) { |
+ unknownFields = builder.getUnknownFields(); |
+ } |
+ |
+ public Parser<? extends GeneratedMessage> getParserForType() { |
+ throw new UnsupportedOperationException( |
+ "This is supposed to be overridden by subclasses."); |
+ } |
+ |
+ /** |
+ * For testing. Allows a test to disable the optimization that avoids using |
+ * field builders for nested messages until they are requested. By disabling |
+ * this optimization, existing tests can be reused to test the field builders. |
+ * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}. |
+ */ |
+ static void enableAlwaysUseFieldBuildersForTesting() { |
+ alwaysUseFieldBuilders = true; |
+ } |
+ |
+ /** |
+ * Get the FieldAccessorTable for this type. We can't have the message |
+ * class pass this in to the constructor because of bootstrapping trouble |
+ * with DescriptorProtos. |
+ */ |
+ protected abstract FieldAccessorTable internalGetFieldAccessorTable(); |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Descriptor getDescriptorForType() { |
+ return internalGetFieldAccessorTable().descriptor; |
+ } |
+ |
+ /** |
+ * Internal helper to return a modifiable map containing all the fields. |
+ * The returned Map is modifialbe so that the caller can add additional |
+ * extension fields to implement {@link #getAllFields()}. |
+ * |
+ * @param getBytesForString whether to generate ByteString for string fields |
+ */ |
+ private Map<FieldDescriptor, Object> getAllFieldsMutable( |
+ boolean getBytesForString) { |
+ final TreeMap<FieldDescriptor, Object> result = |
+ new TreeMap<FieldDescriptor, Object>(); |
+ final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; |
+ final List<FieldDescriptor> fields = descriptor.getFields(); |
+ |
+ for (int i = 0; i < fields.size(); i++) { |
+ FieldDescriptor field = fields.get(i); |
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof(); |
+ |
+ /* |
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set |
+ * and it is not repeated. There is no need to iterate through the others. |
+ */ |
+ if (oneofDescriptor != null) { |
+ // Skip other fields in the Oneof we know are not set |
+ i += oneofDescriptor.getFieldCount() - 1; |
+ if (!hasOneof(oneofDescriptor)) { |
+ // If no field is set in the Oneof, skip all the fields in the Oneof |
+ continue; |
+ } |
+ // Get the pointer to the only field which is set in the Oneof |
+ field = getOneofFieldDescriptor(oneofDescriptor); |
+ } else { |
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated |
+ if (field.isRepeated()) { |
+ final List<?> value = (List<?>) getField(field); |
+ if (!value.isEmpty()) { |
+ result.put(field, value); |
+ } |
+ continue; |
+ } |
+ if (!hasField(field)) { |
+ continue; |
+ } |
+ } |
+ // Add the field to the map |
+ if (getBytesForString && field.getJavaType() == FieldDescriptor.JavaType.STRING) { |
+ result.put(field, getFieldRaw(field)); |
+ } else { |
+ result.put(field, getField(field)); |
+ } |
+ } |
+ return result; |
+ } |
+ |
+ @Override |
+ public boolean isInitialized() { |
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) { |
+ // Check that all required fields are present. |
+ if (field.isRequired()) { |
+ if (!hasField(field)) { |
+ return false; |
+ } |
+ } |
+ // Check that embedded messages are initialized. |
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
+ if (field.isRepeated()) { |
+ @SuppressWarnings("unchecked") final |
+ List<Message> messageList = (List<Message>) getField(field); |
+ for (final Message element : messageList) { |
+ if (!element.isInitialized()) { |
+ return false; |
+ } |
+ } |
+ } else { |
+ if (hasField(field) && !((Message) getField(field)).isInitialized()) { |
+ return false; |
+ } |
+ } |
+ } |
+ } |
+ |
+ return true; |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Map<FieldDescriptor, Object> getAllFields() { |
+ return Collections.unmodifiableMap( |
+ getAllFieldsMutable(/* getBytesForString = */ false)); |
+ } |
+ |
+ /** |
+ * Returns a collection of all the fields in this message which are set |
+ * and their corresponding values. A singular ("required" or "optional") |
+ * field is set iff hasField() returns true for that field. A "repeated" |
+ * field is set iff getRepeatedFieldCount() is greater than zero. The |
+ * values are exactly what would be returned by calling |
+ * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field. The map |
+ * is guaranteed to be a sorted map, so iterating over it will return fields |
+ * in order by field number. |
+ */ |
+ Map<FieldDescriptor, Object> getAllFieldsRaw() { |
+ return Collections.unmodifiableMap( |
+ getAllFieldsMutable(/* getBytesForString = */ true)); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public boolean hasOneof(final OneofDescriptor oneof) { |
+ return internalGetFieldAccessorTable().getOneof(oneof).has(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { |
+ return internalGetFieldAccessorTable().getOneof(oneof).get(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public boolean hasField(final FieldDescriptor field) { |
+ return internalGetFieldAccessorTable().getField(field).has(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Object getField(final FieldDescriptor field) { |
+ return internalGetFieldAccessorTable().getField(field).get(this); |
+ } |
+ |
+ /** |
+ * Obtains the value of the given field, or the default value if it is |
+ * not set. For primitive fields, the boxed primitive value is returned. |
+ * For enum fields, the EnumValueDescriptor for the value is returned. For |
+ * embedded message fields, the sub-message is returned. For repeated |
+ * fields, a java.util.List is returned. For present string fields, a |
+ * ByteString is returned representing the bytes that the field contains. |
+ */ |
+ Object getFieldRaw(final FieldDescriptor field) { |
+ return internalGetFieldAccessorTable().getField(field).getRaw(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public int getRepeatedFieldCount(final FieldDescriptor field) { |
+ return internalGetFieldAccessorTable().getField(field) |
+ .getRepeatedCount(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Object getRepeatedField(final FieldDescriptor field, final int index) { |
+ return internalGetFieldAccessorTable().getField(field) |
+ .getRepeated(this, index); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public UnknownFieldSet getUnknownFields() { |
+ throw new UnsupportedOperationException( |
+ "This is supposed to be overridden by subclasses."); |
+ } |
+ |
+ /** |
+ * Called by subclasses to parse an unknown field. |
+ * @return {@code true} unless the tag is an end-group tag. |
+ */ |
+ protected boolean parseUnknownField( |
+ CodedInputStream input, |
+ UnknownFieldSet.Builder unknownFields, |
+ ExtensionRegistryLite extensionRegistry, |
+ int tag) throws IOException { |
+ return unknownFields.mergeFieldFrom(tag, input); |
+ } |
+ |
+ @Override |
+ public void writeTo(final CodedOutputStream output) throws IOException { |
+ MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false); |
+ } |
+ |
+ @Override |
+ public int getSerializedSize() { |
+ int size = memoizedSize; |
+ if (size != -1) { |
+ return size; |
+ } |
+ |
+ memoizedSize = MessageReflection.getSerializedSize( |
+ this, getAllFieldsRaw()); |
+ return memoizedSize; |
+ } |
+ |
+ |
+ |
+ /** |
+ * Used by parsing constructors in generated classes. |
+ */ |
+ protected void makeExtensionsImmutable() { |
+ // Noop for messages without extensions. |
+ } |
+ |
+ protected abstract Message.Builder newBuilderForType(BuilderParent parent); |
+ |
+ /** |
+ * Interface for the parent of a Builder that allows the builder to |
+ * communicate invalidations back to the parent for use when using nested |
+ * builders. |
+ */ |
+ protected interface BuilderParent { |
+ |
+ /** |
+ * A builder becomes dirty whenever a field is modified -- including fields |
+ * in nested builders -- and becomes clean when build() is called. Thus, |
+ * when a builder becomes dirty, all its parents become dirty as well, and |
+ * when it becomes clean, all its children become clean. The dirtiness |
+ * state is used to invalidate certain cached values. |
+ * <br> |
+ * To this end, a builder calls markAsDirty() on its parent whenever it |
+ * transitions from clean to dirty. The parent must propagate this call to |
+ * its own parent, unless it was already dirty, in which case the |
+ * grandparent must necessarily already be dirty as well. The parent can |
+ * only transition back to "clean" after calling build() on all children. |
+ */ |
+ void markDirty(); |
+ } |
+ |
+ @SuppressWarnings("unchecked") |
+ public abstract static class Builder <BuilderType extends Builder> |
+ extends AbstractMessage.Builder<BuilderType> { |
+ |
+ private BuilderParent builderParent; |
+ |
+ private BuilderParentImpl meAsParent; |
+ |
+ // Indicates that we've built a message and so we are now obligated |
+ // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener. |
+ private boolean isClean; |
+ |
+ private UnknownFieldSet unknownFields = |
+ UnknownFieldSet.getDefaultInstance(); |
+ |
+ protected Builder() { |
+ this(null); |
+ } |
+ |
+ protected Builder(BuilderParent builderParent) { |
+ this.builderParent = builderParent; |
+ } |
+ |
+ void dispose() { |
+ builderParent = null; |
+ } |
+ |
+ /** |
+ * Called by the subclass when a message is built. |
+ */ |
+ protected void onBuilt() { |
+ if (builderParent != null) { |
+ markClean(); |
+ } |
+ } |
+ |
+ /** |
+ * Called by the subclass or a builder to notify us that a message was |
+ * built and may be cached and therefore invalidations are needed. |
+ */ |
+ protected void markClean() { |
+ this.isClean = true; |
+ } |
+ |
+ /** |
+ * Gets whether invalidations are needed |
+ * |
+ * @return whether invalidations are needed |
+ */ |
+ protected boolean isClean() { |
+ return isClean; |
+ } |
+ |
+ @Override |
+ public BuilderType clone() { |
+ BuilderType builder = |
+ (BuilderType) getDefaultInstanceForType().newBuilderForType(); |
+ builder.mergeFrom(buildPartial()); |
+ return builder; |
+ } |
+ |
+ /** |
+ * Called by the initialization and clear code paths to allow subclasses to |
+ * reset any of their builtin fields back to the initial values. |
+ */ |
+ public BuilderType clear() { |
+ unknownFields = UnknownFieldSet.getDefaultInstance(); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } |
+ |
+ /** |
+ * Get the FieldAccessorTable for this type. We can't have the message |
+ * class pass this in to the constructor because of bootstrapping trouble |
+ * with DescriptorProtos. |
+ */ |
+ protected abstract FieldAccessorTable internalGetFieldAccessorTable(); |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Descriptor getDescriptorForType() { |
+ return internalGetFieldAccessorTable().descriptor; |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Map<FieldDescriptor, Object> getAllFields() { |
+ return Collections.unmodifiableMap(getAllFieldsMutable()); |
+ } |
+ |
+ /** Internal helper which returns a mutable map. */ |
+ private Map<FieldDescriptor, Object> getAllFieldsMutable() { |
+ final TreeMap<FieldDescriptor, Object> result = |
+ new TreeMap<FieldDescriptor, Object>(); |
+ final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; |
+ final List<FieldDescriptor> fields = descriptor.getFields(); |
+ |
+ for (int i = 0; i < fields.size(); i++) { |
+ FieldDescriptor field = fields.get(i); |
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof(); |
+ |
+ /* |
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set |
+ * and it is not repeated. There is no need to iterate through the others. |
+ */ |
+ if (oneofDescriptor != null) { |
+ // Skip other fields in the Oneof we know are not set |
+ i += oneofDescriptor.getFieldCount() - 1; |
+ if (!hasOneof(oneofDescriptor)) { |
+ // If no field is set in the Oneof, skip all the fields in the Oneof |
+ continue; |
+ } |
+ // Get the pointer to the only field which is set in the Oneof |
+ field = getOneofFieldDescriptor(oneofDescriptor); |
+ } else { |
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated |
+ if (field.isRepeated()) { |
+ final List<?> value = (List<?>) getField(field); |
+ if (!value.isEmpty()) { |
+ result.put(field, value); |
+ } |
+ continue; |
+ } |
+ if (!hasField(field)) { |
+ continue; |
+ } |
+ } |
+ // Add the field to the map |
+ result.put(field, getField(field)); |
+ } |
+ return result; |
+ } |
+ |
+ public Message.Builder newBuilderForField( |
+ final FieldDescriptor field) { |
+ return internalGetFieldAccessorTable().getField(field).newBuilder(); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Message.Builder getFieldBuilder(final FieldDescriptor field) { |
+ return internalGetFieldAccessorTable().getField(field).getBuilder(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, |
+ int index) { |
+ return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder( |
+ this, index); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public boolean hasOneof(final OneofDescriptor oneof) { |
+ return internalGetFieldAccessorTable().getOneof(oneof).has(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { |
+ return internalGetFieldAccessorTable().getOneof(oneof).get(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public boolean hasField(final FieldDescriptor field) { |
+ return internalGetFieldAccessorTable().getField(field).has(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Object getField(final FieldDescriptor field) { |
+ Object object = internalGetFieldAccessorTable().getField(field).get(this); |
+ if (field.isRepeated()) { |
+ // The underlying list object is still modifiable at this point. |
+ // Make sure not to expose the modifiable list to the caller. |
+ return Collections.unmodifiableList((List) object); |
+ } else { |
+ return object; |
+ } |
+ } |
+ |
+ public BuilderType setField(final FieldDescriptor field, |
+ final Object value) { |
+ internalGetFieldAccessorTable().getField(field).set(this, value); |
+ return (BuilderType) this; |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public BuilderType clearField(final FieldDescriptor field) { |
+ internalGetFieldAccessorTable().getField(field).clear(this); |
+ return (BuilderType) this; |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public BuilderType clearOneof(final OneofDescriptor oneof) { |
+ internalGetFieldAccessorTable().getOneof(oneof).clear(this); |
+ return (BuilderType) this; |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public int getRepeatedFieldCount(final FieldDescriptor field) { |
+ return internalGetFieldAccessorTable().getField(field) |
+ .getRepeatedCount(this); |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public Object getRepeatedField(final FieldDescriptor field, |
+ final int index) { |
+ return internalGetFieldAccessorTable().getField(field) |
+ .getRepeated(this, index); |
+ } |
+ |
+ public BuilderType setRepeatedField(final FieldDescriptor field, |
+ final int index, final Object value) { |
+ internalGetFieldAccessorTable().getField(field) |
+ .setRepeated(this, index, value); |
+ return (BuilderType) this; |
+ } |
+ |
+ public BuilderType addRepeatedField(final FieldDescriptor field, |
+ final Object value) { |
+ internalGetFieldAccessorTable().getField(field).addRepeated(this, value); |
+ return (BuilderType) this; |
+ } |
+ |
+ public BuilderType setUnknownFields( |
+ final UnknownFieldSet unknownFields) { |
+ this.unknownFields = unknownFields; |
+ onChanged(); |
+ return (BuilderType) this; |
+ } |
+ |
+ @Override |
+ public BuilderType mergeUnknownFields( |
+ final UnknownFieldSet unknownFields) { |
+ this.unknownFields = |
+ UnknownFieldSet.newBuilder(this.unknownFields) |
+ .mergeFrom(unknownFields) |
+ .build(); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public boolean isInitialized() { |
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) { |
+ // Check that all required fields are present. |
+ if (field.isRequired()) { |
+ if (!hasField(field)) { |
+ return false; |
+ } |
+ } |
+ // Check that embedded messages are initialized. |
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
+ if (field.isRepeated()) { |
+ @SuppressWarnings("unchecked") final |
+ List<Message> messageList = (List<Message>) getField(field); |
+ for (final Message element : messageList) { |
+ if (!element.isInitialized()) { |
+ return false; |
+ } |
+ } |
+ } else { |
+ if (hasField(field) && |
+ !((Message) getField(field)).isInitialized()) { |
+ return false; |
+ } |
+ } |
+ } |
+ } |
+ return true; |
+ } |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public final UnknownFieldSet getUnknownFields() { |
+ return unknownFields; |
+ } |
+ |
+ /** |
+ * Called by subclasses to parse an unknown field. |
+ * @return {@code true} unless the tag is an end-group tag. |
+ */ |
+ protected boolean parseUnknownField( |
+ final CodedInputStream input, |
+ final UnknownFieldSet.Builder unknownFields, |
+ final ExtensionRegistryLite extensionRegistry, |
+ final int tag) throws IOException { |
+ return unknownFields.mergeFieldFrom(tag, input); |
+ } |
+ |
+ /** |
+ * Implementation of {@link BuilderParent} for giving to our children. This |
+ * small inner class makes it so we don't publicly expose the BuilderParent |
+ * methods. |
+ */ |
+ private class BuilderParentImpl implements BuilderParent { |
+ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public void markDirty() { |
+ onChanged(); |
+ } |
+ } |
+ |
+ /** |
+ * Gets the {@link BuilderParent} for giving to our children. |
+ * @return The builder parent for our children. |
+ */ |
+ protected BuilderParent getParentForChildren() { |
+ if (meAsParent == null) { |
+ meAsParent = new BuilderParentImpl(); |
+ } |
+ return meAsParent; |
+ } |
+ |
+ /** |
+ * Called when a the builder or one of its nested children has changed |
+ * and any parent should be notified of its invalidation. |
+ */ |
+ protected final void onChanged() { |
+ if (isClean && builderParent != null) { |
+ builderParent.markDirty(); |
+ |
+ // Don't keep dispatching invalidations until build is called again. |
+ isClean = false; |
+ } |
+ } |
+ |
+ /** |
+ * Gets the map field with the given field number. This method should be |
+ * overridden in the generated message class if the message contains map |
+ * fields. |
+ * |
+ * Unlike other field types, reflection support for map fields can't be |
+ * implemented based on generated public API because we need to access a |
+ * map field as a list in reflection API but the generated API only allows |
+ * us to access it as a map. This method returns the underlying map field |
+ * directly and thus enables us to access the map field as a list. |
+ */ |
+ @SuppressWarnings({"unused", "rawtypes"}) |
+ protected MapField internalGetMapField(int fieldNumber) { |
+ // Note that we can't use descriptor names here because this method will |
+ // be called when descriptor is being initialized. |
+ throw new RuntimeException( |
+ "No map fields found in " + getClass().getName()); |
+ } |
+ |
+ /** Like {@link internalGetMapField} but return a mutable version. */ |
+ @SuppressWarnings({"unused", "rawtypes"}) |
+ protected MapField internalGetMutableMapField(int fieldNumber) { |
+ // Note that we can't use descriptor names here because this method will |
+ // be called when descriptor is being initialized. |
+ throw new RuntimeException( |
+ "No map fields found in " + getClass().getName()); |
+ } |
+ } |
+ |
+ // ================================================================= |
+ // Extensions-related stuff |
+ |
+ public interface ExtendableMessageOrBuilder< |
+ MessageType extends ExtendableMessage> extends MessageOrBuilder { |
+ // Re-define for return type covariance. |
+ Message getDefaultInstanceForType(); |
+ |
+ /** Check if a singular extension is present. */ |
+ <Type> boolean hasExtension( |
+ ExtensionLite<MessageType, Type> extension); |
+ |
+ /** Get the number of elements in a repeated extension. */ |
+ <Type> int getExtensionCount( |
+ ExtensionLite<MessageType, List<Type>> extension); |
+ |
+ /** Get the value of an extension. */ |
+ <Type> Type getExtension( |
+ ExtensionLite<MessageType, Type> extension); |
+ |
+ /** Get one element of a repeated extension. */ |
+ <Type> Type getExtension( |
+ ExtensionLite<MessageType, List<Type>> extension, |
+ int index); |
+ } |
+ |
+ /** |
+ * Generated message classes for message types that contain extension ranges |
+ * subclass this. |
+ * |
+ * <p>This class implements type-safe accessors for extensions. They |
+ * implement all the same operations that you can do with normal fields -- |
+ * e.g. "has", "get", and "getCount" -- but for extensions. The extensions |
+ * are identified using instances of the class {@link GeneratedExtension}; |
+ * the protocol compiler generates a static instance of this class for every |
+ * extension in its input. Through the magic of generics, all is made |
+ * type-safe. |
+ * |
+ * <p>For example, imagine you have the {@code .proto} file: |
+ * |
+ * <pre> |
+ * option java_class = "MyProto"; |
+ * |
+ * message Foo { |
+ * extensions 1000 to max; |
+ * } |
+ * |
+ * extend Foo { |
+ * optional int32 bar; |
+ * } |
+ * </pre> |
+ * |
+ * <p>Then you might write code like: |
+ * |
+ * <pre> |
+ * MyProto.Foo foo = getFoo(); |
+ * int i = foo.getExtension(MyProto.bar); |
+ * </pre> |
+ * |
+ * <p>See also {@link ExtendableBuilder}. |
+ */ |
+ public abstract static class ExtendableMessage< |
+ MessageType extends ExtendableMessage> |
+ extends GeneratedMessage |
+ implements ExtendableMessageOrBuilder<MessageType> { |
+ |
+ private final FieldSet<FieldDescriptor> extensions; |
+ |
+ protected ExtendableMessage() { |
+ this.extensions = FieldSet.newFieldSet(); |
+ } |
+ |
+ protected ExtendableMessage( |
+ ExtendableBuilder<MessageType, ?> builder) { |
+ super(builder); |
+ this.extensions = builder.buildExtensions(); |
+ } |
+ |
+ private void verifyExtensionContainingType( |
+ final Extension<MessageType, ?> extension) { |
+ if (extension.getDescriptor().getContainingType() != |
+ getDescriptorForType()) { |
+ // This can only happen if someone uses unchecked operations. |
+ throw new IllegalArgumentException( |
+ "Extension is for type \"" + |
+ extension.getDescriptor().getContainingType().getFullName() + |
+ "\" which does not match message type \"" + |
+ getDescriptorForType().getFullName() + "\"."); |
+ } |
+ } |
+ |
+ /** Check if a singular extension is present. */ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public final <Type> boolean hasExtension( |
+ final ExtensionLite<MessageType, Type> extensionLite) { |
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ return extensions.hasField(extension.getDescriptor()); |
+ } |
+ |
+ /** Get the number of elements in a repeated extension. */ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public final <Type> int getExtensionCount( |
+ final ExtensionLite<MessageType, List<Type>> extensionLite) { |
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ final FieldDescriptor descriptor = extension.getDescriptor(); |
+ return extensions.getRepeatedFieldCount(descriptor); |
+ } |
+ |
+ /** Get the value of an extension. */ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ @SuppressWarnings("unchecked") |
+ public final <Type> Type getExtension( |
+ final ExtensionLite<MessageType, Type> extensionLite) { |
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ FieldDescriptor descriptor = extension.getDescriptor(); |
+ final Object value = extensions.getField(descriptor); |
+ if (value == null) { |
+ if (descriptor.isRepeated()) { |
+ return (Type) Collections.emptyList(); |
+ } else if (descriptor.getJavaType() == |
+ FieldDescriptor.JavaType.MESSAGE) { |
+ return (Type) extension.getMessageDefaultInstance(); |
+ } else { |
+ return (Type) extension.fromReflectionType( |
+ descriptor.getDefaultValue()); |
+ } |
+ } else { |
+ return (Type) extension.fromReflectionType(value); |
+ } |
+ } |
+ |
+ /** Get one element of a repeated extension. */ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ @SuppressWarnings("unchecked") |
+ public final <Type> Type getExtension( |
+ final ExtensionLite<MessageType, List<Type>> extensionLite, |
+ final int index) { |
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ FieldDescriptor descriptor = extension.getDescriptor(); |
+ return (Type) extension.singularFromReflectionType( |
+ extensions.getRepeatedField(descriptor, index)); |
+ } |
+ |
+ /** Called by subclasses to check if all extensions are initialized. */ |
+ protected boolean extensionsAreInitialized() { |
+ return extensions.isInitialized(); |
+ } |
+ |
+ @Override |
+ public boolean isInitialized() { |
+ return super.isInitialized() && extensionsAreInitialized(); |
+ } |
+ |
+ @Override |
+ protected boolean parseUnknownField( |
+ CodedInputStream input, |
+ UnknownFieldSet.Builder unknownFields, |
+ ExtensionRegistryLite extensionRegistry, |
+ int tag) throws IOException { |
+ return MessageReflection.mergeFieldFrom( |
+ input, unknownFields, extensionRegistry, getDescriptorForType(), |
+ new MessageReflection.ExtensionAdapter(extensions), tag); |
+ } |
+ |
+ |
+ /** |
+ * Used by parsing constructors in generated classes. |
+ */ |
+ @Override |
+ protected void makeExtensionsImmutable() { |
+ extensions.makeImmutable(); |
+ } |
+ |
+ /** |
+ * Used by subclasses to serialize extensions. Extension ranges may be |
+ * interleaved with field numbers, but we must write them in canonical |
+ * (sorted by field number) order. ExtensionWriter helps us write |
+ * individual ranges of extensions at once. |
+ */ |
+ protected class ExtensionWriter { |
+ // Imagine how much simpler this code would be if Java iterators had |
+ // a way to get the next element without advancing the iterator. |
+ |
+ private final Iterator<Map.Entry<FieldDescriptor, Object>> iter = |
+ extensions.iterator(); |
+ private Map.Entry<FieldDescriptor, Object> next; |
+ private final boolean messageSetWireFormat; |
+ |
+ private ExtensionWriter(final boolean messageSetWireFormat) { |
+ if (iter.hasNext()) { |
+ next = iter.next(); |
+ } |
+ this.messageSetWireFormat = messageSetWireFormat; |
+ } |
+ |
+ public void writeUntil(final int end, final CodedOutputStream output) |
+ throws IOException { |
+ while (next != null && next.getKey().getNumber() < end) { |
+ FieldDescriptor descriptor = next.getKey(); |
+ if (messageSetWireFormat && descriptor.getLiteJavaType() == |
+ WireFormat.JavaType.MESSAGE && |
+ !descriptor.isRepeated()) { |
+ if (next instanceof LazyField.LazyEntry<?>) { |
+ output.writeRawMessageSetExtension(descriptor.getNumber(), |
+ ((LazyField.LazyEntry<?>) next).getField().toByteString()); |
+ } else { |
+ output.writeMessageSetExtension(descriptor.getNumber(), |
+ (Message) next.getValue()); |
+ } |
+ } else { |
+ // TODO(xiangl): Taken care of following code, it may cause |
+ // problem when we use LazyField for normal fields/extensions. |
+ // Due to the optional field can be duplicated at the end of |
+ // serialized bytes, which will make the serialized size change |
+ // after lazy field parsed. So when we use LazyField globally, |
+ // we need to change the following write method to write cached |
+ // bytes directly rather than write the parsed message. |
+ FieldSet.writeField(descriptor, next.getValue(), output); |
+ } |
+ if (iter.hasNext()) { |
+ next = iter.next(); |
+ } else { |
+ next = null; |
+ } |
+ } |
+ } |
+ } |
+ |
+ protected ExtensionWriter newExtensionWriter() { |
+ return new ExtensionWriter(false); |
+ } |
+ protected ExtensionWriter newMessageSetExtensionWriter() { |
+ return new ExtensionWriter(true); |
+ } |
+ |
+ /** Called by subclasses to compute the size of extensions. */ |
+ protected int extensionsSerializedSize() { |
+ return extensions.getSerializedSize(); |
+ } |
+ protected int extensionsSerializedSizeAsMessageSet() { |
+ return extensions.getMessageSetSerializedSize(); |
+ } |
+ |
+ // --------------------------------------------------------------- |
+ // Reflection |
+ |
+ protected Map<FieldDescriptor, Object> getExtensionFields() { |
+ return extensions.getAllFields(); |
+ } |
+ |
+ @Override |
+ public Map<FieldDescriptor, Object> getAllFields() { |
+ final Map<FieldDescriptor, Object> result = |
+ super.getAllFieldsMutable(/* getBytesForString = */ false); |
+ result.putAll(getExtensionFields()); |
+ return Collections.unmodifiableMap(result); |
+ } |
+ |
+ @Override |
+ public Map<FieldDescriptor, Object> getAllFieldsRaw() { |
+ final Map<FieldDescriptor, Object> result = |
+ super.getAllFieldsMutable(/* getBytesForString = */ false); |
+ result.putAll(getExtensionFields()); |
+ return Collections.unmodifiableMap(result); |
+ } |
+ |
+ @Override |
+ public boolean hasField(final FieldDescriptor field) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ return extensions.hasField(field); |
+ } else { |
+ return super.hasField(field); |
+ } |
+ } |
+ |
+ @Override |
+ public Object getField(final FieldDescriptor field) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ final Object value = extensions.getField(field); |
+ if (value == null) { |
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
+ // Lacking an ExtensionRegistry, we have no way to determine the |
+ // extension's real type, so we return a DynamicMessage. |
+ return DynamicMessage.getDefaultInstance(field.getMessageType()); |
+ } else { |
+ return field.getDefaultValue(); |
+ } |
+ } else { |
+ return value; |
+ } |
+ } else { |
+ return super.getField(field); |
+ } |
+ } |
+ |
+ @Override |
+ public int getRepeatedFieldCount(final FieldDescriptor field) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ return extensions.getRepeatedFieldCount(field); |
+ } else { |
+ return super.getRepeatedFieldCount(field); |
+ } |
+ } |
+ |
+ @Override |
+ public Object getRepeatedField(final FieldDescriptor field, |
+ final int index) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ return extensions.getRepeatedField(field, index); |
+ } else { |
+ return super.getRepeatedField(field, index); |
+ } |
+ } |
+ |
+ private void verifyContainingType(final FieldDescriptor field) { |
+ if (field.getContainingType() != getDescriptorForType()) { |
+ throw new IllegalArgumentException( |
+ "FieldDescriptor does not match message type."); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * Generated message builders for message types that contain extension ranges |
+ * subclass this. |
+ * |
+ * <p>This class implements type-safe accessors for extensions. They |
+ * implement all the same operations that you can do with normal fields -- |
+ * e.g. "get", "set", and "add" -- but for extensions. The extensions are |
+ * identified using instances of the class {@link GeneratedExtension}; the |
+ * protocol compiler generates a static instance of this class for every |
+ * extension in its input. Through the magic of generics, all is made |
+ * type-safe. |
+ * |
+ * <p>For example, imagine you have the {@code .proto} file: |
+ * |
+ * <pre> |
+ * option java_class = "MyProto"; |
+ * |
+ * message Foo { |
+ * extensions 1000 to max; |
+ * } |
+ * |
+ * extend Foo { |
+ * optional int32 bar; |
+ * } |
+ * </pre> |
+ * |
+ * <p>Then you might write code like: |
+ * |
+ * <pre> |
+ * MyProto.Foo foo = |
+ * MyProto.Foo.newBuilder() |
+ * .setExtension(MyProto.bar, 123) |
+ * .build(); |
+ * </pre> |
+ * |
+ * <p>See also {@link ExtendableMessage}. |
+ */ |
+ @SuppressWarnings("unchecked") |
+ public abstract static class ExtendableBuilder< |
+ MessageType extends ExtendableMessage, |
+ BuilderType extends ExtendableBuilder> |
+ extends Builder<BuilderType> |
+ implements ExtendableMessageOrBuilder<MessageType> { |
+ |
+ private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet(); |
+ |
+ protected ExtendableBuilder() {} |
+ |
+ protected ExtendableBuilder( |
+ BuilderParent parent) { |
+ super(parent); |
+ } |
+ |
+ // For immutable message conversion. |
+ void internalSetExtensionSet(FieldSet<FieldDescriptor> extensions) { |
+ this.extensions = extensions; |
+ } |
+ |
+ @Override |
+ public BuilderType clear() { |
+ extensions = FieldSet.emptySet(); |
+ return super.clear(); |
+ } |
+ |
+ // This is implemented here only to work around an apparent bug in the |
+ // Java compiler and/or build system. See bug #1898463. The mere presence |
+ // of this clone() implementation makes it go away. |
+ @Override |
+ public BuilderType clone() { |
+ return super.clone(); |
+ } |
+ |
+ private void ensureExtensionsIsMutable() { |
+ if (extensions.isImmutable()) { |
+ extensions = extensions.clone(); |
+ } |
+ } |
+ |
+ private void verifyExtensionContainingType( |
+ final Extension<MessageType, ?> extension) { |
+ if (extension.getDescriptor().getContainingType() != |
+ getDescriptorForType()) { |
+ // This can only happen if someone uses unchecked operations. |
+ throw new IllegalArgumentException( |
+ "Extension is for type \"" + |
+ extension.getDescriptor().getContainingType().getFullName() + |
+ "\" which does not match message type \"" + |
+ getDescriptorForType().getFullName() + "\"."); |
+ } |
+ } |
+ |
+ /** Check if a singular extension is present. */ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public final <Type> boolean hasExtension( |
+ final ExtensionLite<MessageType, Type> extensionLite) { |
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ return extensions.hasField(extension.getDescriptor()); |
+ } |
+ |
+ /** Get the number of elements in a repeated extension. */ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public final <Type> int getExtensionCount( |
+ final ExtensionLite<MessageType, List<Type>> extensionLite) { |
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ final FieldDescriptor descriptor = extension.getDescriptor(); |
+ return extensions.getRepeatedFieldCount(descriptor); |
+ } |
+ |
+ /** Get the value of an extension. */ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public final <Type> Type getExtension( |
+ final ExtensionLite<MessageType, Type> extensionLite) { |
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ FieldDescriptor descriptor = extension.getDescriptor(); |
+ final Object value = extensions.getField(descriptor); |
+ if (value == null) { |
+ if (descriptor.isRepeated()) { |
+ return (Type) Collections.emptyList(); |
+ } else if (descriptor.getJavaType() == |
+ FieldDescriptor.JavaType.MESSAGE) { |
+ return (Type) extension.getMessageDefaultInstance(); |
+ } else { |
+ return (Type) extension.fromReflectionType( |
+ descriptor.getDefaultValue()); |
+ } |
+ } else { |
+ return (Type) extension.fromReflectionType(value); |
+ } |
+ } |
+ |
+ /** Get one element of a repeated extension. */ |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public final <Type> Type getExtension( |
+ final ExtensionLite<MessageType, List<Type>> extensionLite, |
+ final int index) { |
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ FieldDescriptor descriptor = extension.getDescriptor(); |
+ return (Type) extension.singularFromReflectionType( |
+ extensions.getRepeatedField(descriptor, index)); |
+ } |
+ |
+ /** Set the value of an extension. */ |
+ public final <Type> BuilderType setExtension( |
+ final ExtensionLite<MessageType, Type> extensionLite, |
+ final Type value) { |
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ ensureExtensionsIsMutable(); |
+ final FieldDescriptor descriptor = extension.getDescriptor(); |
+ extensions.setField(descriptor, extension.toReflectionType(value)); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } |
+ |
+ /** Set the value of one element of a repeated extension. */ |
+ public final <Type> BuilderType setExtension( |
+ final ExtensionLite<MessageType, List<Type>> extensionLite, |
+ final int index, final Type value) { |
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ ensureExtensionsIsMutable(); |
+ final FieldDescriptor descriptor = extension.getDescriptor(); |
+ extensions.setRepeatedField( |
+ descriptor, index, |
+ extension.singularToReflectionType(value)); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } |
+ |
+ /** Append a value to a repeated extension. */ |
+ public final <Type> BuilderType addExtension( |
+ final ExtensionLite<MessageType, List<Type>> extensionLite, |
+ final Type value) { |
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ ensureExtensionsIsMutable(); |
+ final FieldDescriptor descriptor = extension.getDescriptor(); |
+ extensions.addRepeatedField( |
+ descriptor, extension.singularToReflectionType(value)); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } |
+ |
+ /** Clear an extension. */ |
+ public final <Type> BuilderType clearExtension( |
+ final ExtensionLite<MessageType, ?> extensionLite) { |
+ Extension<MessageType, ?> extension = checkNotLite(extensionLite); |
+ |
+ verifyExtensionContainingType(extension); |
+ ensureExtensionsIsMutable(); |
+ extensions.clearField(extension.getDescriptor()); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } |
+ |
+ /** Called by subclasses to check if all extensions are initialized. */ |
+ protected boolean extensionsAreInitialized() { |
+ return extensions.isInitialized(); |
+ } |
+ |
+ /** |
+ * Called by the build code path to create a copy of the extensions for |
+ * building the message. |
+ */ |
+ private FieldSet<FieldDescriptor> buildExtensions() { |
+ extensions.makeImmutable(); |
+ return extensions; |
+ } |
+ |
+ @Override |
+ public boolean isInitialized() { |
+ return super.isInitialized() && extensionsAreInitialized(); |
+ } |
+ |
+ /** |
+ * Called by subclasses to parse an unknown field or an extension. |
+ * @return {@code true} unless the tag is an end-group tag. |
+ */ |
+ @Override |
+ protected boolean parseUnknownField( |
+ final CodedInputStream input, |
+ final UnknownFieldSet.Builder unknownFields, |
+ final ExtensionRegistryLite extensionRegistry, |
+ final int tag) throws IOException { |
+ return MessageReflection.mergeFieldFrom( |
+ input, unknownFields, extensionRegistry, getDescriptorForType(), |
+ new MessageReflection.BuilderAdapter(this), tag); |
+ } |
+ |
+ // --------------------------------------------------------------- |
+ // Reflection |
+ |
+ @Override |
+ public Map<FieldDescriptor, Object> getAllFields() { |
+ final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable(); |
+ result.putAll(extensions.getAllFields()); |
+ return Collections.unmodifiableMap(result); |
+ } |
+ |
+ @Override |
+ public Object getField(final FieldDescriptor field) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ final Object value = extensions.getField(field); |
+ if (value == null) { |
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
+ // Lacking an ExtensionRegistry, we have no way to determine the |
+ // extension's real type, so we return a DynamicMessage. |
+ return DynamicMessage.getDefaultInstance(field.getMessageType()); |
+ } else { |
+ return field.getDefaultValue(); |
+ } |
+ } else { |
+ return value; |
+ } |
+ } else { |
+ return super.getField(field); |
+ } |
+ } |
+ |
+ @Override |
+ public int getRepeatedFieldCount(final FieldDescriptor field) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ return extensions.getRepeatedFieldCount(field); |
+ } else { |
+ return super.getRepeatedFieldCount(field); |
+ } |
+ } |
+ |
+ @Override |
+ public Object getRepeatedField(final FieldDescriptor field, |
+ final int index) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ return extensions.getRepeatedField(field, index); |
+ } else { |
+ return super.getRepeatedField(field, index); |
+ } |
+ } |
+ |
+ @Override |
+ public boolean hasField(final FieldDescriptor field) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ return extensions.hasField(field); |
+ } else { |
+ return super.hasField(field); |
+ } |
+ } |
+ |
+ @Override |
+ public BuilderType setField(final FieldDescriptor field, |
+ final Object value) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ ensureExtensionsIsMutable(); |
+ extensions.setField(field, value); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } else { |
+ return super.setField(field, value); |
+ } |
+ } |
+ |
+ @Override |
+ public BuilderType clearField(final FieldDescriptor field) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ ensureExtensionsIsMutable(); |
+ extensions.clearField(field); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } else { |
+ return super.clearField(field); |
+ } |
+ } |
+ |
+ @Override |
+ public BuilderType setRepeatedField(final FieldDescriptor field, |
+ final int index, final Object value) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ ensureExtensionsIsMutable(); |
+ extensions.setRepeatedField(field, index, value); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } else { |
+ return super.setRepeatedField(field, index, value); |
+ } |
+ } |
+ |
+ @Override |
+ public BuilderType addRepeatedField(final FieldDescriptor field, |
+ final Object value) { |
+ if (field.isExtension()) { |
+ verifyContainingType(field); |
+ ensureExtensionsIsMutable(); |
+ extensions.addRepeatedField(field, value); |
+ onChanged(); |
+ return (BuilderType) this; |
+ } else { |
+ return super.addRepeatedField(field, value); |
+ } |
+ } |
+ |
+ protected final void mergeExtensionFields(final ExtendableMessage other) { |
+ ensureExtensionsIsMutable(); |
+ extensions.mergeFrom(other.extensions); |
+ onChanged(); |
+ } |
+ |
+ private void verifyContainingType(final FieldDescriptor field) { |
+ if (field.getContainingType() != getDescriptorForType()) { |
+ throw new IllegalArgumentException( |
+ "FieldDescriptor does not match message type."); |
+ } |
+ } |
+ } |
+ |
+ // ----------------------------------------------------------------- |
+ |
+ /** |
+ * Gets the descriptor for an extension. The implementation depends on whether |
+ * the extension is scoped in the top level of a file or scoped in a Message. |
+ */ |
+ static interface ExtensionDescriptorRetriever { |
+ FieldDescriptor getDescriptor(); |
+ } |
+ |
+ /** For use by generated code only. */ |
+ public static <ContainingType extends Message, Type> |
+ GeneratedExtension<ContainingType, Type> |
+ newMessageScopedGeneratedExtension(final Message scope, |
+ final int descriptorIndex, |
+ final Class singularType, |
+ final Message defaultInstance) { |
+ // For extensions scoped within a Message, we use the Message to resolve |
+ // the outer class's descriptor, from which the extension descriptor is |
+ // obtained. |
+ return new GeneratedExtension<ContainingType, Type>( |
+ new CachedDescriptorRetriever() { |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public FieldDescriptor loadDescriptor() { |
+ return scope.getDescriptorForType().getExtensions() |
+ .get(descriptorIndex); |
+ } |
+ }, |
+ singularType, |
+ defaultInstance, |
+ Extension.ExtensionType.IMMUTABLE); |
+ } |
+ |
+ /** For use by generated code only. */ |
+ public static <ContainingType extends Message, Type> |
+ GeneratedExtension<ContainingType, Type> |
+ newFileScopedGeneratedExtension(final Class singularType, |
+ final Message defaultInstance) { |
+ // For extensions scoped within a file, we rely on the outer class's |
+ // static initializer to call internalInit() on the extension when the |
+ // descriptor is available. |
+ return new GeneratedExtension<ContainingType, Type>( |
+ null, // ExtensionDescriptorRetriever is initialized in internalInit(); |
+ singularType, |
+ defaultInstance, |
+ Extension.ExtensionType.IMMUTABLE); |
+ } |
+ |
+ private abstract static class CachedDescriptorRetriever |
+ implements ExtensionDescriptorRetriever { |
+ private volatile FieldDescriptor descriptor; |
+ protected abstract FieldDescriptor loadDescriptor(); |
+ |
+ public FieldDescriptor getDescriptor() { |
+ if (descriptor == null) { |
+ synchronized (this) { |
+ if (descriptor == null) { |
+ descriptor = loadDescriptor(); |
+ } |
+ } |
+ } |
+ return descriptor; |
+ } |
+ } |
+ |
+ /** |
+ * Used in proto1 generated code only. |
+ * |
+ * After enabling bridge, we can define proto2 extensions (the extended type |
+ * is a proto2 mutable message) in a proto1 .proto file. For these extensions |
+ * we should generate proto2 GeneratedExtensions. |
+ */ |
+ public static <ContainingType extends Message, Type> |
+ GeneratedExtension<ContainingType, Type> |
+ newMessageScopedGeneratedExtension( |
+ final Message scope, final String name, |
+ final Class singularType, final Message defaultInstance) { |
+ // For extensions scoped within a Message, we use the Message to resolve |
+ // the outer class's descriptor, from which the extension descriptor is |
+ // obtained. |
+ return new GeneratedExtension<ContainingType, Type>( |
+ new CachedDescriptorRetriever() { |
+ protected FieldDescriptor loadDescriptor() { |
+ return scope.getDescriptorForType().findFieldByName(name); |
+ } |
+ }, |
+ singularType, |
+ defaultInstance, |
+ Extension.ExtensionType.MUTABLE); |
+ } |
+ |
+ /** |
+ * Used in proto1 generated code only. |
+ * |
+ * After enabling bridge, we can define proto2 extensions (the extended type |
+ * is a proto2 mutable message) in a proto1 .proto file. For these extensions |
+ * we should generate proto2 GeneratedExtensions. |
+ */ |
+ public static <ContainingType extends Message, Type> |
+ GeneratedExtension<ContainingType, Type> |
+ newFileScopedGeneratedExtension( |
+ final Class singularType, final Message defaultInstance, |
+ final String descriptorOuterClass, final String extensionName) { |
+ // For extensions scoped within a file, we load the descriptor outer |
+ // class and rely on it to get the FileDescriptor which then can be |
+ // used to obtain the extension's FieldDescriptor. |
+ return new GeneratedExtension<ContainingType, Type>( |
+ new CachedDescriptorRetriever() { |
+ protected FieldDescriptor loadDescriptor() { |
+ try { |
+ Class clazz = |
+ singularType.getClassLoader().loadClass(descriptorOuterClass); |
+ FileDescriptor file = |
+ (FileDescriptor) clazz.getField("descriptor").get(null); |
+ return file.findExtensionByName(extensionName); |
+ } catch (Exception e) { |
+ throw new RuntimeException( |
+ "Cannot load descriptors: " + descriptorOuterClass + |
+ " is not a valid descriptor class name", e); |
+ } |
+ } |
+ }, |
+ singularType, |
+ defaultInstance, |
+ Extension.ExtensionType.MUTABLE); |
+ } |
+ |
+ /** |
+ * Type used to represent generated extensions. The protocol compiler |
+ * generates a static singleton instance of this class for each extension. |
+ * |
+ * <p>For example, imagine you have the {@code .proto} file: |
+ * |
+ * <pre> |
+ * option java_class = "MyProto"; |
+ * |
+ * message Foo { |
+ * extensions 1000 to max; |
+ * } |
+ * |
+ * extend Foo { |
+ * optional int32 bar; |
+ * } |
+ * </pre> |
+ * |
+ * <p>Then, {@code MyProto.Foo.bar} has type |
+ * {@code GeneratedExtension<MyProto.Foo, Integer>}. |
+ * |
+ * <p>In general, users should ignore the details of this type, and simply use |
+ * these static singletons as parameters to the extension accessors defined |
+ * in {@link ExtendableMessage} and {@link ExtendableBuilder}. |
+ */ |
+ public static class GeneratedExtension< |
+ ContainingType extends Message, Type> extends |
+ Extension<ContainingType, Type> { |
+ // TODO(kenton): Find ways to avoid using Java reflection within this |
+ // class. Also try to avoid suppressing unchecked warnings. |
+ |
+ // We can't always initialize the descriptor of a GeneratedExtension when |
+ // we first construct it due to initialization order difficulties (namely, |
+ // the descriptor may not have been constructed yet, since it is often |
+ // constructed by the initializer of a separate module). |
+ // |
+ // In the case of nested extensions, we initialize the |
+ // ExtensionDescriptorRetriever with an instance that uses the scoping |
+ // Message's default instance to retrieve the extension's descriptor. |
+ // |
+ // In the case of non-nested extensions, we initialize the |
+ // ExtensionDescriptorRetriever to null and rely on the outer class's static |
+ // initializer to call internalInit() after the descriptor has been parsed. |
+ GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever, |
+ Class singularType, |
+ Message messageDefaultInstance, |
+ ExtensionType extensionType) { |
+ if (Message.class.isAssignableFrom(singularType) && |
+ !singularType.isInstance(messageDefaultInstance)) { |
+ throw new IllegalArgumentException( |
+ "Bad messageDefaultInstance for " + singularType.getName()); |
+ } |
+ this.descriptorRetriever = descriptorRetriever; |
+ this.singularType = singularType; |
+ this.messageDefaultInstance = messageDefaultInstance; |
+ |
+ if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) { |
+ this.enumValueOf = getMethodOrDie(singularType, "valueOf", |
+ EnumValueDescriptor.class); |
+ this.enumGetValueDescriptor = |
+ getMethodOrDie(singularType, "getValueDescriptor"); |
+ } else { |
+ this.enumValueOf = null; |
+ this.enumGetValueDescriptor = null; |
+ } |
+ this.extensionType = extensionType; |
+ } |
+ |
+ /** For use by generated code only. */ |
+ public void internalInit(final FieldDescriptor descriptor) { |
+ if (descriptorRetriever != null) { |
+ throw new IllegalStateException("Already initialized."); |
+ } |
+ descriptorRetriever = new ExtensionDescriptorRetriever() { |
+ //@Override (Java 1.6 override semantics, but we must support 1.5) |
+ public FieldDescriptor getDescriptor() { |
+ return descriptor; |
+ } |
+ }; |
+ } |
+ |
+ private ExtensionDescriptorRetriever descriptorRetriever; |
+ private final Class singularType; |
+ private final Message messageDefaultInstance; |
+ private final Method enumValueOf; |
+ private final Method enumGetValueDescriptor; |
+ private final ExtensionType extensionType; |
+ |
+ public FieldDescriptor getDescriptor() { |
+ if (descriptorRetriever == null) { |
+ throw new IllegalStateException( |
+ "getDescriptor() called before internalInit()"); |
+ } |
+ return descriptorRetriever.getDescriptor(); |
+ } |
+ |
+ /** |
+ * If the extension is an embedded message or group, returns the default |
+ * instance of the message. |
+ */ |
+ public Message getMessageDefaultInstance() { |
+ return messageDefaultInstance; |
+ } |
+ |
+ protected ExtensionType getExtensionType() { |
+ return extensionType; |
+ } |
+ |
+ /** |
+ * Convert from the type used by the reflection accessors to the type used |
+ * by native accessors. E.g., for enums, the reflection accessors use |
+ * EnumValueDescriptors but the native accessors use the generated enum |
+ * type. |
+ */ |
+ // @Override |
+ @SuppressWarnings("unchecked") |
+ protected Object fromReflectionType(final Object value) { |
+ FieldDescriptor descriptor = getDescriptor(); |
+ if (descriptor.isRepeated()) { |
+ if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE || |
+ descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { |
+ // Must convert the whole list. |
+ final List result = new ArrayList(); |
+ for (final Object element : (List) value) { |
+ result.add(singularFromReflectionType(element)); |
+ } |
+ return result; |
+ } else { |
+ return value; |
+ } |
+ } else { |
+ return singularFromReflectionType(value); |
+ } |
+ } |
+ |
+ /** |
+ * Like {@link #fromReflectionType(Object)}, but if the type is a repeated |
+ * type, this converts a single element. |
+ */ |
+ // @Override |
+ protected Object singularFromReflectionType(final Object value) { |
+ FieldDescriptor descriptor = getDescriptor(); |
+ switch (descriptor.getJavaType()) { |
+ case MESSAGE: |
+ if (singularType.isInstance(value)) { |
+ return value; |
+ } else { |
+ return messageDefaultInstance.newBuilderForType() |
+ .mergeFrom((Message) value).build(); |
+ } |
+ case ENUM: |
+ return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value); |
+ default: |
+ return value; |
+ } |
+ } |
+ |
+ /** |
+ * Convert from the type used by the native accessors to the type used |
+ * by reflection accessors. E.g., for enums, the reflection accessors use |
+ * EnumValueDescriptors but the native accessors use the generated enum |
+ * type. |
+ */ |
+ // @Override |
+ @SuppressWarnings("unchecked") |
+ protected Object toReflectionType(final Object value) { |
+ FieldDescriptor descriptor = getDescriptor(); |
+ if (descriptor.isRepeated()) { |
+ if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) { |
+ // Must convert the whole list. |
+ final List result = new ArrayList(); |
+ for (final Object element : (List) value) { |
+ result.add(singularToReflectionType(element)); |
+ } |
+ return result; |
+ } else { |
+ return value; |
+ } |
+ } else { |
+ return singularToReflectionType(value); |
+ } |
+ } |
+ |
+ /** |
+ * Like {@link #toReflectionType(Object)}, but if the type is a repeated |
+ * type, this converts a single element. |
+ */ |
+ // @Override |
+ protected Object singularToReflectionType(final Object value) { |
+ FieldDescriptor descriptor = getDescriptor(); |
+ switch (descriptor.getJavaType()) { |
+ case ENUM: |
+ return invokeOrDie(enumGetValueDescriptor, value); |
+ default: |
+ return value; |
+ } |
+ } |
+ |
+ // @Override |
+ public int getNumber() { |
+ return getDescriptor().getNumber(); |
+ } |
+ |
+ // @Override |
+ public WireFormat.FieldType getLiteType() { |
+ return getDescriptor().getLiteType(); |
+ } |
+ |
+ // @Override |
+ public boolean isRepeated() { |
+ return getDescriptor().isRepeated(); |
+ } |
+ |
+ // @Override |
+ @SuppressWarnings("unchecked") |
+ public Type getDefaultValue() { |
+ if (isRepeated()) { |
+ return (Type) Collections.emptyList(); |
+ } |
+ if (getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
+ return (Type) messageDefaultInstance; |
+ } |
+ return (Type) singularFromReflectionType( |
+ getDescriptor().getDefaultValue()); |
+ } |
+ } |
+ |
+ // ================================================================= |
+ |
+ /** Calls Class.getMethod and throws a RuntimeException if it fails. */ |
+ @SuppressWarnings("unchecked") |
+ private static Method getMethodOrDie( |
+ final Class clazz, final String name, final Class... params) { |
+ try { |
+ return clazz.getMethod(name, params); |
+ } catch (NoSuchMethodException e) { |
+ throw new RuntimeException( |
+ "Generated message class \"" + clazz.getName() + |
+ "\" missing method \"" + name + "\".", e); |
+ } |
+ } |
+ |
+ /** Calls invoke and throws a RuntimeException if it fails. */ |
+ private static Object invokeOrDie( |
+ final Method method, final Object object, final Object... params) { |
+ try { |
+ return method.invoke(object, params); |
+ } catch (IllegalAccessException e) { |
+ throw new RuntimeException( |
+ "Couldn't use Java reflection to implement protocol message " + |
+ "reflection.", e); |
+ } catch (InvocationTargetException e) { |
+ final Throwable cause = e.getCause(); |
+ if (cause instanceof RuntimeException) { |
+ throw (RuntimeException) cause; |
+ } else if (cause instanceof Error) { |
+ throw (Error) cause; |
+ } else { |
+ throw new RuntimeException( |
+ "Unexpected exception thrown by generated accessor method.", cause); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * Gets the map field with the given field number. This method should be |
+ * overridden in the generated message class if the message contains map |
+ * fields. |
+ * |
+ * Unlike other field types, reflection support for map fields can't be |
+ * implemented based on generated public API because we need to access a |
+ * map field as a list in reflection API but the generated API only allows |
+ * us to access it as a map. This method returns the underlying map field |
+ * directly and thus enables us to access the map field as a list. |
+ */ |
+ @SuppressWarnings({"rawtypes", "unused"}) |
+ protected MapField internalGetMapField(int fieldNumber) { |
+ // Note that we can't use descriptor names here because this method will |
+ // be called when descriptor is being initialized. |
+ throw new RuntimeException( |
+ "No map fields found in " + getClass().getName()); |
+ } |
+ |
+ /** |
+ * Users should ignore this class. This class provides the implementation |
+ * with access to the fields of a message object using Java reflection. |
+ */ |
+ public static final class FieldAccessorTable { |
+ |
+ /** |
+ * Construct a FieldAccessorTable for a particular message class. Only |
+ * one FieldAccessorTable should ever be constructed per class. |
+ * |
+ * @param descriptor The type's descriptor. |
+ * @param camelCaseNames The camelcase names of all fields in the message. |
+ * These are used to derive the accessor method names. |
+ * @param messageClass The message type. |
+ * @param builderClass The builder type. |
+ */ |
+ public FieldAccessorTable( |
+ final Descriptor descriptor, |
+ final String[] camelCaseNames, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass) { |
+ this(descriptor, camelCaseNames); |
+ ensureFieldAccessorsInitialized(messageClass, builderClass); |
+ } |
+ |
+ /** |
+ * Construct a FieldAccessorTable for a particular message class without |
+ * initializing FieldAccessors. |
+ */ |
+ public FieldAccessorTable( |
+ final Descriptor descriptor, |
+ final String[] camelCaseNames) { |
+ this.descriptor = descriptor; |
+ this.camelCaseNames = camelCaseNames; |
+ fields = new FieldAccessor[descriptor.getFields().size()]; |
+ oneofs = new OneofAccessor[descriptor.getOneofs().size()]; |
+ initialized = false; |
+ } |
+ |
+ private boolean isMapFieldEnabled(FieldDescriptor field) { |
+ boolean result = true; |
+ return result; |
+ } |
+ |
+ /** |
+ * Ensures the field accessors are initialized. This method is thread-safe. |
+ * |
+ * @param messageClass The message type. |
+ * @param builderClass The builder type. |
+ * @return this |
+ */ |
+ public FieldAccessorTable ensureFieldAccessorsInitialized( |
+ Class<? extends GeneratedMessage> messageClass, |
+ Class<? extends Builder> builderClass) { |
+ if (initialized) { return this; } |
+ synchronized (this) { |
+ if (initialized) { return this; } |
+ int fieldsSize = fields.length; |
+ for (int i = 0; i < fieldsSize; i++) { |
+ FieldDescriptor field = descriptor.getFields().get(i); |
+ String containingOneofCamelCaseName = null; |
+ if (field.getContainingOneof() != null) { |
+ containingOneofCamelCaseName = |
+ camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()]; |
+ } |
+ if (field.isRepeated()) { |
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
+ if (field.isMapField() && isMapFieldEnabled(field)) { |
+ fields[i] = new MapFieldAccessor( |
+ field, camelCaseNames[i], messageClass, builderClass); |
+ } else { |
+ fields[i] = new RepeatedMessageFieldAccessor( |
+ field, camelCaseNames[i], messageClass, builderClass); |
+ } |
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { |
+ fields[i] = new RepeatedEnumFieldAccessor( |
+ field, camelCaseNames[i], messageClass, builderClass); |
+ } else { |
+ fields[i] = new RepeatedFieldAccessor( |
+ field, camelCaseNames[i], messageClass, builderClass); |
+ } |
+ } else { |
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { |
+ fields[i] = new SingularMessageFieldAccessor( |
+ field, camelCaseNames[i], messageClass, builderClass, |
+ containingOneofCamelCaseName); |
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) { |
+ fields[i] = new SingularEnumFieldAccessor( |
+ field, camelCaseNames[i], messageClass, builderClass, |
+ containingOneofCamelCaseName); |
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) { |
+ fields[i] = new SingularStringFieldAccessor( |
+ field, camelCaseNames[i], messageClass, builderClass, |
+ containingOneofCamelCaseName); |
+ } else { |
+ fields[i] = new SingularFieldAccessor( |
+ field, camelCaseNames[i], messageClass, builderClass, |
+ containingOneofCamelCaseName); |
+ } |
+ } |
+ } |
+ |
+ int oneofsSize = oneofs.length; |
+ for (int i = 0; i < oneofsSize; i++) { |
+ oneofs[i] = new OneofAccessor( |
+ descriptor, camelCaseNames[i + fieldsSize], |
+ messageClass, builderClass); |
+ } |
+ initialized = true; |
+ camelCaseNames = null; |
+ return this; |
+ } |
+ } |
+ |
+ private final Descriptor descriptor; |
+ private final FieldAccessor[] fields; |
+ private String[] camelCaseNames; |
+ private final OneofAccessor[] oneofs; |
+ private volatile boolean initialized; |
+ |
+ /** Get the FieldAccessor for a particular field. */ |
+ private FieldAccessor getField(final FieldDescriptor field) { |
+ if (field.getContainingType() != descriptor) { |
+ throw new IllegalArgumentException( |
+ "FieldDescriptor does not match message type."); |
+ } else if (field.isExtension()) { |
+ // If this type had extensions, it would subclass ExtendableMessage, |
+ // which overrides the reflection interface to handle extensions. |
+ throw new IllegalArgumentException( |
+ "This type does not have extensions."); |
+ } |
+ return fields[field.getIndex()]; |
+ } |
+ |
+ /** Get the OneofAccessor for a particular oneof. */ |
+ private OneofAccessor getOneof(final OneofDescriptor oneof) { |
+ if (oneof.getContainingType() != descriptor) { |
+ throw new IllegalArgumentException( |
+ "OneofDescriptor does not match message type."); |
+ } |
+ return oneofs[oneof.getIndex()]; |
+ } |
+ |
+ /** |
+ * Abstract interface that provides access to a single field. This is |
+ * implemented differently depending on the field type and cardinality. |
+ */ |
+ private interface FieldAccessor { |
+ Object get(GeneratedMessage message); |
+ Object get(GeneratedMessage.Builder builder); |
+ Object getRaw(GeneratedMessage message); |
+ Object getRaw(GeneratedMessage.Builder builder); |
+ void set(Builder builder, Object value); |
+ Object getRepeated(GeneratedMessage message, int index); |
+ Object getRepeated(GeneratedMessage.Builder builder, int index); |
+ Object getRepeatedRaw(GeneratedMessage message, int index); |
+ Object getRepeatedRaw(GeneratedMessage.Builder builder, int index); |
+ void setRepeated(Builder builder, |
+ int index, Object value); |
+ void addRepeated(Builder builder, Object value); |
+ boolean has(GeneratedMessage message); |
+ boolean has(GeneratedMessage.Builder builder); |
+ int getRepeatedCount(GeneratedMessage message); |
+ int getRepeatedCount(GeneratedMessage.Builder builder); |
+ void clear(Builder builder); |
+ Message.Builder newBuilder(); |
+ Message.Builder getBuilder(GeneratedMessage.Builder builder); |
+ Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, |
+ int index); |
+ } |
+ |
+ /** OneofAccessor provides access to a single oneof. */ |
+ private static class OneofAccessor { |
+ OneofAccessor( |
+ final Descriptor descriptor, final String camelCaseName, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass) { |
+ this.descriptor = descriptor; |
+ caseMethod = |
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Case"); |
+ caseMethodBuilder = |
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Case"); |
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); |
+ } |
+ |
+ private final Descriptor descriptor; |
+ private final Method caseMethod; |
+ private final Method caseMethodBuilder; |
+ private final Method clearMethod; |
+ |
+ public boolean has(final GeneratedMessage message) { |
+ if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) { |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ public boolean has(GeneratedMessage.Builder builder) { |
+ if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) { |
+ return false; |
+ } |
+ return true; |
+ } |
+ |
+ public FieldDescriptor get(final GeneratedMessage message) { |
+ int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); |
+ if (fieldNumber > 0) { |
+ return descriptor.findFieldByNumber(fieldNumber); |
+ } |
+ return null; |
+ } |
+ |
+ public FieldDescriptor get(GeneratedMessage.Builder builder) { |
+ int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); |
+ if (fieldNumber > 0) { |
+ return descriptor.findFieldByNumber(fieldNumber); |
+ } |
+ return null; |
+ } |
+ |
+ public void clear(final Builder builder) { |
+ invokeOrDie(clearMethod, builder); |
+ } |
+ } |
+ |
+ private static boolean supportFieldPresence(FileDescriptor file) { |
+ return file.getSyntax() == FileDescriptor.Syntax.PROTO2; |
+ } |
+ |
+ // --------------------------------------------------------------- |
+ |
+ private static class SingularFieldAccessor implements FieldAccessor { |
+ SingularFieldAccessor( |
+ final FieldDescriptor descriptor, final String camelCaseName, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass, |
+ final String containingOneofCamelCaseName) { |
+ field = descriptor; |
+ isOneofField = descriptor.getContainingOneof() != null; |
+ hasHasMethod = supportFieldPresence(descriptor.getFile()) |
+ || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE); |
+ getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); |
+ getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); |
+ type = getMethod.getReturnType(); |
+ setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type); |
+ hasMethod = |
+ hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null; |
+ hasMethodBuilder = |
+ hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null; |
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); |
+ caseMethod = isOneofField ? getMethodOrDie( |
+ messageClass, "get" + containingOneofCamelCaseName + "Case") : null; |
+ caseMethodBuilder = isOneofField ? getMethodOrDie( |
+ builderClass, "get" + containingOneofCamelCaseName + "Case") : null; |
+ } |
+ |
+ // Note: We use Java reflection to call public methods rather than |
+ // access private fields directly as this avoids runtime security |
+ // checks. |
+ protected final Class<?> type; |
+ protected final Method getMethod; |
+ protected final Method getMethodBuilder; |
+ protected final Method setMethod; |
+ protected final Method hasMethod; |
+ protected final Method hasMethodBuilder; |
+ protected final Method clearMethod; |
+ protected final Method caseMethod; |
+ protected final Method caseMethodBuilder; |
+ protected final FieldDescriptor field; |
+ protected final boolean isOneofField; |
+ protected final boolean hasHasMethod; |
+ |
+ private int getOneofFieldNumber(final GeneratedMessage message) { |
+ return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); |
+ } |
+ |
+ private int getOneofFieldNumber(final GeneratedMessage.Builder builder) { |
+ return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); |
+ } |
+ |
+ public Object get(final GeneratedMessage message) { |
+ return invokeOrDie(getMethod, message); |
+ } |
+ public Object get(GeneratedMessage.Builder builder) { |
+ return invokeOrDie(getMethodBuilder, builder); |
+ } |
+ public Object getRaw(final GeneratedMessage message) { |
+ return get(message); |
+ } |
+ public Object getRaw(GeneratedMessage.Builder builder) { |
+ return get(builder); |
+ } |
+ public void set(final Builder builder, final Object value) { |
+ invokeOrDie(setMethod, builder, value); |
+ } |
+ public Object getRepeated(final GeneratedMessage message, |
+ final int index) { |
+ throw new UnsupportedOperationException( |
+ "getRepeatedField() called on a singular field."); |
+ } |
+ public Object getRepeatedRaw(final GeneratedMessage message, |
+ final int index) { |
+ throw new UnsupportedOperationException( |
+ "getRepeatedFieldRaw() called on a singular field."); |
+ } |
+ public Object getRepeated(GeneratedMessage.Builder builder, int index) { |
+ throw new UnsupportedOperationException( |
+ "getRepeatedField() called on a singular field."); |
+ } |
+ public Object getRepeatedRaw(GeneratedMessage.Builder builder, |
+ int index) { |
+ throw new UnsupportedOperationException( |
+ "getRepeatedFieldRaw() called on a singular field."); |
+ } |
+ public void setRepeated(final Builder builder, final int index, |
+ final Object value) { |
+ throw new UnsupportedOperationException( |
+ "setRepeatedField() called on a singular field."); |
+ } |
+ public void addRepeated(final Builder builder, final Object value) { |
+ throw new UnsupportedOperationException( |
+ "addRepeatedField() called on a singular field."); |
+ } |
+ public boolean has(final GeneratedMessage message) { |
+ if (!hasHasMethod) { |
+ if (isOneofField) { |
+ return getOneofFieldNumber(message) == field.getNumber(); |
+ } |
+ return !get(message).equals(field.getDefaultValue()); |
+ } |
+ return (Boolean) invokeOrDie(hasMethod, message); |
+ } |
+ public boolean has(GeneratedMessage.Builder builder) { |
+ if (!hasHasMethod) { |
+ if (isOneofField) { |
+ return getOneofFieldNumber(builder) == field.getNumber(); |
+ } |
+ return !get(builder).equals(field.getDefaultValue()); |
+ } |
+ return (Boolean) invokeOrDie(hasMethodBuilder, builder); |
+ } |
+ public int getRepeatedCount(final GeneratedMessage message) { |
+ throw new UnsupportedOperationException( |
+ "getRepeatedFieldSize() called on a singular field."); |
+ } |
+ public int getRepeatedCount(GeneratedMessage.Builder builder) { |
+ throw new UnsupportedOperationException( |
+ "getRepeatedFieldSize() called on a singular field."); |
+ } |
+ public void clear(final Builder builder) { |
+ invokeOrDie(clearMethod, builder); |
+ } |
+ public Message.Builder newBuilder() { |
+ throw new UnsupportedOperationException( |
+ "newBuilderForField() called on a non-Message type."); |
+ } |
+ public Message.Builder getBuilder(GeneratedMessage.Builder builder) { |
+ throw new UnsupportedOperationException( |
+ "getFieldBuilder() called on a non-Message type."); |
+ } |
+ public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, |
+ int index) { |
+ throw new UnsupportedOperationException( |
+ "getRepeatedFieldBuilder() called on a non-Message type."); |
+ } |
+ } |
+ |
+ private static class RepeatedFieldAccessor implements FieldAccessor { |
+ protected final Class type; |
+ protected final Method getMethod; |
+ protected final Method getMethodBuilder; |
+ protected final Method getRepeatedMethod; |
+ protected final Method getRepeatedMethodBuilder; |
+ protected final Method setRepeatedMethod; |
+ protected final Method addRepeatedMethod; |
+ protected final Method getCountMethod; |
+ protected final Method getCountMethodBuilder; |
+ protected final Method clearMethod; |
+ |
+ RepeatedFieldAccessor( |
+ final FieldDescriptor descriptor, final String camelCaseName, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass) { |
+ getMethod = getMethodOrDie(messageClass, |
+ "get" + camelCaseName + "List"); |
+ getMethodBuilder = getMethodOrDie(builderClass, |
+ "get" + camelCaseName + "List"); |
+ getRepeatedMethod = |
+ getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE); |
+ getRepeatedMethodBuilder = |
+ getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE); |
+ type = getRepeatedMethod.getReturnType(); |
+ setRepeatedMethod = |
+ getMethodOrDie(builderClass, "set" + camelCaseName, |
+ Integer.TYPE, type); |
+ addRepeatedMethod = |
+ getMethodOrDie(builderClass, "add" + camelCaseName, type); |
+ getCountMethod = |
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Count"); |
+ getCountMethodBuilder = |
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Count"); |
+ |
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); |
+ } |
+ |
+ public Object get(final GeneratedMessage message) { |
+ return invokeOrDie(getMethod, message); |
+ } |
+ public Object get(GeneratedMessage.Builder builder) { |
+ return invokeOrDie(getMethodBuilder, builder); |
+ } |
+ public Object getRaw(final GeneratedMessage message) { |
+ return get(message); |
+ } |
+ public Object getRaw(GeneratedMessage.Builder builder) { |
+ return get(builder); |
+ } |
+ public void set(final Builder builder, final Object value) { |
+ // Add all the elements individually. This serves two purposes: |
+ // 1) Verifies that each element has the correct type. |
+ // 2) Insures that the caller cannot modify the list later on and |
+ // have the modifications be reflected in the message. |
+ clear(builder); |
+ for (final Object element : (List<?>) value) { |
+ addRepeated(builder, element); |
+ } |
+ } |
+ public Object getRepeated(final GeneratedMessage message, |
+ final int index) { |
+ return invokeOrDie(getRepeatedMethod, message, index); |
+ } |
+ public Object getRepeated(GeneratedMessage.Builder builder, int index) { |
+ return invokeOrDie(getRepeatedMethodBuilder, builder, index); |
+ } |
+ public Object getRepeatedRaw(GeneratedMessage message, int index) { |
+ return getRepeated(message, index); |
+ } |
+ public Object getRepeatedRaw(GeneratedMessage.Builder builder, |
+ int index) { |
+ return getRepeated(builder, index); |
+ } |
+ public void setRepeated(final Builder builder, |
+ final int index, final Object value) { |
+ invokeOrDie(setRepeatedMethod, builder, index, value); |
+ } |
+ public void addRepeated(final Builder builder, final Object value) { |
+ invokeOrDie(addRepeatedMethod, builder, value); |
+ } |
+ public boolean has(final GeneratedMessage message) { |
+ throw new UnsupportedOperationException( |
+ "hasField() called on a repeated field."); |
+ } |
+ public boolean has(GeneratedMessage.Builder builder) { |
+ throw new UnsupportedOperationException( |
+ "hasField() called on a repeated field."); |
+ } |
+ public int getRepeatedCount(final GeneratedMessage message) { |
+ return (Integer) invokeOrDie(getCountMethod, message); |
+ } |
+ public int getRepeatedCount(GeneratedMessage.Builder builder) { |
+ return (Integer) invokeOrDie(getCountMethodBuilder, builder); |
+ } |
+ public void clear(final Builder builder) { |
+ invokeOrDie(clearMethod, builder); |
+ } |
+ public Message.Builder newBuilder() { |
+ throw new UnsupportedOperationException( |
+ "newBuilderForField() called on a non-Message type."); |
+ } |
+ public Message.Builder getBuilder(GeneratedMessage.Builder builder) { |
+ throw new UnsupportedOperationException( |
+ "getFieldBuilder() called on a non-Message type."); |
+ } |
+ public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, |
+ int index) { |
+ throw new UnsupportedOperationException( |
+ "getRepeatedFieldBuilder() called on a non-Message type."); |
+ } |
+ } |
+ |
+ private static class MapFieldAccessor implements FieldAccessor { |
+ MapFieldAccessor( |
+ final FieldDescriptor descriptor, final String camelCaseName, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass) { |
+ field = descriptor; |
+ Method getDefaultInstanceMethod = |
+ getMethodOrDie(messageClass, "getDefaultInstance"); |
+ MapField defaultMapField = getMapField( |
+ (GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null)); |
+ mapEntryMessageDefaultInstance = |
+ defaultMapField.getMapEntryMessageDefaultInstance(); |
+ } |
+ |
+ private final FieldDescriptor field; |
+ private final Message mapEntryMessageDefaultInstance; |
+ |
+ private MapField<?, ?> getMapField(GeneratedMessage message) { |
+ return (MapField<?, ?>) message.internalGetMapField(field.getNumber()); |
+ } |
+ |
+ private MapField<?, ?> getMapField(GeneratedMessage.Builder builder) { |
+ return (MapField<?, ?>) builder.internalGetMapField(field.getNumber()); |
+ } |
+ |
+ private MapField<?, ?> getMutableMapField( |
+ GeneratedMessage.Builder builder) { |
+ return (MapField<?, ?>) builder.internalGetMutableMapField( |
+ field.getNumber()); |
+ } |
+ |
+ public Object get(GeneratedMessage message) { |
+ List result = new ArrayList(); |
+ for (int i = 0; i < getRepeatedCount(message); i++) { |
+ result.add(getRepeated(message, i)); |
+ } |
+ return Collections.unmodifiableList(result); |
+ } |
+ |
+ public Object get(Builder builder) { |
+ List result = new ArrayList(); |
+ for (int i = 0; i < getRepeatedCount(builder); i++) { |
+ result.add(getRepeated(builder, i)); |
+ } |
+ return Collections.unmodifiableList(result); |
+ } |
+ |
+ public Object getRaw(GeneratedMessage message) { |
+ return get(message); |
+ } |
+ |
+ public Object getRaw(GeneratedMessage.Builder builder) { |
+ return get(builder); |
+ } |
+ |
+ public void set(Builder builder, Object value) { |
+ clear(builder); |
+ for (Object entry : (List) value) { |
+ addRepeated(builder, entry); |
+ } |
+ } |
+ |
+ public Object getRepeated(GeneratedMessage message, int index) { |
+ return getMapField(message).getList().get(index); |
+ } |
+ |
+ public Object getRepeated(Builder builder, int index) { |
+ return getMapField(builder).getList().get(index); |
+ } |
+ |
+ public Object getRepeatedRaw(GeneratedMessage message, int index) { |
+ return getRepeated(message, index); |
+ } |
+ |
+ public Object getRepeatedRaw(Builder builder, int index) { |
+ return getRepeated(builder, index); |
+ } |
+ |
+ public void setRepeated(Builder builder, int index, Object value) { |
+ getMutableMapField(builder).getMutableList().set(index, (Message) value); |
+ } |
+ |
+ public void addRepeated(Builder builder, Object value) { |
+ getMutableMapField(builder).getMutableList().add((Message) value); |
+ } |
+ |
+ public boolean has(GeneratedMessage message) { |
+ throw new UnsupportedOperationException( |
+ "hasField() is not supported for repeated fields."); |
+ } |
+ |
+ public boolean has(Builder builder) { |
+ throw new UnsupportedOperationException( |
+ "hasField() is not supported for repeated fields."); |
+ } |
+ |
+ public int getRepeatedCount(GeneratedMessage message) { |
+ return getMapField(message).getList().size(); |
+ } |
+ |
+ public int getRepeatedCount(Builder builder) { |
+ return getMapField(builder).getList().size(); |
+ } |
+ |
+ public void clear(Builder builder) { |
+ getMutableMapField(builder).getMutableList().clear(); |
+ } |
+ |
+ public com.google.protobuf.Message.Builder newBuilder() { |
+ return mapEntryMessageDefaultInstance.newBuilderForType(); |
+ } |
+ |
+ public com.google.protobuf.Message.Builder getBuilder(Builder builder) { |
+ throw new UnsupportedOperationException( |
+ "Nested builder not supported for map fields."); |
+ } |
+ |
+ public com.google.protobuf.Message.Builder getRepeatedBuilder( |
+ Builder builder, int index) { |
+ throw new UnsupportedOperationException( |
+ "Nested builder not supported for map fields."); |
+ } |
+ } |
+ |
+ // --------------------------------------------------------------- |
+ |
+ private static final class SingularEnumFieldAccessor |
+ extends SingularFieldAccessor { |
+ SingularEnumFieldAccessor( |
+ final FieldDescriptor descriptor, final String camelCaseName, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass, |
+ final String containingOneofCamelCaseName) { |
+ super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName); |
+ |
+ enumDescriptor = descriptor.getEnumType(); |
+ |
+ valueOfMethod = getMethodOrDie(type, "valueOf", |
+ EnumValueDescriptor.class); |
+ getValueDescriptorMethod = |
+ getMethodOrDie(type, "getValueDescriptor"); |
+ |
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue(); |
+ if (supportUnknownEnumValue) { |
+ getValueMethod = |
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value"); |
+ getValueMethodBuilder = |
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value"); |
+ setValueMethod = |
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class); |
+ } |
+ } |
+ |
+ private EnumDescriptor enumDescriptor; |
+ |
+ private Method valueOfMethod; |
+ private Method getValueDescriptorMethod; |
+ |
+ private boolean supportUnknownEnumValue; |
+ private Method getValueMethod; |
+ private Method getValueMethodBuilder; |
+ private Method setValueMethod; |
+ |
+ @Override |
+ public Object get(final GeneratedMessage message) { |
+ if (supportUnknownEnumValue) { |
+ int value = (Integer) invokeOrDie(getValueMethod, message); |
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value); |
+ } |
+ return invokeOrDie(getValueDescriptorMethod, super.get(message)); |
+ } |
+ |
+ @Override |
+ public Object get(final GeneratedMessage.Builder builder) { |
+ if (supportUnknownEnumValue) { |
+ int value = (Integer) invokeOrDie(getValueMethodBuilder, builder); |
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value); |
+ } |
+ return invokeOrDie(getValueDescriptorMethod, super.get(builder)); |
+ } |
+ |
+ @Override |
+ public void set(final Builder builder, final Object value) { |
+ if (supportUnknownEnumValue) { |
+ invokeOrDie(setValueMethod, builder, |
+ ((EnumValueDescriptor) value).getNumber()); |
+ return; |
+ } |
+ super.set(builder, invokeOrDie(valueOfMethod, null, value)); |
+ } |
+ } |
+ |
+ private static final class RepeatedEnumFieldAccessor |
+ extends RepeatedFieldAccessor { |
+ RepeatedEnumFieldAccessor( |
+ final FieldDescriptor descriptor, final String camelCaseName, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass) { |
+ super(descriptor, camelCaseName, messageClass, builderClass); |
+ |
+ enumDescriptor = descriptor.getEnumType(); |
+ |
+ valueOfMethod = getMethodOrDie(type, "valueOf", |
+ EnumValueDescriptor.class); |
+ getValueDescriptorMethod = |
+ getMethodOrDie(type, "getValueDescriptor"); |
+ |
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue(); |
+ if (supportUnknownEnumValue) { |
+ getRepeatedValueMethod = |
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value", int.class); |
+ getRepeatedValueMethodBuilder = |
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value", int.class); |
+ setRepeatedValueMethod = |
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class, int.class); |
+ addRepeatedValueMethod = |
+ getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class); |
+ } |
+ } |
+ private EnumDescriptor enumDescriptor; |
+ |
+ private final Method valueOfMethod; |
+ private final Method getValueDescriptorMethod; |
+ |
+ private boolean supportUnknownEnumValue; |
+ private Method getRepeatedValueMethod; |
+ private Method getRepeatedValueMethodBuilder; |
+ private Method setRepeatedValueMethod; |
+ private Method addRepeatedValueMethod; |
+ |
+ @Override |
+ @SuppressWarnings("unchecked") |
+ public Object get(final GeneratedMessage message) { |
+ final List newList = new ArrayList(); |
+ final int size = getRepeatedCount(message); |
+ for (int i = 0; i < size; i++) { |
+ newList.add(getRepeated(message, i)); |
+ } |
+ return Collections.unmodifiableList(newList); |
+ } |
+ |
+ @Override |
+ @SuppressWarnings("unchecked") |
+ public Object get(final GeneratedMessage.Builder builder) { |
+ final List newList = new ArrayList(); |
+ final int size = getRepeatedCount(builder); |
+ for (int i = 0; i < size; i++) { |
+ newList.add(getRepeated(builder, i)); |
+ } |
+ return Collections.unmodifiableList(newList); |
+ } |
+ |
+ @Override |
+ public Object getRepeated(final GeneratedMessage message, |
+ final int index) { |
+ if (supportUnknownEnumValue) { |
+ int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index); |
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value); |
+ } |
+ return invokeOrDie(getValueDescriptorMethod, |
+ super.getRepeated(message, index)); |
+ } |
+ @Override |
+ public Object getRepeated(final GeneratedMessage.Builder builder, |
+ final int index) { |
+ if (supportUnknownEnumValue) { |
+ int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index); |
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value); |
+ } |
+ return invokeOrDie(getValueDescriptorMethod, |
+ super.getRepeated(builder, index)); |
+ } |
+ @Override |
+ public void setRepeated(final Builder builder, |
+ final int index, final Object value) { |
+ if (supportUnknownEnumValue) { |
+ invokeOrDie(setRepeatedValueMethod, builder, index, |
+ ((EnumValueDescriptor) value).getNumber()); |
+ return; |
+ } |
+ super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, |
+ value)); |
+ } |
+ @Override |
+ public void addRepeated(final Builder builder, final Object value) { |
+ if (supportUnknownEnumValue) { |
+ invokeOrDie(addRepeatedValueMethod, builder, |
+ ((EnumValueDescriptor) value).getNumber()); |
+ return; |
+ } |
+ super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value)); |
+ } |
+ } |
+ |
+ // --------------------------------------------------------------- |
+ |
+ /** |
+ * Field accessor for string fields. |
+ * |
+ * <p>This class makes getFooBytes() and setFooBytes() available for |
+ * reflection API so that reflection based serialize/parse functions can |
+ * access the raw bytes of the field to preserve non-UTF8 bytes in the |
+ * string. |
+ * |
+ * <p>This ensures the serialize/parse round-trip safety, which is important |
+ * for servers which forward messages. |
+ */ |
+ private static final class SingularStringFieldAccessor |
+ extends SingularFieldAccessor { |
+ SingularStringFieldAccessor( |
+ final FieldDescriptor descriptor, final String camelCaseName, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass, |
+ final String containingOneofCamelCaseName) { |
+ super(descriptor, camelCaseName, messageClass, builderClass, |
+ containingOneofCamelCaseName); |
+ getBytesMethod = getMethodOrDie(messageClass, |
+ "get" + camelCaseName + "Bytes"); |
+ getBytesMethodBuilder = getMethodOrDie(builderClass, |
+ "get" + camelCaseName + "Bytes"); |
+ setBytesMethodBuilder = getMethodOrDie(builderClass, |
+ "set" + camelCaseName + "Bytes", ByteString.class); |
+ } |
+ |
+ private final Method getBytesMethod; |
+ private final Method getBytesMethodBuilder; |
+ private final Method setBytesMethodBuilder; |
+ |
+ @Override |
+ public Object getRaw(final GeneratedMessage message) { |
+ return invokeOrDie(getBytesMethod, message); |
+ } |
+ |
+ @Override |
+ public Object getRaw(GeneratedMessage.Builder builder) { |
+ return invokeOrDie(getBytesMethodBuilder, builder); |
+ } |
+ |
+ @Override |
+ public void set(GeneratedMessage.Builder builder, Object value) { |
+ if (value instanceof ByteString) { |
+ invokeOrDie(setBytesMethodBuilder, builder, value); |
+ } else { |
+ super.set(builder, value); |
+ } |
+ } |
+ } |
+ |
+ // --------------------------------------------------------------- |
+ |
+ private static final class SingularMessageFieldAccessor |
+ extends SingularFieldAccessor { |
+ SingularMessageFieldAccessor( |
+ final FieldDescriptor descriptor, final String camelCaseName, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass, |
+ final String containingOneofCamelCaseName) { |
+ super(descriptor, camelCaseName, messageClass, builderClass, |
+ containingOneofCamelCaseName); |
+ |
+ newBuilderMethod = getMethodOrDie(type, "newBuilder"); |
+ getBuilderMethodBuilder = |
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Builder"); |
+ } |
+ |
+ private final Method newBuilderMethod; |
+ private final Method getBuilderMethodBuilder; |
+ |
+ private Object coerceType(final Object value) { |
+ if (type.isInstance(value)) { |
+ return value; |
+ } else { |
+ // The value is not the exact right message type. However, if it |
+ // is an alternative implementation of the same type -- e.g. a |
+ // DynamicMessage -- we should accept it. In this case we can make |
+ // a copy of the message. |
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) |
+ .mergeFrom((Message) value).buildPartial(); |
+ } |
+ } |
+ |
+ @Override |
+ public void set(final Builder builder, final Object value) { |
+ super.set(builder, coerceType(value)); |
+ } |
+ @Override |
+ public Message.Builder newBuilder() { |
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null); |
+ } |
+ @Override |
+ public Message.Builder getBuilder(GeneratedMessage.Builder builder) { |
+ return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder); |
+ } |
+ } |
+ |
+ private static final class RepeatedMessageFieldAccessor |
+ extends RepeatedFieldAccessor { |
+ RepeatedMessageFieldAccessor( |
+ final FieldDescriptor descriptor, final String camelCaseName, |
+ final Class<? extends GeneratedMessage> messageClass, |
+ final Class<? extends Builder> builderClass) { |
+ super(descriptor, camelCaseName, messageClass, builderClass); |
+ |
+ newBuilderMethod = getMethodOrDie(type, "newBuilder"); |
+ getBuilderMethodBuilder = getMethodOrDie(builderClass, |
+ "get" + camelCaseName + "Builder", Integer.TYPE); |
+ } |
+ |
+ private final Method newBuilderMethod; |
+ private final Method getBuilderMethodBuilder; |
+ |
+ private Object coerceType(final Object value) { |
+ if (type.isInstance(value)) { |
+ return value; |
+ } else { |
+ // The value is not the exact right message type. However, if it |
+ // is an alternative implementation of the same type -- e.g. a |
+ // DynamicMessage -- we should accept it. In this case we can make |
+ // a copy of the message. |
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null)) |
+ .mergeFrom((Message) value).build(); |
+ } |
+ } |
+ |
+ @Override |
+ public void setRepeated(final Builder builder, |
+ final int index, final Object value) { |
+ super.setRepeated(builder, index, coerceType(value)); |
+ } |
+ @Override |
+ public void addRepeated(final Builder builder, final Object value) { |
+ super.addRepeated(builder, coerceType(value)); |
+ } |
+ @Override |
+ public Message.Builder newBuilder() { |
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null); |
+ } |
+ @Override |
+ public Message.Builder getRepeatedBuilder( |
+ final GeneratedMessage.Builder builder, final int index) { |
+ return (Message.Builder) invokeOrDie( |
+ getBuilderMethodBuilder, builder, index); |
+ } |
+ } |
+ } |
+ |
+ /** |
+ * Replaces this object in the output stream with a serialized form. |
+ * Part of Java's serialization magic. Generated sub-classes must override |
+ * this method by calling {@code return super.writeReplace();} |
+ * @return a SerializedForm of this message |
+ */ |
+ protected Object writeReplace() throws ObjectStreamException { |
+ return new GeneratedMessageLite.SerializedForm(this); |
+ } |
+ |
+ /** |
+ * Checks that the {@link Extension} is non-Lite and returns it as a |
+ * {@link GeneratedExtension}. |
+ */ |
+ private static <MessageType extends ExtendableMessage<MessageType>, T> |
+ Extension<MessageType, T> checkNotLite( |
+ ExtensionLite<MessageType, T> extension) { |
+ if (extension.isLite()) { |
+ throw new IllegalArgumentException("Expected non-lite extension."); |
+ } |
+ |
+ return (Extension<MessageType, T>) extension; |
+ } |
+ |
+ protected static int computeStringSize(final int fieldNumber, final Object value) { |
+ if (value instanceof String) { |
+ return CodedOutputStream.computeStringSize(fieldNumber, (String) value); |
+ } else { |
+ return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value); |
+ } |
+ } |
+ |
+ protected static int computeStringSizeNoTag(final Object value) { |
+ if (value instanceof String) { |
+ return CodedOutputStream.computeStringSizeNoTag((String) value); |
+ } else { |
+ return CodedOutputStream.computeBytesSizeNoTag((ByteString) value); |
+ } |
+ } |
+ |
+ protected static void writeString( |
+ CodedOutputStream output, final int fieldNumber, final Object value) throws IOException { |
+ if (value instanceof String) { |
+ output.writeString(fieldNumber, (String) value); |
+ } else { |
+ output.writeBytes(fieldNumber, (ByteString) value); |
+ } |
+ } |
+ |
+ protected static void writeStringNoTag( |
+ CodedOutputStream output, final Object value) throws IOException { |
+ if (value instanceof String) { |
+ output.writeStringNoTag((String) value); |
+ } else { |
+ output.writeBytesNoTag((ByteString) value); |
+ } |
+ } |
+} |