// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf;
import 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;
// In opensource protobuf, we have versioned this GeneratedMessageV3 class to GeneratedMessageV3V3 and
// in the future may have GeneratedMessageV3V4 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 GeneratedMessageV3V? classes to
// interoperate (e.g., a GeneratedMessageV3V3 object has a message extension field whose class
// type is GeneratedMessageV3V4), these classes still share a common parent class AbstractMessage
// and are using the same GeneratedMessage.GeneratedExtension class for extension definitions.
// Since this class becomes GeneratedMessageV3V? 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. */
protected
UnknownFieldSet unknownFields;
protected
GeneratedMessageV3() {
unknownFields =
UnknownFieldSet.
getDefaultInstance();
}
protected
GeneratedMessageV3(
Builder<?>
builder) {
unknownFields =
builder.
getUnknownFields();
}
@
Override
public
Parser<? extends
GeneratedMessageV3>
getParserForType() {
throw new
UnsupportedOperationException(
"This is supposed to be overridden by subclasses.");
}
/**
* For testing. Allows a test to disable the optimization that avoids using
* field builders for nested messages until they are requested. By disabling
* this optimization, existing tests can be reused to test the field builders.
* See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
*/
static void
enableAlwaysUseFieldBuildersForTesting() {
alwaysUseFieldBuilders = true;
}
/**
* Get the FieldAccessorTable for this type. We can't have the message
* class pass this in to the constructor because of bootstrapping trouble
* with DescriptorProtos.
*/
protected abstract
FieldAccessorTable internalGetFieldAccessorTable();
@
Override
public
Descriptor getDescriptorForType() {
return
internalGetFieldAccessorTable().
descriptor;
}
/**
* Internal helper to return a modifiable map containing all the fields.
* The returned Map is modifialbe so that the caller can add additional
* extension fields to implement {@link #getAllFields()}.
*
* @param getBytesForString whether to generate ByteString for string fields
*/
private
Map<
FieldDescriptor,
Object>
getAllFieldsMutable(
boolean
getBytesForString) {
final
TreeMap<
FieldDescriptor,
Object>
result =
new
TreeMap<
FieldDescriptor,
Object>();
final
Descriptor descriptor =
internalGetFieldAccessorTable().
descriptor;
final
List<
FieldDescriptor>
fields =
descriptor.
getFields();
for (int
i = 0;
i <
fields.
size();
i++) {
FieldDescriptor field =
fields.
get(
i);
final
OneofDescriptor oneofDescriptor =
field.
getContainingOneof();
/*
* If the field is part of a Oneof, then at maximum one field in the Oneof is set
* and it is not repeated. There is no need to iterate through the others.
*/
if (
oneofDescriptor != null) {
// Skip other fields in the Oneof we know are not set
i +=
oneofDescriptor.
getFieldCount() - 1;
if (!
hasOneof(
oneofDescriptor)) {
// If no field is set in the Oneof, skip all the fields in the Oneof
continue;
}
// Get the pointer to the only field which is set in the Oneof
field =
getOneofFieldDescriptor(
oneofDescriptor);
} else {
// If we are not in a Oneof, we need to check if the field is set and if it is repeated
if (
field.
isRepeated()) {
final
List<?>
value = (
List<?>)
getField(
field);
if (!
value.
isEmpty()) {
result.
put(
field,
value);
}
continue;
}
if (!
hasField(
field)) {
continue;
}
}
// Add the field to the map
if (
getBytesForString &&
field.
getJavaType() ==
FieldDescriptor.
JavaType.
STRING) {
result.
put(
field,
getFieldRaw(
field));
} else {
result.
put(
field,
getField(
field));
}
}
return
result;
}
@
Override
public boolean
isInitialized() {
for (final
FieldDescriptor field :
getDescriptorForType().
getFields()) {
// Check that all required fields are present.
if (
field.
isRequired()) {
if (!
hasField(
field)) {
return false;
}
}
// Check that embedded messages are initialized.
if (
field.
getJavaType() ==
FieldDescriptor.
JavaType.
MESSAGE) {
if (
field.
isRepeated()) {
@
SuppressWarnings("unchecked") final
List<
Message>
messageList = (
List<
Message>)
getField(
field);
for (final
Message element :
messageList) {
if (!
element.
isInitialized()) {
return false;
}
}
} else {
if (
hasField(
field) && !((
Message)
getField(
field)).
isInitialized()) {
return false;
}
}
}
}
return true;
}
@
Override
public
Map<
FieldDescriptor,
Object>
getAllFields() {
return
Collections.
unmodifiableMap(
getAllFieldsMutable(/* getBytesForString = */ false));
}
/**
* Returns a collection of all the fields in this message which are set
* and their corresponding values. A singular ("required" or "optional")
* field is set iff hasField() returns true for that field. A "repeated"
* field is set iff getRepeatedFieldCount() is greater than zero. The
* values are exactly what would be returned by calling
* {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field. The map
* is guaranteed to be a sorted map, so iterating over it will return fields
* in order by field number.
*/
Map<
FieldDescriptor,
Object>
getAllFieldsRaw() {
return
Collections.
unmodifiableMap(
getAllFieldsMutable(/* getBytesForString = */ true));
}
@
Override
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);
}
@
Override
public
UnknownFieldSet getUnknownFields() {
throw new
UnsupportedOperationException(
"This is supposed to be overridden by subclasses.");
}
/**
* Called by subclasses to parse an unknown field.
*
* @return {@code true} unless the tag is an end-group tag.
*/
protected boolean
parseUnknownField(
CodedInputStream input,
UnknownFieldSet.
Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int
tag)
throws
IOException {
if (
input.
shouldDiscardUnknownFields()) {
return
input.
skipField(
tag);
}
return
unknownFields.
mergeFieldFrom(
tag,
input);
}
protected boolean
parseUnknownFieldProto3(
CodedInputStream input,
UnknownFieldSet.
Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int
tag)
throws
IOException {
if (
input.
shouldDiscardUnknownFieldsProto3()) {
return
input.
skipField(
tag);
}
return
unknownFields.
mergeFieldFrom(
tag,
input);
}
protected static <M extends
Message> M
parseWithIOException(
Parser<M>
parser,
InputStream input)
throws
IOException {
try {
return
parser.
parseFrom(
input);
} catch (
InvalidProtocolBufferException e) {
throw
e.
unwrapIOException();
}
}
protected static <M extends
Message> M
parseWithIOException(
Parser<M>
parser,
InputStream input,
ExtensionRegistryLite extensions) throws
IOException {
try {
return
parser.
parseFrom(
input,
extensions);
} catch (
InvalidProtocolBufferException e) {
throw
e.
unwrapIOException();
}
}
protected static <M extends
Message> M
parseWithIOException(
Parser<M>
parser,
CodedInputStream input) throws
IOException {
try {
return
parser.
parseFrom(
input);
} catch (
InvalidProtocolBufferException e) {
throw
e.
unwrapIOException();
}
}
protected static <M extends
Message> M
parseWithIOException(
Parser<M>
parser,
CodedInputStream input,
ExtensionRegistryLite extensions) throws
IOException {
try {
return
parser.
parseFrom(
input,
extensions);
} catch (
InvalidProtocolBufferException e) {
throw
e.
unwrapIOException();
}
}
protected static <M extends
Message> M
parseDelimitedWithIOException(
Parser<M>
parser,
InputStream input) throws
IOException {
try {
return
parser.
parseDelimitedFrom(
input);
} catch (
InvalidProtocolBufferException e) {
throw
e.
unwrapIOException();
}
}
protected static <M extends
Message> M
parseDelimitedWithIOException(
Parser<M>
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();
}
@
Override
public void
writeTo(final
CodedOutputStream output) throws
IOException {
MessageReflection.
writeMessageTo(this,
getAllFieldsRaw(),
output, false);
}
@
Override
public int
getSerializedSize() {
int
size =
memoizedSize;
if (
size != -1) {
return
size;
}
memoizedSize =
MessageReflection.
getSerializedSize(
this,
getAllFieldsRaw());
return
memoizedSize;
}
/**
* Used by parsing constructors in generated classes.
*/
protected void
makeExtensionsImmutable() {
// Noop for messages without extensions.
}
/**
* TODO(xiaofeng): 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 exlude this from google3.
*/
protected interface
BuilderParent extends
AbstractMessage.
BuilderParent {}
/**
* TODO(xiaofeng): remove this together with GeneratedMessageV3.BuilderParent.
*/
protected abstract
Message.
Builder newBuilderForType(
BuilderParent parent);
@
Override
protected
Message.
Builder newBuilderForType(final
AbstractMessage.
BuilderParent parent) {
return
newBuilderForType(new
BuilderParent() {
@
Override
public void
markDirty() {
parent.
markDirty();
}
});
}
@
SuppressWarnings("unchecked")
public abstract static class
Builder <BuilderType extends
Builder<BuilderType>>
extends
AbstractMessage.
Builder<BuilderType> {
private
BuilderParent builderParent;
private
BuilderParentImpl meAsParent;
// Indicates that we've built a message and so we are now obligated
// to dispatch dirty invalidations. See GeneratedMessageV3.BuilderListener.
private boolean
isClean;
private
UnknownFieldSet unknownFields =
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 BuilderType
clone() {
BuilderType
builder =
(BuilderType)
getDefaultInstanceForType().
newBuilderForType();
builder.
mergeFrom(
buildPartial());
return
builder;
}
/**
* Called by the initialization and clear code paths to allow subclasses to
* reset any of their builtin fields back to the initial values.
*/
@
Override
public BuilderType
clear() {
unknownFields =
UnknownFieldSet.
getDefaultInstance();
onChanged();
return (BuilderType) this;
}
/**
* Get the FieldAccessorTable for this type. We can't have the message
* class pass this in to the constructor because of bootstrapping trouble
* with DescriptorProtos.
*/
protected abstract
FieldAccessorTable internalGetFieldAccessorTable();
@
Override
public
Descriptor getDescriptorForType() {
return
internalGetFieldAccessorTable().
descriptor;
}
@
Override
public
Map<
FieldDescriptor,
Object>
getAllFields() {
return
Collections.
unmodifiableMap(
getAllFieldsMutable());
}
/** Internal helper which returns a mutable map. */
private
Map<
FieldDescriptor,
Object>
getAllFieldsMutable() {
final
TreeMap<
FieldDescriptor,
Object>
result =
new
TreeMap<
FieldDescriptor,
Object>();
final
Descriptor descriptor =
internalGetFieldAccessorTable().
descriptor;
final
List<
FieldDescriptor>
fields =
descriptor.
getFields();
for (int
i = 0;
i <
fields.
size();
i++) {
FieldDescriptor field =
fields.
get(
i);
final
OneofDescriptor oneofDescriptor =
field.
getContainingOneof();
/*
* If the field is part of a Oneof, then at maximum one field in the Oneof is set
* and it is not repeated. There is no need to iterate through the others.
*/
if (
oneofDescriptor != null) {
// Skip other fields in the Oneof we know are not set
i +=
oneofDescriptor.
getFieldCount() - 1;
if (!
hasOneof(
oneofDescriptor)) {
// If no field is set in the Oneof, skip all the fields in the Oneof
continue;
}
// Get the pointer to the only field which is set in the Oneof
field =
getOneofFieldDescriptor(
oneofDescriptor);
} else {
// If we are not in a Oneof, we need to check if the field is set and if it is repeated
if (
field.
isRepeated()) {
final
List<?>
value = (
List<?>)
getField(
field);
if (!
value.
isEmpty()) {
result.
put(
field,
value);
}
continue;
}
if (!
hasField(
field)) {
continue;
}
}
// Add the field to the map
result.
put(
field,
getField(
field));
}
return
result;
}
@
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 BuilderType
setField(final
FieldDescriptor field, final
Object value) {
internalGetFieldAccessorTable().
getField(
field).
set(this,
value);
return (BuilderType) this;
}
@
Override
public BuilderType
clearField(final
FieldDescriptor field) {
internalGetFieldAccessorTable().
getField(
field).
clear(this);
return (BuilderType) this;
}
@
Override
public BuilderType
clearOneof(final
OneofDescriptor oneof) {
internalGetFieldAccessorTable().
getOneof(
oneof).
clear(this);
return (BuilderType) 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 BuilderType
setRepeatedField(
final
FieldDescriptor field, final int
index, final
Object value) {
internalGetFieldAccessorTable().
getField(
field)
.
setRepeated(this,
index,
value);
return (BuilderType) this;
}
@
Override
public BuilderType
addRepeatedField(final
FieldDescriptor field, final
Object value) {
internalGetFieldAccessorTable().
getField(
field).
addRepeated(this,
value);
return (BuilderType) this;
}
@
Override
public BuilderType
setUnknownFields(final
UnknownFieldSet unknownFields) {
this.
unknownFields =
unknownFields;
onChanged();
return (BuilderType) this;
}
protected BuilderType
setUnknownFieldsProto3(final
UnknownFieldSet unknownFields) {
if (
CodedInputStream.
getProto3DiscardUnknownFieldsDefault()) {
return (BuilderType) this;
}
this.
unknownFields =
unknownFields;
onChanged();
return (BuilderType) this;
}
@
Override
public BuilderType
mergeUnknownFields(
final
UnknownFieldSet unknownFields) {
return
setUnknownFields(
UnknownFieldSet.
newBuilder(this.
unknownFields)
.
mergeFrom(
unknownFields)
.
build());
}
@
Override
public boolean
isInitialized() {
for (final
FieldDescriptor field :
getDescriptorForType().
getFields()) {
// Check that all required fields are present.
if (
field.
isRequired()) {
if (!
hasField(
field)) {
return false;
}
}
// Check that embedded messages are initialized.
if (
field.
getJavaType() ==
FieldDescriptor.
JavaType.
MESSAGE) {
if (
field.
isRepeated()) {
@
SuppressWarnings("unchecked") final
List<
Message>
messageList = (
List<
Message>)
getField(
field);
for (final
Message element :
messageList) {
if (!
element.
isInitialized()) {
return false;
}
}
} else {
if (
hasField(
field) &&
!((
Message)
getField(
field)).
isInitialized()) {
return false;
}
}
}
}
return true;
}
@
Override
public final
UnknownFieldSet getUnknownFields() {
return
unknownFields;
}
/**
* 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 the builder or one of its nested children has changed
* and any parent should be notified of its invalidation.
*/
protected final void
onChanged() {
if (
isClean &&
builderParent != null) {
builderParent.
markDirty();
// Don't keep dispatching invalidations until build is called again.
isClean = false;
}
}
/**
* Gets the map field with the given field number. This method should be
* overridden in the generated message class if the message contains map
* fields.
*
* Unlike other field types, reflection support for map fields can't be
* implemented based on generated public API because we need to access a
* map field as a list in reflection API but the generated API only allows
* us to access it as a map. This method returns the underlying map field
* directly and thus enables us to access the map field as a list.
*/
@
SuppressWarnings({"unused", "rawtypes"})
protected
MapField internalGetMapField(int
fieldNumber) {
// Note that we can't use descriptor names here because this method will
// be called when descriptor is being initialized.
throw new
RuntimeException(
"No map fields found in " +
getClass().
getName());
}
/** Like {@link #internalGetMapField} but return a mutable version. */
@
SuppressWarnings({"unused", "rawtypes"})
protected
MapField internalGetMutableMapField(int
fieldNumber) {
// Note that we can't use descriptor names here because this method will
// be called when descriptor is being initialized.
throw new
RuntimeException(
"No map fields found in " +
getClass().
getName());
}
}
// =================================================================
// Extensions-related stuff
public interface
ExtendableMessageOrBuilder<
MessageType extends
ExtendableMessage> extends
MessageOrBuilder {
// Re-define for return type covariance.
@
Override
Message getDefaultInstanceForType();
/** Check if a singular extension is present. */
<Type> boolean
hasExtension(
ExtensionLite<MessageType, Type>
extension);
/** Get the number of elements in a repeated extension. */
<Type> int
getExtensionCount(
ExtensionLite<MessageType,
List<Type>>
extension);
/** Get the value of an extension. */
<Type> Type
getExtension(
ExtensionLite<MessageType, Type>
extension);
/** Get one element of a repeated extension. */
<Type> Type
getExtension(
ExtensionLite<MessageType,
List<Type>>
extension,
int
index);
/** Check if a singular extension is present. */
<Type> boolean
hasExtension(
Extension<MessageType, Type>
extension);
/** Check if a singular extension is present. */
<Type> boolean
hasExtension(
GeneratedExtension<MessageType, Type>
extension);
/** Get the number of elements in a repeated extension. */
<Type> int
getExtensionCount(
Extension<MessageType,
List<Type>>
extension);
/** Get the number of elements in a repeated extension. */
<Type> int
getExtensionCount(
GeneratedExtension<MessageType,
List<Type>>
extension);
/** Get the value of an extension. */
<Type> Type
getExtension(
Extension<MessageType, Type>
extension);
/** Get the value of an extension. */
<Type> Type
getExtension(
GeneratedExtension<MessageType, Type>
extension);
/** Get one element of a repeated extension. */
<Type> Type
getExtension(
Extension<MessageType,
List<Type>>
extension,
int
index);
/** Get one element of a repeated extension. */
<Type> Type
getExtension(
GeneratedExtension<MessageType,
List<Type>>
extension,
int
index);
}
/**
* Generated message classes for message types that contain extension ranges
* subclass this.
*
* <p>This class implements type-safe accessors for extensions. They
* implement all the same operations that you can do with normal fields --
* e.g. "has", "get", and "getCount" -- but for extensions. The extensions
* are identified using instances of the class {@link GeneratedExtension};
* the protocol compiler generates a static instance of this class for every
* extension in its input. Through the magic of generics, all is made
* type-safe.
*
* <p>For example, imagine you have the {@code .proto} file:
*
* <pre>
* option java_class = "MyProto";
*
* message Foo {
* extensions 1000 to max;
* }
*
* extend Foo {
* optional int32 bar;
* }
* </pre>
*
* <p>Then you might write code like:
*
* <pre>
* MyProto.Foo foo = getFoo();
* int i = foo.getExtension(MyProto.bar);
* </pre>
*
* <p>See also {@link ExtendableBuilder}.
*/
public abstract static class
ExtendableMessage<
MessageType extends
ExtendableMessage>
extends
GeneratedMessageV3
implements
ExtendableMessageOrBuilder<MessageType> {
private static final long
serialVersionUID = 1L;
private final
FieldSet<
FieldDescriptor>
extensions;
protected
ExtendableMessage() {
this.
extensions =
FieldSet.
newFieldSet();
}
protected
ExtendableMessage(
ExtendableBuilder<MessageType, ?>
builder) {
super(
builder);
this.
extensions =
builder.
buildExtensions();
}
private void
verifyExtensionContainingType(
final
Extension<MessageType, ?>
extension) {
if (
extension.
getDescriptor().
getContainingType() !=
getDescriptorForType()) {
// This can only happen if someone uses unchecked operations.
throw new
IllegalArgumentException(
"Extension is for type \"" +
extension.
getDescriptor().
getContainingType().
getFullName() +
"\" which does not match message type \"" +
getDescriptorForType().
getFullName() + "\".");
}
}
/** Check if a singular extension is present. */
@
Override
@
SuppressWarnings("unchecked")
public final <Type> boolean
hasExtension(final
ExtensionLite<MessageType, Type>
extensionLite) {
Extension<MessageType, Type>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
return
extensions.
hasField(
extension.
getDescriptor());
}
/** Get the number of elements in a repeated extension. */
@
Override
@
SuppressWarnings("unchecked")
public final <Type> int
getExtensionCount(
final
ExtensionLite<MessageType,
List<Type>>
extensionLite) {
Extension<MessageType,
List<Type>>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
final
FieldDescriptor descriptor =
extension.
getDescriptor();
return
extensions.
getRepeatedFieldCount(
descriptor);
}
/** Get the value of an extension. */
@
Override
@
SuppressWarnings("unchecked")
public final <Type> Type
getExtension(final
ExtensionLite<MessageType, Type>
extensionLite) {
Extension<MessageType, Type>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
FieldDescriptor descriptor =
extension.
getDescriptor();
final
Object value =
extensions.
getField(
descriptor);
if (
value == null) {
if (
descriptor.
isRepeated()) {
return (Type)
Collections.
emptyList();
} else if (
descriptor.
getJavaType() ==
FieldDescriptor.
JavaType.
MESSAGE) {
return (Type)
extension.
getMessageDefaultInstance();
} else {
return (Type)
extension.
fromReflectionType(
descriptor.
getDefaultValue());
}
} else {
return (Type)
extension.
fromReflectionType(
value);
}
}
/** Get one element of a repeated extension. */
@
Override
@
SuppressWarnings("unchecked")
public final <Type> Type
getExtension(
final
ExtensionLite<MessageType,
List<Type>>
extensionLite, final int
index) {
Extension<MessageType,
List<Type>>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
FieldDescriptor descriptor =
extension.
getDescriptor();
return (Type)
extension.
singularFromReflectionType(
extensions.
getRepeatedField(
descriptor,
index));
}
/** Check if a singular extension is present. */
@
Override
public final <Type> boolean
hasExtension(final
Extension<MessageType, Type>
extension) {
return
hasExtension((
ExtensionLite<MessageType, Type>)
extension);
}
/** Check if a singular extension is present. */
@
Override
public final <Type> boolean
hasExtension(
final
GeneratedExtension<MessageType, Type>
extension) {
return
hasExtension((
ExtensionLite<MessageType, Type>)
extension);
}
/** Get the number of elements in a repeated extension. */
@
Override
public final <Type> int
getExtensionCount(
final
Extension<MessageType,
List<Type>>
extension) {
return
getExtensionCount((
ExtensionLite<MessageType,
List<Type>>)
extension);
}
/** Get the number of elements in a repeated extension. */
@
Override
public final <Type> int
getExtensionCount(
final
GeneratedExtension<MessageType,
List<Type>>
extension) {
return
getExtensionCount((
ExtensionLite<MessageType,
List<Type>>)
extension);
}
/** Get the value of an extension. */
@
Override
public final <Type> Type
getExtension(final
Extension<MessageType, Type>
extension) {
return
getExtension((
ExtensionLite<MessageType, Type>)
extension);
}
/** Get the value of an extension. */
@
Override
public final <Type> Type
getExtension(
final
GeneratedExtension<MessageType, Type>
extension) {
return
getExtension((
ExtensionLite<MessageType, Type>)
extension);
}
/** Get one element of a repeated extension. */
@
Override
public final <Type> Type
getExtension(
final
Extension<MessageType,
List<Type>>
extension, final int
index) {
return
getExtension((
ExtensionLite<MessageType,
List<Type>>)
extension,
index);
}
/** Get one element of a repeated extension. */
@
Override
public final <Type> Type
getExtension(
final
GeneratedExtension<MessageType,
List<Type>>
extension, final int
index) {
return
getExtension((
ExtensionLite<MessageType,
List<Type>>)
extension,
index);
}
/** Called by subclasses to check if all extensions are initialized. */
protected boolean
extensionsAreInitialized() {
return
extensions.
isInitialized();
}
@
Override
public boolean
isInitialized() {
return super.isInitialized() &&
extensionsAreInitialized();
}
@
Override
protected boolean
parseUnknownField(
CodedInputStream input,
UnknownFieldSet.
Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int
tag) throws
IOException {
return
MessageReflection.
mergeFieldFrom(
input,
input.
shouldDiscardUnknownFields() ? null :
unknownFields,
extensionRegistry,
getDescriptorForType(), new
MessageReflection.
ExtensionAdapter(
extensions),
tag);
}
@
Override
protected boolean
parseUnknownFieldProto3(
CodedInputStream input,
UnknownFieldSet.
Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int
tag) throws
IOException {
return
MessageReflection.
mergeFieldFrom(
input,
input.
shouldDiscardUnknownFieldsProto3() ? null :
unknownFields,
extensionRegistry,
getDescriptorForType(),
new
MessageReflection.
ExtensionAdapter(
extensions),
tag);
}
/**
* Used by parsing constructors in generated classes.
*/
@
Override
protected void
makeExtensionsImmutable() {
extensions.
makeImmutable();
}
/**
* Used by subclasses to serialize extensions. Extension ranges may be
* interleaved with field numbers, but we must write them in canonical
* (sorted by field number) order. ExtensionWriter helps us write
* individual ranges of extensions at once.
*/
protected class
ExtensionWriter {
// Imagine how much simpler this code would be if Java iterators had
// a way to get the next element without advancing the iterator.
private final
Iterator<
Map.
Entry<
FieldDescriptor,
Object>>
iter =
extensions.
iterator();
private
Map.
Entry<
FieldDescriptor,
Object>
next;
private final boolean
messageSetWireFormat;
private
ExtensionWriter(final boolean
messageSetWireFormat) {
if (
iter.
hasNext()) {
next =
iter.
next();
}
this.
messageSetWireFormat =
messageSetWireFormat;
}
public void
writeUntil(final int
end, final
CodedOutputStream output)
throws
IOException {
while (
next != null &&
next.
getKey().
getNumber() <
end) {
FieldDescriptor descriptor =
next.
getKey();
if (
messageSetWireFormat &&
descriptor.
getLiteJavaType() ==
WireFormat.
JavaType.
MESSAGE &&
!
descriptor.
isRepeated()) {
if (
next instanceof
LazyField.
LazyEntry<?>) {
output.
writeRawMessageSetExtension(
descriptor.
getNumber(),
((
LazyField.
LazyEntry<?>)
next).
getField().
toByteString());
} else {
output.
writeMessageSetExtension(
descriptor.
getNumber(),
(
Message)
next.
getValue());
}
} else {
// TODO(xiangl): Taken care of following code, it may cause
// problem when we use LazyField for normal fields/extensions.
// Due to the optional field can be duplicated at the end of
// serialized bytes, which will make the serialized size change
// after lazy field parsed. So when we use LazyField globally,
// we need to change the following write method to write cached
// bytes directly rather than write the parsed message.
FieldSet.
writeField(
descriptor,
next.
getValue(),
output);
}
if (
iter.
hasNext()) {
next =
iter.
next();
} else {
next = null;
}
}
}
}
protected
ExtensionWriter newExtensionWriter() {
return new
ExtensionWriter(false);
}
protected
ExtensionWriter newMessageSetExtensionWriter() {
return new
ExtensionWriter(true);
}
/** Called by subclasses to compute the size of extensions. */
protected int
extensionsSerializedSize() {
return
extensions.
getSerializedSize();
}
protected int
extensionsSerializedSizeAsMessageSet() {
return
extensions.
getMessageSetSerializedSize();
}
// ---------------------------------------------------------------
// Reflection
protected
Map<
FieldDescriptor,
Object>
getExtensionFields() {
return
extensions.
getAllFields();
}
@
Override
public
Map<
FieldDescriptor,
Object>
getAllFields() {
final
Map<
FieldDescriptor,
Object>
result =
super.getAllFieldsMutable(/* getBytesForString = */ false);
result.
putAll(
getExtensionFields());
return
Collections.
unmodifiableMap(
result);
}
@
Override
public
Map<
FieldDescriptor,
Object>
getAllFieldsRaw() {
final
Map<
FieldDescriptor,
Object>
result =
super.getAllFieldsMutable(/* getBytesForString = */ false);
result.
putAll(
getExtensionFields());
return
Collections.
unmodifiableMap(
result);
}
@
Override
public boolean
hasField(final
FieldDescriptor field) {
if (
field.
isExtension()) {
verifyContainingType(
field);
return
extensions.
hasField(
field);
} else {
return super.hasField(
field);
}
}
@
Override
public
Object getField(final
FieldDescriptor field) {
if (
field.
isExtension()) {
verifyContainingType(
field);
final
Object value =
extensions.
getField(
field);
if (
value == null) {
if (
field.
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.
*
* <p>This class implements type-safe accessors for extensions. They
* implement all the same operations that you can do with normal fields --
* e.g. "get", "set", and "add" -- but for extensions. The extensions are
* identified using instances of the class {@link GeneratedExtension}; the
* protocol compiler generates a static instance of this class for every
* extension in its input. Through the magic of generics, all is made
* type-safe.
*
* <p>For example, imagine you have the {@code .proto} file:
*
* <pre>
* option java_class = "MyProto";
*
* message Foo {
* extensions 1000 to max;
* }
*
* extend Foo {
* optional int32 bar;
* }
* </pre>
*
* <p>Then you might write code like:
*
* <pre>
* MyProto.Foo foo =
* MyProto.Foo.newBuilder()
* .setExtension(MyProto.bar, 123)
* .build();
* </pre>
*
* <p>See also {@link ExtendableMessage}.
*/
@
SuppressWarnings("unchecked")
public abstract static class
ExtendableBuilder<
MessageType extends
ExtendableMessage,
BuilderType extends
ExtendableBuilder<MessageType, BuilderType>>
extends
Builder<BuilderType>
implements
ExtendableMessageOrBuilder<MessageType> {
private
FieldSet<
FieldDescriptor>
extensions =
FieldSet.
emptySet();
protected
ExtendableBuilder() {}
protected
ExtendableBuilder(
BuilderParent parent) {
super(
parent);
}
// For immutable message conversion.
void
internalSetExtensionSet(
FieldSet<
FieldDescriptor>
extensions) {
this.
extensions =
extensions;
}
@
Override
public BuilderType
clear() {
extensions =
FieldSet.
emptySet();
return super.clear();
}
private void
ensureExtensionsIsMutable() {
if (
extensions.
isImmutable()) {
extensions =
extensions.
clone();
}
}
private void
verifyExtensionContainingType(
final
Extension<MessageType, ?>
extension) {
if (
extension.
getDescriptor().
getContainingType() !=
getDescriptorForType()) {
// This can only happen if someone uses unchecked operations.
throw new
IllegalArgumentException(
"Extension is for type \"" +
extension.
getDescriptor().
getContainingType().
getFullName() +
"\" which does not match message type \"" +
getDescriptorForType().
getFullName() + "\".");
}
}
/** Check if a singular extension is present. */
@
Override
public final <Type> boolean
hasExtension(final
ExtensionLite<MessageType, Type>
extensionLite) {
Extension<MessageType, Type>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
return
extensions.
hasField(
extension.
getDescriptor());
}
/** Get the number of elements in a repeated extension. */
@
Override
public final <Type> int
getExtensionCount(
final
ExtensionLite<MessageType,
List<Type>>
extensionLite) {
Extension<MessageType,
List<Type>>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
final
FieldDescriptor descriptor =
extension.
getDescriptor();
return
extensions.
getRepeatedFieldCount(
descriptor);
}
/** Get the value of an extension. */
@
Override
public final <Type> Type
getExtension(final
ExtensionLite<MessageType, Type>
extensionLite) {
Extension<MessageType, Type>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
FieldDescriptor descriptor =
extension.
getDescriptor();
final
Object value =
extensions.
getField(
descriptor);
if (
value == null) {
if (
descriptor.
isRepeated()) {
return (Type)
Collections.
emptyList();
} else if (
descriptor.
getJavaType() ==
FieldDescriptor.
JavaType.
MESSAGE) {
return (Type)
extension.
getMessageDefaultInstance();
} else {
return (Type)
extension.
fromReflectionType(
descriptor.
getDefaultValue());
}
} else {
return (Type)
extension.
fromReflectionType(
value);
}
}
/** Get one element of a repeated extension. */
@
Override
public final <Type> Type
getExtension(
final
ExtensionLite<MessageType,
List<Type>>
extensionLite, final int
index) {
Extension<MessageType,
List<Type>>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
FieldDescriptor descriptor =
extension.
getDescriptor();
return (Type)
extension.
singularFromReflectionType(
extensions.
getRepeatedField(
descriptor,
index));
}
/** Set the value of an extension. */
public final <Type> BuilderType
setExtension(
final
ExtensionLite<MessageType, Type>
extensionLite,
final Type
value) {
Extension<MessageType, Type>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
ensureExtensionsIsMutable();
final
FieldDescriptor descriptor =
extension.
getDescriptor();
extensions.
setField(
descriptor,
extension.
toReflectionType(
value));
onChanged();
return (BuilderType) this;
}
/** Set the value of one element of a repeated extension. */
public final <Type> BuilderType
setExtension(
final
ExtensionLite<MessageType,
List<Type>>
extensionLite,
final int
index, final Type
value) {
Extension<MessageType,
List<Type>>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
ensureExtensionsIsMutable();
final
FieldDescriptor descriptor =
extension.
getDescriptor();
extensions.
setRepeatedField(
descriptor,
index,
extension.
singularToReflectionType(
value));
onChanged();
return (BuilderType) this;
}
/** Append a value to a repeated extension. */
public final <Type> BuilderType
addExtension(
final
ExtensionLite<MessageType,
List<Type>>
extensionLite,
final Type
value) {
Extension<MessageType,
List<Type>>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
ensureExtensionsIsMutable();
final
FieldDescriptor descriptor =
extension.
getDescriptor();
extensions.
addRepeatedField(
descriptor,
extension.
singularToReflectionType(
value));
onChanged();
return (BuilderType) this;
}
/** Clear an extension. */
public final <Type> BuilderType
clearExtension(
final
ExtensionLite<MessageType, ?>
extensionLite) {
Extension<MessageType, ?>
extension =
checkNotLite(
extensionLite);
verifyExtensionContainingType(
extension);
ensureExtensionsIsMutable();
extensions.
clearField(
extension.
getDescriptor());
onChanged();
return (BuilderType) this;
}
/** Check if a singular extension is present. */
@
Override
public final <Type> boolean
hasExtension(final
Extension<MessageType, Type>
extension) {
return
hasExtension((
ExtensionLite<MessageType, Type>)
extension);
}
/** Check if a singular extension is present. */
@
Override
public final <Type> boolean
hasExtension(
final
GeneratedExtension<MessageType, Type>
extension) {
return
hasExtension((
ExtensionLite<MessageType, Type>)
extension);
}
/** Get the number of elements in a repeated extension. */
@
Override
public final <Type> int
getExtensionCount(
final
Extension<MessageType,
List<Type>>
extension) {
return
getExtensionCount((
ExtensionLite<MessageType,
List<Type>>)
extension);
}
/** Get the number of elements in a repeated extension. */
@
Override
public final <Type> int
getExtensionCount(
final
GeneratedExtension<MessageType,
List<Type>>
extension) {
return
getExtensionCount((
ExtensionLite<MessageType,
List<Type>>)
extension);
}
/** Get the value of an extension. */
@
Override
public final <Type> Type
getExtension(final
Extension<MessageType, Type>
extension) {
return
getExtension((
ExtensionLite<MessageType, Type>)
extension);
}
/** Get the value of an extension. */
@
Override
public final <Type> Type
getExtension(
final
GeneratedExtension<MessageType, Type>
extension) {
return
getExtension((
ExtensionLite<MessageType, Type>)
extension);
}
/** Get the value of an extension. */
@
Override
public final <Type> Type
getExtension(
final
Extension<MessageType,
List<Type>>
extension, final int
index) {
return
getExtension((
ExtensionLite<MessageType,
List<Type>>)
extension,
index);
}
/** Get the value of an extension. */
@
Override
public final <Type> Type
getExtension(
final
GeneratedExtension<MessageType,
List<Type>>
extension, final int
index) {
return
getExtension((
ExtensionLite<MessageType,
List<Type>>)
extension,
index);
}
/** Set the value of an extension. */
public final <Type> BuilderType
setExtension(
final
Extension<MessageType, Type>
extension, final Type
value) {
return
setExtension((
ExtensionLite<MessageType, Type>)
extension,
value);
}
/** Set the value of an extension. */
public <Type> BuilderType
setExtension(
final
GeneratedExtension<MessageType, Type>
extension, final Type
value) {
return
setExtension((
ExtensionLite<MessageType, Type>)
extension,
value);
}
/** Set the value of one element of a repeated extension. */
public final <Type> BuilderType
setExtension(
final
Extension<MessageType,
List<Type>>
extension,
final int
index, final Type
value) {
return
setExtension((
ExtensionLite<MessageType,
List<Type>>)
extension,
index,
value);
}
/** Set the value of one element of a repeated extension. */
public <Type> BuilderType
setExtension(
final
GeneratedExtension<MessageType,
List<Type>>
extension,
final int
index, final Type
value) {
return
setExtension((
ExtensionLite<MessageType,
List<Type>>)
extension,
index,
value);
}
/** Append a value to a repeated extension. */
public final <Type> BuilderType
addExtension(
final
Extension<MessageType,
List<Type>>
extension, final Type
value) {
return
addExtension((
ExtensionLite<MessageType,
List<Type>>)
extension,
value);
}
/** Append a value to a repeated extension. */
public <Type> BuilderType
addExtension(
final
GeneratedExtension<MessageType,
List<Type>>
extension, final Type
value) {
return
addExtension((
ExtensionLite<MessageType,
List<Type>>)
extension,
value);
}
/** Clear an extension. */
public final <Type> BuilderType
clearExtension(
final
Extension<MessageType, ?>
extension) {
return
clearExtension((
ExtensionLite<MessageType, ?>)
extension);
}
/** Clear an extension. */
public <Type> BuilderType
clearExtension(
final
GeneratedExtension<MessageType, ?>
extension) {
return
clearExtension((
ExtensionLite<MessageType, ?>)
extension);
}
/** Called by subclasses to check if all extensions are initialized. */
protected boolean
extensionsAreInitialized() {
return
extensions.
isInitialized();
}
/**
* Called by the build code path to create a copy of the extensions for
* building the message.
*/
private
FieldSet<
FieldDescriptor>
buildExtensions() {
extensions.
makeImmutable();
return
extensions;
}
@
Override
public boolean
isInitialized() {
return super.isInitialized() &&
extensionsAreInitialized();
}
// ---------------------------------------------------------------
// Reflection
@
Override
public
Map<
FieldDescriptor,
Object>
getAllFields() {
final
Map<
FieldDescriptor,
Object>
result = super.getAllFieldsMutable();
result.
putAll(
extensions.
getAllFields());
return
Collections.
unmodifiableMap(
result);
}
@
Override
public
Object getField(final
FieldDescriptor field) {
if (
field.
isExtension()) {
verifyContainingType(
field);
final
Object value =
extensions.
getField(
field);
if (
value == null) {
if (
field.
getJavaType() ==
FieldDescriptor.
JavaType.
MESSAGE) {
// Lacking an ExtensionRegistry, we have no way to determine the
// extension's real type, so we return a DynamicMessage.
return
DynamicMessage.
getDefaultInstance(
field.
getMessageType());
} else {
return
field.
getDefaultValue();
}
} else {
return
value;
}
} else {
return super.getField(
field);
}
}
@
Override
public int
getRepeatedFieldCount(final
FieldDescriptor field) {
if (
field.
isExtension()) {
verifyContainingType(
field);
return
extensions.
getRepeatedFieldCount(
field);
} else {
return super.getRepeatedFieldCount(
field);
}
}
@
Override
public
Object getRepeatedField(final
FieldDescriptor field,
final int
index) {
if (
field.
isExtension()) {
verifyContainingType(
field);
return
extensions.
getRepeatedField(
field,
index);
} else {
return super.getRepeatedField(
field,
index);
}
}
@
Override
public boolean
hasField(final
FieldDescriptor field) {
if (
field.
isExtension()) {
verifyContainingType(
field);
return
extensions.
hasField(
field);
} else {
return super.hasField(
field);
}
}
@
Override
public BuilderType
setField(final
FieldDescriptor field,
final
Object value) {
if (
field.
isExtension()) {
verifyContainingType(
field);
ensureExtensionsIsMutable();
extensions.
setField(
field,
value);
onChanged();
return (BuilderType) this;
} else {
return super.setField(
field,
value);
}
}
@
Override
public BuilderType
clearField(final
FieldDescriptor field) {
if (
field.
isExtension()) {
verifyContainingType(
field);
ensureExtensionsIsMutable();
extensions.
clearField(
field);
onChanged();
return (BuilderType) this;
} else {
return super.clearField(
field);
}
}
@
Override
public BuilderType
setRepeatedField(final
FieldDescriptor field,
final int
index, final
Object value) {
if (
field.
isExtension()) {
verifyContainingType(
field);
ensureExtensionsIsMutable();
extensions.
setRepeatedField(
field,
index,
value);
onChanged();
return (BuilderType) this;
} else {
return super.setRepeatedField(
field,
index,
value);
}
}
@
Override
public BuilderType
addRepeatedField(final
FieldDescriptor field,
final
Object value) {
if (
field.
isExtension()) {
verifyContainingType(
field);
ensureExtensionsIsMutable();
extensions.
addRepeatedField(
field,
value);
onChanged();
return (BuilderType) this;
} else {
return super.addRepeatedField(
field,
value);
}
}
protected final void
mergeExtensionFields(final
ExtendableMessage other) {
ensureExtensionsIsMutable();
extensions.
mergeFrom(
other.
extensions);
onChanged();
}
private void
verifyContainingType(final
FieldDescriptor field) {
if (
field.
getContainingType() !=
getDescriptorForType()) {
throw new
IllegalArgumentException(
"FieldDescriptor does not match message type.");
}
}
}
// -----------------------------------------------------------------
/**
* Gets the descriptor for an extension. The implementation depends on whether
* the extension is scoped in the top level of a file or scoped in a Message.
*/
static interface
ExtensionDescriptorRetriever {
FieldDescriptor getDescriptor();
}
// =================================================================
/** Calls Class.getMethod and throws a RuntimeException if it fails. */
@
SuppressWarnings("unchecked")
private static
Method getMethodOrDie(
final
Class clazz, final
String name, final
Class...
params) {
try {
return
clazz.
getMethod(
name,
params);
} catch (
NoSuchMethodException e) {
throw new
RuntimeException(
"Generated message class \"" +
clazz.
getName() +
"\" missing method \"" +
name + "\".",
e);
}
}
/** Calls invoke and throws a RuntimeException if it fails. */
private static
Object invokeOrDie(
final
Method method, final
Object object, final
Object...
params) {
try {
return
method.
invoke(
object,
params);
} catch (
IllegalAccessException e) {
throw new
RuntimeException(
"Couldn't use Java reflection to implement protocol message " +
"reflection.",
e);
} catch (
InvocationTargetException e) {
final
Throwable cause =
e.
getCause();
if (
cause instanceof
RuntimeException) {
throw (
RuntimeException)
cause;
} else if (
cause instanceof
Error) {
throw (
Error)
cause;
} else {
throw new
RuntimeException(
"Unexpected exception thrown by generated accessor method.",
cause);
}
}
}
/**
* Gets the map field with the given field number. This method should be
* overridden in the generated message class if the message contains map
* fields.
*
* Unlike other field types, reflection support for map fields can't be
* implemented based on generated public API because we need to access a
* map field as a list in reflection API but the generated API only allows
* us to access it as a map. This method returns the underlying map field
* directly and thus enables us to access the map field as a list.
*/
@
SuppressWarnings({"rawtypes", "unused"})
protected
MapField internalGetMapField(int
fieldNumber) {
// Note that we can't use descriptor names here because this method will
// be called when descriptor is being initialized.
throw new
RuntimeException(
"No map fields found in " +
getClass().
getName());
}
/**
* Users should ignore this class. This class provides the implementation
* with access to the fields of a message object using Java reflection.
*/
public static final class
FieldAccessorTable {
/**
* Construct a FieldAccessorTable for a particular message class. Only
* one FieldAccessorTable should ever be constructed per class.
*
* @param descriptor The type's descriptor.
* @param camelCaseNames The camelcase names of all fields in the message.
* These are used to derive the accessor method names.
* @param messageClass The message type.
* @param builderClass The builder type.
*/
public
FieldAccessorTable(
final
Descriptor descriptor,
final
String[]
camelCaseNames,
final
Class<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass) {
this(
descriptor,
camelCaseNames);
ensureFieldAccessorsInitialized(
messageClass,
builderClass);
}
/**
* Construct a FieldAccessorTable for a particular message class without
* initializing FieldAccessors.
*/
public
FieldAccessorTable(
final
Descriptor descriptor,
final
String[]
camelCaseNames) {
this.
descriptor =
descriptor;
this.
camelCaseNames =
camelCaseNames;
fields = new
FieldAccessor[
descriptor.
getFields().
size()];
oneofs = new
OneofAccessor[
descriptor.
getOneofs().
size()];
initialized = false;
}
/**
* Ensures the field accessors are initialized. This method is thread-safe.
*
* @param messageClass The message type.
* @param builderClass The builder type.
* @return this
*/
public
FieldAccessorTable ensureFieldAccessorsInitialized(
Class<? extends
GeneratedMessageV3>
messageClass,
Class<? extends
Builder>
builderClass) {
if (
initialized) { return this; }
synchronized (this) {
if (
initialized) { return this; }
int
fieldsSize =
fields.length;
for (int
i = 0;
i <
fieldsSize;
i++) {
FieldDescriptor field =
descriptor.
getFields().
get(
i);
String containingOneofCamelCaseName = null;
if (
field.
getContainingOneof() != null) {
containingOneofCamelCaseName =
camelCaseNames[
fieldsSize +
field.
getContainingOneof().
getIndex()];
}
if (
field.
isRepeated()) {
if (
field.
getJavaType() ==
FieldDescriptor.
JavaType.
MESSAGE) {
if (
field.
isMapField()) {
fields[
i] = new
MapFieldAccessor(
field,
camelCaseNames[
i],
messageClass,
builderClass);
} else {
fields[
i] = new
RepeatedMessageFieldAccessor(
field,
camelCaseNames[
i],
messageClass,
builderClass);
}
} else if (
field.
getJavaType() ==
FieldDescriptor.
JavaType.
ENUM) {
fields[
i] = new
RepeatedEnumFieldAccessor(
field,
camelCaseNames[
i],
messageClass,
builderClass);
} else {
fields[
i] = new
RepeatedFieldAccessor(
field,
camelCaseNames[
i],
messageClass,
builderClass);
}
} else {
if (
field.
getJavaType() ==
FieldDescriptor.
JavaType.
MESSAGE) {
fields[
i] = new
SingularMessageFieldAccessor(
field,
camelCaseNames[
i],
messageClass,
builderClass,
containingOneofCamelCaseName);
} else if (
field.
getJavaType() ==
FieldDescriptor.
JavaType.
ENUM) {
fields[
i] = new
SingularEnumFieldAccessor(
field,
camelCaseNames[
i],
messageClass,
builderClass,
containingOneofCamelCaseName);
} else if (
field.
getJavaType() ==
FieldDescriptor.
JavaType.
STRING) {
fields[
i] = new
SingularStringFieldAccessor(
field,
camelCaseNames[
i],
messageClass,
builderClass,
containingOneofCamelCaseName);
} else {
fields[
i] = new
SingularFieldAccessor(
field,
camelCaseNames[
i],
messageClass,
builderClass,
containingOneofCamelCaseName);
}
}
}
int
oneofsSize =
oneofs.length;
for (int
i = 0;
i <
oneofsSize;
i++) {
oneofs[
i] = new
OneofAccessor(
descriptor,
camelCaseNames[
i +
fieldsSize],
messageClass,
builderClass);
}
initialized = true;
camelCaseNames = null;
return this;
}
}
private final
Descriptor descriptor;
private final
FieldAccessor[]
fields;
private
String[]
camelCaseNames;
private final
OneofAccessor[]
oneofs;
private volatile boolean
initialized;
/** Get the FieldAccessor for a particular field. */
private
FieldAccessor getField(final
FieldDescriptor field) {
if (
field.
getContainingType() !=
descriptor) {
throw new
IllegalArgumentException(
"FieldDescriptor does not match message type.");
} else if (
field.
isExtension()) {
// If this type had extensions, it would subclass ExtendableMessage,
// which overrides the reflection interface to handle extensions.
throw new
IllegalArgumentException(
"This type does not have extensions.");
}
return
fields[
field.
getIndex()];
}
/** Get the OneofAccessor for a particular oneof. */
private
OneofAccessor getOneof(final
OneofDescriptor oneof) {
if (
oneof.
getContainingType() !=
descriptor) {
throw new
IllegalArgumentException(
"OneofDescriptor does not match message type.");
}
return
oneofs[
oneof.
getIndex()];
}
/**
* Abstract interface that provides access to a single field. This is
* implemented differently depending on the field type and cardinality.
*/
private interface
FieldAccessor {
Object get(
GeneratedMessageV3 message);
Object get(
GeneratedMessageV3.
Builder builder);
Object getRaw(
GeneratedMessageV3 message);
Object getRaw(
GeneratedMessageV3.
Builder builder);
void
set(
Builder builder,
Object value);
Object getRepeated(
GeneratedMessageV3 message, int
index);
Object getRepeated(
GeneratedMessageV3.
Builder builder, int
index);
Object getRepeatedRaw(
GeneratedMessageV3 message, int
index);
Object getRepeatedRaw(
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 class
OneofAccessor {
OneofAccessor(
final
Descriptor descriptor, final
String camelCaseName,
final
Class<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass) {
this.
descriptor =
descriptor;
caseMethod =
getMethodOrDie(
messageClass, "get" +
camelCaseName + "Case");
caseMethodBuilder =
getMethodOrDie(
builderClass, "get" +
camelCaseName + "Case");
clearMethod =
getMethodOrDie(
builderClass, "clear" +
camelCaseName);
}
private final
Descriptor descriptor;
private final
Method caseMethod;
private final
Method caseMethodBuilder;
private final
Method clearMethod;
public boolean
has(final
GeneratedMessageV3 message) {
if (((
Internal.
EnumLite)
invokeOrDie(
caseMethod,
message)).
getNumber() == 0) {
return false;
}
return true;
}
public boolean
has(
GeneratedMessageV3.
Builder builder) {
if (((
Internal.
EnumLite)
invokeOrDie(
caseMethodBuilder,
builder)).
getNumber() == 0) {
return false;
}
return true;
}
public
FieldDescriptor get(final
GeneratedMessageV3 message) {
int
fieldNumber = ((
Internal.
EnumLite)
invokeOrDie(
caseMethod,
message)).
getNumber();
if (
fieldNumber > 0) {
return
descriptor.
findFieldByNumber(
fieldNumber);
}
return null;
}
public
FieldDescriptor get(
GeneratedMessageV3.
Builder builder) {
int
fieldNumber = ((
Internal.
EnumLite)
invokeOrDie(
caseMethodBuilder,
builder)).
getNumber();
if (
fieldNumber > 0) {
return
descriptor.
findFieldByNumber(
fieldNumber);
}
return null;
}
public void
clear(final
Builder builder) {
invokeOrDie(
clearMethod,
builder);
}
}
private static boolean
supportFieldPresence(
FileDescriptor file) {
return
file.
getSyntax() ==
FileDescriptor.
Syntax.
PROTO2;
}
// ---------------------------------------------------------------
private static class
SingularFieldAccessor implements
FieldAccessor {
SingularFieldAccessor(
final
FieldDescriptor descriptor, final
String camelCaseName,
final
Class<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass,
final
String containingOneofCamelCaseName) {
field =
descriptor;
isOneofField =
descriptor.
getContainingOneof() != null;
hasHasMethod =
supportFieldPresence(
descriptor.
getFile())
|| (!
isOneofField &&
descriptor.
getJavaType() ==
FieldDescriptor.
JavaType.
MESSAGE);
getMethod =
getMethodOrDie(
messageClass, "get" +
camelCaseName);
getMethodBuilder =
getMethodOrDie(
builderClass, "get" +
camelCaseName);
type =
getMethod.
getReturnType();
setMethod =
getMethodOrDie(
builderClass, "set" +
camelCaseName,
type);
hasMethod =
hasHasMethod ?
getMethodOrDie(
messageClass, "has" +
camelCaseName) : null;
hasMethodBuilder =
hasHasMethod ?
getMethodOrDie(
builderClass, "has" +
camelCaseName) : null;
clearMethod =
getMethodOrDie(
builderClass, "clear" +
camelCaseName);
caseMethod =
isOneofField ?
getMethodOrDie(
messageClass, "get" +
containingOneofCamelCaseName + "Case") : null;
caseMethodBuilder =
isOneofField ?
getMethodOrDie(
builderClass, "get" +
containingOneofCamelCaseName + "Case") : null;
}
// Note: We use Java reflection to call public methods rather than
// access private fields directly as this avoids runtime security
// checks.
protected final
Class<?>
type;
protected final
Method getMethod;
protected final
Method getMethodBuilder;
protected final
Method setMethod;
protected final
Method hasMethod;
protected final
Method hasMethodBuilder;
protected final
Method clearMethod;
protected final
Method caseMethod;
protected final
Method caseMethodBuilder;
protected final
FieldDescriptor field;
protected final boolean
isOneofField;
protected final boolean
hasHasMethod;
private int
getOneofFieldNumber(final
GeneratedMessageV3 message) {
return ((
Internal.
EnumLite)
invokeOrDie(
caseMethod,
message)).
getNumber();
}
private int
getOneofFieldNumber(final
GeneratedMessageV3.
Builder builder) {
return ((
Internal.
EnumLite)
invokeOrDie(
caseMethodBuilder,
builder)).
getNumber();
}
@
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 getRaw(final
GeneratedMessageV3 message) {
return
get(
message);
}
@
Override
public
Object getRaw(
GeneratedMessageV3.
Builder builder) {
return
get(
builder);
}
@
Override
public void
set(final
Builder builder, final
Object value) {
invokeOrDie(
setMethod,
builder,
value);
}
@
Override
public
Object getRepeated(final
GeneratedMessageV3 message, final int
index) {
throw new
UnsupportedOperationException(
"getRepeatedField() called on a singular field.");
}
@
Override
public
Object getRepeatedRaw(final
GeneratedMessageV3 message, final int
index) {
throw new
UnsupportedOperationException(
"getRepeatedFieldRaw() 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
Object getRepeatedRaw(
GeneratedMessageV3.
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) {
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
getOneofFieldNumber(
message) ==
field.
getNumber();
}
return !
get(
message).
equals(
field.
getDefaultValue());
}
return (
Boolean)
invokeOrDie(
hasMethod,
message);
}
@
Override
public boolean
has(
GeneratedMessageV3.
Builder builder) {
if (!
hasHasMethod) {
if (
isOneofField) {
return
getOneofFieldNumber(
builder) ==
field.
getNumber();
}
return !
get(
builder).
equals(
field.
getDefaultValue());
}
return (
Boolean)
invokeOrDie(
hasMethodBuilder,
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) {
invokeOrDie(
clearMethod,
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
RepeatedFieldAccessor implements
FieldAccessor {
protected final
Class type;
protected final
Method getMethod;
protected final
Method getMethodBuilder;
protected final
Method getRepeatedMethod;
protected final
Method getRepeatedMethodBuilder;
protected final
Method setRepeatedMethod;
protected final
Method addRepeatedMethod;
protected final
Method getCountMethod;
protected final
Method getCountMethodBuilder;
protected final
Method clearMethod;
RepeatedFieldAccessor(
final
FieldDescriptor descriptor, final
String camelCaseName,
final
Class<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass) {
getMethod =
getMethodOrDie(
messageClass,
"get" +
camelCaseName + "List");
getMethodBuilder =
getMethodOrDie(
builderClass,
"get" +
camelCaseName + "List");
getRepeatedMethod =
getMethodOrDie(
messageClass, "get" +
camelCaseName,
Integer.
TYPE);
getRepeatedMethodBuilder =
getMethodOrDie(
builderClass, "get" +
camelCaseName,
Integer.
TYPE);
type =
getRepeatedMethod.
getReturnType();
setRepeatedMethod =
getMethodOrDie(
builderClass, "set" +
camelCaseName,
Integer.
TYPE,
type);
addRepeatedMethod =
getMethodOrDie(
builderClass, "add" +
camelCaseName,
type);
getCountMethod =
getMethodOrDie(
messageClass, "get" +
camelCaseName + "Count");
getCountMethodBuilder =
getMethodOrDie(
builderClass, "get" +
camelCaseName + "Count");
clearMethod =
getMethodOrDie(
builderClass, "clear" +
camelCaseName);
}
@
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 getRaw(final
GeneratedMessageV3 message) {
return
get(
message);
}
@
Override
public
Object getRaw(
GeneratedMessageV3.
Builder builder) {
return
get(
builder);
}
@
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
invokeOrDie(
getRepeatedMethod,
message,
index);
}
@
Override
public
Object getRepeated(
GeneratedMessageV3.
Builder builder, int
index) {
return
invokeOrDie(
getRepeatedMethodBuilder,
builder,
index);
}
@
Override
public
Object getRepeatedRaw(
GeneratedMessageV3 message, int
index) {
return
getRepeated(
message,
index);
}
@
Override
public
Object getRepeatedRaw(
GeneratedMessageV3.
Builder builder, int
index) {
return
getRepeated(
builder,
index);
}
@
Override
public void
setRepeated(final
Builder builder, final int
index, final
Object value) {
invokeOrDie(
setRepeatedMethod,
builder,
index,
value);
}
@
Override
public void
addRepeated(final
Builder builder, final
Object value) {
invokeOrDie(
addRepeatedMethod,
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 (
Integer)
invokeOrDie(
getCountMethod,
message);
}
@
Override
public int
getRepeatedCount(
GeneratedMessageV3.
Builder builder) {
return (
Integer)
invokeOrDie(
getCountMethodBuilder,
builder);
}
@
Override
public void
clear(final
Builder builder) {
invokeOrDie(
clearMethod,
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
String camelCaseName,
final
Class<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass) {
field =
descriptor;
Method getDefaultInstanceMethod =
getMethodOrDie(
messageClass, "getDefaultInstance");
MapField defaultMapField =
getMapField(
(
GeneratedMessageV3)
invokeOrDie(
getDefaultInstanceMethod, null));
mapEntryMessageDefaultInstance =
defaultMapField.
getMapEntryMessageDefaultInstance();
}
private final
FieldDescriptor field;
private final
Message mapEntryMessageDefaultInstance;
private
MapField<?, ?>
getMapField(
GeneratedMessageV3 message) {
return (
MapField<?, ?>)
message.
internalGetMapField(
field.
getNumber());
}
private
MapField<?, ?>
getMapField(
GeneratedMessageV3.
Builder builder) {
return (
MapField<?, ?>)
builder.
internalGetMapField(
field.
getNumber());
}
private
MapField<?, ?>
getMutableMapField(
GeneratedMessageV3.
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(
GeneratedMessageV3 message) {
List result = new
ArrayList();
for (int
i = 0;
i <
getRepeatedCount(
message);
i++) {
result.
add(
getRepeated(
message,
i));
}
return
Collections.
unmodifiableList(
result);
}
@
Override
@
SuppressWarnings("unchecked")
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
Object getRaw(
GeneratedMessageV3.
Builder builder) {
return
get(
builder);
}
@
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
Object getRepeatedRaw(
GeneratedMessageV3 message, int
index) {
return
getRepeated(
message,
index);
}
@
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,
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 com.google.protobuf.
Message.
Builder newBuilder() {
return
mapEntryMessageDefaultInstance.
newBuilderForType();
}
@
Override
public com.google.protobuf.
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.");
}
}
// ---------------------------------------------------------------
private static final class
SingularEnumFieldAccessor
extends
SingularFieldAccessor {
SingularEnumFieldAccessor(
final
FieldDescriptor descriptor, final
String camelCaseName,
final
Class<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass,
final
String containingOneofCamelCaseName) {
super(
descriptor,
camelCaseName,
messageClass,
builderClass,
containingOneofCamelCaseName);
enumDescriptor =
descriptor.
getEnumType();
valueOfMethod =
getMethodOrDie(
type, "valueOf",
EnumValueDescriptor.class);
getValueDescriptorMethod =
getMethodOrDie(
type, "getValueDescriptor");
supportUnknownEnumValue =
descriptor.
getFile().
supportsUnknownEnumValue();
if (
supportUnknownEnumValue) {
getValueMethod =
getMethodOrDie(
messageClass, "get" +
camelCaseName + "Value");
getValueMethodBuilder =
getMethodOrDie(
builderClass, "get" +
camelCaseName + "Value");
setValueMethod =
getMethodOrDie(
builderClass, "set" +
camelCaseName + "Value", int.class);
}
}
private
EnumDescriptor enumDescriptor;
private
Method valueOfMethod;
private
Method getValueDescriptorMethod;
private boolean
supportUnknownEnumValue;
private
Method getValueMethod;
private
Method getValueMethodBuilder;
private
Method setValueMethod;
@
Override
public
Object get(final
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) {
invokeOrDie(
setValueMethod,
builder,
((
EnumValueDescriptor)
value).
getNumber());
return;
}
super.set(
builder,
invokeOrDie(
valueOfMethod, null,
value));
}
}
private static final class
RepeatedEnumFieldAccessor
extends
RepeatedFieldAccessor {
RepeatedEnumFieldAccessor(
final
FieldDescriptor descriptor, final
String camelCaseName,
final
Class<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass) {
super(
descriptor,
camelCaseName,
messageClass,
builderClass);
enumDescriptor =
descriptor.
getEnumType();
valueOfMethod =
getMethodOrDie(
type, "valueOf",
EnumValueDescriptor.class);
getValueDescriptorMethod =
getMethodOrDie(
type, "getValueDescriptor");
supportUnknownEnumValue =
descriptor.
getFile().
supportsUnknownEnumValue();
if (
supportUnknownEnumValue) {
getRepeatedValueMethod =
getMethodOrDie(
messageClass, "get" +
camelCaseName + "Value", int.class);
getRepeatedValueMethodBuilder =
getMethodOrDie(
builderClass, "get" +
camelCaseName + "Value", int.class);
setRepeatedValueMethod =
getMethodOrDie(
builderClass, "set" +
camelCaseName + "Value", int.class, int.class);
addRepeatedValueMethod =
getMethodOrDie(
builderClass, "add" +
camelCaseName + "Value", int.class);
}
}
private
EnumDescriptor enumDescriptor;
private final
Method valueOfMethod;
private final
Method getValueDescriptorMethod;
private boolean
supportUnknownEnumValue;
private
Method getRepeatedValueMethod;
private
Method getRepeatedValueMethodBuilder;
private
Method setRepeatedValueMethod;
private
Method addRepeatedValueMethod;
@
Override
@
SuppressWarnings("unchecked")
public
Object get(final
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
@
SuppressWarnings("unchecked")
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) {
invokeOrDie(
setRepeatedValueMethod,
builder,
index,
((
EnumValueDescriptor)
value).
getNumber());
return;
}
super.setRepeated(
builder,
index,
invokeOrDie(
valueOfMethod, null,
value));
}
@
Override
public void
addRepeated(final
Builder builder, final
Object value) {
if (
supportUnknownEnumValue) {
invokeOrDie(
addRepeatedValueMethod,
builder,
((
EnumValueDescriptor)
value).
getNumber());
return;
}
super.addRepeated(
builder,
invokeOrDie(
valueOfMethod, null,
value));
}
}
// ---------------------------------------------------------------
/**
* Field accessor for string fields.
*
* <p>This class makes getFooBytes() and setFooBytes() available for
* reflection API so that reflection based serialize/parse functions can
* access the raw bytes of the field to preserve non-UTF8 bytes in the
* string.
*
* <p>This ensures the serialize/parse round-trip safety, which is important
* for servers which forward messages.
*/
private static final class
SingularStringFieldAccessor
extends
SingularFieldAccessor {
SingularStringFieldAccessor(
final
FieldDescriptor descriptor, final
String camelCaseName,
final
Class<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass,
final
String containingOneofCamelCaseName) {
super(
descriptor,
camelCaseName,
messageClass,
builderClass,
containingOneofCamelCaseName);
getBytesMethod =
getMethodOrDie(
messageClass,
"get" +
camelCaseName + "Bytes");
getBytesMethodBuilder =
getMethodOrDie(
builderClass,
"get" +
camelCaseName + "Bytes");
setBytesMethodBuilder =
getMethodOrDie(
builderClass,
"set" +
camelCaseName + "Bytes",
ByteString.class);
}
private final
Method getBytesMethod;
private final
Method getBytesMethodBuilder;
private final
Method setBytesMethodBuilder;
@
Override
public
Object getRaw(final
GeneratedMessageV3 message) {
return
invokeOrDie(
getBytesMethod,
message);
}
@
Override
public
Object getRaw(
GeneratedMessageV3.
Builder builder) {
return
invokeOrDie(
getBytesMethodBuilder,
builder);
}
@
Override
public void
set(
GeneratedMessageV3.
Builder builder,
Object value) {
if (
value instanceof
ByteString) {
invokeOrDie(
setBytesMethodBuilder,
builder,
value);
} else {
super.set(
builder,
value);
}
}
}
// ---------------------------------------------------------------
private static final class
SingularMessageFieldAccessor
extends
SingularFieldAccessor {
SingularMessageFieldAccessor(
final
FieldDescriptor descriptor, final
String camelCaseName,
final
Class<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass,
final
String containingOneofCamelCaseName) {
super(
descriptor,
camelCaseName,
messageClass,
builderClass,
containingOneofCamelCaseName);
newBuilderMethod =
getMethodOrDie(
type, "newBuilder");
getBuilderMethodBuilder =
getMethodOrDie(
builderClass, "get" +
camelCaseName + "Builder");
}
private final
Method newBuilderMethod;
private final
Method getBuilderMethodBuilder;
private
Object coerceType(final
Object value) {
if (
type.
isInstance(
value)) {
return
value;
} else {
// The value is not the exact right message type. However, if it
// is an alternative implementation of the same type -- e.g. a
// DynamicMessage -- we should accept it. In this case we can make
// a copy of the message.
return ((
Message.
Builder)
invokeOrDie(
newBuilderMethod, null))
.
mergeFrom((
Message)
value).
buildPartial();
}
}
@
Override
public void
set(final
Builder builder, final
Object value) {
super.set(
builder,
coerceType(
value));
}
@
Override
public
Message.
Builder newBuilder() {
return (
Message.
Builder)
invokeOrDie(
newBuilderMethod, null);
}
@
Override
public
Message.
Builder getBuilder(
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<? extends
GeneratedMessageV3>
messageClass,
final
Class<? extends
Builder>
builderClass) {
super(
descriptor,
camelCaseName,
messageClass,
builderClass);
newBuilderMethod =
getMethodOrDie(
type, "newBuilder");
getBuilderMethodBuilder =
getMethodOrDie(
builderClass,
"get" +
camelCaseName + "Builder",
Integer.
TYPE);
}
private final
Method newBuilderMethod;
private final
Method getBuilderMethodBuilder;
private
Object coerceType(final
Object value) {
if (
type.
isInstance(
value)) {
return
value;
} else {
// The value is not the exact right message type. However, if it
// is an alternative implementation of the same type -- e.g. a
// DynamicMessage -- we should accept it. In this case we can make
// a copy of the message.
return ((
Message.
Builder)
invokeOrDie(
newBuilderMethod, null))
.
mergeFrom((
Message)
value).
build();
}
}
@
Override
public void
setRepeated(final
Builder builder,
final int
index, final
Object value) {
super.setRepeated(
builder,
index,
coerceType(
value));
}
@
Override
public void
addRepeated(final
Builder builder, final
Object value) {
super.addRepeated(
builder,
coerceType(
value));
}
@
Override
public
Message.
Builder newBuilder() {
return (
Message.
Builder)
invokeOrDie(
newBuilderMethod, null);
}
@
Override
public
Message.
Builder getRepeatedBuilder(
final
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 <MessageType extends
ExtendableMessage<MessageType>, T>
Extension<MessageType, T>
checkNotLite(
ExtensionLite<MessageType, T>
extension) {
if (
extension.
isLite()) {
throw new
IllegalArgumentException("Expected non-lite extension.");
}
return (
Extension<MessageType, T>)
extension;
}
protected static int
computeStringSize(final int
fieldNumber, final
Object value) {
if (
value instanceof
String) {
return
CodedOutputStream.
computeStringSize(
fieldNumber, (
String)
value);
} else {
return
CodedOutputStream.
computeBytesSize(
fieldNumber, (
ByteString)
value);
}
}
protected static int
computeStringSizeNoTag(final
Object value) {
if (
value instanceof
String) {
return
CodedOutputStream.
computeStringSizeNoTag((
String)
value);
} else {
return
CodedOutputStream.
computeBytesSizeNoTag((
ByteString)
value);
}
}
protected static void
writeString(
CodedOutputStream output, final int
fieldNumber, final
Object value) throws
IOException {
if (
value instanceof
String) {
output.
writeString(
fieldNumber, (
String)
value);
} else {
output.
writeBytes(
fieldNumber, (
ByteString)
value);
}
}
protected static void
writeStringNoTag(
CodedOutputStream output, final
Object value) throws
IOException {
if (
value instanceof
String) {
output.
writeStringNoTag((
String)
value);
} else {
output.
writeBytesNoTag((
ByteString)
value);
}
}
protected static <V> void
serializeIntegerMapTo(
CodedOutputStream out,
MapField<
Integer, V>
field,
MapEntry<
Integer, V>
defaultEntry,
int
fieldNumber) throws
IOException {
Map<
Integer, V>
m =
field.
getMap();
if (!
out.
isSerializationDeterministic()) {
serializeMapTo(
out,
m,
defaultEntry,
fieldNumber);
return;
}
// Sorting the unboxed keys and then look up the values during serialziation 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 <V> void
serializeLongMapTo(
CodedOutputStream out,
MapField<
Long, V>
field,
MapEntry<
Long, V>
defaultEntry,
int
fieldNumber)
throws
IOException {
Map<
Long, V>
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 <V> void
serializeStringMapTo(
CodedOutputStream out,
MapField<
String, V>
field,
MapEntry<
String, V>
defaultEntry,
int
fieldNumber)
throws
IOException {
Map<
String, V>
m =
field.
getMap();
if (!
out.
isSerializationDeterministic()) {
serializeMapTo(
out,
m,
defaultEntry,
fieldNumber);
return;
}
// Sorting the String keys and then look up the values during serialziation 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 <V> void
serializeBooleanMapTo(
CodedOutputStream out,
MapField<
Boolean, V>
field,
MapEntry<
Boolean, V>
defaultEntry,
int
fieldNumber)
throws
IOException {
Map<
Boolean, V>
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 <V> void
maybeSerializeBooleanEntryTo(
CodedOutputStream out,
Map<
Boolean, V>
m,
MapEntry<
Boolean, V>
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 <K, V> void
serializeMapTo(
CodedOutputStream out,
Map<K, V>
m,
MapEntry<K, V>
defaultEntry,
int
fieldNumber)
throws
IOException {
for (
Map.
Entry<K, V>
entry :
m.
entrySet()) {
out.
writeMessage(
fieldNumber,
defaultEntry.
newBuilderForType()
.
setKey(
entry.
getKey())
.
setValue(
entry.
getValue())
.
build());
}
}
}