From 5df0387224e8e3b7c04f48c6f25a8ec1fc957a10 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Thu, 11 Jan 2024 13:38:38 -0800 Subject: [PATCH] Breaking Change: The base class for generated messages will be GeneratedMessage, not GeneratedMessageV3. Please rerun protoc on your .proto files to regenerate the binding code. https://protobuf.dev/news/2023-12-05/ https://protobuf.dev/support/cross-version-runtime-guarantee/ To fix source compatibility with surrounding code make these replacements: GeneratedMessageV3 --> GeneratedMessage SingleFieldBuilderV3 --> SingleFieldBuilder RepeatedFieldBuilderV3 --> RepeatedFieldBuilder PiperOrigin-RevId: 597642289 --- java/core/BUILD.bazel | 4 +- .../DescriptorMessageInfoFactory.java | 6 +- .../google/protobuf/ExtensionSchemaFull.java | 4 +- .../com/google/protobuf/GeneratedMessage.java | 2014 ++++++---- .../google/protobuf/GeneratedMessageV3.java | 3421 ----------------- .../protobuf/NewInstanceSchemaFull.java | 4 +- .../protobuf/RepeatedFieldBuilderV3.java | 647 ---- .../java/com/google/protobuf/SchemaUtil.java | 6 +- .../google/protobuf/SingleFieldBuilderV3.java | 210 - .../protobuf/UnknownFieldSetSchema.java | 8 +- .../google/protobuf/GeneratedMessageTest.java | 8 +- ...est.java => RepeatedFieldBuilderTest.java} | 26 +- ...3Test.java => SingleFieldBuilderTest.java} | 20 +- .../protobuf/ExtendableMessageExtensions.kt | 14 +- java/lite/pom.xml | 4 +- src/google/protobuf/compiler/java/helpers.h | 4 - .../protobuf/compiler/java/map_field.cc | 4 +- src/google/protobuf/compiler/java/message.cc | 70 +- .../protobuf/compiler/java/message_builder.cc | 26 +- .../protobuf/compiler/java/message_field.cc | 21 +- .../protobuf/compiler/java/string_field.cc | 9 +- 21 files changed, 1467 insertions(+), 5063 deletions(-) delete mode 100644 java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java delete mode 100644 java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java delete mode 100644 java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java rename java/core/src/test/java/com/google/protobuf/{RepeatedFieldBuilderV3Test.java => RepeatedFieldBuilderTest.java} (86%) rename java/core/src/test/java/com/google/protobuf/{SingleFieldBuilderV3Test.java => SingleFieldBuilderTest.java} (82%) diff --git a/java/core/BUILD.bazel b/java/core/BUILD.bazel index 4168a54b20..af5691c0ff 100644 --- a/java/core/BUILD.bazel +++ b/java/core/BUILD.bazel @@ -486,10 +486,10 @@ LITE_TEST_EXCLUSIONS = [ "src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java", "src/test/java/com/google/protobuf/Proto2SchemaTest.java", "src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java", - "src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java", + "src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java", "src/test/java/com/google/protobuf/RuntimeVersionTest.java", "src/test/java/com/google/protobuf/ServiceTest.java", - "src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java", + "src/test/java/com/google/protobuf/SingleFieldBuilderTest.java", "src/test/java/com/google/protobuf/TestBadIdentifiers.java", "src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java", "src/test/java/com/google/protobuf/TextFormatParseLocationTest.java", diff --git a/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java b/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java index 8210969035..8578a72083 100644 --- a/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java +++ b/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java @@ -34,7 +34,7 @@ import java.util.Set; import java.util.Stack; import java.util.concurrent.ConcurrentHashMap; -/** A factory for message info based on protobuf descriptors for a {@link GeneratedMessageV3}. */ +/** A factory for message info based on protobuf descriptors for a {@link GeneratedMessage}. */ @ExperimentalApi final class DescriptorMessageInfoFactory implements MessageInfoFactory { private static final String GET_DEFAULT_INSTANCE_METHOD_NAME = "getDefaultInstance"; @@ -74,12 +74,12 @@ final class DescriptorMessageInfoFactory implements MessageInfoFactory { @Override public boolean isSupported(Class messageType) { - return GeneratedMessageV3.class.isAssignableFrom(messageType); + return GeneratedMessage.class.isAssignableFrom(messageType); } @Override public MessageInfo messageInfoFor(Class messageType) { - if (!GeneratedMessageV3.class.isAssignableFrom(messageType)) { + if (!GeneratedMessage.class.isAssignableFrom(messageType)) { throw new IllegalArgumentException("Unsupported message type: " + messageType.getName()); } diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java index 9133e7a56d..f01884a2cb 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java @@ -23,7 +23,7 @@ final class ExtensionSchemaFull extends ExtensionSchema { private static long getExtensionsFieldOffset() { try { - Field field = GeneratedMessageV3.ExtendableMessage.class.getDeclaredField("extensions"); + Field field = GeneratedMessage.ExtendableMessage.class.getDeclaredField("extensions"); return UnsafeUtil.objectFieldOffset(field); } catch (Throwable e) { throw new IllegalStateException("Unable to lookup extension field offset"); @@ -32,7 +32,7 @@ final class ExtensionSchemaFull extends ExtensionSchema { @Override boolean hasExtensions(MessageLite prototype) { - return prototype instanceof GeneratedMessageV3.ExtendableMessage; + return prototype instanceof GeneratedMessage.ExtendableMessage; } @Override diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java index f722f8852c..c44ef4cb4d 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java @@ -7,12 +7,20 @@ package com.google.protobuf; +import static com.google.protobuf.Internal.checkNotNull; + 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.Internal.BooleanList; +import com.google.protobuf.Internal.DoubleList; +import com.google.protobuf.Internal.FloatList; +import com.google.protobuf.Internal.IntList; +import com.google.protobuf.Internal.LongList; +import com.google.protobuf.Internal.ProtobufList; import java.io.IOException; import java.io.InputStream; import java.io.ObjectStreamException; @@ -20,6 +28,7 @@ import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -43,7 +52,11 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial */ protected static boolean alwaysUseFieldBuilders = false; - /** For use by generated code only. */ + /** + * For use by generated code only. + * + *

TODO: mark this private and final (breaking change) + */ protected UnknownFieldSet unknownFields; protected GeneratedMessage() { @@ -54,19 +67,31 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial unknownFields = builder.getUnknownFields(); } + /** TODO: Remove this unnecessary intermediate implementation of this method. */ @Override public Parser 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}. + * TODO: Stop using SingleFieldBuilder and remove this setting + * + * @see #setAlwaysUseFieldBuildersForTesting(boolean) */ static void enableAlwaysUseFieldBuildersForTesting() { - alwaysUseFieldBuilders = true; + setAlwaysUseFieldBuildersForTesting(true); + } + + /** + * For testing. Allows a test to disable/re-enable 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}. + * + *

TODO: Stop using SingleFieldBuilder and remove this setting + */ + static void setAlwaysUseFieldBuildersForTesting(boolean useBuilders) { + alwaysUseFieldBuilders = useBuilders; } /** @@ -80,15 +105,36 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return internalGetFieldAccessorTable().descriptor; } + /** + * TODO: This method should be removed. It enables parsing directly into an + * "immutable" message. Have to leave it for now to support old gencode. + * + * @deprecated use newBuilder().mergeFrom() instead + */ + @Deprecated + protected void mergeFromAndMakeImmutableInternal( + CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + Schema schema = Protobuf.getInstance().schemaFor(this); + try { + schema.mergeFrom(this, CodedInputStreamReader.forCodedInput(input), extensionRegistry); + } catch (InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (IOException e) { + throw new InvalidProtocolBufferException(e).setUnfinishedMessage(this); + } + schema.makeImmutable(this); + } + /** * 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 + * modifiable so that the caller can add additional extension fields to implement {@link * #getAllFields()}. * * @param getBytesForString whether to generate ByteString for string fields */ private Map getAllFieldsMutable(boolean getBytesForString) { - final TreeMap result = new TreeMap(); + final TreeMap result = new TreeMap<>(); final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; final List fields = descriptor.getFields(); @@ -132,6 +178,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return result; } + // TODO: compute this at {@code build()} time in the Builder class. @Override public boolean isInitialized() { for (final FieldDescriptor field : getDescriptorForType().getFields()) { @@ -164,7 +211,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial @Override public Map getAllFields() { - return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString = */ false)); + return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString= */ false)); } /** @@ -176,7 +223,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * fields in order by field number. */ Map getAllFieldsRaw() { - return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString = */ true)); + return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString= */ true)); } @Override @@ -220,14 +267,23 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return internalGetFieldAccessorTable().getField(field).getRepeated(this, index); } + // TODO: This method should be final. @Override public UnknownFieldSet getUnknownFields() { - throw new UnsupportedOperationException("This is supposed to be overridden by subclasses."); + return unknownFields; + } + + // TODO: This should go away when Schema classes cannot modify immutable + // GeneratedMessage objects anymore. + void setUnknownFields(UnknownFieldSet unknownFields) { + this.unknownFields = unknownFields; } /** * Called by subclasses to parse an unknown field. * + *

TODO remove this method + * * @return {@code true} unless the tag is an end-group tag. */ protected boolean parseUnknownField( @@ -236,9 +292,29 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial ExtensionRegistryLite extensionRegistry, int tag) throws IOException { + if (input.shouldDiscardUnknownFields()) { + return input.skipField(tag); + } return unknownFields.mergeFieldFrom(tag, input); } + /** + * Delegates to parseUnknownField. This method is obsolete, but we must retain it for + * compatibility with older generated code. + * + *

TODO remove this method + */ + protected boolean parseUnknownFieldProto3( + CodedInputStream input, + UnknownFieldSet.Builder unknownFields, + ExtensionRegistryLite extensionRegistry, + int tag) + throws IOException { + return parseUnknownField(input, unknownFields, extensionRegistry, tag); + } + + /** Used by generated code. */ + @SuppressWarnings("ProtoParseWithRegistry") protected static M parseWithIOException(Parser parser, InputStream input) throws IOException { try { @@ -248,6 +324,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } + /** Used by generated code. */ protected static M parseWithIOException( Parser parser, InputStream input, ExtensionRegistryLite extensions) throws IOException { try { @@ -257,6 +334,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } + /** Used by generated code. */ + @SuppressWarnings("ProtoParseWithRegistry") protected static M parseWithIOException( Parser parser, CodedInputStream input) throws IOException { try { @@ -266,6 +345,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } + /** Used by generated code. */ protected static M parseWithIOException( Parser parser, CodedInputStream input, ExtensionRegistryLite extensions) throws IOException { @@ -276,6 +356,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } + /** Used by generated code. */ + @SuppressWarnings("ProtoParseWithRegistry") protected static M parseDelimitedWithIOException( Parser parser, InputStream input) throws IOException { try { @@ -285,6 +367,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } + /** Used by generated code. */ protected static M parseDelimitedWithIOException( Parser parser, InputStream input, ExtensionRegistryLite extensions) throws IOException { try { @@ -294,6 +377,103 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } + protected static boolean canUseUnsafe() { + return UnsafeUtil.hasUnsafeArrayOperations() && UnsafeUtil.hasUnsafeByteBufferOperations(); + } + + protected static IntList emptyIntList() { + return IntArrayList.emptyList(); + } + + // TODO: Unused. Remove. + protected static IntList newIntList() { + return new IntArrayList(); + } + + // TODO: Redundant with makeMutableCopy(). Remove. + protected static IntList mutableCopy(IntList list) { + return makeMutableCopy(list); + } + + // TODO: Redundant with makeMutableCopy(). Remove. + protected static LongList mutableCopy(LongList list) { + return makeMutableCopy(list); + } + + // TODO: Redundant with makeMutableCopy(). Remove. + protected static FloatList mutableCopy(FloatList list) { + return makeMutableCopy(list); + } + + // TODO: Redundant with makeMutableCopy(). Remove. + protected static DoubleList mutableCopy(DoubleList list) { + return makeMutableCopy(list); + } + + // TODO: Redundant with makeMutableCopy(). Remove. + protected static BooleanList mutableCopy(BooleanList list) { + return makeMutableCopy(list); + } + + protected static LongList emptyLongList() { + return LongArrayList.emptyList(); + } + + // TODO: Unused. Remove. + protected static LongList newLongList() { + return new LongArrayList(); + } + + protected static FloatList emptyFloatList() { + return FloatArrayList.emptyList(); + } + + // TODO: Unused. Remove. + protected static FloatList newFloatList() { + return new FloatArrayList(); + } + + protected static DoubleList emptyDoubleList() { + return DoubleArrayList.emptyList(); + } + + // TODO: Unused. Remove. + protected static DoubleList newDoubleList() { + return new DoubleArrayList(); + } + + protected static BooleanList emptyBooleanList() { + return BooleanArrayList.emptyList(); + } + + // TODO: Unused. Remove. + protected static BooleanList newBooleanList() { + return new BooleanArrayList(); + } + + protected static > ListT makeMutableCopy(ListT list) { + return makeMutableCopy(list, 0); + } + + @SuppressWarnings("unchecked") // Guaranteed by proto runtime. + protected static > ListT makeMutableCopy( + ListT list, int minCapacity) { + int size = list.size(); + if (minCapacity <= size) { + minCapacity = size * 2; + } + if (minCapacity <= 0) { + minCapacity = AbstractProtobufList.DEFAULT_CAPACITY; + } + + return (ListT) list.mutableCopyWithCapacity(minCapacity); + } + + @SuppressWarnings("unchecked") // The empty list can be safely cast + protected static ProtobufList emptyList(Class elementType) { + return (ProtobufList) ProtobufArrayList.emptyList(); + } + @Override public void writeTo(final CodedOutputStream output) throws IOException { MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false); @@ -306,11 +486,35 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return size; } - memoizedSize = MessageReflection.getSerializedSize(this, getAllFieldsRaw()); + memoizedSize = MessageReflection.getSerializedSize( + this, getAllFieldsRaw()); return memoizedSize; } - /** Used by parsing constructors in generated classes. */ + /** + * This class is used to make a generated protected method inaccessible from user's code (e.g., + * the {@link #newInstance} method below). When this class is used as a parameter's type in a + * generated protected method, the method is visible to user's code in the same package, but since + * the constructor of this class is private to protobuf runtime, user's code can't obtain an + * instance of this class and as such can't actually make a method call on the protected method. + */ + protected static final class UnusedPrivateParameter { + static final UnusedPrivateParameter INSTANCE = new UnusedPrivateParameter(); + + private UnusedPrivateParameter() {} + } + + /** Creates a new instance of this message type. Overridden in the generated code. */ + @SuppressWarnings({"unused"}) + protected Object newInstance(UnusedPrivateParameter unused) { + throw new UnsupportedOperationException("This method must be overridden by the subclass."); + } + + /** + * Used by parsing constructors in generated classes. + * + *

TODO: remove unused method (extensions should be immutable after build) + */ protected void makeExtensionsImmutable() { // Noop for messages without extensions. } @@ -319,12 +523,15 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * TODO: remove this after b/29368482 is fixed. We need to move this interface to * AbstractMessage in order to versioning GeneratedMessage but this move breaks binary * compatibility for AppEngine. After AppEngine is fixed we can exclude this from google3. + * + *

TODO: Remove at breaking change since b/29368482 was fixed in 2020 */ protected interface BuilderParent extends AbstractMessage.BuilderParent {} /** TODO: remove this together with GeneratedMessage.BuilderParent. */ protected abstract Message.Builder newBuilderForType(BuilderParent parent); + /** TODO: generated class should implement this directly */ @Override protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) { return newBuilderForType( @@ -336,9 +543,10 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial }); } + /** Builder class for {@link GeneratedMessage}. */ @SuppressWarnings("unchecked") - public abstract static class Builder> - extends AbstractMessage.Builder { + public abstract static class Builder> + extends AbstractMessage.Builder { private BuilderParent builderParent; @@ -348,7 +556,18 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener. private boolean isClean; - private UnknownFieldSet unknownFields = UnknownFieldSet.getDefaultInstance(); + /** + * This field holds either an {@link UnknownFieldSet} or {@link UnknownFieldSet.Builder}. + * + *

We use an object because it should only be one or the other of those things at a time and + * Object is the only common base. This also saves space. + * + *

Conversions are lazy: if {@link #setUnknownFields} is called, this will contain {@link + * UnknownFieldSet}. If unknown fields are merged into this builder, the current {@link + * UnknownFieldSet} will be converted to a {@link UnknownFieldSet.Builder} and left that way + * until either {@link #setUnknownFields} or {@link #buildPartial} or {@link #build} is called. + */ + private Object unknownFieldsOrBuilder = UnknownFieldSet.getDefaultInstance(); protected Builder() { this(null); @@ -389,8 +608,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public BuilderType clone() { - BuilderType builder = (BuilderType) getDefaultInstanceForType().newBuilderForType(); + public BuilderT clone() { + BuilderT builder = (BuilderT) getDefaultInstanceForType().newBuilderForType(); builder.mergeFrom(buildPartial()); return builder; } @@ -400,10 +619,10 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * builtin fields back to the initial values. */ @Override - public BuilderType clear() { - unknownFields = UnknownFieldSet.getDefaultInstance(); + public BuilderT clear() { + unknownFieldsOrBuilder = UnknownFieldSet.getDefaultInstance(); onChanged(); - return (BuilderType) this; + return (BuilderT) this; } /** @@ -424,7 +643,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial /** Internal helper which returns a mutable map. */ private Map getAllFieldsMutable() { - final TreeMap result = new TreeMap(); + final TreeMap result = new TreeMap<>(); final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; final List fields = descriptor.getFields(); @@ -500,28 +719,28 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial 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); + return Collections.unmodifiableList((List) object); } else { return object; } } @Override - public BuilderType setField(final FieldDescriptor field, final Object value) { + public BuilderT setField(final FieldDescriptor field, final Object value) { internalGetFieldAccessorTable().getField(field).set(this, value); - return (BuilderType) this; + return (BuilderT) this; } @Override - public BuilderType clearField(final FieldDescriptor field) { + public BuilderT clearField(final FieldDescriptor field) { internalGetFieldAccessorTable().getField(field).clear(this); - return (BuilderType) this; + return (BuilderT) this; } @Override - public BuilderType clearOneof(final OneofDescriptor oneof) { + public BuilderT clearOneof(final OneofDescriptor oneof) { internalGetFieldAccessorTable().getOneof(oneof).clear(this); - return (BuilderType) this; + return (BuilderT) this; } @Override @@ -535,31 +754,51 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public BuilderType setRepeatedField( + public BuilderT setRepeatedField( final FieldDescriptor field, final int index, final Object value) { internalGetFieldAccessorTable().getField(field).setRepeated(this, index, value); - return (BuilderType) this; + return (BuilderT) this; } @Override - public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) { + public BuilderT addRepeatedField(final FieldDescriptor field, final Object value) { internalGetFieldAccessorTable().getField(field).addRepeated(this, value); - return (BuilderType) this; + return (BuilderT) this; } - @Override - public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) { - this.unknownFields = unknownFields; + private BuilderT setUnknownFieldsInternal(final UnknownFieldSet unknownFields) { + unknownFieldsOrBuilder = unknownFields; onChanged(); - return (BuilderType) this; + return (BuilderT) this; + } + + @Override + public BuilderT setUnknownFields(final UnknownFieldSet unknownFields) { + return setUnknownFieldsInternal(unknownFields); + } + + /** + * This method is obsolete, but we must retain it for compatibility with older generated code. + */ + protected BuilderT setUnknownFieldsProto3(final UnknownFieldSet unknownFields) { + return setUnknownFieldsInternal(unknownFields); } @Override - public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) { - this.unknownFields = - UnknownFieldSet.newBuilder(this.unknownFields).mergeFrom(unknownFields).build(); + public BuilderT mergeUnknownFields(final UnknownFieldSet unknownFields) { + if (UnknownFieldSet.getDefaultInstance().equals(unknownFields)) { + return (BuilderT) this; + } + + if (UnknownFieldSet.getDefaultInstance().equals(unknownFieldsOrBuilder)) { + unknownFieldsOrBuilder = unknownFields; + onChanged(); + return (BuilderT) this; + } + + getUnknownFieldSetBuilder().mergeFrom(unknownFields); onChanged(); - return (BuilderType) this; + return (BuilderT) this; } @Override @@ -593,21 +832,50 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial @Override public final UnknownFieldSet getUnknownFields() { - return unknownFields; + if (unknownFieldsOrBuilder instanceof UnknownFieldSet) { + return (UnknownFieldSet) unknownFieldsOrBuilder; + } else { + return ((UnknownFieldSet.Builder) unknownFieldsOrBuilder).buildPartial(); + } } /** - * Called by subclasses to parse an unknown field. + * Called by generated 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) + CodedInputStream input, ExtensionRegistryLite extensionRegistry, int tag) throws IOException { - return unknownFields.mergeFieldFrom(tag, input); + if (input.shouldDiscardUnknownFields()) { + return input.skipField(tag); + } + return getUnknownFieldSetBuilder().mergeFieldFrom(tag, input); + } + + /** Called by generated subclasses to add to the unknown field set. */ + protected final void mergeUnknownLengthDelimitedField(int number, ByteString bytes) { + getUnknownFieldSetBuilder().mergeLengthDelimitedField(number, bytes); + } + + /** Called by generated subclasses to add to the unknown field set. */ + protected final void mergeUnknownVarintField(int number, int value) { + getUnknownFieldSetBuilder().mergeVarintField(number, value); + } + + @Override + protected UnknownFieldSet.Builder getUnknownFieldSetBuilder() { + if (unknownFieldsOrBuilder instanceof UnknownFieldSet) { + unknownFieldsOrBuilder = ((UnknownFieldSet) unknownFieldsOrBuilder).toBuilder(); + } + onChanged(); + return (UnknownFieldSet.Builder) unknownFieldsOrBuilder; + } + + @Override + protected void setUnknownFieldSetBuilder(UnknownFieldSet.Builder builder) { + unknownFieldsOrBuilder = builder; + onChanged(); } /** @@ -635,7 +903,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } /** - * Called when a the builder or one of its nested children has changed and any parent should be + * Called when a builder or one of its nested children has changed and any parent should be * notified of its invalidation. */ protected final void onChanged() { @@ -657,58 +925,107 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * map field directly and thus enables us to access the map field as a list. */ @SuppressWarnings({"unused", "rawtypes"}) + protected MapFieldReflectionAccessor internalGetMapFieldReflection(int fieldNumber) { + return internalGetMapField(fieldNumber); + } + + /** TODO: Remove, exists for compatibility with generated code. */ + @Deprecated + @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()); + throw new IllegalArgumentException("No map fields found in " + getClass().getName()); } - /** Like {@link #internalGetMapField} but return a mutable version. */ + /** Like {@link #internalGetMapFieldReflection} but return a mutable version. */ + @SuppressWarnings({"unused", "rawtypes"}) + protected MapFieldReflectionAccessor internalGetMutableMapFieldReflection(int fieldNumber) { + return internalGetMutableMapField(fieldNumber); + } + + /** TODO: Remove, exists for compatibility with generated code. */ + @Deprecated @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()); + throw new IllegalArgumentException("No map fields found in " + getClass().getName()); } } // ================================================================= // Extensions-related stuff - public interface ExtendableMessageOrBuilder + /** Extends {@link MessageOrBuilder} with extension-related functions. */ + public interface ExtendableMessageOrBuilder> extends MessageOrBuilder { // Re-define for return type covariance. @Override Message getDefaultInstanceForType(); /** Check if a singular extension is present. */ - boolean hasExtension(ExtensionLite extension); + boolean hasExtension(ExtensionLite extension); /** Get the number of elements in a repeated extension. */ - int getExtensionCount(ExtensionLite> extension); + int getExtensionCount(ExtensionLite> extension); /** Get the value of an extension. */ - Type getExtension(ExtensionLite extension); + T getExtension(ExtensionLite extension); /** Get one element of a repeated extension. */ - Type getExtension(ExtensionLite> extension, int index); + T getExtension(ExtensionLite> extension, int index); - /** Check if a singular extension is present. */ - boolean hasExtension(Extension extension); - /** Check if a singular extension is present. */ - boolean hasExtension(GeneratedExtension extension); - /** Get the number of elements in a repeated extension. */ - int getExtensionCount(Extension> extension); - /** Get the number of elements in a repeated extension. */ - int getExtensionCount(GeneratedExtension> extension); - /** Get the value of an extension. */ - Type getExtension(Extension extension); - /** Get the value of an extension. */ - Type getExtension(GeneratedExtension extension); - /** Get one element of a repeated extension. */ - Type getExtension(Extension> extension, int index); - /** Get one element of a repeated extension. */ - Type getExtension(GeneratedExtension> extension, int index); + /** + * Check if a singular extension is present. + *

TODO: handled by ExtensionLite version + */ + boolean hasExtension( + Extension extension); + /** + * Check if a singular extension is present. + *

TODO: handled by ExtensionLite version + */ + boolean hasExtension( + GeneratedExtension extension); + /** + * Get the number of elements in a repeated extension. + *

TODO: handled by ExtensionLite version + */ + int getExtensionCount( + Extension> extension); + /** + * Get the number of elements in a repeated extension. + *

TODO: handled by ExtensionLite version + */ + int getExtensionCount( + GeneratedExtension> extension); + /** + * Get the value of an extension. + *

TODO: handled by ExtensionLite version + */ + T getExtension( + Extension extension); + /** + * Get the value of an extension. + *

TODO: handled by ExtensionLite version + */ + T getExtension( + GeneratedExtension extension); + /** + * Get one element of a repeated extension. + *

TODO: handled by ExtensionLite version + */ + T getExtension( + Extension> extension, + int index); + /** + * Get one element of a repeated extension. + *

TODO: handled by ExtensionLite version + */ + T getExtension( + GeneratedExtension> extension, + int index); } /** @@ -743,8 +1060,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * *

See also {@link ExtendableBuilder}. */ - public abstract static class ExtendableMessage - extends GeneratedMessage implements ExtendableMessageOrBuilder { + public abstract static class ExtendableMessage> + extends GeneratedMessage implements ExtendableMessageOrBuilder { private static final long serialVersionUID = 1L; @@ -754,12 +1071,12 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial this.extensions = FieldSet.newFieldSet(); } - protected ExtendableMessage(ExtendableBuilder builder) { + protected ExtendableMessage(ExtendableBuilder builder) { super(builder); this.extensions = builder.buildExtensions(); } - private void verifyExtensionContainingType(final Extension extension) { + private void verifyExtensionContainingType(final Extension extension) { if (extension.getDescriptor().getContainingType() != getDescriptorForType()) { // This can only happen if someone uses unchecked operations. throw new IllegalArgumentException( @@ -773,9 +1090,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial /** Check if a singular extension is present. */ @Override - @SuppressWarnings("unchecked") - public final boolean hasExtension(final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); + public final boolean hasExtension(final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); return extensions.hasField(extension.getDescriptor()); @@ -783,10 +1099,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial /** Get the number of elements in a repeated extension. */ @Override - @SuppressWarnings("unchecked") - public final int getExtensionCount( - final ExtensionLite> extensionLite) { - Extension> extension = checkNotLite(extensionLite); + public final int getExtensionCount(final ExtensionLite> extensionLite) { + Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); final FieldDescriptor descriptor = extension.getDescriptor(); @@ -796,81 +1110,107 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial /** Get the value of an extension. */ @Override @SuppressWarnings("unchecked") - public final Type getExtension(final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); + public final T getExtension(final ExtensionLite extensionLite) { + Extension 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(); + return (T) Collections.emptyList(); } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - return (Type) extension.getMessageDefaultInstance(); + return (T) extension.getMessageDefaultInstance(); } else { - return (Type) extension.fromReflectionType(descriptor.getDefaultValue()); + return (T) extension.fromReflectionType(descriptor.getDefaultValue()); } } else { - return (Type) extension.fromReflectionType(value); + return (T) extension.fromReflectionType(value); } } /** Get one element of a repeated extension. */ @Override @SuppressWarnings("unchecked") - public final Type getExtension( - final ExtensionLite> extensionLite, final int index) { - Extension> extension = checkNotLite(extensionLite); + public final T getExtension( + final ExtensionLite> extensionLite, final int index) { + Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); - return (Type) + return (T) extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index)); } - /** Check if a singular extension is present. */ + /** + * Check if a singular extension is present. + *

TODO: handled by ExtensionLite version + */ @Override - public final boolean hasExtension(final Extension extension) { - return hasExtension((ExtensionLite) extension); + public final boolean hasExtension(final Extension extension) { + return hasExtension((ExtensionLite) extension); } - /** Check if a singular extension is present. */ + /** + * Check if a singular extension is present. + *

TODO: handled by ExtensionLite version + */ @Override - public final boolean hasExtension( - final GeneratedExtension extension) { - return hasExtension((ExtensionLite) extension); + public final boolean hasExtension( + final GeneratedExtension extension) { + return hasExtension((ExtensionLite) extension); } - /** Get the number of elements in a repeated extension. */ + /** + * Get the number of elements in a repeated extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final int getExtensionCount(final Extension> extension) { - return getExtensionCount((ExtensionLite>) extension); + public final int getExtensionCount( + final Extension> extension) { + return getExtensionCount((ExtensionLite>) extension); } - /** Get the number of elements in a repeated extension. */ + /** + * Get the number of elements in a repeated extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final int getExtensionCount( - final GeneratedExtension> extension) { - return getExtensionCount((ExtensionLite>) extension); + public final int getExtensionCount( + final GeneratedExtension> extension) { + return getExtensionCount((ExtensionLite>) extension); } - /** Get the value of an extension. */ + /** + * Get the value of an extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final Type getExtension(final Extension extension) { - return getExtension((ExtensionLite) extension); + public final T getExtension(final Extension extension) { + return getExtension((ExtensionLite) extension); } - /** Get the value of an extension. */ + /** + * Get the value of an extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final Type getExtension(final GeneratedExtension extension) { - return getExtension((ExtensionLite) extension); + public final T getExtension( + final GeneratedExtension extension) { + return getExtension((ExtensionLite) extension); } - /** Get one element of a repeated extension. */ + /** + * Get one element of a repeated extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final Type getExtension( - final Extension> extension, final int index) { - return getExtension((ExtensionLite>) extension, index); + public final T getExtension( + final Extension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); } - /** Get one element of a repeated extension. */ + /** + * Get one element of a repeated extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final Type getExtension( - final GeneratedExtension> extension, final int index) { - return getExtension((ExtensionLite>) extension, index); + public final T getExtension( + final GeneratedExtension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); } /** Called by subclasses to check if all extensions are initialized. */ @@ -878,11 +1218,13 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return extensions.isInitialized(); } + // TODO: compute this in the builder at {@code build()} time. @Override public boolean isInitialized() { return super.isInitialized() && extensionsAreInitialized(); } + // TODO: remove mutating method from immutable type @Override protected boolean parseUnknownField( CodedInputStream input, @@ -892,14 +1234,34 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial throws IOException { return MessageReflection.mergeFieldFrom( input, - unknownFields, + input.shouldDiscardUnknownFields() ? null : unknownFields, extensionRegistry, getDescriptorForType(), new MessageReflection.ExtensionAdapter(extensions), tag); } - /** Used by parsing constructors in generated classes. */ + /** + * Delegates to parseUnknownField. This method is obsolete, but we must retain it for + * compatibility with older generated code. + * + *

TODO: remove mutating method from immutable type + */ + @Override + protected boolean parseUnknownFieldProto3( + CodedInputStream input, + UnknownFieldSet.Builder unknownFields, + ExtensionRegistryLite extensionRegistry, + int tag) + throws IOException { + return parseUnknownField(input, unknownFields, extensionRegistry, tag); + } + + /** + * Used by parsing constructors in generated classes. + * + *

TODO: remove unused method (extensions should be immutable after build) + */ @Override protected void makeExtensionsImmutable() { extensions.makeImmutable(); @@ -984,7 +1346,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial @Override public Map getAllFields() { final Map result = - super.getAllFieldsMutable(/* getBytesForString = */ false); + super.getAllFieldsMutable(/* getBytesForString= */ false); result.putAll(getExtensionFields()); return Collections.unmodifiableMap(result); } @@ -992,7 +1354,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial @Override public Map getAllFieldsRaw() { final Map result = - super.getAllFieldsMutable(/* getBytesForString = */ false); + super.getAllFieldsMutable(/* getBytesForString= */ false); result.putAll(getExtensionFields()); return Collections.unmodifiableMap(result); } @@ -1093,11 +1455,11 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial */ @SuppressWarnings("unchecked") public abstract static class ExtendableBuilder< - MessageType extends ExtendableMessage, - BuilderType extends ExtendableBuilder> - extends Builder implements ExtendableMessageOrBuilder { + MessageT extends ExtendableMessage, + BuilderT extends ExtendableBuilder> + extends Builder implements ExtendableMessageOrBuilder { - private FieldSet extensions = FieldSet.emptySet(); + private FieldSet.Builder extensions; protected ExtendableBuilder() {} @@ -1107,30 +1469,22 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial // For immutable message conversion. void internalSetExtensionSet(FieldSet extensions) { - this.extensions = extensions; + this.extensions = FieldSet.Builder.fromFieldSet(extensions); } @Override - public BuilderType clear() { - extensions = FieldSet.emptySet(); + public BuilderT clear() { + extensions = null; 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(); + if (extensions == null) { + extensions = FieldSet.newBuilder(); } } - private void verifyExtensionContainingType(final Extension extension) { + private void verifyExtensionContainingType(final Extension extension) { if (extension.getDescriptor().getContainingType() != getDescriptorForType()) { // This can only happen if someone uses unchecked operations. throw new IllegalArgumentException( @@ -1144,206 +1498,257 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial /** Check if a singular extension is present. */ @Override - public final boolean hasExtension(final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); + public final boolean hasExtension(final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); - return extensions.hasField(extension.getDescriptor()); + return extensions != null && extensions.hasField(extension.getDescriptor()); } /** Get the number of elements in a repeated extension. */ @Override - public final int getExtensionCount( - final ExtensionLite> extensionLite) { - Extension> extension = checkNotLite(extensionLite); + public final int getExtensionCount(final ExtensionLite> extensionLite) { + Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); final FieldDescriptor descriptor = extension.getDescriptor(); - return extensions.getRepeatedFieldCount(descriptor); + return extensions == null ? 0 : extensions.getRepeatedFieldCount(descriptor); } /** Get the value of an extension. */ @Override - public final Type getExtension(final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); + public final T getExtension(final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); - final Object value = extensions.getField(descriptor); + final Object value = extensions == null ? null : extensions.getField(descriptor); if (value == null) { if (descriptor.isRepeated()) { - return (Type) Collections.emptyList(); + return (T) Collections.emptyList(); } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - return (Type) extension.getMessageDefaultInstance(); + return (T) extension.getMessageDefaultInstance(); } else { - return (Type) extension.fromReflectionType(descriptor.getDefaultValue()); + return (T) extension.fromReflectionType(descriptor.getDefaultValue()); } } else { - return (Type) extension.fromReflectionType(value); + return (T) extension.fromReflectionType(value); } } /** Get one element of a repeated extension. */ @Override - public final Type getExtension( - final ExtensionLite> extensionLite, final int index) { - Extension> extension = checkNotLite(extensionLite); + public final T getExtension( + final ExtensionLite> extensionLite, final int index) { + Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); FieldDescriptor descriptor = extension.getDescriptor(); - return (Type) + if (extensions == null) { + throw new IndexOutOfBoundsException(); + } + return (T) extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index)); } /** Set the value of an extension. */ - public final BuilderType setExtension( - final ExtensionLite extensionLite, final Type value) { - Extension extension = checkNotLite(extensionLite); + public final BuilderT setExtension( + final ExtensionLite extensionLite, final T value) { + Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); final FieldDescriptor descriptor = extension.getDescriptor(); extensions.setField(descriptor, extension.toReflectionType(value)); onChanged(); - return (BuilderType) this; + return (BuilderT) this; } /** Set the value of one element of a repeated extension. */ - public final BuilderType setExtension( - final ExtensionLite> extensionLite, - final int index, - final Type value) { - Extension> extension = checkNotLite(extensionLite); + public final BuilderT setExtension( + final ExtensionLite> extensionLite, final int index, final T value) { + Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); final FieldDescriptor descriptor = extension.getDescriptor(); extensions.setRepeatedField(descriptor, index, extension.singularToReflectionType(value)); onChanged(); - return (BuilderType) this; + return (BuilderT) this; } /** Append a value to a repeated extension. */ - public final BuilderType addExtension( - final ExtensionLite> extensionLite, final Type value) { - Extension> extension = checkNotLite(extensionLite); + public final BuilderT addExtension( + final ExtensionLite> extensionLite, final T value) { + Extension> extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); final FieldDescriptor descriptor = extension.getDescriptor(); extensions.addRepeatedField(descriptor, extension.singularToReflectionType(value)); onChanged(); - return (BuilderType) this; + return (BuilderT) this; } /** Clear an extension. */ - public final BuilderType clearExtension( - final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); + public final BuilderT clearExtension(final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); verifyExtensionContainingType(extension); ensureExtensionsIsMutable(); extensions.clearField(extension.getDescriptor()); onChanged(); - return (BuilderType) this; + return (BuilderT) this; } - /** Check if a singular extension is present. */ + /** + * Check if a singular extension is present. + *

TODO: handled by ExtensionLite version + */ @Override - public final boolean hasExtension(final Extension extension) { - return hasExtension((ExtensionLite) extension); + public final boolean hasExtension(final Extension extension) { + return hasExtension((ExtensionLite) extension); } - /** Check if a singular extension is present. */ + /** + * Check if a singular extension is present. + *

TODO: handled by ExtensionLite version + */ @Override - public final boolean hasExtension( - final GeneratedExtension extension) { - return hasExtension((ExtensionLite) extension); + public final boolean hasExtension( + final GeneratedExtension extension) { + return hasExtension((ExtensionLite) extension); } - /** Get the number of elements in a repeated extension. */ + /** + * Get the number of elements in a repeated extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final int getExtensionCount(final Extension> extension) { - return getExtensionCount((ExtensionLite>) extension); + public final int getExtensionCount( + final Extension> extension) { + return getExtensionCount((ExtensionLite>) extension); } - /** Get the number of elements in a repeated extension. */ + /** + * Get the number of elements in a repeated extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final int getExtensionCount( - final GeneratedExtension> extension) { - return getExtensionCount((ExtensionLite>) extension); + public final int getExtensionCount( + final GeneratedExtension> extension) { + return getExtensionCount((ExtensionLite>) extension); } - /** Get the value of an extension. */ + /** + * Get the value of an extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final Type getExtension(final Extension extension) { - return getExtension((ExtensionLite) extension); + public final T getExtension(final Extension extension) { + return getExtension((ExtensionLite) extension); } - /** Get the value of an extension. */ + /** Get the value of an extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final Type getExtension(final GeneratedExtension extension) { - return getExtension((ExtensionLite) extension); + public final T getExtension( + final GeneratedExtension extension) { + return getExtension((ExtensionLite) extension); } - /** Get the value of an extension. */ + /** + * Get the value of an extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final Type getExtension( - final Extension> extension, final int index) { - return getExtension((ExtensionLite>) extension, index); + public final T getExtension( + final Extension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); } - /** Get the value of an extension. */ + /** + * Get the value of an extension. + *

TODO: handled by ExtensionLite version + */ @Override - public final Type getExtension( - final GeneratedExtension> extension, final int index) { - return getExtension((ExtensionLite>) extension, index); + public final T getExtension( + final GeneratedExtension> extension, final int index) { + return getExtension((ExtensionLite>) extension, index); } - /** Set the value of an extension. */ - public final BuilderType setExtension( - final Extension extension, final Type value) { - return setExtension((ExtensionLite) extension, value); + /** + * Set the value of an extension. + *

TODO: handled by ExtensionLite version + */ + public final BuilderT setExtension( + final Extension extension, final T value) { + return setExtension((ExtensionLite) extension, value); } - /** Set the value of an extension. */ - public BuilderType setExtension( - final GeneratedExtension extension, final Type value) { - return setExtension((ExtensionLite) extension, value); + /** + * Set the value of an extension. + *

TODO: handled by ExtensionLite version + */ + public BuilderT setExtension( + final GeneratedExtension extension, final T value) { + return setExtension((ExtensionLite) extension, value); } - /** Set the value of one element of a repeated extension. */ - public final BuilderType setExtension( - final Extension> extension, final int index, final Type value) { - return setExtension((ExtensionLite>) extension, index, value); + /** + * Set the value of one element of a repeated extension. + *

TODO: handled by ExtensionLite version + */ + public final BuilderT setExtension( + final Extension> extension, + final int index, final T value) { + return setExtension((ExtensionLite>) extension, index, value); } - /** Set the value of one element of a repeated extension. */ - public BuilderType setExtension( - final GeneratedExtension> extension, - final int index, - final Type value) { - return setExtension((ExtensionLite>) extension, index, value); + /** + * Set the value of one element of a repeated extension. + *

TODO: handled by ExtensionLite version + */ + public BuilderT setExtension( + final GeneratedExtension> extension, + final int index, final T value) { + return setExtension((ExtensionLite>) extension, index, value); } - /** Append a value to a repeated extension. */ - public final BuilderType addExtension( - final Extension> extension, final Type value) { - return addExtension((ExtensionLite>) extension, value); + /** + * Append a value to a repeated extension. + *

TODO: handled by ExtensionLite version + */ + public final BuilderT addExtension( + final Extension> extension, final T value) { + return addExtension((ExtensionLite>) extension, value); } - /** Append a value to a repeated extension. */ - public BuilderType addExtension( - final GeneratedExtension> extension, final Type value) { - return addExtension((ExtensionLite>) extension, value); + /** + * Append a value to a repeated extension. + *

TODO: handled by ExtensionLite version + */ + public BuilderT addExtension( + final GeneratedExtension> extension, final T value) { + return addExtension((ExtensionLite>) extension, value); } - /** Clear an extension. */ - public final BuilderType clearExtension(final Extension extension) { - return clearExtension((ExtensionLite) extension); + /** + * Clear an extension. + *

TODO: handled by ExtensionLite version + */ + public final BuilderT clearExtension( + final Extension extension) { + return clearExtension((ExtensionLite) extension); } - /** Clear an extension. */ - public BuilderType clearExtension(final GeneratedExtension extension) { - return clearExtension((ExtensionLite) extension); + /** + * Clears an extension. + *

TODO: handled by ExtensionLite version + */ + public BuilderT clearExtension( + final GeneratedExtension extension) { + return clearExtension((ExtensionLite) extension); } /** Called by subclasses to check if all extensions are initialized. */ protected boolean extensionsAreInitialized() { - return extensions.isInitialized(); + return extensions == null || extensions.isInitialized(); } /** * Called by the build code path to create a copy of the extensions for building the message. */ private FieldSet buildExtensions() { - extensions.makeImmutable(); - return extensions; + return extensions == null + ? (FieldSet) FieldSet.emptySet() + : extensions.buildPartial(); } @Override @@ -1351,55 +1756,69 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial 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 getAllFields() { final Map result = super.getAllFieldsMutable(); - result.putAll(extensions.getAllFields()); + if (extensions != null) { + result.putAll(extensions.getAllFields()); + } return Collections.unmodifiableMap(result); } @Override - public Object getField(final FieldDescriptor field) { + public Object getField(final FieldDescriptor field) { + if (field.isExtension()) { + verifyContainingType(field); + final Object value = extensions == null ? null : 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 Message.Builder getFieldBuilder(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); - final Object value = extensions.getField(field); + if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { + throw new UnsupportedOperationException( + "getFieldBuilder() called on a non-Message type."); + } + ensureExtensionsIsMutable(); + final Object value = extensions.getFieldAllowBuilders(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()); + Message.Builder builder = DynamicMessage.newBuilder(field.getMessageType()); + extensions.setField(field, builder); + onChanged(); + return builder; + } else { + if (value instanceof Message.Builder) { + return (Message.Builder) value; + } else if (value instanceof Message) { + Message.Builder builder = ((Message) value).toBuilder(); + extensions.setField(field, builder); + onChanged(); + return builder; } else { - return field.getDefaultValue(); + throw new UnsupportedOperationException( + "getRepeatedFieldBuilder() called on a non-Message type."); } - } else { - return value; } } else { - return super.getField(field); + return super.getFieldBuilder(field); } } @@ -1407,7 +1826,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial public int getRepeatedFieldCount(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); - return extensions.getRepeatedFieldCount(field); + return extensions == null ? 0 : extensions.getRepeatedFieldCount(field); } else { return super.getRepeatedFieldCount(field); } @@ -1417,79 +1836,133 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial public Object getRepeatedField(final FieldDescriptor field, final int index) { if (field.isExtension()) { verifyContainingType(field); + if (extensions == null) { + throw new IndexOutOfBoundsException(); + } return extensions.getRepeatedField(field, index); } else { return super.getRepeatedField(field, index); } } + @Override + public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, final int index) { + if (field.isExtension()) { + verifyContainingType(field); + ensureExtensionsIsMutable(); + if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { + throw new UnsupportedOperationException( + "getRepeatedFieldBuilder() called on a non-Message type."); + } + final Object value = extensions.getRepeatedFieldAllowBuilders(field, index); + if (value instanceof Message.Builder) { + return (Message.Builder) value; + } else if (value instanceof Message) { + Message.Builder builder = ((Message) value).toBuilder(); + extensions.setRepeatedField(field, index, builder); + onChanged(); + return builder; + } else { + throw new UnsupportedOperationException( + "getRepeatedFieldBuilder() called on a non-Message type."); + } + } else { + return super.getRepeatedFieldBuilder(field, index); + } + } + @Override public boolean hasField(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); - return extensions.hasField(field); + return extensions != null && extensions.hasField(field); } else { return super.hasField(field); } } @Override - public BuilderType setField(final FieldDescriptor field, final Object value) { + public BuilderT setField(final FieldDescriptor field, final Object value) { if (field.isExtension()) { verifyContainingType(field); ensureExtensionsIsMutable(); extensions.setField(field, value); onChanged(); - return (BuilderType) this; + return (BuilderT) this; } else { return super.setField(field, value); } } @Override - public BuilderType clearField(final FieldDescriptor field) { + public BuilderT clearField(final FieldDescriptor field) { if (field.isExtension()) { verifyContainingType(field); ensureExtensionsIsMutable(); extensions.clearField(field); onChanged(); - return (BuilderType) this; + return (BuilderT) this; } else { return super.clearField(field); } } @Override - public BuilderType setRepeatedField( + public BuilderT 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; + return (BuilderT) this; } else { return super.setRepeatedField(field, index, value); } } @Override - public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) { + public BuilderT addRepeatedField(final FieldDescriptor field, final Object value) { if (field.isExtension()) { verifyContainingType(field); ensureExtensionsIsMutable(); extensions.addRepeatedField(field, value); onChanged(); - return (BuilderType) this; + return (BuilderT) this; } else { return super.addRepeatedField(field, value); } } - protected final void mergeExtensionFields(final ExtendableMessage other) { + @Override + public Message.Builder newBuilderForField(final FieldDescriptor field) { + if (field.isExtension()) { + return DynamicMessage.newBuilder(field.getMessageType()); + } else { + return super.newBuilderForField(field); + } + } + + protected final void mergeExtensionFields(final ExtendableMessage other) { + if (other.extensions != null) { + ensureExtensionsIsMutable(); + extensions.mergeFrom(other.extensions); + onChanged(); + } + } + + @Override + protected boolean parseUnknownField( + CodedInputStream input, ExtensionRegistryLite extensionRegistry, int tag) + throws IOException { ensureExtensionsIsMutable(); - extensions.mergeFrom(other.extensions); - onChanged(); + return MessageReflection.mergeFieldFrom( + input, + input.shouldDiscardUnknownFields() ? null : getUnknownFieldSetBuilder(), + extensionRegistry, + getDescriptorForType(), + new MessageReflection.ExtensionBuilderAdapter(extensions), + tag); } private void verifyContainingType(final FieldDescriptor field) { @@ -1505,21 +1978,21 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * 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 { + interface ExtensionDescriptorRetriever { FieldDescriptor getDescriptor(); } /** For use by generated code only. */ - public static - GeneratedExtension newMessageScopedGeneratedExtension( + public static + GeneratedExtension newMessageScopedGeneratedExtension( final Message scope, final int descriptorIndex, - final Class singularType, + 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( + return new GeneratedExtension<>( new CachedDescriptorRetriever() { @Override public FieldDescriptor loadDescriptor() { @@ -1532,13 +2005,13 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } /** For use by generated code only. */ - public static - GeneratedExtension newFileScopedGeneratedExtension( - final Class singularType, final Message defaultInstance) { + public static + GeneratedExtension 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( + return new GeneratedExtension<>( null, // ExtensionDescriptorRetriever is initialized in internalInit(); singularType, defaultInstance, @@ -1553,9 +2026,10 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial @Override public FieldDescriptor getDescriptor() { if (descriptor == null) { + FieldDescriptor tmpDescriptor = loadDescriptor(); synchronized (this) { if (descriptor == null) { - descriptor = loadDescriptor(); + descriptor = tmpDescriptor; } } } @@ -1563,72 +2037,6 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } - /** - * 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 - GeneratedExtension 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( - new CachedDescriptorRetriever() { - @Override - 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 - GeneratedExtension 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( - new CachedDescriptorRetriever() { - @Override - protected FieldDescriptor loadDescriptor() { - try { - Class clazz = singularType.getClassLoader().loadClass(descriptorOuterClass); - FileDescriptor file = (FileDescriptor) clazz.getMethod("getDescriptor").invoke(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. @@ -1653,10 +2061,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * singletons as parameters to the extension accessors defined in {@link ExtendableMessage} and * {@link ExtendableBuilder}. */ - public static class GeneratedExtension - extends Extension { - // TODO: Find ways to avoid using Java reflection within this - // class. Also try to avoid suppressing unchecked warnings. + public static class GeneratedExtension + extends Extension { // We can't always initialize the descriptor of a GeneratedExtension when // we first construct it due to initialization order difficulties (namely, @@ -1672,7 +2078,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial // initializer to call internalInit() after the descriptor has been parsed. GeneratedExtension( ExtensionDescriptorRetriever descriptorRetriever, - Class singularType, + Class singularType, Message messageDefaultInstance, ExtensionType extensionType) { if (Message.class.isAssignableFrom(singularType) @@ -1709,7 +2115,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } private ExtensionDescriptorRetriever descriptorRetriever; - private final Class singularType; + private final Class singularType; private final Message messageDefaultInstance; private final Method enumValueOf; private final Method enumGetValueDescriptor; @@ -1743,15 +2149,14 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * 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) { + final List result = new ArrayList<>(); + for (final Object element : (List) value) { result.add(singularFromReflectionType(element)); } return result; @@ -1778,7 +2183,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return messageDefaultInstance.newBuilderForType().mergeFrom((Message) value).build(); } case ENUM: - return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value); + return invokeOrDie(enumValueOf, null, value); default: return value; } @@ -1790,14 +2195,13 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * 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) { + final List result = new ArrayList<>(); + for (final Object element : (List) value) { result.add(singularToReflectionType(element)); } return result; @@ -1841,40 +2245,40 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial @Override @SuppressWarnings("unchecked") - public Type getDefaultValue() { + public T getDefaultValue() { if (isRepeated()) { - return (Type) Collections.emptyList(); + return (T) Collections.emptyList(); } if (getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - return (Type) messageDefaultInstance; + return (T) messageDefaultInstance; } - return (Type) singularFromReflectionType(getDescriptor().getDefaultValue()); + return (T) 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) { + final Class clazz, final String name, final Class... params) { try { return clazz.getMethod(name, params); } catch (NoSuchMethodException e) { - throw new RuntimeException( + throw new IllegalStateException( "Generated message class \"" + clazz.getName() + "\" missing method \"" + name + "\".", e); } } /** Calls invoke and throws a RuntimeException if it fails. */ + @CanIgnoreReturnValue 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); + throw new IllegalStateException( + "Couldn't use Java reflection to implement protocol message reflection.", e); } catch (InvocationTargetException e) { final Throwable cause = e.getCause(); if (cause instanceof RuntimeException) { @@ -1882,7 +2286,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } else if (cause instanceof Error) { throw (Error) cause; } else { - throw new RuntimeException( + throw new IllegalStateException( "Unexpected exception thrown by generated accessor method.", cause); } } @@ -1897,11 +2301,18 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * 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") + protected MapFieldReflectionAccessor internalGetMapFieldReflection(int fieldNumber) { + return internalGetMapField(fieldNumber); + } + + /** TODO: Remove, exists for compatibility with generated code. */ + @Deprecated @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()); + throw new IllegalArgumentException("No map fields found in " + getClass().getName()); } /** @@ -1924,7 +2335,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial final Descriptor descriptor, final String[] camelCaseNames, final Class messageClass, - final Class builderClass) { + final Class> builderClass) { this(descriptor, camelCaseNames); ensureFieldAccessorsInitialized(messageClass, builderClass); } @@ -1941,11 +2352,6 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial initialized = false; } - private boolean isMapFieldEnabled(FieldDescriptor field) { - boolean result = true; - return result; - } - /** * Ensures the field accessors are initialized. This method is thread-safe. * @@ -1954,7 +2360,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial * @return this */ public FieldAccessorTable ensureFieldAccessorsInitialized( - Class messageClass, Class builderClass) { + Class messageClass, Class> builderClass) { if (initialized) { return this; } @@ -1967,14 +2373,15 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial FieldDescriptor field = descriptor.getFields().get(i); String containingOneofCamelCaseName = null; if (field.getContainingOneof() != null) { - containingOneofCamelCaseName = - camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()]; + int index = fieldsSize + field.getContainingOneof().getIndex(); + if (index < camelCaseNames.length) { + containingOneofCamelCaseName = camelCaseNames[index]; + } } if (field.isRepeated()) { if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - if (field.isMapField() && isMapFieldEnabled(field)) { - fields[i] = - new MapFieldAccessor(field, camelCaseNames[i], messageClass, builderClass); + if (field.isMapField()) { + fields[i] = new MapFieldAccessor(field, messageClass); } else { fields[i] = new RepeatedMessageFieldAccessor( @@ -2025,12 +2432,16 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } - int oneofsSize = oneofs.length; - for (int i = 0; i < oneofsSize; i++) { - oneofs[i] = - new OneofAccessor( - descriptor, camelCaseNames[i + fieldsSize], messageClass, builderClass); + for (int i = 0; i < descriptor.getOneofs().size(); i++) { + if (i < descriptor.getRealOneofs().size()) { + oneofs[i] = + new RealOneofAccessor( + descriptor, i, camelCaseNames[i + fieldsSize], messageClass, builderClass); + } else { + oneofs[i] = new SyntheticOneofAccessor(descriptor, i); + } } + initialized = true; camelCaseNames = null; return this; @@ -2070,50 +2481,58 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial private interface FieldAccessor { Object get(GeneratedMessage message); - Object get(GeneratedMessage.Builder builder); + Object get(GeneratedMessage.Builder builder); Object getRaw(GeneratedMessage message); - Object getRaw(GeneratedMessage.Builder builder); - - void set(Builder builder, Object value); + 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 getRepeated(GeneratedMessage.Builder builder, int index); - Object getRepeatedRaw(GeneratedMessage.Builder builder, int index); + void setRepeated(Builder builder, int index, Object value); - void setRepeated(Builder builder, int index, Object value); - - void addRepeated(Builder builder, Object value); + void addRepeated(Builder builder, Object value); boolean has(GeneratedMessage message); - boolean has(GeneratedMessage.Builder builder); + boolean has(GeneratedMessage.Builder builder); int getRepeatedCount(GeneratedMessage message); - int getRepeatedCount(GeneratedMessage.Builder builder); + int getRepeatedCount(GeneratedMessage.Builder builder); - void clear(Builder builder); + void clear(Builder builder); Message.Builder newBuilder(); - Message.Builder getBuilder(GeneratedMessage.Builder builder); + Message.Builder getBuilder(GeneratedMessage.Builder builder); - Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index); + Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index); } /** OneofAccessor provides access to a single oneof. */ - private static class OneofAccessor { - OneofAccessor( + private static interface OneofAccessor { + public boolean has(final GeneratedMessage message); + + public boolean has(GeneratedMessage.Builder builder); + + public FieldDescriptor get(final GeneratedMessage message); + + public FieldDescriptor get(GeneratedMessage.Builder builder); + + public void clear(final Builder builder); + } + + /** RealOneofAccessor provides access to a single real oneof. */ + private static class RealOneofAccessor implements OneofAccessor { + RealOneofAccessor( final Descriptor descriptor, + final int oneofIndex, final String camelCaseName, final Class messageClass, - final Class builderClass) { + final Class> builderClass) { this.descriptor = descriptor; caseMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Case"); caseMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Case"); @@ -2125,20 +2544,17 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial private final Method caseMethodBuilder; private final Method clearMethod; + @Override public boolean has(final GeneratedMessage message) { - if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) { - return false; - } - return true; + return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() != 0; } - public boolean has(GeneratedMessage.Builder builder) { - if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) { - return false; - } - return true; + @Override + public boolean has(GeneratedMessage.Builder builder) { + return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() != 0; } + @Override public FieldDescriptor get(final GeneratedMessage message) { int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); if (fieldNumber > 0) { @@ -2147,7 +2563,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return null; } - public FieldDescriptor get(GeneratedMessage.Builder builder) { + @Override + public FieldDescriptor get(GeneratedMessage.Builder builder) { int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); if (fieldNumber > 0) { return descriptor.findFieldByNumber(fieldNumber); @@ -2155,79 +2572,192 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return null; } - public void clear(final Builder builder) { - invokeOrDie(clearMethod, builder); + @Override + public void clear(final Builder builder) { + // TODO: remove the unused variable + Object unused = invokeOrDie(clearMethod, builder); } } - private static boolean supportFieldPresence(FileDescriptor file) { - return file.getSyntax() == FileDescriptor.Syntax.PROTO2; + /** SyntheticOneofAccessor provides access to a single synthetic oneof. */ + private static class SyntheticOneofAccessor implements OneofAccessor { + SyntheticOneofAccessor(final Descriptor descriptor, final int oneofIndex) { + OneofDescriptor oneofDescriptor = descriptor.getOneofs().get(oneofIndex); + fieldDescriptor = oneofDescriptor.getFields().get(0); + } + + private final FieldDescriptor fieldDescriptor; + + @Override + public boolean has(final GeneratedMessage message) { + return message.hasField(fieldDescriptor); + } + + @Override + public boolean has(GeneratedMessage.Builder builder) { + return builder.hasField(fieldDescriptor); + } + + @Override + public FieldDescriptor get(final GeneratedMessage message) { + return message.hasField(fieldDescriptor) ? fieldDescriptor : null; + } + + public FieldDescriptor get(GeneratedMessage.Builder builder) { + return builder.hasField(fieldDescriptor) ? fieldDescriptor : null; + } + + @Override + public void clear(final Builder builder) { + builder.clearField(fieldDescriptor); + } } // --------------------------------------------------------------- + @SuppressWarnings("SameNameButDifferent") private static class SingularFieldAccessor implements FieldAccessor { + private interface MethodInvoker { + Object get(final GeneratedMessage message); + + Object get(GeneratedMessage.Builder builder); + + int getOneofFieldNumber(final GeneratedMessage message); + + int getOneofFieldNumber(final GeneratedMessage.Builder builder); + + void set(final GeneratedMessage.Builder builder, final Object value); + + boolean has(final GeneratedMessage message); + + boolean has(GeneratedMessage.Builder builder); + + void clear(final GeneratedMessage.Builder builder); + } + + private static final class ReflectionInvoker implements MethodInvoker { + private final Method getMethod; + private final Method getMethodBuilder; + private final Method setMethod; + private final Method hasMethod; + private final Method hasMethodBuilder; + private final Method clearMethod; + private final Method caseMethod; + private final Method caseMethodBuilder; + + ReflectionInvoker( + final FieldDescriptor descriptor, + final String camelCaseName, + final Class messageClass, + final Class> builderClass, + final String containingOneofCamelCaseName, + boolean isOneofField, + boolean hasHasMethod) { + getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); + getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); + Class 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; + } + + @Override + public Object get(final GeneratedMessage message) { + return invokeOrDie(getMethod, message); + } + + @Override + public Object get(GeneratedMessage.Builder builder) { + return invokeOrDie(getMethodBuilder, builder); + } + + @Override + public int getOneofFieldNumber(final GeneratedMessage message) { + return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); + } + + @Override + public int getOneofFieldNumber(final GeneratedMessage.Builder builder) { + return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); + } + + @Override + public void set(final GeneratedMessage.Builder builder, final Object value) { + // TODO: remove the unused variable + Object unused = invokeOrDie(setMethod, builder, value); + } + + @Override + public boolean has(final GeneratedMessage message) { + return (Boolean) invokeOrDie(hasMethod, message); + } + + @Override + public boolean has(GeneratedMessage.Builder builder) { + return (Boolean) invokeOrDie(hasMethodBuilder, builder); + } + + @Override + public void clear(final GeneratedMessage.Builder builder) { + // TODO: remove the unused variable + Object unused = invokeOrDie(clearMethod, builder); + } + } + SingularFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class builderClass, + final Class> builderClass, final String containingOneofCamelCaseName) { + isOneofField = + descriptor.getRealContainingOneof() != null; + hasHasMethod = descriptor.hasPresence(); + ReflectionInvoker reflectionInvoker = + new ReflectionInvoker( + descriptor, + camelCaseName, + messageClass, + builderClass, + containingOneofCamelCaseName, + isOneofField, + hasHasMethod); 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; + type = reflectionInvoker.getMethod.getReturnType(); + invoker = getMethodInvoker(reflectionInvoker); + } + + static MethodInvoker getMethodInvoker(ReflectionInvoker accessor) { + return accessor; } // 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(); - } + protected final MethodInvoker invoker; @Override public Object get(final GeneratedMessage message) { - return invokeOrDie(getMethod, message); + return invoker.get(message); } @Override - public Object get(GeneratedMessage.Builder builder) { - return invokeOrDie(getMethodBuilder, builder); + public Object get(GeneratedMessage.Builder builder) { + return invoker.get(builder); } @Override @@ -2236,13 +2766,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Object getRaw(GeneratedMessage.Builder builder) { - return get(builder); - } - - @Override - public void set(final Builder builder, final Object value) { - invokeOrDie(setMethod, builder, value); + public void set(final Builder builder, final Object value) { + invoker.set(builder, value); } @Override @@ -2251,29 +2776,17 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Object getRepeatedRaw(final GeneratedMessage message, final int index) { - throw new UnsupportedOperationException( - "getRepeatedFieldRaw() called on a singular field."); - } - - @Override - public Object getRepeated(GeneratedMessage.Builder builder, int index) { + public Object getRepeated(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException("getRepeatedField() called on a singular field."); } @Override - public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) { - throw new UnsupportedOperationException( - "getRepeatedFieldRaw() called on a singular field."); - } - - @Override - public void setRepeated(final Builder builder, final int index, final Object value) { + public void setRepeated(final Builder builder, final int index, final Object value) { throw new UnsupportedOperationException("setRepeatedField() called on a singular field."); } @Override - public void addRepeated(final Builder builder, final Object value) { + public void addRepeated(final Builder builder, final Object value) { throw new UnsupportedOperationException("addRepeatedField() called on a singular field."); } @@ -2281,22 +2794,22 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial public boolean has(final GeneratedMessage message) { if (!hasHasMethod) { if (isOneofField) { - return getOneofFieldNumber(message) == field.getNumber(); + return invoker.getOneofFieldNumber(message) == field.getNumber(); } return !get(message).equals(field.getDefaultValue()); } - return (Boolean) invokeOrDie(hasMethod, message); + return invoker.has(message); } @Override - public boolean has(GeneratedMessage.Builder builder) { + public boolean has(GeneratedMessage.Builder builder) { if (!hasHasMethod) { if (isOneofField) { - return getOneofFieldNumber(builder) == field.getNumber(); + return invoker.getOneofFieldNumber(builder) == field.getNumber(); } return !get(builder).equals(field.getDefaultValue()); } - return (Boolean) invokeOrDie(hasMethodBuilder, builder); + return invoker.has(builder); } @Override @@ -2306,14 +2819,14 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public int getRepeatedCount(GeneratedMessage.Builder builder) { + public int getRepeatedCount(GeneratedMessage.Builder builder) { throw new UnsupportedOperationException( "getRepeatedFieldSize() called on a singular field."); } @Override - public void clear(final Builder builder) { - invokeOrDie(clearMethod, builder); + public void clear(final Builder builder) { + invoker.clear(builder); } @Override @@ -2323,56 +2836,146 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Message.Builder getBuilder(GeneratedMessage.Builder builder) { + public Message.Builder getBuilder(GeneratedMessage.Builder builder) { throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); } @Override - public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) { + public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( "getRepeatedFieldBuilder() called on a non-Message type."); } } + @SuppressWarnings("SameNameButDifferent") 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; + interface MethodInvoker { + Object get(final GeneratedMessage message); + + Object get(GeneratedMessage.Builder builder); + + Object getRepeated(final GeneratedMessage message, final int index); + + Object getRepeated(GeneratedMessage.Builder builder, int index); + + void setRepeated( + final GeneratedMessage.Builder builder, final int index, final Object value); + + void addRepeated(final GeneratedMessage.Builder builder, final Object value); + + int getRepeatedCount(final GeneratedMessage message); + + int getRepeatedCount(GeneratedMessage.Builder builder); + + void clear(final GeneratedMessage.Builder builder); + } + + private static final class ReflectionInvoker implements MethodInvoker { + private final Method getMethod; + private final Method getMethodBuilder; + private final Method getRepeatedMethod; + private final Method getRepeatedMethodBuilder; + private final Method setRepeatedMethod; + private final Method addRepeatedMethod; + private final Method getCountMethod; + private final Method getCountMethodBuilder; + private final Method clearMethod; + + ReflectionInvoker( + final FieldDescriptor descriptor, + final String camelCaseName, + final Class messageClass, + final Class> 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); + Class 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); + } + + @Override + public Object get(final GeneratedMessage message) { + return invokeOrDie(getMethod, message); + } + + @Override + public Object get(GeneratedMessage.Builder builder) { + return invokeOrDie(getMethodBuilder, builder); + } + + @Override + public Object getRepeated(final GeneratedMessage message, final int index) { + return invokeOrDie(getRepeatedMethod, message, index); + } + + @Override + public Object getRepeated(GeneratedMessage.Builder builder, int index) { + return invokeOrDie(getRepeatedMethodBuilder, builder, index); + } + + @Override + public void setRepeated( + final GeneratedMessage.Builder builder, final int index, final Object value) { + // TODO: remove the unused variable + Object unused = invokeOrDie(setRepeatedMethod, builder, index, value); + } + + @Override + public void addRepeated(final GeneratedMessage.Builder builder, final Object value) { + // TODO: remove the unused variable + Object unused = invokeOrDie(addRepeatedMethod, builder, value); + } + + @Override + public int getRepeatedCount(final GeneratedMessage message) { + return (Integer) invokeOrDie(getCountMethod, message); + } + + @Override + public int getRepeatedCount(GeneratedMessage.Builder builder) { + return (Integer) invokeOrDie(getCountMethodBuilder, builder); + } + + @Override + public void clear(final GeneratedMessage.Builder builder) { + // TODO: remove the unused variable + Object unused = invokeOrDie(clearMethod, builder); + } + } + + protected final Class type; + protected final MethodInvoker invoker; RepeatedFieldAccessor( final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class 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"); + final Class> builderClass) { + ReflectionInvoker reflectionInvoker = + new ReflectionInvoker(descriptor, camelCaseName, messageClass, builderClass); + type = reflectionInvoker.getRepeatedMethod.getReturnType(); + invoker = getMethodInvoker(reflectionInvoker); + } - clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName); + static MethodInvoker getMethodInvoker(ReflectionInvoker accessor) { + return accessor; } @Override public Object get(final GeneratedMessage message) { - return invokeOrDie(getMethod, message); + return invoker.get(message); } @Override - public Object get(GeneratedMessage.Builder builder) { - return invokeOrDie(getMethodBuilder, builder); + public Object get(GeneratedMessage.Builder builder) { + return invoker.get(builder); } @Override @@ -2381,12 +2984,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Object getRaw(GeneratedMessage.Builder builder) { - return get(builder); - } - - @Override - public void set(final Builder builder, final Object value) { + 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 @@ -2399,32 +2997,22 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial @Override public Object getRepeated(final GeneratedMessage message, final int index) { - return invokeOrDie(getRepeatedMethod, message, index); - } - - @Override - public Object getRepeated(GeneratedMessage.Builder builder, int index) { - return invokeOrDie(getRepeatedMethodBuilder, builder, index); - } - - @Override - public Object getRepeatedRaw(GeneratedMessage message, int index) { - return getRepeated(message, index); + return invoker.getRepeated(message, index); } @Override - public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) { - return getRepeated(builder, index); + public Object getRepeated(GeneratedMessage.Builder builder, int index) { + return invoker.getRepeated(builder, index); } @Override - public void setRepeated(final Builder builder, final int index, final Object value) { - invokeOrDie(setRepeatedMethod, builder, index, value); + public void setRepeated(final Builder builder, final int index, final Object value) { + invoker.setRepeated(builder, index, value); } @Override - public void addRepeated(final Builder builder, final Object value) { - invokeOrDie(addRepeatedMethod, builder, value); + public void addRepeated(final Builder builder, final Object value) { + invoker.addRepeated(builder, value); } @Override @@ -2433,23 +3021,23 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public boolean has(GeneratedMessage.Builder builder) { + public boolean has(GeneratedMessage.Builder builder) { throw new UnsupportedOperationException("hasField() called on a repeated field."); } @Override public int getRepeatedCount(final GeneratedMessage message) { - return (Integer) invokeOrDie(getCountMethod, message); + return invoker.getRepeatedCount(message); } @Override - public int getRepeatedCount(GeneratedMessage.Builder builder) { - return (Integer) invokeOrDie(getCountMethodBuilder, builder); + public int getRepeatedCount(GeneratedMessage.Builder builder) { + return invoker.getRepeatedCount(builder); } @Override - public void clear(final Builder builder) { - invokeOrDie(clearMethod, builder); + public void clear(final Builder builder) { + invoker.clear(builder); } @Override @@ -2459,12 +3047,12 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Message.Builder getBuilder(GeneratedMessage.Builder builder) { + public Message.Builder getBuilder(GeneratedMessage.Builder builder) { throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); } @Override - public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) { + public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( "getRepeatedFieldBuilder() called on a non-Message type."); } @@ -2472,13 +3060,10 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial private static class MapFieldAccessor implements FieldAccessor { MapFieldAccessor( - final FieldDescriptor descriptor, - final String camelCaseName, - final Class messageClass, - final Class builderClass) { + final FieldDescriptor descriptor, final Class messageClass) { field = descriptor; Method getDefaultInstanceMethod = getMethodOrDie(messageClass, "getDefaultInstance"); - MapField defaultMapField = + MapFieldReflectionAccessor defaultMapField = getMapField((GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null)); mapEntryMessageDefaultInstance = defaultMapField.getMapEntryMessageDefaultInstance(); } @@ -2486,22 +3071,35 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial private final FieldDescriptor field; private final Message mapEntryMessageDefaultInstance; - private MapField getMapField(GeneratedMessage message) { - return (MapField) message.internalGetMapField(field.getNumber()); + private MapFieldReflectionAccessor getMapField(GeneratedMessage message) { + return message.internalGetMapFieldReflection(field.getNumber()); + } + + private MapFieldReflectionAccessor getMapField(GeneratedMessage.Builder builder) { + return builder.internalGetMapFieldReflection(field.getNumber()); } - private MapField getMapField(GeneratedMessage.Builder builder) { - return (MapField) builder.internalGetMapField(field.getNumber()); + private MapFieldReflectionAccessor getMutableMapField(GeneratedMessage.Builder builder) { + return builder.internalGetMutableMapFieldReflection(field.getNumber()); } - private MapField getMutableMapField(GeneratedMessage.Builder builder) { - return (MapField) builder.internalGetMutableMapField(field.getNumber()); + private Message coerceType(Message value) { + if (value == null) { + return null; + } + if (mapEntryMessageDefaultInstance.getClass().isInstance(value)) { + return value; + } + // 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 mapEntryMessageDefaultInstance.toBuilder().mergeFrom(value).build(); } @Override - @SuppressWarnings("unchecked") public Object get(GeneratedMessage message) { - List result = new ArrayList(); + List result = new ArrayList<>(); for (int i = 0; i < getRepeatedCount(message); i++) { result.add(getRepeated(message, i)); } @@ -2509,9 +3107,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - @SuppressWarnings("unchecked") - public Object get(Builder builder) { - List result = new ArrayList(); + public Object get(Builder builder) { + List result = new ArrayList<>(); for (int i = 0; i < getRepeatedCount(builder); i++) { result.add(getRepeated(builder, i)); } @@ -2524,14 +3121,9 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Object getRaw(GeneratedMessage.Builder builder) { - return get(builder); - } - - @Override - public void set(Builder builder, Object value) { + public void set(Builder builder, Object value) { clear(builder); - for (Object entry : (List) value) { + for (Object entry : (List) value) { addRepeated(builder, entry); } } @@ -2542,28 +3134,18 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Object getRepeated(Builder builder, int index) { + public Object getRepeated(Builder builder, int index) { return getMapField(builder).getList().get(index); } @Override - public Object getRepeatedRaw(GeneratedMessage message, int index) { - return getRepeated(message, index); + public void setRepeated(Builder builder, int index, Object value) { + getMutableMapField(builder).getMutableList().set(index, coerceType((Message) value)); } @Override - public Object getRepeatedRaw(Builder builder, int index) { - return getRepeated(builder, index); - } - - @Override - public void setRepeated(Builder builder, int index, Object value) { - getMutableMapField(builder).getMutableList().set(index, (Message) value); - } - - @Override - public void addRepeated(Builder builder, Object value) { - getMutableMapField(builder).getMutableList().add((Message) value); + public void addRepeated(Builder builder, Object value) { + getMutableMapField(builder).getMutableList().add(coerceType((Message) value)); } @Override @@ -2572,7 +3154,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public boolean has(Builder builder) { + public boolean has(Builder builder) { throw new UnsupportedOperationException("hasField() is not supported for repeated fields."); } @@ -2582,28 +3164,28 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public int getRepeatedCount(Builder builder) { + public int getRepeatedCount(Builder builder) { return getMapField(builder).getList().size(); } @Override - public void clear(Builder builder) { + public void clear(Builder builder) { getMutableMapField(builder).getMutableList().clear(); } @Override - public com.google.protobuf.Message.Builder newBuilder() { + public Message.Builder newBuilder() { return mapEntryMessageDefaultInstance.newBuilderForType(); } @Override - public com.google.protobuf.Message.Builder getBuilder(Builder builder) { + public Message.Builder getBuilder(Builder builder) { throw new UnsupportedOperationException("Nested builder not supported for map fields."); } @Override - public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) { - throw new UnsupportedOperationException("Nested builder not supported for map fields."); + public Message.Builder getRepeatedBuilder(Builder builder, int index) { + throw new UnsupportedOperationException("Map fields cannot be repeated"); } } @@ -2614,7 +3196,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class builderClass, + final Class> builderClass, final String containingOneofCamelCaseName) { super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName); @@ -2631,12 +3213,12 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } - private EnumDescriptor enumDescriptor; + private final EnumDescriptor enumDescriptor; - private Method valueOfMethod; - private Method getValueDescriptorMethod; + private final Method valueOfMethod; + private final Method getValueDescriptorMethod; - private boolean supportUnknownEnumValue; + private final boolean supportUnknownEnumValue; private Method getValueMethod; private Method getValueMethodBuilder; private Method setValueMethod; @@ -2651,7 +3233,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Object get(final GeneratedMessage.Builder builder) { + public Object get(final GeneratedMessage.Builder builder) { if (supportUnknownEnumValue) { int value = (Integer) invokeOrDie(getValueMethodBuilder, builder); return enumDescriptor.findValueByNumberCreatingIfUnknown(value); @@ -2660,9 +3242,11 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public void set(final Builder builder, final Object value) { + public void set(final Builder builder, final Object value) { if (supportUnknownEnumValue) { - invokeOrDie(setValueMethod, builder, ((EnumValueDescriptor) value).getNumber()); + // TODO: remove the unused variable + Object unused = + invokeOrDie(setValueMethod, builder, ((EnumValueDescriptor) value).getNumber()); return; } super.set(builder, invokeOrDie(valueOfMethod, null, value)); @@ -2674,7 +3258,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class builderClass) { + final Class> builderClass) { super(descriptor, camelCaseName, messageClass, builderClass); enumDescriptor = descriptor.getEnumType(); @@ -2695,21 +3279,21 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } } - private EnumDescriptor enumDescriptor; + private final EnumDescriptor enumDescriptor; private final Method valueOfMethod; private final Method getValueDescriptorMethod; - private boolean supportUnknownEnumValue; + private final 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 List newList = new ArrayList<>(); final int size = getRepeatedCount(message); for (int i = 0; i < size; i++) { newList.add(getRepeated(message, i)); @@ -2718,9 +3302,8 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - @SuppressWarnings("unchecked") - public Object get(final GeneratedMessage.Builder builder) { - final List newList = new ArrayList(); + 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)); @@ -2738,7 +3321,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Object getRepeated(final GeneratedMessage.Builder builder, final int index) { + public Object getRepeated(final GeneratedMessage.Builder builder, final int index) { if (supportUnknownEnumValue) { int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index); return enumDescriptor.findValueByNumberCreatingIfUnknown(value); @@ -2747,19 +3330,27 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public void setRepeated(final Builder builder, final int index, final Object value) { + public void setRepeated(final Builder builder, final int index, final Object value) { if (supportUnknownEnumValue) { - invokeOrDie( - setRepeatedValueMethod, builder, index, ((EnumValueDescriptor) value).getNumber()); + // TODO: remove the unused variable + Object unused = + 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) { + public void addRepeated(final Builder builder, final Object value) { if (supportUnknownEnumValue) { - invokeOrDie(addRepeatedValueMethod, builder, ((EnumValueDescriptor) value).getNumber()); + // TODO: remove the unused variable + Object unused = + invokeOrDie( + addRepeatedValueMethod, builder, ((EnumValueDescriptor) value).getNumber()); return; } super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value)); @@ -2783,17 +3374,15 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class builderClass, + final Class> 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 @@ -2802,14 +3391,10 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Object getRaw(GeneratedMessage.Builder builder) { - return invokeOrDie(getBytesMethodBuilder, builder); - } - - @Override - public void set(GeneratedMessage.Builder builder, Object value) { + public void set(GeneratedMessage.Builder builder, Object value) { if (value instanceof ByteString) { - invokeOrDie(setBytesMethodBuilder, builder, value); + // TODO: remove the unused variable + Object unused = invokeOrDie(setBytesMethodBuilder, builder, value); } else { super.set(builder, value); } @@ -2823,7 +3408,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class builderClass, + final Class> builderClass, final String containingOneofCamelCaseName) { super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName); @@ -2849,7 +3434,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public void set(final Builder builder, final Object value) { + public void set(final Builder builder, final Object value) { super.set(builder, coerceType(value)); } @@ -2859,7 +3444,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public Message.Builder getBuilder(GeneratedMessage.Builder builder) { + public Message.Builder getBuilder(GeneratedMessage.Builder builder) { return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder); } } @@ -2869,7 +3454,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial final FieldDescriptor descriptor, final String camelCaseName, final Class messageClass, - final Class builderClass) { + final Class> builderClass) { super(descriptor, camelCaseName, messageClass, builderClass); newBuilderMethod = getMethodOrDie(type, "newBuilder"); @@ -2895,12 +3480,12 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial } @Override - public void setRepeated(final Builder builder, final int index, final Object value) { + 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) { + public void addRepeated(final Builder builder, final Object value) { super.addRepeated(builder, coerceType(value)); } @@ -2911,7 +3496,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial @Override public Message.Builder getRepeatedBuilder( - final GeneratedMessage.Builder builder, final int index) { + final GeneratedMessage.Builder builder, final int index) { return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder, index); } } @@ -2931,13 +3516,21 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial /** * Checks that the {@link Extension} is non-Lite and returns it as a {@link GeneratedExtension}. */ - private static , T> - Extension checkNotLite(ExtensionLite extension) { + private static , T> + Extension checkNotLite(ExtensionLite extension) { if (extension.isLite()) { throw new IllegalArgumentException("Expected non-lite extension."); } - return (Extension) extension; + return (Extension) extension; + } + + protected static boolean isStringEmpty(final Object value) { + if (value instanceof String) { + return ((String) value).isEmpty(); + } else { + return ((ByteString) value).isEmpty(); + } } protected static int computeStringSize(final int fieldNumber, final Object value) { @@ -2973,4 +3566,119 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial output.writeBytesNoTag((ByteString) value); } } + + protected static void serializeIntegerMapTo( + CodedOutputStream out, + MapField field, + MapEntry defaultEntry, + int fieldNumber) + throws IOException { + Map m = field.getMap(); + if (!out.isSerializationDeterministic()) { + serializeMapTo(out, m, defaultEntry, fieldNumber); + return; + } + // Sorting the unboxed keys and then look up the values during serialization is 2x faster + // than sorting map entries with a custom comparator directly. + int[] keys = new int[m.size()]; + int index = 0; + for (int k : m.keySet()) { + keys[index++] = k; + } + Arrays.sort(keys); + for (int key : keys) { + out.writeMessage( + fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build()); + } + } + + protected static void serializeLongMapTo( + CodedOutputStream out, + MapField field, + MapEntry defaultEntry, + int fieldNumber) + throws IOException { + Map m = field.getMap(); + if (!out.isSerializationDeterministic()) { + serializeMapTo(out, m, defaultEntry, fieldNumber); + return; + } + + long[] keys = new long[m.size()]; + int index = 0; + for (long k : m.keySet()) { + keys[index++] = k; + } + Arrays.sort(keys); + for (long key : keys) { + out.writeMessage( + fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build()); + } + } + + protected static void serializeStringMapTo( + CodedOutputStream out, + MapField field, + MapEntry defaultEntry, + int fieldNumber) + throws IOException { + Map m = field.getMap(); + if (!out.isSerializationDeterministic()) { + serializeMapTo(out, m, defaultEntry, fieldNumber); + return; + } + + // Sorting the String keys and then look up the values during serialization is 25% faster than + // sorting map entries with a custom comparator directly. + String[] keys = new String[m.size()]; + keys = m.keySet().toArray(keys); + Arrays.sort(keys); + for (String key : keys) { + out.writeMessage( + fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build()); + } + } + + protected static void serializeBooleanMapTo( + CodedOutputStream out, + MapField field, + MapEntry defaultEntry, + int fieldNumber) + throws IOException { + Map m = field.getMap(); + if (!out.isSerializationDeterministic()) { + serializeMapTo(out, m, defaultEntry, fieldNumber); + return; + } + maybeSerializeBooleanEntryTo(out, m, defaultEntry, fieldNumber, false); + maybeSerializeBooleanEntryTo(out, m, defaultEntry, fieldNumber, true); + } + + private static void maybeSerializeBooleanEntryTo( + CodedOutputStream out, + Map m, + MapEntry defaultEntry, + int fieldNumber, + boolean key) + throws IOException { + if (m.containsKey(key)) { + out.writeMessage( + fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build()); + } + } + + /** Serialize the map using the iteration order. */ + private static void serializeMapTo( + CodedOutputStream out, Map m, MapEntry defaultEntry, int fieldNumber) + throws IOException { + for (Map.Entry entry : m.entrySet()) { + out.writeMessage( + fieldNumber, + defaultEntry + .newBuilderForType() + .setKey(entry.getKey()) + .setValue(entry.getValue()) + .build()); + } + } } diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java deleted file mode 100644 index 0a5bfda6bb..0000000000 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java +++ /dev/null @@ -1,3421 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd - -package com.google.protobuf; - -import static com.google.protobuf.Internal.checkNotNull; - -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.Internal.BooleanList; -import com.google.protobuf.Internal.DoubleList; -import com.google.protobuf.Internal.FloatList; -import com.google.protobuf.Internal.IntList; -import com.google.protobuf.Internal.LongList; -import com.google.protobuf.Internal.ProtobufList; -// In opensource protobuf, we have versioned this GeneratedMessageV3 class to GeneratedMessageV3 and -// in the future may have GeneratedMessageV4 etc. This allows us to change some aspects of this -// class without breaking binary compatibility with old generated code that still subclasses -// the old GeneratedMessageV3 class. To allow these different GeneratedMessageV? classes to -// interoperate (e.g., a GeneratedMessageV3 object has a message extension field whose class -// type is GeneratedMessageV4), these classes still share a common parent class AbstractMessage -// and are using the same GeneratedMessage.GeneratedExtension class for extension definitions. -// Since this class becomes GeneratedMessageV? in opensource, we have to add an import here -// to be able to use GeneratedMessage.GeneratedExtension. The GeneratedExtension definition in -// this file is also excluded from opensource to avoid conflict. -import com.google.protobuf.GeneratedMessage.GeneratedExtension; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectStreamException; -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -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 GeneratedMessageV3 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. - * - *

TODO: mark this private and final (breaking change) - */ - protected UnknownFieldSet unknownFields; - - protected GeneratedMessageV3() { - unknownFields = UnknownFieldSet.getDefaultInstance(); - } - - protected GeneratedMessageV3(Builder builder) { - unknownFields = builder.getUnknownFields(); - } - - /** TODO: Remove this unnecessary intermediate implementation of this method. */ - @Override - public Parser getParserForType() { - throw new UnsupportedOperationException("This is supposed to be overridden by subclasses."); - } - - /** - * TODO: Stop using SingleFieldBuilder and remove this setting - * - * @see #setAlwaysUseFieldBuildersForTesting(boolean) - */ - static void enableAlwaysUseFieldBuildersForTesting() { - setAlwaysUseFieldBuildersForTesting(true); - } - - /** - * For testing. Allows a test to disable/re-enable 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}. - * - *

TODO: Stop using SingleFieldBuilder and remove this setting - */ - static void setAlwaysUseFieldBuildersForTesting(boolean useBuilders) { - alwaysUseFieldBuilders = useBuilders; - } - - /** - * 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 - public Descriptor getDescriptorForType() { - return internalGetFieldAccessorTable().descriptor; - } - - /** - * TODO: This method should be removed. It enables parsing directly into an - * "immutable" message. Have to leave it for now to support old gencode. - * - * @deprecated use newBuilder().mergeFrom() instead - */ - @Deprecated - protected void mergeFromAndMakeImmutableInternal( - CodedInputStream input, ExtensionRegistryLite extensionRegistry) - throws InvalidProtocolBufferException { - Schema schema = Protobuf.getInstance().schemaFor(this); - try { - schema.mergeFrom(this, CodedInputStreamReader.forCodedInput(input), extensionRegistry); - } catch (InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (IOException e) { - throw new InvalidProtocolBufferException(e).setUnfinishedMessage(this); - } - schema.makeImmutable(this); - } - - /** - * Internal helper to return a modifiable map containing all the fields. The returned Map is - * modifiable so that the caller can add additional extension fields to implement {@link - * #getAllFields()}. - * - * @param getBytesForString whether to generate ByteString for string fields - */ - private Map getAllFieldsMutable(boolean getBytesForString) { - final TreeMap result = new TreeMap<>(); - final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; - final List 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; - } - - // TODO: compute this at {@code build()} time in the Builder class. - @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 messageList = (List) 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 - public Map 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 getAllFieldsRaw() { - return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString= */ true)); - } - - @Override - public boolean hasOneof(final OneofDescriptor oneof) { - return internalGetFieldAccessorTable().getOneof(oneof).has(this); - } - - @Override - public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { - return internalGetFieldAccessorTable().getOneof(oneof).get(this); - } - - @Override - public boolean hasField(final FieldDescriptor field) { - return internalGetFieldAccessorTable().getField(field).has(this); - } - - @Override - 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 - public int getRepeatedFieldCount(final FieldDescriptor field) { - return internalGetFieldAccessorTable().getField(field).getRepeatedCount(this); - } - - @Override - public Object getRepeatedField(final FieldDescriptor field, final int index) { - return internalGetFieldAccessorTable().getField(field).getRepeated(this, index); - } - - // TODO: This method should be final. - @Override - public UnknownFieldSet getUnknownFields() { - return unknownFields; - } - - // TODO: This should go away when Schema classes cannot modify immutable - // GeneratedMessageV3 objects anymore. - void setUnknownFields(UnknownFieldSet unknownFields) { - this.unknownFields = unknownFields; - } - - /** - * Called by subclasses to parse an unknown field. - * - *

TODO remove this method - * - * @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 { - if (input.shouldDiscardUnknownFields()) { - return input.skipField(tag); - } - return unknownFields.mergeFieldFrom(tag, input); - } - - /** - * Delegates to parseUnknownField. This method is obsolete, but we must retain it for - * compatibility with older generated code. - * - *

TODO remove this method - */ - protected boolean parseUnknownFieldProto3( - CodedInputStream input, - UnknownFieldSet.Builder unknownFields, - ExtensionRegistryLite extensionRegistry, - int tag) - throws IOException { - return parseUnknownField(input, unknownFields, extensionRegistry, tag); - } - - /** Used by generated code. */ - @SuppressWarnings("ProtoParseWithRegistry") - protected static M parseWithIOException(Parser parser, InputStream input) - throws IOException { - try { - return parser.parseFrom(input); - } catch (InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } - } - - /** Used by generated code. */ - protected static M parseWithIOException( - Parser parser, InputStream input, ExtensionRegistryLite extensions) throws IOException { - try { - return parser.parseFrom(input, extensions); - } catch (InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } - } - - /** Used by generated code. */ - @SuppressWarnings("ProtoParseWithRegistry") - protected static M parseWithIOException( - Parser parser, CodedInputStream input) throws IOException { - try { - return parser.parseFrom(input); - } catch (InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } - } - - /** Used by generated code. */ - protected static M parseWithIOException( - Parser parser, CodedInputStream input, ExtensionRegistryLite extensions) - throws IOException { - try { - return parser.parseFrom(input, extensions); - } catch (InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } - } - - /** Used by generated code. */ - @SuppressWarnings("ProtoParseWithRegistry") - protected static M parseDelimitedWithIOException( - Parser parser, InputStream input) throws IOException { - try { - return parser.parseDelimitedFrom(input); - } catch (InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } - } - - /** Used by generated code. */ - protected static M parseDelimitedWithIOException( - Parser parser, InputStream input, ExtensionRegistryLite extensions) throws IOException { - try { - return parser.parseDelimitedFrom(input, extensions); - } catch (InvalidProtocolBufferException e) { - throw e.unwrapIOException(); - } - } - - protected static boolean canUseUnsafe() { - return UnsafeUtil.hasUnsafeArrayOperations() && UnsafeUtil.hasUnsafeByteBufferOperations(); - } - - protected static IntList emptyIntList() { - return IntArrayList.emptyList(); - } - - // TODO: Unused. Remove. - protected static IntList newIntList() { - return new IntArrayList(); - } - - // TODO: Redundant with makeMutableCopy(). Remove. - protected static IntList mutableCopy(IntList list) { - return makeMutableCopy(list); - } - - // TODO: Redundant with makeMutableCopy(). Remove. - protected static LongList mutableCopy(LongList list) { - return makeMutableCopy(list); - } - - // TODO: Redundant with makeMutableCopy(). Remove. - protected static FloatList mutableCopy(FloatList list) { - return makeMutableCopy(list); - } - - // TODO: Redundant with makeMutableCopy(). Remove. - protected static DoubleList mutableCopy(DoubleList list) { - return makeMutableCopy(list); - } - - // TODO: Redundant with makeMutableCopy(). Remove. - protected static BooleanList mutableCopy(BooleanList list) { - return makeMutableCopy(list); - } - - protected static LongList emptyLongList() { - return LongArrayList.emptyList(); - } - - // TODO: Unused. Remove. - protected static LongList newLongList() { - return new LongArrayList(); - } - - protected static FloatList emptyFloatList() { - return FloatArrayList.emptyList(); - } - - // TODO: Unused. Remove. - protected static FloatList newFloatList() { - return new FloatArrayList(); - } - - protected static DoubleList emptyDoubleList() { - return DoubleArrayList.emptyList(); - } - - // TODO: Unused. Remove. - protected static DoubleList newDoubleList() { - return new DoubleArrayList(); - } - - protected static BooleanList emptyBooleanList() { - return BooleanArrayList.emptyList(); - } - - // TODO: Unused. Remove. - protected static BooleanList newBooleanList() { - return new BooleanArrayList(); - } - - protected static > ListT makeMutableCopy(ListT list) { - return makeMutableCopy(list, 0); - } - - @SuppressWarnings("unchecked") // Guaranteed by proto runtime. - protected static > ListT makeMutableCopy( - ListT list, int minCapacity) { - int size = list.size(); - if (minCapacity <= size) { - minCapacity = size * 2; - } - if (minCapacity <= 0) { - minCapacity = AbstractProtobufList.DEFAULT_CAPACITY; - } - - return (ListT) list.mutableCopyWithCapacity(minCapacity); - } - - @SuppressWarnings("unchecked") // The empty list can be safely cast - protected static ProtobufList emptyList(Class elementType) { - return (ProtobufList) ProtobufArrayList.emptyList(); - } - - @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; - } - - /** - * This class is used to make a generated protected method inaccessible from user's code (e.g., - * the {@link #newInstance} method below). When this class is used as a parameter's type in a - * generated protected method, the method is visible to user's code in the same package, but since - * the constructor of this class is private to protobuf runtime, user's code can't obtain an - * instance of this class and as such can't actually make a method call on the protected method. - */ - protected static final class UnusedPrivateParameter { - static final UnusedPrivateParameter INSTANCE = new UnusedPrivateParameter(); - - private UnusedPrivateParameter() {} - } - - /** Creates a new instance of this message type. Overridden in the generated code. */ - @SuppressWarnings({"unused"}) - protected Object newInstance(UnusedPrivateParameter unused) { - throw new UnsupportedOperationException("This method must be overridden by the subclass."); - } - - /** - * Used by parsing constructors in generated classes. - * - *

TODO: remove unused method (extensions should be immutable after build) - */ - protected void makeExtensionsImmutable() { - // Noop for messages without extensions. - } - - /** - * TODO: remove this after b/29368482 is fixed. We need to move this interface to - * AbstractMessage in order to versioning GeneratedMessageV3 but this move breaks binary - * compatibility for AppEngine. After AppEngine is fixed we can exclude this from google3. - * - *

TODO: Remove at breaking change since b/29368482 was fixed in 2020 - */ - protected interface BuilderParent extends AbstractMessage.BuilderParent {} - - /** TODO: remove this together with GeneratedMessageV3.BuilderParent. */ - protected abstract Message.Builder newBuilderForType(BuilderParent parent); - - /** TODO: generated class should implement this directly */ - @Override - protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) { - return newBuilderForType( - new BuilderParent() { - @Override - public void markDirty() { - parent.markDirty(); - } - }); - } - - /** Builder class for {@link GeneratedMessageV3}. */ - @SuppressWarnings("unchecked") - public abstract static class Builder> - extends AbstractMessage.Builder { - - private BuilderParent builderParent; - - private BuilderParentImpl meAsParent; - - // Indicates that we've built a message and so we are now obligated - // to dispatch dirty invalidations. See GeneratedMessageV3.BuilderListener. - private boolean isClean; - - /** - * This field holds either an {@link UnknownFieldSet} or {@link UnknownFieldSet.Builder}. - * - *

We use an object because it should only be one or the other of those things at a time and - * Object is the only common base. This also saves space. - * - *

Conversions are lazy: if {@link #setUnknownFields} is called, this will contain {@link - * UnknownFieldSet}. If unknown fields are merged into this builder, the current {@link - * UnknownFieldSet} will be converted to a {@link UnknownFieldSet.Builder} and left that way - * until either {@link #setUnknownFields} or {@link #buildPartial} or {@link #build} is called. - */ - private Object unknownFieldsOrBuilder = UnknownFieldSet.getDefaultInstance(); - - protected Builder() { - this(null); - } - - protected Builder(BuilderParent builderParent) { - this.builderParent = builderParent; - } - - @Override - 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. - */ - @Override - protected void markClean() { - this.isClean = true; - } - - /** - * Gets whether invalidations are needed - * - * @return whether invalidations are needed - */ - protected boolean isClean() { - return isClean; - } - - @Override - public BuilderT clone() { - BuilderT builder = (BuilderT) 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. - */ - @Override - public BuilderT clear() { - unknownFieldsOrBuilder = UnknownFieldSet.getDefaultInstance(); - onChanged(); - return (BuilderT) 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 - public Descriptor getDescriptorForType() { - return internalGetFieldAccessorTable().descriptor; - } - - @Override - public Map getAllFields() { - return Collections.unmodifiableMap(getAllFieldsMutable()); - } - - /** Internal helper which returns a mutable map. */ - private Map getAllFieldsMutable() { - final TreeMap result = new TreeMap<>(); - final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; - final List 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; - } - - @Override - public Message.Builder newBuilderForField(final FieldDescriptor field) { - return internalGetFieldAccessorTable().getField(field).newBuilder(); - } - - @Override - public Message.Builder getFieldBuilder(final FieldDescriptor field) { - return internalGetFieldAccessorTable().getField(field).getBuilder(this); - } - - @Override - public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) { - return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(this, index); - } - - @Override - public boolean hasOneof(final OneofDescriptor oneof) { - return internalGetFieldAccessorTable().getOneof(oneof).has(this); - } - - @Override - public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) { - return internalGetFieldAccessorTable().getOneof(oneof).get(this); - } - - @Override - public boolean hasField(final FieldDescriptor field) { - return internalGetFieldAccessorTable().getField(field).has(this); - } - - @Override - 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; - } - } - - @Override - public BuilderT setField(final FieldDescriptor field, final Object value) { - internalGetFieldAccessorTable().getField(field).set(this, value); - return (BuilderT) this; - } - - @Override - public BuilderT clearField(final FieldDescriptor field) { - internalGetFieldAccessorTable().getField(field).clear(this); - return (BuilderT) this; - } - - @Override - public BuilderT clearOneof(final OneofDescriptor oneof) { - internalGetFieldAccessorTable().getOneof(oneof).clear(this); - return (BuilderT) this; - } - - @Override - public int getRepeatedFieldCount(final FieldDescriptor field) { - return internalGetFieldAccessorTable().getField(field).getRepeatedCount(this); - } - - @Override - public Object getRepeatedField(final FieldDescriptor field, final int index) { - return internalGetFieldAccessorTable().getField(field).getRepeated(this, index); - } - - @Override - public BuilderT setRepeatedField( - final FieldDescriptor field, final int index, final Object value) { - internalGetFieldAccessorTable().getField(field).setRepeated(this, index, value); - return (BuilderT) this; - } - - @Override - public BuilderT addRepeatedField(final FieldDescriptor field, final Object value) { - internalGetFieldAccessorTable().getField(field).addRepeated(this, value); - return (BuilderT) this; - } - - private BuilderT setUnknownFieldsInternal(final UnknownFieldSet unknownFields) { - unknownFieldsOrBuilder = unknownFields; - onChanged(); - return (BuilderT) this; - } - - @Override - public BuilderT setUnknownFields(final UnknownFieldSet unknownFields) { - return setUnknownFieldsInternal(unknownFields); - } - - /** - * This method is obsolete, but we must retain it for compatibility with older generated code. - */ - protected BuilderT setUnknownFieldsProto3(final UnknownFieldSet unknownFields) { - return setUnknownFieldsInternal(unknownFields); - } - - @Override - public BuilderT mergeUnknownFields(final UnknownFieldSet unknownFields) { - if (UnknownFieldSet.getDefaultInstance().equals(unknownFields)) { - return (BuilderT) this; - } - - if (UnknownFieldSet.getDefaultInstance().equals(unknownFieldsOrBuilder)) { - unknownFieldsOrBuilder = unknownFields; - onChanged(); - return (BuilderT) this; - } - - getUnknownFieldSetBuilder().mergeFrom(unknownFields); - onChanged(); - return (BuilderT) this; - } - - @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 messageList = (List) 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 - public final UnknownFieldSet getUnknownFields() { - if (unknownFieldsOrBuilder instanceof UnknownFieldSet) { - return (UnknownFieldSet) unknownFieldsOrBuilder; - } else { - return ((UnknownFieldSet.Builder) unknownFieldsOrBuilder).buildPartial(); - } - } - - /** - * Called by generated subclasses to parse an unknown field. - * - * @return {@code true} unless the tag is an end-group tag. - */ - protected boolean parseUnknownField( - CodedInputStream input, ExtensionRegistryLite extensionRegistry, int tag) - throws IOException { - if (input.shouldDiscardUnknownFields()) { - return input.skipField(tag); - } - return getUnknownFieldSetBuilder().mergeFieldFrom(tag, input); - } - - /** Called by generated subclasses to add to the unknown field set. */ - protected final void mergeUnknownLengthDelimitedField(int number, ByteString bytes) { - getUnknownFieldSetBuilder().mergeLengthDelimitedField(number, bytes); - } - - /** Called by generated subclasses to add to the unknown field set. */ - protected final void mergeUnknownVarintField(int number, int value) { - getUnknownFieldSetBuilder().mergeVarintField(number, value); - } - - @Override - protected UnknownFieldSet.Builder getUnknownFieldSetBuilder() { - if (unknownFieldsOrBuilder instanceof UnknownFieldSet) { - unknownFieldsOrBuilder = ((UnknownFieldSet) unknownFieldsOrBuilder).toBuilder(); - } - onChanged(); - return (UnknownFieldSet.Builder) unknownFieldsOrBuilder; - } - - @Override - protected void setUnknownFieldSetBuilder(UnknownFieldSet.Builder builder) { - unknownFieldsOrBuilder = builder; - onChanged(); - } - - /** - * 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 - 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 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 MapFieldReflectionAccessor internalGetMapFieldReflection(int fieldNumber) { - return internalGetMapField(fieldNumber); - } - - /** TODO: Remove, exists for compatibility with generated code. */ - @Deprecated - @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 IllegalArgumentException("No map fields found in " + getClass().getName()); - } - - /** Like {@link #internalGetMapFieldReflection} but return a mutable version. */ - @SuppressWarnings({"unused", "rawtypes"}) - protected MapFieldReflectionAccessor internalGetMutableMapFieldReflection(int fieldNumber) { - return internalGetMutableMapField(fieldNumber); - } - - /** TODO: Remove, exists for compatibility with generated code. */ - @Deprecated - @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 IllegalArgumentException("No map fields found in " + getClass().getName()); - } - } - - // ================================================================= - // Extensions-related stuff - - /** Extends {@link MessageOrBuilder} with extension-related functions. */ - public interface ExtendableMessageOrBuilder> - extends MessageOrBuilder { - // Re-define for return type covariance. - @Override - Message getDefaultInstanceForType(); - - /** Check if a singular extension is present. */ - boolean hasExtension(ExtensionLite extension); - - /** Get the number of elements in a repeated extension. */ - int getExtensionCount(ExtensionLite> extension); - - /** Get the value of an extension. */ - T getExtension(ExtensionLite extension); - - /** Get one element of a repeated extension. */ - T getExtension(ExtensionLite> extension, int index); - - /** - * Check if a singular extension is present. - *

TODO: handled by ExtensionLite version - */ - boolean hasExtension( - Extension extension); - /** - * Check if a singular extension is present. - *

TODO: handled by ExtensionLite version - */ - boolean hasExtension( - GeneratedExtension extension); - /** - * Get the number of elements in a repeated extension. - *

TODO: handled by ExtensionLite version - */ - int getExtensionCount( - Extension> extension); - /** - * Get the number of elements in a repeated extension. - *

TODO: handled by ExtensionLite version - */ - int getExtensionCount( - GeneratedExtension> extension); - /** - * Get the value of an extension. - *

TODO: handled by ExtensionLite version - */ - T getExtension( - Extension extension); - /** - * Get the value of an extension. - *

TODO: handled by ExtensionLite version - */ - T getExtension( - GeneratedExtension extension); - /** - * Get one element of a repeated extension. - *

TODO: handled by ExtensionLite version - */ - T getExtension( - Extension> extension, - int index); - /** - * Get one element of a repeated extension. - *

TODO: handled by ExtensionLite version - */ - T getExtension( - GeneratedExtension> extension, - int index); - } - - /** - * Generated message classes for message types that contain extension ranges subclass this. - * - *

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. - * - *

For example, imagine you have the {@code .proto} file: - * - *

-   * option java_class = "MyProto";
-   *
-   * message Foo {
-   *   extensions 1000 to max;
-   * }
-   *
-   * extend Foo {
-   *   optional int32 bar;
-   * }
-   * 
- * - *

Then you might write code like: - * - *

-   * MyProto.Foo foo = getFoo();
-   * int i = foo.getExtension(MyProto.bar);
-   * 
- * - *

See also {@link ExtendableBuilder}. - */ - public abstract static class ExtendableMessage> - extends GeneratedMessageV3 implements ExtendableMessageOrBuilder { - - private static final long serialVersionUID = 1L; - - private final FieldSet extensions; - - protected ExtendableMessage() { - this.extensions = FieldSet.newFieldSet(); - } - - protected ExtendableMessage(ExtendableBuilder builder) { - super(builder); - this.extensions = builder.buildExtensions(); - } - - private void verifyExtensionContainingType(final Extension 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 - public final boolean hasExtension(final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - return extensions.hasField(extension.getDescriptor()); - } - - /** Get the number of elements in a repeated extension. */ - @Override - public final int getExtensionCount(final ExtensionLite> extensionLite) { - Extension> extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - final FieldDescriptor descriptor = extension.getDescriptor(); - return extensions.getRepeatedFieldCount(descriptor); - } - - /** Get the value of an extension. */ - @Override - @SuppressWarnings("unchecked") - public final T getExtension(final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - FieldDescriptor descriptor = extension.getDescriptor(); - final Object value = extensions.getField(descriptor); - if (value == null) { - if (descriptor.isRepeated()) { - return (T) Collections.emptyList(); - } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - return (T) extension.getMessageDefaultInstance(); - } else { - return (T) extension.fromReflectionType(descriptor.getDefaultValue()); - } - } else { - return (T) extension.fromReflectionType(value); - } - } - - /** Get one element of a repeated extension. */ - @Override - @SuppressWarnings("unchecked") - public final T getExtension( - final ExtensionLite> extensionLite, final int index) { - Extension> extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - FieldDescriptor descriptor = extension.getDescriptor(); - return (T) - extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index)); - } - - /** - * Check if a singular extension is present. - *

TODO: handled by ExtensionLite version - */ - @Override - public final boolean hasExtension(final Extension extension) { - return hasExtension((ExtensionLite) extension); - } - /** - * Check if a singular extension is present. - *

TODO: handled by ExtensionLite version - */ - @Override - public final boolean hasExtension( - final GeneratedExtension extension) { - return hasExtension((ExtensionLite) extension); - } - /** - * Get the number of elements in a repeated extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final int getExtensionCount( - final Extension> extension) { - return getExtensionCount((ExtensionLite>) extension); - } - /** - * Get the number of elements in a repeated extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final int getExtensionCount( - final GeneratedExtension> extension) { - return getExtensionCount((ExtensionLite>) extension); - } - /** - * Get the value of an extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final T getExtension(final Extension extension) { - return getExtension((ExtensionLite) extension); - } - /** - * Get the value of an extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final T getExtension( - final GeneratedExtension extension) { - return getExtension((ExtensionLite) extension); - } - /** - * Get one element of a repeated extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final T getExtension( - final Extension> extension, final int index) { - return getExtension((ExtensionLite>) extension, index); - } - /** - * Get one element of a repeated extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final T getExtension( - final GeneratedExtension> extension, final int index) { - return getExtension((ExtensionLite>) extension, index); - } - - /** Called by subclasses to check if all extensions are initialized. */ - protected boolean extensionsAreInitialized() { - return extensions.isInitialized(); - } - - // TODO: compute this in the builder at {@code build()} time. - @Override - public boolean isInitialized() { - return super.isInitialized() && extensionsAreInitialized(); - } - - // TODO: remove mutating method from immutable type - @Override - protected boolean parseUnknownField( - CodedInputStream input, - UnknownFieldSet.Builder unknownFields, - ExtensionRegistryLite extensionRegistry, - int tag) - throws IOException { - return MessageReflection.mergeFieldFrom( - input, - input.shouldDiscardUnknownFields() ? null : unknownFields, - extensionRegistry, - getDescriptorForType(), - new MessageReflection.ExtensionAdapter(extensions), - tag); - } - - /** - * Delegates to parseUnknownField. This method is obsolete, but we must retain it for - * compatibility with older generated code. - * - *

TODO: remove mutating method from immutable type - */ - @Override - protected boolean parseUnknownFieldProto3( - CodedInputStream input, - UnknownFieldSet.Builder unknownFields, - ExtensionRegistryLite extensionRegistry, - int tag) - throws IOException { - return parseUnknownField(input, unknownFields, extensionRegistry, tag); - } - - /** - * Used by parsing constructors in generated classes. - * - *

TODO: remove unused method (extensions should be immutable after build) - */ - @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> iter = extensions.iterator(); - private Map.Entry 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: 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 getExtensionFields() { - return extensions.getAllFields(); - } - - @Override - public Map getAllFields() { - final Map result = - super.getAllFieldsMutable(/* getBytesForString= */ false); - result.putAll(getExtensionFields()); - return Collections.unmodifiableMap(result); - } - - @Override - public Map getAllFieldsRaw() { - final Map 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.isRepeated()) { - return Collections.emptyList(); - } else 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. - * - *

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. - * - *

For example, imagine you have the {@code .proto} file: - * - *

-   * option java_class = "MyProto";
-   *
-   * message Foo {
-   *   extensions 1000 to max;
-   * }
-   *
-   * extend Foo {
-   *   optional int32 bar;
-   * }
-   * 
- * - *

Then you might write code like: - * - *

-   * MyProto.Foo foo =
-   *   MyProto.Foo.newBuilder()
-   *     .setExtension(MyProto.bar, 123)
-   *     .build();
-   * 
- * - *

See also {@link ExtendableMessage}. - */ - @SuppressWarnings("unchecked") - public abstract static class ExtendableBuilder< - MessageT extends ExtendableMessage, - BuilderT extends ExtendableBuilder> - extends Builder implements ExtendableMessageOrBuilder { - - private FieldSet.Builder extensions; - - protected ExtendableBuilder() {} - - protected ExtendableBuilder(BuilderParent parent) { - super(parent); - } - - // For immutable message conversion. - void internalSetExtensionSet(FieldSet extensions) { - this.extensions = FieldSet.Builder.fromFieldSet(extensions); - } - - @Override - public BuilderT clear() { - extensions = null; - return super.clear(); - } - - private void ensureExtensionsIsMutable() { - if (extensions == null) { - extensions = FieldSet.newBuilder(); - } - } - - private void verifyExtensionContainingType(final Extension 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 - public final boolean hasExtension(final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - return extensions != null && extensions.hasField(extension.getDescriptor()); - } - - /** Get the number of elements in a repeated extension. */ - @Override - public final int getExtensionCount(final ExtensionLite> extensionLite) { - Extension> extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - final FieldDescriptor descriptor = extension.getDescriptor(); - return extensions == null ? 0 : extensions.getRepeatedFieldCount(descriptor); - } - - /** Get the value of an extension. */ - @Override - public final T getExtension(final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - FieldDescriptor descriptor = extension.getDescriptor(); - final Object value = extensions == null ? null : extensions.getField(descriptor); - if (value == null) { - if (descriptor.isRepeated()) { - return (T) Collections.emptyList(); - } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - return (T) extension.getMessageDefaultInstance(); - } else { - return (T) extension.fromReflectionType(descriptor.getDefaultValue()); - } - } else { - return (T) extension.fromReflectionType(value); - } - } - - /** Get one element of a repeated extension. */ - @Override - public final T getExtension( - final ExtensionLite> extensionLite, final int index) { - Extension> extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - FieldDescriptor descriptor = extension.getDescriptor(); - if (extensions == null) { - throw new IndexOutOfBoundsException(); - } - return (T) - extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index)); - } - - /** Set the value of an extension. */ - public final BuilderT setExtension( - final ExtensionLite extensionLite, final T value) { - Extension extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - ensureExtensionsIsMutable(); - final FieldDescriptor descriptor = extension.getDescriptor(); - extensions.setField(descriptor, extension.toReflectionType(value)); - onChanged(); - return (BuilderT) this; - } - - /** Set the value of one element of a repeated extension. */ - public final BuilderT setExtension( - final ExtensionLite> extensionLite, final int index, final T value) { - Extension> extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - ensureExtensionsIsMutable(); - final FieldDescriptor descriptor = extension.getDescriptor(); - extensions.setRepeatedField(descriptor, index, extension.singularToReflectionType(value)); - onChanged(); - return (BuilderT) this; - } - - /** Append a value to a repeated extension. */ - public final BuilderT addExtension( - final ExtensionLite> extensionLite, final T value) { - Extension> extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - ensureExtensionsIsMutable(); - final FieldDescriptor descriptor = extension.getDescriptor(); - extensions.addRepeatedField(descriptor, extension.singularToReflectionType(value)); - onChanged(); - return (BuilderT) this; - } - - /** Clear an extension. */ - public final BuilderT clearExtension(final ExtensionLite extensionLite) { - Extension extension = checkNotLite(extensionLite); - - verifyExtensionContainingType(extension); - ensureExtensionsIsMutable(); - extensions.clearField(extension.getDescriptor()); - onChanged(); - return (BuilderT) this; - } - - /** - * Check if a singular extension is present. - *

TODO: handled by ExtensionLite version - */ - @Override - public final boolean hasExtension(final Extension extension) { - return hasExtension((ExtensionLite) extension); - } - /** - * Check if a singular extension is present. - *

TODO: handled by ExtensionLite version - */ - @Override - public final boolean hasExtension( - final GeneratedExtension extension) { - return hasExtension((ExtensionLite) extension); - } - /** - * Get the number of elements in a repeated extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final int getExtensionCount( - final Extension> extension) { - return getExtensionCount((ExtensionLite>) extension); - } - /** - * Get the number of elements in a repeated extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final int getExtensionCount( - final GeneratedExtension> extension) { - return getExtensionCount((ExtensionLite>) extension); - } - /** - * Get the value of an extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final T getExtension(final Extension extension) { - return getExtension((ExtensionLite) extension); - } - /** Get the value of an extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final T getExtension( - final GeneratedExtension extension) { - return getExtension((ExtensionLite) extension); - } - /** - * Get the value of an extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final T getExtension( - final Extension> extension, final int index) { - return getExtension((ExtensionLite>) extension, index); - } - /** - * Get the value of an extension. - *

TODO: handled by ExtensionLite version - */ - @Override - public final T getExtension( - final GeneratedExtension> extension, final int index) { - return getExtension((ExtensionLite>) extension, index); - } - /** - * Set the value of an extension. - *

TODO: handled by ExtensionLite version - */ - public final BuilderT setExtension( - final Extension extension, final T value) { - return setExtension((ExtensionLite) extension, value); - } - /** - * Set the value of an extension. - *

TODO: handled by ExtensionLite version - */ - public BuilderT setExtension( - final GeneratedExtension extension, final T value) { - return setExtension((ExtensionLite) extension, value); - } - /** - * Set the value of one element of a repeated extension. - *

TODO: handled by ExtensionLite version - */ - public final BuilderT setExtension( - final Extension> extension, - final int index, final T value) { - return setExtension((ExtensionLite>) extension, index, value); - } - /** - * Set the value of one element of a repeated extension. - *

TODO: handled by ExtensionLite version - */ - public BuilderT setExtension( - final GeneratedExtension> extension, - final int index, final T value) { - return setExtension((ExtensionLite>) extension, index, value); - } - /** - * Append a value to a repeated extension. - *

TODO: handled by ExtensionLite version - */ - public final BuilderT addExtension( - final Extension> extension, final T value) { - return addExtension((ExtensionLite>) extension, value); - } - /** - * Append a value to a repeated extension. - *

TODO: handled by ExtensionLite version - */ - public BuilderT addExtension( - final GeneratedExtension> extension, final T value) { - return addExtension((ExtensionLite>) extension, value); - } - /** - * Clear an extension. - *

TODO: handled by ExtensionLite version - */ - public final BuilderT clearExtension( - final Extension extension) { - return clearExtension((ExtensionLite) extension); - } - /** - * Clears an extension. - *

TODO: handled by ExtensionLite version - */ - public BuilderT clearExtension( - final GeneratedExtension extension) { - return clearExtension((ExtensionLite) extension); - } - - /** Called by subclasses to check if all extensions are initialized. */ - protected boolean extensionsAreInitialized() { - return extensions == null || extensions.isInitialized(); - } - - /** - * Called by the build code path to create a copy of the extensions for building the message. - */ - private FieldSet buildExtensions() { - return extensions == null - ? (FieldSet) FieldSet.emptySet() - : extensions.buildPartial(); - } - - @Override - public boolean isInitialized() { - return super.isInitialized() && extensionsAreInitialized(); - } - - // --------------------------------------------------------------- - // Reflection - - @Override - public Map getAllFields() { - final Map result = super.getAllFieldsMutable(); - if (extensions != null) { - result.putAll(extensions.getAllFields()); - } - return Collections.unmodifiableMap(result); - } - - @Override - public Object getField(final FieldDescriptor field) { - if (field.isExtension()) { - verifyContainingType(field); - final Object value = extensions == null ? null : 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 Message.Builder getFieldBuilder(final FieldDescriptor field) { - if (field.isExtension()) { - verifyContainingType(field); - if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { - throw new UnsupportedOperationException( - "getFieldBuilder() called on a non-Message type."); - } - ensureExtensionsIsMutable(); - final Object value = extensions.getFieldAllowBuilders(field); - if (value == null) { - Message.Builder builder = DynamicMessage.newBuilder(field.getMessageType()); - extensions.setField(field, builder); - onChanged(); - return builder; - } else { - if (value instanceof Message.Builder) { - return (Message.Builder) value; - } else if (value instanceof Message) { - Message.Builder builder = ((Message) value).toBuilder(); - extensions.setField(field, builder); - onChanged(); - return builder; - } else { - throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); - } - } - } else { - return super.getFieldBuilder(field); - } - } - - @Override - public int getRepeatedFieldCount(final FieldDescriptor field) { - if (field.isExtension()) { - verifyContainingType(field); - return extensions == null ? 0 : extensions.getRepeatedFieldCount(field); - } else { - return super.getRepeatedFieldCount(field); - } - } - - @Override - public Object getRepeatedField(final FieldDescriptor field, final int index) { - if (field.isExtension()) { - verifyContainingType(field); - if (extensions == null) { - throw new IndexOutOfBoundsException(); - } - return extensions.getRepeatedField(field, index); - } else { - return super.getRepeatedField(field, index); - } - } - - @Override - public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, final int index) { - if (field.isExtension()) { - verifyContainingType(field); - ensureExtensionsIsMutable(); - if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) { - throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); - } - final Object value = extensions.getRepeatedFieldAllowBuilders(field, index); - if (value instanceof Message.Builder) { - return (Message.Builder) value; - } else if (value instanceof Message) { - Message.Builder builder = ((Message) value).toBuilder(); - extensions.setRepeatedField(field, index, builder); - onChanged(); - return builder; - } else { - throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); - } - } else { - return super.getRepeatedFieldBuilder(field, index); - } - } - - @Override - public boolean hasField(final FieldDescriptor field) { - if (field.isExtension()) { - verifyContainingType(field); - return extensions != null && extensions.hasField(field); - } else { - return super.hasField(field); - } - } - - @Override - public BuilderT setField(final FieldDescriptor field, final Object value) { - if (field.isExtension()) { - verifyContainingType(field); - ensureExtensionsIsMutable(); - extensions.setField(field, value); - onChanged(); - return (BuilderT) this; - } else { - return super.setField(field, value); - } - } - - @Override - public BuilderT clearField(final FieldDescriptor field) { - if (field.isExtension()) { - verifyContainingType(field); - ensureExtensionsIsMutable(); - extensions.clearField(field); - onChanged(); - return (BuilderT) this; - } else { - return super.clearField(field); - } - } - - @Override - public BuilderT setRepeatedField( - final FieldDescriptor field, final int index, final Object value) { - if (field.isExtension()) { - verifyContainingType(field); - ensureExtensionsIsMutable(); - extensions.setRepeatedField(field, index, value); - onChanged(); - return (BuilderT) this; - } else { - return super.setRepeatedField(field, index, value); - } - } - - @Override - public BuilderT addRepeatedField(final FieldDescriptor field, final Object value) { - if (field.isExtension()) { - verifyContainingType(field); - ensureExtensionsIsMutable(); - extensions.addRepeatedField(field, value); - onChanged(); - return (BuilderT) this; - } else { - return super.addRepeatedField(field, value); - } - } - - @Override - public Message.Builder newBuilderForField(final FieldDescriptor field) { - if (field.isExtension()) { - return DynamicMessage.newBuilder(field.getMessageType()); - } else { - return super.newBuilderForField(field); - } - } - - protected final void mergeExtensionFields(final ExtendableMessage other) { - if (other.extensions != null) { - ensureExtensionsIsMutable(); - extensions.mergeFrom(other.extensions); - onChanged(); - } - } - - @Override - protected boolean parseUnknownField( - CodedInputStream input, ExtensionRegistryLite extensionRegistry, int tag) - throws IOException { - ensureExtensionsIsMutable(); - return MessageReflection.mergeFieldFrom( - input, - input.shouldDiscardUnknownFields() ? null : getUnknownFieldSetBuilder(), - extensionRegistry, - getDescriptorForType(), - new MessageReflection.ExtensionBuilderAdapter(extensions), - tag); - } - - 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. - */ - interface ExtensionDescriptorRetriever { - FieldDescriptor getDescriptor(); - } - - // ================================================================= - - /** Calls Class.getMethod and throws a RuntimeException if it fails. */ - private static Method getMethodOrDie( - final Class clazz, final String name, final Class... params) { - try { - return clazz.getMethod(name, params); - } catch (NoSuchMethodException e) { - throw new IllegalStateException( - "Generated message class \"" + clazz.getName() + "\" missing method \"" + name + "\".", - e); - } - } - - /** Calls invoke and throws a RuntimeException if it fails. */ - @CanIgnoreReturnValue - private static Object invokeOrDie( - final Method method, final Object object, final Object... params) { - try { - return method.invoke(object, params); - } catch (IllegalAccessException e) { - throw new IllegalStateException( - "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 IllegalStateException( - "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("unused") - protected MapFieldReflectionAccessor internalGetMapFieldReflection(int fieldNumber) { - return internalGetMapField(fieldNumber); - } - - /** TODO: Remove, exists for compatibility with generated code. */ - @Deprecated - @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 IllegalArgumentException("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 messageClass, - final Class> 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; - } - - /** - * 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 messageClass, Class> 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) { - int index = fieldsSize + field.getContainingOneof().getIndex(); - if (index < camelCaseNames.length) { - containingOneofCamelCaseName = camelCaseNames[index]; - } - } - if (field.isRepeated()) { - if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { - if (field.isMapField()) { - fields[i] = new MapFieldAccessor(field, messageClass); - } 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); - } - } - } - - for (int i = 0; i < descriptor.getOneofs().size(); i++) { - if (i < descriptor.getRealOneofs().size()) { - oneofs[i] = - new RealOneofAccessor( - descriptor, i, camelCaseNames[i + fieldsSize], messageClass, builderClass); - } else { - oneofs[i] = new SyntheticOneofAccessor(descriptor, i); - } - } - - 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(GeneratedMessageV3 message); - - Object get(GeneratedMessageV3.Builder builder); - - Object getRaw(GeneratedMessageV3 message); - - void set(Builder builder, Object value); - - Object getRepeated(GeneratedMessageV3 message, int index); - - Object getRepeated(GeneratedMessageV3.Builder builder, int index); - - void setRepeated(Builder builder, int index, Object value); - - void addRepeated(Builder builder, Object value); - - boolean has(GeneratedMessageV3 message); - - boolean has(GeneratedMessageV3.Builder builder); - - int getRepeatedCount(GeneratedMessageV3 message); - - int getRepeatedCount(GeneratedMessageV3.Builder builder); - - void clear(Builder builder); - - Message.Builder newBuilder(); - - Message.Builder getBuilder(GeneratedMessageV3.Builder builder); - - Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index); - } - - /** OneofAccessor provides access to a single oneof. */ - private static interface OneofAccessor { - public boolean has(final GeneratedMessageV3 message); - - public boolean has(GeneratedMessageV3.Builder builder); - - public FieldDescriptor get(final GeneratedMessageV3 message); - - public FieldDescriptor get(GeneratedMessageV3.Builder builder); - - public void clear(final Builder builder); - } - - /** RealOneofAccessor provides access to a single real oneof. */ - private static class RealOneofAccessor implements OneofAccessor { - RealOneofAccessor( - final Descriptor descriptor, - final int oneofIndex, - final String camelCaseName, - final Class messageClass, - final Class> 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; - - @Override - public boolean has(final GeneratedMessageV3 message) { - return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() != 0; - } - - @Override - public boolean has(GeneratedMessageV3.Builder builder) { - return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() != 0; - } - - @Override - public FieldDescriptor get(final GeneratedMessageV3 message) { - int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); - if (fieldNumber > 0) { - return descriptor.findFieldByNumber(fieldNumber); - } - return null; - } - - @Override - public FieldDescriptor get(GeneratedMessageV3.Builder builder) { - int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); - if (fieldNumber > 0) { - return descriptor.findFieldByNumber(fieldNumber); - } - return null; - } - - @Override - public void clear(final Builder builder) { - // TODO: remove the unused variable - Object unused = invokeOrDie(clearMethod, builder); - } - } - - /** SyntheticOneofAccessor provides access to a single synthetic oneof. */ - private static class SyntheticOneofAccessor implements OneofAccessor { - SyntheticOneofAccessor(final Descriptor descriptor, final int oneofIndex) { - OneofDescriptor oneofDescriptor = descriptor.getOneofs().get(oneofIndex); - fieldDescriptor = oneofDescriptor.getFields().get(0); - } - - private final FieldDescriptor fieldDescriptor; - - @Override - public boolean has(final GeneratedMessageV3 message) { - return message.hasField(fieldDescriptor); - } - - @Override - public boolean has(GeneratedMessageV3.Builder builder) { - return builder.hasField(fieldDescriptor); - } - - @Override - public FieldDescriptor get(final GeneratedMessageV3 message) { - return message.hasField(fieldDescriptor) ? fieldDescriptor : null; - } - - public FieldDescriptor get(GeneratedMessageV3.Builder builder) { - return builder.hasField(fieldDescriptor) ? fieldDescriptor : null; - } - - @Override - public void clear(final Builder builder) { - builder.clearField(fieldDescriptor); - } - } - - // --------------------------------------------------------------- - - @SuppressWarnings("SameNameButDifferent") - private static class SingularFieldAccessor implements FieldAccessor { - private interface MethodInvoker { - Object get(final GeneratedMessageV3 message); - - Object get(GeneratedMessageV3.Builder builder); - - int getOneofFieldNumber(final GeneratedMessageV3 message); - - int getOneofFieldNumber(final GeneratedMessageV3.Builder builder); - - void set(final GeneratedMessageV3.Builder builder, final Object value); - - boolean has(final GeneratedMessageV3 message); - - boolean has(GeneratedMessageV3.Builder builder); - - void clear(final GeneratedMessageV3.Builder builder); - } - - private static final class ReflectionInvoker implements MethodInvoker { - private final Method getMethod; - private final Method getMethodBuilder; - private final Method setMethod; - private final Method hasMethod; - private final Method hasMethodBuilder; - private final Method clearMethod; - private final Method caseMethod; - private final Method caseMethodBuilder; - - ReflectionInvoker( - final FieldDescriptor descriptor, - final String camelCaseName, - final Class messageClass, - final Class> builderClass, - final String containingOneofCamelCaseName, - boolean isOneofField, - boolean hasHasMethod) { - getMethod = getMethodOrDie(messageClass, "get" + camelCaseName); - getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName); - Class 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; - } - - @Override - public Object get(final GeneratedMessageV3 message) { - return invokeOrDie(getMethod, message); - } - - @Override - public Object get(GeneratedMessageV3.Builder builder) { - return invokeOrDie(getMethodBuilder, builder); - } - - @Override - public int getOneofFieldNumber(final GeneratedMessageV3 message) { - return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber(); - } - - @Override - public int getOneofFieldNumber(final GeneratedMessageV3.Builder builder) { - return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber(); - } - - @Override - public void set(final GeneratedMessageV3.Builder builder, final Object value) { - // TODO: remove the unused variable - Object unused = invokeOrDie(setMethod, builder, value); - } - - @Override - public boolean has(final GeneratedMessageV3 message) { - return (Boolean) invokeOrDie(hasMethod, message); - } - - @Override - public boolean has(GeneratedMessageV3.Builder builder) { - return (Boolean) invokeOrDie(hasMethodBuilder, builder); - } - - @Override - public void clear(final GeneratedMessageV3.Builder builder) { - // TODO: remove the unused variable - Object unused = invokeOrDie(clearMethod, builder); - } - } - - SingularFieldAccessor( - final FieldDescriptor descriptor, - final String camelCaseName, - final Class messageClass, - final Class> builderClass, - final String containingOneofCamelCaseName) { - isOneofField = - descriptor.getRealContainingOneof() != null; - hasHasMethod = descriptor.hasPresence(); - ReflectionInvoker reflectionInvoker = - new ReflectionInvoker( - descriptor, - camelCaseName, - messageClass, - builderClass, - containingOneofCamelCaseName, - isOneofField, - hasHasMethod); - field = descriptor; - type = reflectionInvoker.getMethod.getReturnType(); - invoker = getMethodInvoker(reflectionInvoker); - } - - static MethodInvoker getMethodInvoker(ReflectionInvoker accessor) { - return accessor; - } - - // 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 FieldDescriptor field; - protected final boolean isOneofField; - protected final boolean hasHasMethod; - protected final MethodInvoker invoker; - - @Override - public Object get(final GeneratedMessageV3 message) { - return invoker.get(message); - } - - @Override - public Object get(GeneratedMessageV3.Builder builder) { - return invoker.get(builder); - } - - @Override - public Object getRaw(final GeneratedMessageV3 message) { - return get(message); - } - - @Override - public void set(final Builder builder, final Object value) { - invoker.set(builder, value); - } - - @Override - public Object getRepeated(final GeneratedMessageV3 message, final int index) { - throw new UnsupportedOperationException("getRepeatedField() called on a singular field."); - } - - @Override - public Object getRepeated(GeneratedMessageV3.Builder builder, int index) { - throw new UnsupportedOperationException("getRepeatedField() called on a singular field."); - } - - @Override - public void setRepeated(final Builder builder, final int index, final Object value) { - throw new UnsupportedOperationException("setRepeatedField() called on a singular field."); - } - - @Override - public void addRepeated(final Builder builder, final Object value) { - throw new UnsupportedOperationException("addRepeatedField() called on a singular field."); - } - - @Override - public boolean has(final GeneratedMessageV3 message) { - if (!hasHasMethod) { - if (isOneofField) { - return invoker.getOneofFieldNumber(message) == field.getNumber(); - } - return !get(message).equals(field.getDefaultValue()); - } - return invoker.has(message); - } - - @Override - public boolean has(GeneratedMessageV3.Builder builder) { - if (!hasHasMethod) { - if (isOneofField) { - return invoker.getOneofFieldNumber(builder) == field.getNumber(); - } - return !get(builder).equals(field.getDefaultValue()); - } - return invoker.has(builder); - } - - @Override - public int getRepeatedCount(final GeneratedMessageV3 message) { - throw new UnsupportedOperationException( - "getRepeatedFieldSize() called on a singular field."); - } - - @Override - public int getRepeatedCount(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException( - "getRepeatedFieldSize() called on a singular field."); - } - - @Override - public void clear(final Builder builder) { - invoker.clear(builder); - } - - @Override - public Message.Builder newBuilder() { - throw new UnsupportedOperationException( - "newBuilderForField() called on a non-Message type."); - } - - @Override - public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); - } - - @Override - public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) { - throw new UnsupportedOperationException( - "getRepeatedFieldBuilder() called on a non-Message type."); - } - } - - @SuppressWarnings("SameNameButDifferent") - private static class RepeatedFieldAccessor implements FieldAccessor { - interface MethodInvoker { - Object get(final GeneratedMessageV3 message); - - Object get(GeneratedMessageV3.Builder builder); - - Object getRepeated(final GeneratedMessageV3 message, final int index); - - Object getRepeated(GeneratedMessageV3.Builder builder, int index); - - void setRepeated( - final GeneratedMessageV3.Builder builder, final int index, final Object value); - - void addRepeated(final GeneratedMessageV3.Builder builder, final Object value); - - int getRepeatedCount(final GeneratedMessageV3 message); - - int getRepeatedCount(GeneratedMessageV3.Builder builder); - - void clear(final GeneratedMessageV3.Builder builder); - } - - private static final class ReflectionInvoker implements MethodInvoker { - private final Method getMethod; - private final Method getMethodBuilder; - private final Method getRepeatedMethod; - private final Method getRepeatedMethodBuilder; - private final Method setRepeatedMethod; - private final Method addRepeatedMethod; - private final Method getCountMethod; - private final Method getCountMethodBuilder; - private final Method clearMethod; - - ReflectionInvoker( - final FieldDescriptor descriptor, - final String camelCaseName, - final Class messageClass, - final Class> 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); - Class 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); - } - - @Override - public Object get(final GeneratedMessageV3 message) { - return invokeOrDie(getMethod, message); - } - - @Override - public Object get(GeneratedMessageV3.Builder builder) { - return invokeOrDie(getMethodBuilder, builder); - } - - @Override - public Object getRepeated(final GeneratedMessageV3 message, final int index) { - return invokeOrDie(getRepeatedMethod, message, index); - } - - @Override - public Object getRepeated(GeneratedMessageV3.Builder builder, int index) { - return invokeOrDie(getRepeatedMethodBuilder, builder, index); - } - - @Override - public void setRepeated( - final GeneratedMessageV3.Builder builder, final int index, final Object value) { - // TODO: remove the unused variable - Object unused = invokeOrDie(setRepeatedMethod, builder, index, value); - } - - @Override - public void addRepeated(final GeneratedMessageV3.Builder builder, final Object value) { - // TODO: remove the unused variable - Object unused = invokeOrDie(addRepeatedMethod, builder, value); - } - - @Override - public int getRepeatedCount(final GeneratedMessageV3 message) { - return (Integer) invokeOrDie(getCountMethod, message); - } - - @Override - public int getRepeatedCount(GeneratedMessageV3.Builder builder) { - return (Integer) invokeOrDie(getCountMethodBuilder, builder); - } - - @Override - public void clear(final GeneratedMessageV3.Builder builder) { - // TODO: remove the unused variable - Object unused = invokeOrDie(clearMethod, builder); - } - } - - protected final Class type; - protected final MethodInvoker invoker; - - RepeatedFieldAccessor( - final FieldDescriptor descriptor, - final String camelCaseName, - final Class messageClass, - final Class> builderClass) { - ReflectionInvoker reflectionInvoker = - new ReflectionInvoker(descriptor, camelCaseName, messageClass, builderClass); - type = reflectionInvoker.getRepeatedMethod.getReturnType(); - invoker = getMethodInvoker(reflectionInvoker); - } - - static MethodInvoker getMethodInvoker(ReflectionInvoker accessor) { - return accessor; - } - - @Override - public Object get(final GeneratedMessageV3 message) { - return invoker.get(message); - } - - @Override - public Object get(GeneratedMessageV3.Builder builder) { - return invoker.get(builder); - } - - @Override - public Object getRaw(final GeneratedMessageV3 message) { - return get(message); - } - - @Override - 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); - } - } - - @Override - public Object getRepeated(final GeneratedMessageV3 message, final int index) { - return invoker.getRepeated(message, index); - } - - @Override - public Object getRepeated(GeneratedMessageV3.Builder builder, int index) { - return invoker.getRepeated(builder, index); - } - - @Override - public void setRepeated(final Builder builder, final int index, final Object value) { - invoker.setRepeated(builder, index, value); - } - - @Override - public void addRepeated(final Builder builder, final Object value) { - invoker.addRepeated(builder, value); - } - - @Override - public boolean has(final GeneratedMessageV3 message) { - throw new UnsupportedOperationException("hasField() called on a repeated field."); - } - - @Override - public boolean has(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException("hasField() called on a repeated field."); - } - - @Override - public int getRepeatedCount(final GeneratedMessageV3 message) { - return invoker.getRepeatedCount(message); - } - - @Override - public int getRepeatedCount(GeneratedMessageV3.Builder builder) { - return invoker.getRepeatedCount(builder); - } - - @Override - public void clear(final Builder builder) { - invoker.clear(builder); - } - - @Override - public Message.Builder newBuilder() { - throw new UnsupportedOperationException( - "newBuilderForField() called on a non-Message type."); - } - - @Override - public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) { - throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type."); - } - - @Override - public Message.Builder getRepeatedBuilder(GeneratedMessageV3.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 Class messageClass) { - field = descriptor; - Method getDefaultInstanceMethod = getMethodOrDie(messageClass, "getDefaultInstance"); - MapFieldReflectionAccessor defaultMapField = - getMapField((GeneratedMessageV3) invokeOrDie(getDefaultInstanceMethod, null)); - mapEntryMessageDefaultInstance = defaultMapField.getMapEntryMessageDefaultInstance(); - } - - private final FieldDescriptor field; - private final Message mapEntryMessageDefaultInstance; - - private MapFieldReflectionAccessor getMapField(GeneratedMessageV3 message) { - return message.internalGetMapFieldReflection(field.getNumber()); - } - - private MapFieldReflectionAccessor getMapField(GeneratedMessageV3.Builder builder) { - return builder.internalGetMapFieldReflection(field.getNumber()); - } - - private MapFieldReflectionAccessor getMutableMapField(GeneratedMessageV3.Builder builder) { - return builder.internalGetMutableMapFieldReflection(field.getNumber()); - } - - private Message coerceType(Message value) { - if (value == null) { - return null; - } - if (mapEntryMessageDefaultInstance.getClass().isInstance(value)) { - return value; - } - // 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 mapEntryMessageDefaultInstance.toBuilder().mergeFrom(value).build(); - } - - @Override - public Object get(GeneratedMessageV3 message) { - List result = new ArrayList<>(); - for (int i = 0; i < getRepeatedCount(message); i++) { - result.add(getRepeated(message, i)); - } - return Collections.unmodifiableList(result); - } - - @Override - 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); - } - - @Override - public Object getRaw(GeneratedMessageV3 message) { - return get(message); - } - - @Override - public void set(Builder builder, Object value) { - clear(builder); - for (Object entry : (List) value) { - addRepeated(builder, entry); - } - } - - @Override - public Object getRepeated(GeneratedMessageV3 message, int index) { - return getMapField(message).getList().get(index); - } - - @Override - public Object getRepeated(Builder builder, int index) { - return getMapField(builder).getList().get(index); - } - - @Override - public void setRepeated(Builder builder, int index, Object value) { - getMutableMapField(builder).getMutableList().set(index, coerceType((Message) value)); - } - - @Override - public void addRepeated(Builder builder, Object value) { - getMutableMapField(builder).getMutableList().add(coerceType((Message) value)); - } - - @Override - public boolean has(GeneratedMessageV3 message) { - throw new UnsupportedOperationException("hasField() is not supported for repeated fields."); - } - - @Override - public boolean has(Builder builder) { - throw new UnsupportedOperationException("hasField() is not supported for repeated fields."); - } - - @Override - public int getRepeatedCount(GeneratedMessageV3 message) { - return getMapField(message).getList().size(); - } - - @Override - public int getRepeatedCount(Builder builder) { - return getMapField(builder).getList().size(); - } - - @Override - public void clear(Builder builder) { - getMutableMapField(builder).getMutableList().clear(); - } - - @Override - public Message.Builder newBuilder() { - return mapEntryMessageDefaultInstance.newBuilderForType(); - } - - @Override - public Message.Builder getBuilder(Builder builder) { - throw new UnsupportedOperationException("Nested builder not supported for map fields."); - } - - @Override - public Message.Builder getRepeatedBuilder(Builder builder, int index) { - throw new UnsupportedOperationException("Map fields cannot be repeated"); - } - } - - // --------------------------------------------------------------- - - private static final class SingularEnumFieldAccessor extends SingularFieldAccessor { - SingularEnumFieldAccessor( - final FieldDescriptor descriptor, - final String camelCaseName, - final Class messageClass, - final Class> 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.legacyEnumFieldTreatedAsClosed(); - if (supportUnknownEnumValue) { - getValueMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Value"); - getValueMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Value"); - setValueMethod = getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class); - } - } - - private final EnumDescriptor enumDescriptor; - - private final Method valueOfMethod; - private final Method getValueDescriptorMethod; - - private final boolean supportUnknownEnumValue; - private Method getValueMethod; - private Method getValueMethodBuilder; - private Method setValueMethod; - - @Override - public Object get(final GeneratedMessageV3 message) { - if (supportUnknownEnumValue) { - int value = (Integer) invokeOrDie(getValueMethod, message); - return enumDescriptor.findValueByNumberCreatingIfUnknown(value); - } - return invokeOrDie(getValueDescriptorMethod, super.get(message)); - } - - @Override - public Object get(final GeneratedMessageV3.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) { - // TODO: remove the unused variable - Object unused = - 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 messageClass, - final Class> builderClass) { - super(descriptor, camelCaseName, messageClass, builderClass); - - enumDescriptor = descriptor.getEnumType(); - - valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class); - getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor"); - - supportUnknownEnumValue = !descriptor.legacyEnumFieldTreatedAsClosed(); - 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 final EnumDescriptor enumDescriptor; - - private final Method valueOfMethod; - private final Method getValueDescriptorMethod; - - private final boolean supportUnknownEnumValue; - - private Method getRepeatedValueMethod; - private Method getRepeatedValueMethodBuilder; - private Method setRepeatedValueMethod; - private Method addRepeatedValueMethod; - - @Override - public Object get(final GeneratedMessageV3 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 - public Object get(final GeneratedMessageV3.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 GeneratedMessageV3 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 GeneratedMessageV3.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) { - // TODO: remove the unused variable - Object unused = - 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) { - // TODO: remove the unused variable - Object unused = - invokeOrDie( - addRepeatedValueMethod, builder, ((EnumValueDescriptor) value).getNumber()); - return; - } - super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value)); - } - } - - // --------------------------------------------------------------- - - /** - * Field accessor for string fields. - * - *

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. - * - *

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 messageClass, - final Class> builderClass, - final String containingOneofCamelCaseName) { - super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName); - getBytesMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Bytes"); - setBytesMethodBuilder = - getMethodOrDie(builderClass, "set" + camelCaseName + "Bytes", ByteString.class); - } - - private final Method getBytesMethod; - private final Method setBytesMethodBuilder; - - @Override - public Object getRaw(final GeneratedMessageV3 message) { - return invokeOrDie(getBytesMethod, message); - } - - @Override - public void set(GeneratedMessageV3.Builder builder, Object value) { - if (value instanceof ByteString) { - // TODO: remove the unused variable - Object unused = 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 messageClass, - final Class> 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(GeneratedMessageV3.Builder builder) { - return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder); - } - } - - private static final class RepeatedMessageFieldAccessor extends RepeatedFieldAccessor { - RepeatedMessageFieldAccessor( - final FieldDescriptor descriptor, - final String camelCaseName, - final Class messageClass, - final Class> 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 GeneratedMessageV3.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 , T> - Extension checkNotLite(ExtensionLite extension) { - if (extension.isLite()) { - throw new IllegalArgumentException("Expected non-lite extension."); - } - - return (Extension) extension; - } - - protected static boolean isStringEmpty(final Object value) { - if (value instanceof String) { - return ((String) value).isEmpty(); - } else { - return ((ByteString) value).isEmpty(); - } - } - - 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); - } - } - - protected static void serializeIntegerMapTo( - CodedOutputStream out, - MapField field, - MapEntry defaultEntry, - int fieldNumber) - throws IOException { - Map m = field.getMap(); - if (!out.isSerializationDeterministic()) { - serializeMapTo(out, m, defaultEntry, fieldNumber); - return; - } - // Sorting the unboxed keys and then look up the values during serialization is 2x faster - // than sorting map entries with a custom comparator directly. - int[] keys = new int[m.size()]; - int index = 0; - for (int k : m.keySet()) { - keys[index++] = k; - } - Arrays.sort(keys); - for (int key : keys) { - out.writeMessage( - fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build()); - } - } - - protected static void serializeLongMapTo( - CodedOutputStream out, - MapField field, - MapEntry defaultEntry, - int fieldNumber) - throws IOException { - Map m = field.getMap(); - if (!out.isSerializationDeterministic()) { - serializeMapTo(out, m, defaultEntry, fieldNumber); - return; - } - - long[] keys = new long[m.size()]; - int index = 0; - for (long k : m.keySet()) { - keys[index++] = k; - } - Arrays.sort(keys); - for (long key : keys) { - out.writeMessage( - fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build()); - } - } - - protected static void serializeStringMapTo( - CodedOutputStream out, - MapField field, - MapEntry defaultEntry, - int fieldNumber) - throws IOException { - Map m = field.getMap(); - if (!out.isSerializationDeterministic()) { - serializeMapTo(out, m, defaultEntry, fieldNumber); - return; - } - - // Sorting the String keys and then look up the values during serialization is 25% faster than - // sorting map entries with a custom comparator directly. - String[] keys = new String[m.size()]; - keys = m.keySet().toArray(keys); - Arrays.sort(keys); - for (String key : keys) { - out.writeMessage( - fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build()); - } - } - - protected static void serializeBooleanMapTo( - CodedOutputStream out, - MapField field, - MapEntry defaultEntry, - int fieldNumber) - throws IOException { - Map m = field.getMap(); - if (!out.isSerializationDeterministic()) { - serializeMapTo(out, m, defaultEntry, fieldNumber); - return; - } - maybeSerializeBooleanEntryTo(out, m, defaultEntry, fieldNumber, false); - maybeSerializeBooleanEntryTo(out, m, defaultEntry, fieldNumber, true); - } - - private static void maybeSerializeBooleanEntryTo( - CodedOutputStream out, - Map m, - MapEntry defaultEntry, - int fieldNumber, - boolean key) - throws IOException { - if (m.containsKey(key)) { - out.writeMessage( - fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build()); - } - } - - /** Serialize the map using the iteration order. */ - private static void serializeMapTo( - CodedOutputStream out, Map m, MapEntry defaultEntry, int fieldNumber) - throws IOException { - for (Map.Entry entry : m.entrySet()) { - out.writeMessage( - fieldNumber, - defaultEntry - .newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build()); - } - } -} diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java index aacec0a55a..2c839aa659 100644 --- a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java +++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java @@ -10,7 +10,7 @@ package com.google.protobuf; final class NewInstanceSchemaFull implements NewInstanceSchema { @Override public Object newInstance(Object defaultInstance) { - return ((GeneratedMessageV3) defaultInstance) - .newInstance(GeneratedMessageV3.UnusedPrivateParameter.INSTANCE); + return ((GeneratedMessage) defaultInstance) + .newInstance(GeneratedMessage.UnusedPrivateParameter.INSTANCE); } } diff --git a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java deleted file mode 100644 index b36794ffa9..0000000000 --- a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java +++ /dev/null @@ -1,647 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd - -package com.google.protobuf; - -import static com.google.protobuf.Internal.checkNotNull; - -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.RandomAccess; - -/** - * {@code RepeatedFieldBuilderV3} implements a structure that a protocol message uses to hold a - * repeated field of other protocol messages. It supports the classical use case of adding immutable - * {@link Message}'s to the repeated field and is highly optimized around this (no extra memory - * allocations and sharing of immutable arrays).
- * It also supports the additional use case of adding a {@link Message.Builder} to the repeated - * field and deferring conversion of that {@code Builder} to an immutable {@code Message}. In this - * way, it's possible to maintain a tree of {@code Builder}'s that acts as a fully read/write data - * structure.
- * Logically, one can think of a tree of builders as converting the entire tree to messages when - * build is called on the root or when any method is called that desires a Message instead of a - * Builder. In terms of the implementation, the {@code SingleFieldBuilderV3} and {@code - * RepeatedFieldBuilderV3} classes cache messages that were created so that messages only need to be - * created when some change occurred in its builder or a builder for one of its descendants. - * - * @param the type of message for the field - * @param the type of builder for the field - * @param the common interface for the message and the builder - * @author jonp@google.com (Jon Perlow) - */ -public class RepeatedFieldBuilderV3< - MType extends AbstractMessage, - BType extends AbstractMessage.Builder, - IType extends MessageOrBuilder> - implements AbstractMessage.BuilderParent { - - // Parent to send changes to. - private AbstractMessage.BuilderParent parent; - - // List of messages. Never null. It may be immutable, in which case - // isMessagesListMutable will be false. See note below. - private List messages; - - // Whether messages is an mutable array that can be modified. - private boolean isMessagesListMutable; - - // List of builders. May be null, in which case, no nested builders were - // created. If not null, entries represent the builder for that index. - private List> builders; - - // Here are the invariants for messages and builders: - // 1. messages is never null and its count corresponds to the number of items - // in the repeated field. - // 2. If builders is non-null, messages and builders MUST always - // contain the same number of items. - // 3. Entries in either array can be null, but for any index, there MUST be - // either a Message in messages or a builder in builders. - // 4. If the builder at an index is non-null, the builder is - // authoritative. This is the case where a Builder was set on the index. - // Any message in the messages array MUST be ignored. - // t. If the builder at an index is null, the message in the messages - // list is authoritative. This is the case where a Message (not a Builder) - // was set directly for an index. - - // Indicates that we've built a message and so we are now obligated - // to dispatch dirty invalidations. See AbstractMessage.BuilderListener. - private boolean isClean; - - // A view of this builder that exposes a List interface of messages. This is - // initialized on demand. This is fully backed by this object and all changes - // are reflected in it. Access to any item converts it to a message if it - // was a builder. - private MessageExternalList externalMessageList; - - // A view of this builder that exposes a List interface of builders. This is - // initialized on demand. This is fully backed by this object and all changes - // are reflected in it. Access to any item converts it to a builder if it - // was a message. - private BuilderExternalList externalBuilderList; - - // A view of this builder that exposes a List interface of the interface - // implemented by messages and builders. This is initialized on demand. This - // is fully backed by this object and all changes are reflected in it. - // Access to any item returns either a builder or message depending on - // what is most efficient. - private MessageOrBuilderExternalList externalMessageOrBuilderList; - - /** - * Constructs a new builder with an empty list of messages. - * - * @param messages the current list of messages - * @param isMessagesListMutable Whether the messages list is mutable - * @param parent a listener to notify of changes - * @param isClean whether the builder is initially marked clean - */ - public RepeatedFieldBuilderV3( - List messages, - boolean isMessagesListMutable, - AbstractMessage.BuilderParent parent, - boolean isClean) { - this.messages = messages; - this.isMessagesListMutable = isMessagesListMutable; - this.parent = parent; - this.isClean = isClean; - } - - public void dispose() { - // Null out parent so we stop sending it invalidations. - parent = null; - } - - /** - * Ensures that the list of messages is mutable so it can be updated. If it's immutable, a copy is - * made. - */ - private void ensureMutableMessageList() { - if (!isMessagesListMutable) { - messages = new ArrayList(messages); - isMessagesListMutable = true; - } - } - - /** - * Ensures that the list of builders is not null. If it's null, the list is created and - * initialized to be the same size as the messages list with null entries. - */ - private void ensureBuilders() { - if (this.builders == null) { - this.builders = new ArrayList>(messages.size()); - for (int i = 0; i < messages.size(); i++) { - builders.add(null); - } - } - } - - /** - * Gets the count of items in the list. - * - * @return the count of items in the list. - */ - public int getCount() { - return messages.size(); - } - - /** - * Gets whether the list is empty. - * - * @return whether the list is empty - */ - public boolean isEmpty() { - return messages.isEmpty(); - } - - /** - * Get the message at the specified index. If the message is currently stored as a {@code - * Builder}, it is converted to a {@code Message} by calling {@link Message.Builder#buildPartial} - * on it. - * - * @param index the index of the message to get - * @return the message for the specified index - */ - public MType getMessage(int index) { - return getMessage(index, false); - } - - /** - * Get the message at the specified index. If the message is currently stored as a {@code - * Builder}, it is converted to a {@code Message} by calling {@link Message.Builder#buildPartial} - * on it. - * - * @param index the index of the message to get - * @param forBuild this is being called for build so we want to make sure we - * SingleFieldBuilderV3.build to send dirty invalidations - * @return the message for the specified index - */ - private MType getMessage(int index, boolean forBuild) { - if (this.builders == null) { - // We don't have any builders -- return the current Message. - // This is the case where no builder was created, so we MUST have a - // Message. - return messages.get(index); - } - - SingleFieldBuilderV3 builder = builders.get(index); - if (builder == null) { - // We don't have a builder -- return the current message. - // This is the case where no builder was created for the entry at index, - // so we MUST have a message. - return messages.get(index); - - } else { - return forBuild ? builder.build() : builder.getMessage(); - } - } - - /** - * Gets a builder for the specified index. If no builder has been created for that index, a - * builder is created on demand by calling {@link Message#toBuilder}. - * - * @param index the index of the message to get - * @return The builder for that index - */ - public BType getBuilder(int index) { - ensureBuilders(); - SingleFieldBuilderV3 builder = builders.get(index); - if (builder == null) { - MType message = messages.get(index); - builder = new SingleFieldBuilderV3(message, this, isClean); - builders.set(index, builder); - } - return builder.getBuilder(); - } - - /** - * Gets the base class interface for the specified index. This may either be a builder or a - * message. It will return whatever is more efficient. - * - * @param index the index of the message to get - * @return the message or builder for the index as the base class interface - */ - @SuppressWarnings("unchecked") - public IType getMessageOrBuilder(int index) { - if (this.builders == null) { - // We don't have any builders -- return the current Message. - // This is the case where no builder was created, so we MUST have a - // Message. - return (IType) messages.get(index); - } - - SingleFieldBuilderV3 builder = builders.get(index); - if (builder == null) { - // We don't have a builder -- return the current message. - // This is the case where no builder was created for the entry at index, - // so we MUST have a message. - return (IType) messages.get(index); - - } else { - return builder.getMessageOrBuilder(); - } - } - - /** - * Sets a message at the specified index replacing the existing item at that index. - * - * @param index the index to set. - * @param message the message to set - * @return the builder - */ - @CanIgnoreReturnValue - public RepeatedFieldBuilderV3 setMessage(int index, MType message) { - checkNotNull(message); - ensureMutableMessageList(); - messages.set(index, message); - if (builders != null) { - SingleFieldBuilderV3 entry = builders.set(index, null); - if (entry != null) { - entry.dispose(); - } - } - onChanged(); - incrementModCounts(); - return this; - } - - /** - * Appends the specified element to the end of this list. - * - * @param message the message to add - * @return the builder - */ - @CanIgnoreReturnValue - public RepeatedFieldBuilderV3 addMessage(MType message) { - checkNotNull(message); - ensureMutableMessageList(); - messages.add(message); - if (builders != null) { - builders.add(null); - } - onChanged(); - incrementModCounts(); - return this; - } - - /** - * Inserts the specified message at the specified position in this list. Shifts the element - * currently at that position (if any) and any subsequent elements to the right (adds one to their - * indices). - * - * @param index the index at which to insert the message - * @param message the message to add - * @return the builder - */ - @CanIgnoreReturnValue - public RepeatedFieldBuilderV3 addMessage(int index, MType message) { - checkNotNull(message); - ensureMutableMessageList(); - messages.add(index, message); - if (builders != null) { - builders.add(index, null); - } - onChanged(); - incrementModCounts(); - return this; - } - - /** - * Appends all of the messages in the specified collection to the end of this list, in the order - * that they are returned by the specified collection's iterator. - * - * @param values the messages to add - * @return the builder - */ - @CanIgnoreReturnValue - public RepeatedFieldBuilderV3 addAllMessages( - Iterable values) { - for (final MType value : values) { - checkNotNull(value); - } - - // If we can inspect the size, we can more efficiently add messages. - int size = -1; - if (values instanceof Collection) { - final Collection collection = (Collection) values; - if (collection.isEmpty()) { - return this; - } - size = collection.size(); - } - ensureMutableMessageList(); - - if (size >= 0 && messages instanceof ArrayList) { - ((ArrayList) messages).ensureCapacity(messages.size() + size); - } - - for (MType value : values) { - addMessage(value); - } - - onChanged(); - incrementModCounts(); - return this; - } - - /** - * Appends a new builder to the end of this list and returns the builder. - * - * @param message the message to add which is the basis of the builder - * @return the new builder - */ - public BType addBuilder(MType message) { - ensureMutableMessageList(); - ensureBuilders(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3(message, this, isClean); - messages.add(null); - builders.add(builder); - onChanged(); - incrementModCounts(); - return builder.getBuilder(); - } - - /** - * Inserts a new builder at the specified position in this list. Shifts the element currently at - * that position (if any) and any subsequent elements to the right (adds one to their indices). - * - * @param index the index at which to insert the builder - * @param message the message to add which is the basis of the builder - * @return the builder - */ - public BType addBuilder(int index, MType message) { - ensureMutableMessageList(); - ensureBuilders(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3(message, this, isClean); - messages.add(index, null); - builders.add(index, builder); - onChanged(); - incrementModCounts(); - return builder.getBuilder(); - } - - /** - * Removes the element at the specified position in this list. Shifts any subsequent elements to - * the left (subtracts one from their indices). - * - * @param index the index at which to remove the message - */ - public void remove(int index) { - ensureMutableMessageList(); - messages.remove(index); - if (builders != null) { - SingleFieldBuilderV3 entry = builders.remove(index); - if (entry != null) { - entry.dispose(); - } - } - onChanged(); - incrementModCounts(); - } - - /** Removes all of the elements from this list. The list will be empty after this call returns. */ - public void clear() { - messages = Collections.emptyList(); - isMessagesListMutable = false; - if (builders != null) { - for (SingleFieldBuilderV3 entry : builders) { - if (entry != null) { - entry.dispose(); - } - } - builders = null; - } - onChanged(); - incrementModCounts(); - } - - /** - * Builds the list of messages from the builder and returns them. - * - * @return an immutable list of messages - */ - public List build() { - // Now that build has been called, we are required to dispatch - // invalidations. - isClean = true; - - if (!isMessagesListMutable && builders == null) { - // We still have an immutable list and we never created a builder. - return messages; - } - - boolean allMessagesInSync = true; - if (!isMessagesListMutable) { - // We still have an immutable list. Let's see if any of them are out - // of sync with their builders. - for (int i = 0; i < messages.size(); i++) { - Message message = messages.get(i); - SingleFieldBuilderV3 builder = builders.get(i); - if (builder != null) { - if (builder.build() != message) { - allMessagesInSync = false; - break; - } - } - } - if (allMessagesInSync) { - // Immutable list is still in sync. - return messages; - } - } - - // Need to make sure messages is up to date - ensureMutableMessageList(); - for (int i = 0; i < messages.size(); i++) { - messages.set(i, getMessage(i, true)); - } - - // We're going to return our list as immutable so we mark that we can - // no longer update it. - messages = Collections.unmodifiableList(messages); - isMessagesListMutable = false; - return messages; - } - - /** - * Gets a view of the builder as a list of messages. The returned list is live and will reflect - * any changes to the underlying builder. - * - * @return the messages in the list - */ - public List getMessageList() { - if (externalMessageList == null) { - externalMessageList = new MessageExternalList(this); - } - return externalMessageList; - } - - /** - * Gets a view of the builder as a list of builders. This returned list is live and will reflect - * any changes to the underlying builder. - * - * @return the builders in the list - */ - public List getBuilderList() { - if (externalBuilderList == null) { - externalBuilderList = new BuilderExternalList(this); - } - return externalBuilderList; - } - - /** - * Gets a view of the builder as a list of MessageOrBuilders. This returned list is live and will - * reflect any changes to the underlying builder. - * - * @return the builders in the list - */ - public List getMessageOrBuilderList() { - if (externalMessageOrBuilderList == null) { - externalMessageOrBuilderList = new MessageOrBuilderExternalList(this); - } - return externalMessageOrBuilderList; - } - - /** - * Called when a the builder or one of its nested children has changed and any parent should be - * notified of its invalidation. - */ - private void onChanged() { - if (isClean && parent != null) { - parent.markDirty(); - - // Don't keep dispatching invalidations until build is called again. - isClean = false; - } - } - - @Override - public void markDirty() { - onChanged(); - } - - /** - * Increments the mod counts so that an ConcurrentModificationException can be thrown if calling - * code tries to modify the builder while its iterating the list. - */ - private void incrementModCounts() { - if (externalMessageList != null) { - externalMessageList.incrementModCount(); - } - if (externalBuilderList != null) { - externalBuilderList.incrementModCount(); - } - if (externalMessageOrBuilderList != null) { - externalMessageOrBuilderList.incrementModCount(); - } - } - - /** - * Provides a live view of the builder as a list of messages. - * - * @param the type of message for the field - * @param the type of builder for the field - * @param the common interface for the message and the builder - */ - private static class MessageExternalList< - MType extends AbstractMessage, - BType extends AbstractMessage.Builder, - IType extends MessageOrBuilder> - extends AbstractList implements List, RandomAccess { - - RepeatedFieldBuilderV3 builder; - - MessageExternalList(RepeatedFieldBuilderV3 builder) { - this.builder = builder; - } - - @Override - public int size() { - return this.builder.getCount(); - } - - @Override - public MType get(int index) { - return builder.getMessage(index); - } - - void incrementModCount() { - modCount++; - } - } - - /** - * Provides a live view of the builder as a list of builders. - * - * @param the type of message for the field - * @param the type of builder for the field - * @param the common interface for the message and the builder - */ - private static class BuilderExternalList< - MType extends AbstractMessage, - BType extends AbstractMessage.Builder, - IType extends MessageOrBuilder> - extends AbstractList implements List, RandomAccess { - - RepeatedFieldBuilderV3 builder; - - BuilderExternalList(RepeatedFieldBuilderV3 builder) { - this.builder = builder; - } - - @Override - public int size() { - return this.builder.getCount(); - } - - @Override - public BType get(int index) { - return builder.getBuilder(index); - } - - void incrementModCount() { - modCount++; - } - } - - /** - * Provides a live view of the builder as a list of builders. - * - * @param the type of message for the field - * @param the type of builder for the field - * @param the common interface for the message and the builder - */ - private static class MessageOrBuilderExternalList< - MType extends AbstractMessage, - BType extends AbstractMessage.Builder, - IType extends MessageOrBuilder> - extends AbstractList implements List, RandomAccess { - - RepeatedFieldBuilderV3 builder; - - MessageOrBuilderExternalList(RepeatedFieldBuilderV3 builder) { - this.builder = builder; - } - - @Override - public int size() { - return this.builder.getCount(); - } - - @Override - public IType get(int index) { - return builder.getMessageOrBuilder(index); - } - - void incrementModCount() { - modCount++; - } - } -} diff --git a/java/core/src/main/java/com/google/protobuf/SchemaUtil.java b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java index ecc9b2a326..1eb6870764 100644 --- a/java/core/src/main/java/com/google/protobuf/SchemaUtil.java +++ b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java @@ -31,7 +31,7 @@ final class SchemaUtil { private SchemaUtil() {} /** - * Requires that the given message extend {@link com.google.protobuf.GeneratedMessageV3} or {@link + * Requires that the given message extend {@link com.google.protobuf.GeneratedMessage} or {@link * GeneratedMessageLite}. */ public static void requireGeneratedMessage(Class messageType) { @@ -41,7 +41,7 @@ final class SchemaUtil { && GENERATED_MESSAGE_CLASS != null && !GENERATED_MESSAGE_CLASS.isAssignableFrom(messageType)) { throw new IllegalArgumentException( - "Message classes must extend GeneratedMessageV3 or GeneratedMessageLite"); + "Message classes must extend GeneratedMessage or GeneratedMessageLite"); } } @@ -784,7 +784,7 @@ final class SchemaUtil { try { // TODO decide if we're keeping support for Full in schema classes and handle // this better. - return Class.forName("com.google.protobuf.GeneratedMessageV3"); + return Class.forName("com.google.protobuf.GeneratedMessage"); } catch (Throwable e) { return null; } diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java deleted file mode 100644 index 0aff2b82a3..0000000000 --- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java +++ /dev/null @@ -1,210 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd - -package com.google.protobuf; - -import static com.google.protobuf.Internal.checkNotNull; - -/** - * {@code SingleFieldBuilderV3} implements a structure that a protocol message uses to hold a single - * field of another protocol message. It supports the classical use case of setting an immutable - * {@link Message} as the value of the field and is highly optimized around this. - * - *

It also supports the additional use case of setting a {@link Message.Builder} as the field and - * deferring conversion of that {@code Builder} to an immutable {@code Message}. In this way, it's - * possible to maintain a tree of {@code Builder}'s that acts as a fully read/write data structure. - *
- * Logically, one can think of a tree of builders as converting the entire tree to messages when - * build is called on the root or when any method is called that desires a Message instead of a - * Builder. In terms of the implementation, the {@code SingleFieldBuilderV3} and {@code - * RepeatedFieldBuilderV3} classes cache messages that were created so that messages only need to be - * created when some change occurred in its builder or a builder for one of its descendants. - * - * @param the type of message for the field - * @param the type of builder for the field - * @param the common interface for the message and the builder - * @author jonp@google.com (Jon Perlow) - */ -public class SingleFieldBuilderV3< - MType extends AbstractMessage, - BType extends AbstractMessage.Builder, - IType extends MessageOrBuilder> - implements AbstractMessage.BuilderParent { - - // Parent to send changes to. - private AbstractMessage.BuilderParent parent; - - // Invariant: one of builder or message fields must be non-null. - - // If set, this is the case where we are backed by a builder. In this case, - // message field represents a cached message for the builder (or null if - // there is no cached message). - private BType builder; - - // If builder is non-null, this represents a cached message from the builder. - // If builder is null, this is the authoritative message for the field. - private MType message; - - // Indicates that we've built a message and so we are now obligated - // to dispatch dirty invalidations. See AbstractMessage.BuilderListener. - private boolean isClean; - - public SingleFieldBuilderV3(MType message, AbstractMessage.BuilderParent parent, boolean isClean) { - this.message = checkNotNull(message); - this.parent = parent; - this.isClean = isClean; - } - - public void dispose() { - // Null out parent so we stop sending it invalidations. - parent = null; - } - - /** - * Get the message for the field. If the message is currently stored as a {@code Builder}, it is - * converted to a {@code Message} by calling {@link Message.Builder#buildPartial} on it. If no - * message has been set, returns the default instance of the message. - * - * @return the message for the field - */ - @SuppressWarnings("unchecked") - public MType getMessage() { - if (message == null) { - // If message is null, the invariant is that we must be have a builder. - message = (MType) builder.buildPartial(); - } - return message; - } - - /** - * Builds the message and returns it. - * - * @return the message - */ - public MType build() { - // Now that build has been called, we are required to dispatch - // invalidations. - isClean = true; - return getMessage(); - } - - /** - * Gets a builder for the field. If no builder has been created yet, a builder is created on - * demand by calling {@link Message#toBuilder}. - * - * @return The builder for the field - */ - @SuppressWarnings("unchecked") - public BType getBuilder() { - if (builder == null) { - // builder.mergeFrom() on a fresh builder - // does not create any sub-objects with independent clean/dirty states, - // therefore setting the builder itself to clean without actually calling - // build() cannot break any invariants. - builder = (BType) message.newBuilderForType(this); - builder.mergeFrom(message); // no-op if message is the default message - builder.markClean(); - } - return builder; - } - - /** - * Gets the base class interface for the field. This may either be a builder or a message. It will - * return whatever is more efficient. - * - * @return the message or builder for the field as the base class interface - */ - @SuppressWarnings("unchecked") - public IType getMessageOrBuilder() { - if (builder != null) { - return (IType) builder; - } else { - return (IType) message; - } - } - - /** - * Sets a message for the field replacing any existing value. - * - * @param message the message to set - * @return the builder - */ - @CanIgnoreReturnValue - public SingleFieldBuilderV3 setMessage(MType message) { - this.message = checkNotNull(message); - if (builder != null) { - builder.dispose(); - builder = null; - } - onChanged(); - return this; - } - - /** - * Merges the field from another field. - * - * @param value the value to merge from - * @return the builder - */ - @CanIgnoreReturnValue - public SingleFieldBuilderV3 mergeFrom(MType value) { - if (builder == null && message == message.getDefaultInstanceForType()) { - message = value; - } else { - getBuilder().mergeFrom(value); - } - onChanged(); - return this; - } - - /** - * Clears the value of the field. - * - * @return the builder - */ - @SuppressWarnings("unchecked") - @CanIgnoreReturnValue - public SingleFieldBuilderV3 clear() { - message = - (MType) - (message != null - ? message.getDefaultInstanceForType() - : builder.getDefaultInstanceForType()); - if (builder != null) { - builder.dispose(); - builder = null; - } - onChanged(); - // After clearing, parent is dirty, but this field builder is now clean and any changes should - // trickle up. - isClean = true; - return this; - } - - /** - * Called when a the builder or one of its nested children has changed and any parent should be - * notified of its invalidation. - */ - private void onChanged() { - // If builder is null, this is the case where onChanged is being called - // from setMessage or clear. - if (builder != null) { - message = null; - } - if (isClean && parent != null) { - parent.markDirty(); - - // Don't keep dispatching invalidations until build is called again. - isClean = false; - } - } - - @Override - public void markDirty() { - onChanged(); - } -} diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java index e1eccccea3..d60deba181 100644 --- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java +++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java @@ -65,22 +65,22 @@ class UnknownFieldSetSchema extends UnknownFieldSchema> ignored = + Class> ignored = TestAllExtensions.Builder.class; } diff --git a/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java b/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java similarity index 86% rename from java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java rename to java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java index 8cc552713e..19587e588e 100644 --- a/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java +++ b/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java @@ -19,17 +19,17 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** - * Tests for {@link RepeatedFieldBuilderV3}. This tests basic functionality. More extensive testing is + * Tests for {@link RepeatedFieldBuilder}. This tests basic functionality. More extensive testing is * provided via other tests that exercise the builder. */ @RunWith(JUnit4.class) -public class RepeatedFieldBuilderV3Test { +public class RepeatedFieldBuilderTest { @Test public void testBasicUse() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - RepeatedFieldBuilderV3 builder = - newRepeatedFieldBuilderV3(mockParent); + RepeatedFieldBuilder builder = + newRepeatedFieldBuilder(mockParent); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); assertThat(builder.getMessage(0).getOptionalInt32()).isEqualTo(0); @@ -50,8 +50,8 @@ public class RepeatedFieldBuilderV3Test { @Test public void testGoingBackAndForth() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - RepeatedFieldBuilderV3 builder = - newRepeatedFieldBuilderV3(mockParent); + RepeatedFieldBuilder builder = + newRepeatedFieldBuilder(mockParent); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); assertThat(builder.getMessage(0).getOptionalInt32()).isEqualTo(0); @@ -80,8 +80,8 @@ public class RepeatedFieldBuilderV3Test { @Test public void testVariousMethods() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - RepeatedFieldBuilderV3 builder = - newRepeatedFieldBuilderV3(mockParent); + RepeatedFieldBuilder builder = + newRepeatedFieldBuilder(mockParent); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build()); builder.addBuilder(0, TestAllTypes.getDefaultInstance()).setOptionalInt32(0); @@ -122,8 +122,8 @@ public class RepeatedFieldBuilderV3Test { @Test public void testLists() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - RepeatedFieldBuilderV3 builder = - newRepeatedFieldBuilderV3(mockParent); + RepeatedFieldBuilder builder = + newRepeatedFieldBuilder(mockParent); builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build()); builder.addMessage(0, TestAllTypes.newBuilder().setOptionalInt32(0).build()); assertThat(builder.getMessage(0).getOptionalInt32()).isEqualTo(0); @@ -160,9 +160,9 @@ public class RepeatedFieldBuilderV3Test { } } - private RepeatedFieldBuilderV3 - newRepeatedFieldBuilderV3(AbstractMessage.BuilderParent parent) { - return new RepeatedFieldBuilderV3( + private RepeatedFieldBuilder + newRepeatedFieldBuilder(GeneratedMessage.BuilderParent parent) { + return new RepeatedFieldBuilder( Collections.emptyList(), false, parent, false); } } diff --git a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java similarity index 82% rename from java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java rename to java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java index e316176199..e1806110d4 100644 --- a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java +++ b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderTest.java @@ -16,17 +16,17 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** - * Tests for {@link SingleFieldBuilderV3}. This tests basic functionality. More extensive testing is + * Tests for {@link SingleFieldBuilder}. This tests basic functionality. More extensive testing is * provided via other tests that exercise the builder. */ @RunWith(JUnit4.class) -public class SingleFieldBuilderV3Test { +public class SingleFieldBuilderTest { @Test public void testBasicUseAndInvalidations() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3<>(TestAllTypes.getDefaultInstance(), mockParent, false); + SingleFieldBuilder builder = + new SingleFieldBuilder<>(TestAllTypes.getDefaultInstance(), mockParent, false); assertThat(builder.getMessage()).isSameInstanceAs(TestAllTypes.getDefaultInstance()); assertThat(builder.getBuilder().buildPartial()).isEqualTo(TestAllTypes.getDefaultInstance()); assertThat(mockParent.getInvalidationCount()).isEqualTo(0); @@ -49,8 +49,8 @@ public class SingleFieldBuilderV3Test { @Test public void testSetMessage() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3<>(TestAllTypes.getDefaultInstance(), mockParent, false); + SingleFieldBuilder builder = + new SingleFieldBuilder<>(TestAllTypes.getDefaultInstance(), mockParent, false); builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); assertThat(builder.getMessage().getOptionalInt32()).isEqualTo(0); @@ -71,8 +71,8 @@ public class SingleFieldBuilderV3Test { @Test public void testClear() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3<>(TestAllTypes.getDefaultInstance(), mockParent, false); + SingleFieldBuilder builder = + new SingleFieldBuilder<>(TestAllTypes.getDefaultInstance(), mockParent, false); builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build()); assertThat(TestAllTypes.getDefaultInstance()).isNotSameInstanceAs(builder.getMessage()); builder.clear(); @@ -87,8 +87,8 @@ public class SingleFieldBuilderV3Test { @Test public void testMerge() { TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent(); - SingleFieldBuilderV3 builder = - new SingleFieldBuilderV3<>(TestAllTypes.getDefaultInstance(), mockParent, false); + SingleFieldBuilder builder = + new SingleFieldBuilder<>(TestAllTypes.getDefaultInstance(), mockParent, false); // Merge into default field. builder.mergeFrom(TestAllTypes.getDefaultInstance()); diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt index 2723f27831..9f62a3f7e4 100644 --- a/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt +++ b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt @@ -31,25 +31,25 @@ package com.google.protobuf.kotlin import com.google.protobuf.ExtensionLite -import com.google.protobuf.GeneratedMessageV3 +import com.google.protobuf.GeneratedMessage /** Sets the current value of the proto extension in this builder. */ operator fun < - M : GeneratedMessageV3.ExtendableMessage, - B : GeneratedMessageV3.ExtendableBuilder, + M : GeneratedMessage.ExtendableMessage, + B : GeneratedMessage.ExtendableBuilder, T : Any> B.set(extension: ExtensionLite, value: T) { setExtension(extension, value) } /** Gets the current value of the proto extension. */ operator fun < - M : GeneratedMessageV3.ExtendableMessage, - MorBT : GeneratedMessageV3.ExtendableMessageOrBuilder, + M : GeneratedMessage.ExtendableMessage, + MorBT : GeneratedMessage.ExtendableMessageOrBuilder, T : Any> MorBT.get(extension: ExtensionLite): T = getExtension(extension) /** Returns true if the specified extension is set on this builder. */ operator fun < - M : GeneratedMessageV3.ExtendableMessage, - MorBT : GeneratedMessageV3.ExtendableMessageOrBuilder> MorBT.contains( + M : GeneratedMessage.ExtendableMessage, + MorBT : GeneratedMessage.ExtendableMessageOrBuilder> MorBT.contains( extension: ExtensionLite ): Boolean = hasExtension(extension) diff --git a/java/lite/pom.xml b/java/lite/pom.xml index 38621da3ff..a94789eff9 100644 --- a/java/lite/pom.xml +++ b/java/lite/pom.xml @@ -224,10 +224,10 @@ Proto2ExtensionLookupSchemaTest.java Proto2SchemaTest.java Proto2UnknownEnumValueTest.java - RepeatedFieldBuilderV3Test.java + RepeatedFieldBuilderTest.java RuntimeVersionTest.java ServiceTest.java - SingleFieldBuilderV3Test.java + SingleFieldBuilderTest.java TestBadIdentifiers.java TextFormatParseInfoTreeTest.java TextFormatParseLocationTest.java diff --git a/src/google/protobuf/compiler/java/helpers.h b/src/google/protobuf/compiler/java/helpers.h index ab6786446f..33fc9675ba 100644 --- a/src/google/protobuf/compiler/java/helpers.h +++ b/src/google/protobuf/compiler/java/helpers.h @@ -386,10 +386,6 @@ inline bool CheckUtf8(const FieldDescriptor* descriptor) { descriptor->file()->options().java_string_check_utf8(); } -inline std::string GeneratedCodeVersionSuffix() { - return "V3"; -} - void WriteUInt32ToUtf16CharSequence(uint32_t number, std::vector* output); diff --git a/src/google/protobuf/compiler/java/map_field.cc b/src/google/protobuf/compiler/java/map_field.cc index 18e2c09cef..258418fb37 100644 --- a/src/google/protobuf/compiler/java/map_field.cc +++ b/src/google/protobuf/compiler/java/map_field.cc @@ -184,8 +184,6 @@ void ImmutableMapFieldGenerator::SetMessageVariables( variables_["descriptor"] = absl::StrCat( name_resolver->GetImmutableClassName(descriptor_->file()), ".internal_", UniqueFileScopeIdentifier(descriptor_->message_type()), "_descriptor, "); - variables_["ver"] = GeneratedCodeVersionSuffix(); - variables_["get_has_field_bit_builder"] = GenerateGetBit(builder_bit_index_); variables_["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builder_bit_index_); @@ -1132,7 +1130,7 @@ void ImmutableMapFieldGenerator::GenerateBuilderParsingCode( void ImmutableMapFieldGenerator::GenerateSerializationCode( io::Printer* printer) const { printer->Print(variables_, - "com.google.protobuf.GeneratedMessage$ver$\n" + "com.google.protobuf.GeneratedMessage\n" " .serialize$short_key_type$MapTo(\n" " output,\n" " internalGet$capitalized_name$(),\n" diff --git a/src/google/protobuf/compiler/java/message.cc b/src/google/protobuf/compiler/java/message.cc index 04bc3ec9b7..57003839ca 100644 --- a/src/google/protobuf/compiler/java/message.cc +++ b/src/google/protobuf/compiler/java/message.cc @@ -187,12 +187,10 @@ void ImmutableMessageGenerator::GenerateFieldAccessorTable( } else { vars["final"] = ""; } - vars["ver"] = GeneratedCodeVersionSuffix(); - printer->Print( - vars, - "$private$static $final$\n" - " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" - " internal_$identifier$_fieldAccessorTable;\n"); + printer->Print(vars, + "$private$static $final$\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internal_$identifier$_fieldAccessorTable;\n"); // The following bytecode_estimate calculation logic must stay in sync with // the similar logic in the GenerateFieldAccessorTableInitializer method below @@ -209,11 +207,10 @@ int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer( int bytecode_estimate = 10; printer->Print( "internal_$identifier$_fieldAccessorTable = new\n" - " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" " internal_$identifier$_descriptor,\n" " new java.lang.String[] { ", - "identifier", UniqueFileScopeIdentifier(descriptor_), "ver", - GeneratedCodeVersionSuffix()); + "identifier", UniqueFileScopeIdentifier(descriptor_)); // All the bytecode_estimate calculation logic in this method must stay in // sync with the similar logic in the GenerateFieldAccessorTable method // above. See the corresponding comment in GenerateFieldAccessorTable for @@ -247,13 +244,12 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { printer->Print( "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n" " $extra_interfaces$\n" - " com.google.protobuf.GeneratedMessage$ver$.\n" + " com.google.protobuf.GeneratedMessage.\n" " ExtendableMessageOrBuilder<$classname$> {\n", "deprecation", descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "", "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name(), "{", "", "}", "", "ver", - GeneratedCodeVersionSuffix()); + "classname", descriptor_->name(), "{", "", "}", ""); } else { printer->Print( "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n" @@ -296,7 +292,6 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { variables["static"] = is_own_file ? "" : "static "; variables["classname"] = descriptor_->name(); variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_); - variables["ver"] = GeneratedCodeVersionSuffix(); variables["deprecation"] = descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""; @@ -316,26 +311,23 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { printer->Annotate("classname", descriptor_); printer->Print( variables, - " com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n" + " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" " $classname$> implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n"); builder_type = absl::Substitute( - "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", - name_resolver_->GetImmutableClassName(descriptor_), - GeneratedCodeVersionSuffix()); + "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>", + name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print( variables, "$deprecation$public $static$final class $classname$ extends\n"); printer->Annotate("classname", descriptor_); printer->Print(variables, - " com.google.protobuf.GeneratedMessage$ver$ implements\n" + " com.google.protobuf.GeneratedMessage implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n"); - builder_type = - absl::Substitute("com.google.protobuf.GeneratedMessage$0.Builder", - GeneratedCodeVersionSuffix()); + builder_type = "com.google.protobuf.GeneratedMessage.Builder"; } printer->Print("private static final long serialVersionUID = 0L;\n"); @@ -596,18 +588,16 @@ void ImmutableMessageGenerator::GenerateMessageSerializationMethods( if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { printer->Print( - "com.google.protobuf.GeneratedMessage$ver$\n" + "com.google.protobuf.GeneratedMessage\n" " .ExtendableMessage<$classname$>.ExtensionWriter\n" " extensionWriter = newMessageSetExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print( - "com.google.protobuf.GeneratedMessage$ver$\n" + "com.google.protobuf.GeneratedMessage\n" " .ExtendableMessage<$classname$>.ExtensionWriter\n" " extensionWriter = newExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "ver", GeneratedCodeVersionSuffix()); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } } @@ -701,21 +691,21 @@ void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(java.io.InputStream input)\n" " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" + " return com.google.protobuf.GeneratedMessage\n" " .parseWithIOException(PARSER, input);\n" "}\n" "public static $classname$ parseFrom(\n" " java.io.InputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" + " return com.google.protobuf.GeneratedMessage\n" " .parseWithIOException(PARSER, input, extensionRegistry);\n" "}\n" "$parsedelimitedreturnannotation$\n" "public static $classname$ parseDelimitedFrom(java.io.InputStream " "input)\n" " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" + " return com.google.protobuf.GeneratedMessage\n" " .parseDelimitedWithIOException(PARSER, input);\n" "}\n" "$parsedelimitedreturnannotation$\n" @@ -723,26 +713,26 @@ void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) { " java.io.InputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" + " return com.google.protobuf.GeneratedMessage\n" " .parseDelimitedWithIOException(PARSER, input, " "extensionRegistry);\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input)\n" " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" + " return com.google.protobuf.GeneratedMessage\n" " .parseWithIOException(PARSER, input);\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage$ver$\n" + " return com.google.protobuf.GeneratedMessage\n" " .parseWithIOException(PARSER, input, extensionRegistry);\n" "}\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver", - GeneratedCodeVersionSuffix(), "parsedelimitedreturnannotation", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "parsedelimitedreturnannotation", context_->options().opensource_runtime ? "" : "@com.google.protobuf.Internal.ProtoMethodMayReturnNull"); @@ -774,11 +764,10 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( "@java.lang.Override\n" "protected Builder newBuilderForType(\n" - " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" " Builder builder = new Builder(parent);\n" " return builder;\n" - "}\n", - "ver", GeneratedCodeVersionSuffix()); + "}\n"); MessageBuilderGenerator builderGenerator(descriptor_, context_); builderGenerator.Generate(printer); @@ -835,7 +824,7 @@ void ImmutableMessageGenerator::GenerateDescriptorMethods( } printer->Print( "@java.lang.Override\n" - "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" " internalGetFieldAccessorTable() {\n" " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" " .ensureFieldAccessorsInitialized(\n" @@ -844,8 +833,7 @@ void ImmutableMessageGenerator::GenerateDescriptorMethods( "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_), "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_), "ver", - GeneratedCodeVersionSuffix()); + "identifier", UniqueFileScopeIdentifier(descriptor_)); } // =================================================================== diff --git a/src/google/protobuf/compiler/java/message_builder.cc b/src/google/protobuf/compiler/java/message_builder.cc index 15c60823c2..5f23adf704 100644 --- a/src/google/protobuf/compiler/java/message_builder.cc +++ b/src/google/protobuf/compiler/java/message_builder.cc @@ -95,23 +95,21 @@ void MessageBuilderGenerator::Generate(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { printer->Print( "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage$ver$.ExtendableBuilder<\n" + " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" " $classname$, Builder> implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n", "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "ver", - GeneratedCodeVersionSuffix()); + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage$ver$.Builder " + " com.google.protobuf.GeneratedMessage.Builder " "implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n", "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "ver", - GeneratedCodeVersionSuffix()); + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } printer->Indent(); @@ -277,7 +275,7 @@ void MessageBuilderGenerator::GenerateDescriptorMethods(io::Printer* printer) { } printer->Print( "@java.lang.Override\n" - "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" " internalGetFieldAccessorTable() {\n" " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" " .ensureFieldAccessorsInitialized(\n" @@ -286,8 +284,7 @@ void MessageBuilderGenerator::GenerateDescriptorMethods(io::Printer* printer) { "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_), "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_), "ver", - GeneratedCodeVersionSuffix()); + "identifier", UniqueFileScopeIdentifier(descriptor_)); } // =================================================================== @@ -322,19 +319,18 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods( printer->Print( "private Builder(\n" - " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" " super(parent);\n" "$force_builder_init$\n" "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver", - GeneratedCodeVersionSuffix(), "force_builder_init", force_builder_init); + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "force_builder_init", force_builder_init); if (need_maybe_force_builder_init) { printer->Print( "private void maybeForceBuilderInitialization() {\n" - " if (com.google.protobuf.GeneratedMessage$ver$\n" - " .alwaysUseFieldBuilders) {\n", - "ver", GeneratedCodeVersionSuffix()); + " if (com.google.protobuf.GeneratedMessage\n" + " .alwaysUseFieldBuilders) {\n"); printer->Indent(); printer->Indent(); diff --git a/src/google/protobuf/compiler/java/message_field.cc b/src/google/protobuf/compiler/java/message_field.cc index 2bc8a578c2..3036813205 100644 --- a/src/google/protobuf/compiler/java/message_field.cc +++ b/src/google/protobuf/compiler/java/message_field.cc @@ -60,7 +60,6 @@ void SetMessageVariables( (*variables)["name"], " is deprecated\") ") : ""}); (*variables)["on_changed"] = "onChanged();"; - (*variables)["ver"] = GeneratedCodeVersionSuffix(); (*variables)["get_parser"] = "parser()"; if (HasHasbit(descriptor)) { @@ -232,7 +231,7 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, // If this builder is non-null, it is used and the other fields // are ignored. - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" + "private com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" "\n"); @@ -357,11 +356,11 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print( variables_, - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" + "private com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder> \n" " get$capitalized_name$FieldBuilder() {\n" " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder>(\n" " get$capitalized_name$(),\n" " getParentForChildren(),\n" @@ -568,7 +567,7 @@ void ImmutableMessageOneofFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, // If this builder is non-null, it is used and the other fields // are ignored. - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" + "private com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" "\n"); @@ -709,14 +708,14 @@ void ImmutableMessageOneofFieldGenerator::GenerateBuilderMembers( WriteFieldDocComment(printer, descriptor_, context_->options()); printer->Print( variables_, - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" + "private com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder> \n" " ${$get$capitalized_name$FieldBuilder$}$() {\n" " if ($name$Builder_ == null) {\n" " if (!($has_oneof_case_message$)) {\n" " $oneof_name$_ = $type$.getDefaultInstance();\n" " }\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder>(\n" " ($type$) $oneof_name$_,\n" " getParentForChildren(),\n" @@ -958,7 +957,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( variables_, // If this builder is non-null, it is used and the other fields are // ignored. - "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n" + "private com.google.protobuf.RepeatedFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" "\n"); @@ -1204,12 +1203,12 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( " ${$get$capitalized_name$BuilderList$}$() {\n" " return get$capitalized_name$FieldBuilder().getBuilderList();\n" "}\n" - "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n" + "private com.google.protobuf.RepeatedFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder> \n" " get$capitalized_name$FieldBuilder() {\n" " if ($name$Builder_ == null) {\n" " $name$Builder_ = new " - "com.google.protobuf.RepeatedFieldBuilder$ver$<\n" + "com.google.protobuf.RepeatedFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder>(\n" " $name$_,\n" " $get_mutable_bit_builder$,\n" @@ -1270,7 +1269,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMergingCode( " $name$_ = other.$name$_;\n" " $clear_mutable_bit_builder$;\n" " $name$Builder_ = \n" - " com.google.protobuf.GeneratedMessage$ver$.alwaysUseFieldBuilders " + " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders " "?\n" " get$capitalized_name$FieldBuilder() : null;\n" " } else {\n" diff --git a/src/google/protobuf/compiler/java/string_field.cc b/src/google/protobuf/compiler/java/string_field.cc index e34051ea1c..11b06ff4fd 100644 --- a/src/google/protobuf/compiler/java/string_field.cc +++ b/src/google/protobuf/compiler/java/string_field.cc @@ -59,14 +59,11 @@ void SetPrimitiveVariables( (*variables)["null_check"] = "if (value == null) { throw new NullPointerException(); }"; (*variables)["isStringEmpty"] = - absl::StrCat("com.google.protobuf.GeneratedMessage", - GeneratedCodeVersionSuffix(), ".isStringEmpty"); + "com.google.protobuf.GeneratedMessage.isStringEmpty"; (*variables)["writeString"] = - absl::StrCat("com.google.protobuf.GeneratedMessage", - GeneratedCodeVersionSuffix(), ".writeString"); + "com.google.protobuf.GeneratedMessage.writeString"; (*variables)["computeStringSize"] = - absl::StrCat("com.google.protobuf.GeneratedMessage", - GeneratedCodeVersionSuffix(), ".computeStringSize"); + "com.google.protobuf.GeneratedMessage.computeStringSize"; // TODO: Add @deprecated javadoc when generating javadoc is supported // by the proto compiler