aboutsummaryrefslogtreecommitdiff
path: root/java/src/main/java/com/google/protobuf/AbstractMessage.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/com/google/protobuf/AbstractMessage.java')
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java730
1 files changed, 133 insertions, 597 deletions
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index f4d115de..a645c205 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -30,14 +30,13 @@
package com.google.protobuf;
-import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.GeneratedMessage.ExtendableBuilder;
+import com.google.protobuf.Descriptors.OneofDescriptor;
import com.google.protobuf.Internal.EnumLite;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -49,56 +48,30 @@ import java.util.Map;
*/
public abstract class AbstractMessage extends AbstractMessageLite
implements Message {
- @SuppressWarnings("unchecked")
public boolean isInitialized() {
- // Check that all required fields are present.
- for (final FieldDescriptor field : getDescriptorForType().getFields()) {
- if (field.isRequired()) {
- if (!hasField(field)) {
- return false;
- }
- }
- }
-
- // Check that embedded messages are initialized.
- for (final Map.Entry<FieldDescriptor, Object> entry :
- getAllFields().entrySet()) {
- final FieldDescriptor field = entry.getKey();
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- if (field.isRepeated()) {
- for (final Message element : (List<Message>) entry.getValue()) {
- if (!element.isInitialized()) {
- return false;
- }
- }
- } else {
- if (!((Message) entry.getValue()).isInitialized()) {
- return false;
- }
- }
- }
- }
-
- return true;
+ return MessageReflection.isInitialized(this);
}
+
public List<String> findInitializationErrors() {
- return Builder.findMissingFields(this);
+ return MessageReflection.findMissingFields(this);
}
public String getInitializationErrorString() {
- return delimitWithCommas(findInitializationErrors());
+ return MessageReflection.delimitWithCommas(findInitializationErrors());
}
- private static String delimitWithCommas(List<String> parts) {
- StringBuilder result = new StringBuilder();
- for (String part : parts) {
- if (result.length() > 0) {
- result.append(", ");
- }
- result.append(part);
- }
- return result.toString();
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public boolean hasOneof(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException("hasOneof() is not implemented.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException(
+ "getOneofFieldDescriptor() is not implemented.");
}
@Override
@@ -107,28 +80,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
}
public void writeTo(final CodedOutputStream output) throws IOException {
- final boolean isMessageSet =
- getDescriptorForType().getOptions().getMessageSetWireFormat();
-
- for (final Map.Entry<FieldDescriptor, Object> entry :
- getAllFields().entrySet()) {
- final FieldDescriptor field = entry.getKey();
- final Object value = entry.getValue();
- if (isMessageSet && field.isExtension() &&
- field.getType() == FieldDescriptor.Type.MESSAGE &&
- !field.isRepeated()) {
- output.writeMessageSetExtension(field.getNumber(), (Message) value);
- } else {
- FieldSet.writeField(field, value, output);
- }
- }
-
- final UnknownFieldSet unknownFields = getUnknownFields();
- if (isMessageSet) {
- unknownFields.writeAsMessageSetTo(output);
- } else {
- unknownFields.writeTo(output);
- }
+ MessageReflection.writeMessageTo(this, output, false);
}
private int memoizedSize = -1;
@@ -139,33 +91,8 @@ public abstract class AbstractMessage extends AbstractMessageLite
return size;
}
- size = 0;
- final boolean isMessageSet =
- getDescriptorForType().getOptions().getMessageSetWireFormat();
-
- for (final Map.Entry<FieldDescriptor, Object> entry :
- getAllFields().entrySet()) {
- final FieldDescriptor field = entry.getKey();
- final Object value = entry.getValue();
- if (isMessageSet && field.isExtension() &&
- field.getType() == FieldDescriptor.Type.MESSAGE &&
- !field.isRepeated()) {
- size += CodedOutputStream.computeMessageSetExtensionSize(
- field.getNumber(), (Message) value);
- } else {
- size += FieldSet.computeFieldSize(field, value);
- }
- }
-
- final UnknownFieldSet unknownFields = getUnknownFields();
- if (isMessageSet) {
- size += unknownFields.getSerializedSizeAsMessageSet();
- } else {
- size += unknownFields.getSerializedSize();
- }
-
- memoizedSize = size;
- return size;
+ memoizedSize = MessageReflection.getSerializedSize(this);
+ return memoizedSize;
}
@Override
@@ -180,22 +107,93 @@ public abstract class AbstractMessage extends AbstractMessageLite
if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
return false;
}
- return getAllFields().equals(otherMessage.getAllFields()) &&
+ return compareFields(getAllFields(), otherMessage.getAllFields()) &&
getUnknownFields().equals(otherMessage.getUnknownFields());
}
@Override
public int hashCode() {
- int hash = 41;
- hash = (19 * hash) + getDescriptorForType().hashCode();
- hash = hashFields(hash, getAllFields());
- hash = (29 * hash) + getUnknownFields().hashCode();
+ int hash = memoizedHashCode;
+ if (hash == 0) {
+ hash = 41;
+ hash = (19 * hash) + getDescriptorForType().hashCode();
+ hash = hashFields(hash, getAllFields());
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ }
return hash;
}
+
+ private static ByteString toByteString(Object value) {
+ if (value instanceof byte[]) {
+ return ByteString.copyFrom((byte[]) value);
+ } else {
+ return (ByteString) value;
+ }
+ }
+
+ /**
+ * Compares two bytes fields. The parameters must be either a byte array or a
+ * ByteString object. They can be of different type though.
+ */
+ private static boolean compareBytes(Object a, Object b) {
+ if (a instanceof byte[] && b instanceof byte[]) {
+ return Arrays.equals((byte[])a, (byte[])b);
+ }
+ return toByteString(a).equals(toByteString(b));
+ }
+
+ /**
+ * Compares two set of fields.
+ * This method is used to implement {@link AbstractMessage#equals(Object)}
+ * and {@link AbstractMutableMessage#equals(Object)}. It takes special care
+ * of bytes fields because immutable messages and mutable messages use
+ * different Java type to reprensent a bytes field and this method should be
+ * able to compare immutable messages, mutable messages and also an immutable
+ * message to a mutable message.
+ */
+ static boolean compareFields(Map<FieldDescriptor, Object> a,
+ Map<FieldDescriptor, Object> b) {
+ if (a.size() != b.size()) {
+ return false;
+ }
+ for (FieldDescriptor descriptor : a.keySet()) {
+ if (!b.containsKey(descriptor)) {
+ return false;
+ }
+ Object value1 = a.get(descriptor);
+ Object value2 = b.get(descriptor);
+ if (descriptor.getType() == FieldDescriptor.Type.BYTES) {
+ if (descriptor.isRepeated()) {
+ List list1 = (List) value1;
+ List list2 = (List) value2;
+ if (list1.size() != list2.size()) {
+ return false;
+ }
+ for (int i = 0; i < list1.size(); i++) {
+ if (!compareBytes(list1.get(i), list2.get(i))) {
+ return false;
+ }
+ }
+ } else {
+ // Compares a singular bytes field.
+ if (!compareBytes(value1, value2)) {
+ return false;
+ }
+ }
+ } else {
+ // Compare non-bytes fields.
+ if (!value1.equals(value2)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
/** Get a hash code for given fields and values, using the given seed. */
@SuppressWarnings("unchecked")
- protected int hashFields(int hash, Map<FieldDescriptor, Object> map) {
+ protected static int hashFields(int hash, Map<FieldDescriptor, Object> map) {
for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
FieldDescriptor field = entry.getKey();
Object value = entry.getValue();
@@ -204,31 +202,15 @@ public abstract class AbstractMessage extends AbstractMessageLite
hash = (53 * hash) + value.hashCode();
} else if (field.isRepeated()) {
List<? extends EnumLite> list = (List<? extends EnumLite>) value;
- hash = (53 * hash) + hashEnumList(list);
+ hash = (53 * hash) + Internal.hashEnumList(list);
} else {
- hash = (53 * hash) + hashEnum((EnumLite) value);
+ hash = (53 * hash) + Internal.hashEnum((EnumLite) value);
}
}
return hash;
}
/**
- * Helper method for implementing {@link Message#hashCode()}.
- * @see Boolean#hashCode()
- */
- protected static int hashLong(long n) {
- return (int) (n ^ (n >>> 32));
- }
-
- /**
- * Helper method for implementing {@link Message#hashCode()}.
- * @see Boolean#hashCode()
- */
- protected static int hashBoolean(boolean b) {
- return b ? 1231 : 1237;
- }
-
- /**
* Package private helper method for AbstractParser to create
* UninitializedMessageException with missing field information.
*/
@@ -237,26 +219,6 @@ public abstract class AbstractMessage extends AbstractMessageLite
return Builder.newUninitializedMessageException(this);
}
- /**
- * Helper method for implementing {@link Message#hashCode()}.
- * <p>
- * This is needed because {@link java.lang.Enum#hashCode()} is final, but we
- * need to use the field number as the hash code to ensure compatibility
- * between statically and dynamically generated enum objects.
- */
- protected static int hashEnum(EnumLite e) {
- return e.getNumber();
- }
-
- /** Helper method for implementing {@link Message#hashCode()}. */
- protected static int hashEnumList(List<? extends EnumLite> list) {
- int hash = 1;
- for (EnumLite e : list) {
- hash = 31 * hash + hashEnum(e);
- }
- return hash;
- }
-
// =================================================================
/**
@@ -272,6 +234,25 @@ public abstract class AbstractMessage extends AbstractMessageLite
@Override
public abstract BuilderType clone();
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public boolean hasOneof(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException("hasOneof() is not implemented.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException(
+ "getOneofFieldDescriptor() is not implemented.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public BuilderType clearOneof(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException("clearOneof() is not implemented.");
+ }
+
public BuilderType clear() {
for (final Map.Entry<FieldDescriptor, Object> entry :
getAllFields().entrySet()) {
@@ -281,11 +262,11 @@ public abstract class AbstractMessage extends AbstractMessageLite
}
public List<String> findInitializationErrors() {
- return findMissingFields(this);
+ return MessageReflection.findMissingFields(this);
}
public String getInitializationErrorString() {
- return delimitWithCommas(findInitializationErrors());
+ return MessageReflection.delimitWithCommas(findInitializationErrors());
}
public BuilderType mergeFrom(final Message other) {
@@ -350,8 +331,13 @@ public abstract class AbstractMessage extends AbstractMessageLite
break;
}
- if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
- getDescriptorForType(), this, null, tag)) {
+ MessageReflection.BuilderAdapter builderAdapter =
+ new MessageReflection.BuilderAdapter(this);
+ if (!MessageReflection.mergeFieldFrom(input, unknownFields,
+ extensionRegistry,
+ getDescriptorForType(),
+ builderAdapter,
+ tag)) {
// end group tag
break;
}
@@ -360,394 +346,6 @@ public abstract class AbstractMessage extends AbstractMessageLite
return (BuilderType) this;
}
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static void addRepeatedField(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field,
- Object value) {
- if (builder != null) {
- builder.addRepeatedField(field, value);
- } else {
- extensions.addRepeatedField(field, value);
- }
- }
-
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static void setField(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field,
- Object value) {
- if (builder != null) {
- builder.setField(field, value);
- } else {
- extensions.setField(field, value);
- }
- }
-
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static boolean hasOriginalMessage(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field) {
- if (builder != null) {
- return builder.hasField(field);
- } else {
- return extensions.hasField(field);
- }
- }
-
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static Message getOriginalMessage(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field) {
- if (builder != null) {
- return (Message) builder.getField(field);
- } else {
- return (Message) extensions.getField(field);
- }
- }
-
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static void mergeOriginalMessage(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field,
- Message.Builder subBuilder) {
- Message originalMessage = getOriginalMessage(builder, extensions, field);
- if (originalMessage != null) {
- subBuilder.mergeFrom(originalMessage);
- }
- }
-
- /**
- * Like {@link #mergeFrom(CodedInputStream, ExtensionRegistryLite)}, but
- * parses a single field.
- *
- * When {@code builder} is not null, the method will parse and merge the
- * field into {@code builder}. Otherwise, it will try to parse the field
- * into {@code extensions}, when it's called by the parsing constructor in
- * generated classes.
- *
- * Package-private because it is used by GeneratedMessage.ExtendableMessage.
- * @param tag The tag, which should have already been read.
- * @return {@code true} unless the tag is an end-group tag.
- */
- static boolean mergeFieldFrom(
- CodedInputStream input,
- UnknownFieldSet.Builder unknownFields,
- ExtensionRegistryLite extensionRegistry,
- Descriptor type,
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- int tag) throws IOException {
- if (type.getOptions().getMessageSetWireFormat() &&
- tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
- mergeMessageSetExtensionFromCodedStream(
- input, unknownFields, extensionRegistry, type, builder, extensions);
- return true;
- }
-
- final int wireType = WireFormat.getTagWireType(tag);
- final int fieldNumber = WireFormat.getTagFieldNumber(tag);
-
- final FieldDescriptor field;
- Message defaultInstance = null;
-
- if (type.isExtensionNumber(fieldNumber)) {
- // extensionRegistry may be either ExtensionRegistry or
- // ExtensionRegistryLite. Since the type we are parsing is a full
- // message, only a full ExtensionRegistry could possibly contain
- // extensions of it. Otherwise we will treat the registry as if it
- // were empty.
- if (extensionRegistry instanceof ExtensionRegistry) {
- final ExtensionRegistry.ExtensionInfo extension =
- ((ExtensionRegistry) extensionRegistry)
- .findExtensionByNumber(type, fieldNumber);
- if (extension == null) {
- field = null;
- } else {
- field = extension.descriptor;
- defaultInstance = extension.defaultInstance;
- if (defaultInstance == null &&
- field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- throw new IllegalStateException(
- "Message-typed extension lacked default instance: " +
- field.getFullName());
- }
- }
- } else {
- field = null;
- }
- } else if (builder != null) {
- field = type.findFieldByNumber(fieldNumber);
- } else {
- field = null;
- }
-
- boolean unknown = false;
- boolean packed = false;
- if (field == null) {
- unknown = true; // Unknown field.
- } else if (wireType == FieldSet.getWireFormatForFieldType(
- field.getLiteType(),
- false /* isPacked */)) {
- packed = false;
- } else if (field.isPackable() &&
- wireType == FieldSet.getWireFormatForFieldType(
- field.getLiteType(),
- true /* isPacked */)) {
- packed = true;
- } else {
- unknown = true; // Unknown wire type.
- }
-
- if (unknown) { // Unknown field or wrong wire type. Skip.
- return unknownFields.mergeFieldFrom(tag, input);
- }
-
- if (packed) {
- final int length = input.readRawVarint32();
- final int limit = input.pushLimit(length);
- if (field.getLiteType() == WireFormat.FieldType.ENUM) {
- while (input.getBytesUntilLimit() > 0) {
- final int rawValue = input.readEnum();
- final Object value = field.getEnumType().findValueByNumber(rawValue);
- if (value == null) {
- // If the number isn't recognized as a valid value for this
- // enum, drop it (don't even add it to unknownFields).
- return true;
- }
- addRepeatedField(builder, extensions, field, value);
- }
- } else {
- while (input.getBytesUntilLimit() > 0) {
- final Object value =
- FieldSet.readPrimitiveField(input, field.getLiteType());
- addRepeatedField(builder, extensions, field, value);
- }
- }
- input.popLimit(limit);
- } else {
- final Object value;
- switch (field.getType()) {
- case GROUP: {
- final Message.Builder subBuilder;
- if (defaultInstance != null) {
- subBuilder = defaultInstance.newBuilderForType();
- } else {
- subBuilder = builder.newBuilderForField(field);
- }
- if (!field.isRepeated()) {
- mergeOriginalMessage(builder, extensions, field, subBuilder);
- }
- input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
- value = subBuilder.buildPartial();
- break;
- }
- case MESSAGE: {
- final Message.Builder subBuilder;
- if (defaultInstance != null) {
- subBuilder = defaultInstance.newBuilderForType();
- } else {
- subBuilder = builder.newBuilderForField(field);
- }
- if (!field.isRepeated()) {
- mergeOriginalMessage(builder, extensions, field, subBuilder);
- }
- input.readMessage(subBuilder, extensionRegistry);
- value = subBuilder.buildPartial();
- break;
- }
- case ENUM:
- final int rawValue = input.readEnum();
- value = field.getEnumType().findValueByNumber(rawValue);
- // If the number isn't recognized as a valid value for this enum,
- // drop it.
- if (value == null) {
- unknownFields.mergeVarintField(fieldNumber, rawValue);
- return true;
- }
- break;
- default:
- value = FieldSet.readPrimitiveField(input, field.getLiteType());
- break;
- }
-
- if (field.isRepeated()) {
- addRepeatedField(builder, extensions, field, value);
- } else {
- setField(builder, extensions, field, value);
- }
- }
-
- return true;
- }
-
- /**
- * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension.
- * If {@code builder} is not null, this method will merge MessageSet into
- * the builder. Otherwise, it will merge the MessageSet into {@code
- * extensions}.
- */
- private static void mergeMessageSetExtensionFromCodedStream(
- CodedInputStream input,
- UnknownFieldSet.Builder unknownFields,
- ExtensionRegistryLite extensionRegistry,
- Descriptor type,
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions) throws IOException {
-
- // The wire format for MessageSet is:
- // message MessageSet {
- // repeated group Item = 1 {
- // required int32 typeId = 2;
- // required bytes message = 3;
- // }
- // }
- // "typeId" is the extension's field number. The extension can only be
- // a message type, where "message" contains the encoded bytes of that
- // message.
- //
- // In practice, we will probably never see a MessageSet item in which
- // the message appears before the type ID, or where either field does not
- // appear exactly once. However, in theory such cases are valid, so we
- // should be prepared to accept them.
-
- int typeId = 0;
- ByteString rawBytes = null; // If we encounter "message" before "typeId"
- ExtensionRegistry.ExtensionInfo extension = null;
-
- // Read bytes from input, if we get it's type first then parse it eagerly,
- // otherwise we store the raw bytes in a local variable.
- while (true) {
- final int tag = input.readTag();
- if (tag == 0) {
- break;
- }
-
- if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
- typeId = input.readUInt32();
- if (typeId != 0) {
- // extensionRegistry may be either ExtensionRegistry or
- // ExtensionRegistryLite. Since the type we are parsing is a full
- // message, only a full ExtensionRegistry could possibly contain
- // extensions of it. Otherwise we will treat the registry as if it
- // were empty.
- if (extensionRegistry instanceof ExtensionRegistry) {
- extension = ((ExtensionRegistry) extensionRegistry)
- .findExtensionByNumber(type, typeId);
- }
- }
-
- } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
- if (typeId != 0) {
- if (extension != null && ExtensionRegistryLite.isEagerlyParseMessageSets()) {
- // We already know the type, so we can parse directly from the
- // input with no copying. Hooray!
- eagerlyMergeMessageSetExtension(
- input, extension, extensionRegistry, builder, extensions);
- rawBytes = null;
- continue;
- }
- }
- // We haven't seen a type ID yet or we want parse message lazily.
- rawBytes = input.readBytes();
-
- } else { // Unknown tag. Skip it.
- if (!input.skipField(tag)) {
- break; // End of group
- }
- }
- }
- input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
-
- // Process the raw bytes.
- if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
- if (extension != null) { // We known the type
- mergeMessageSetExtensionFromBytes(
- rawBytes, extension, extensionRegistry, builder, extensions);
- } else { // We don't know how to parse this. Ignore it.
- if (rawBytes != null) {
- unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
- .addLengthDelimited(rawBytes).build());
- }
- }
- }
- }
-
- private static void eagerlyMergeMessageSetExtension(
- CodedInputStream input,
- ExtensionRegistry.ExtensionInfo extension,
- ExtensionRegistryLite extensionRegistry,
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions) throws IOException {
-
- FieldDescriptor field = extension.descriptor;
- Message value = null;
- if (hasOriginalMessage(builder, extensions, field)) {
- Message originalMessage =
- getOriginalMessage(builder, extensions, field);
- Message.Builder subBuilder = originalMessage.toBuilder();
- input.readMessage(subBuilder, extensionRegistry);
- value = subBuilder.buildPartial();
- } else {
- value = input.readMessage(extension.defaultInstance.getParserForType(),
- extensionRegistry);
- }
-
- if (builder != null) {
- builder.setField(field, value);
- } else {
- extensions.setField(field, value);
- }
- }
-
- private static void mergeMessageSetExtensionFromBytes(
- ByteString rawBytes,
- ExtensionRegistry.ExtensionInfo extension,
- ExtensionRegistryLite extensionRegistry,
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions) throws IOException {
-
- FieldDescriptor field = extension.descriptor;
- boolean hasOriginalValue = hasOriginalMessage(builder, extensions, field);
-
- if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) {
- // If the field already exists, we just parse the field.
- Message value = null;
- if (hasOriginalValue) {
- Message originalMessage =
- getOriginalMessage(builder, extensions, field);
- Message.Builder subBuilder= originalMessage.toBuilder();
- subBuilder.mergeFrom(rawBytes, extensionRegistry);
- value = subBuilder.buildPartial();
- } else {
- value = extension.defaultInstance.getParserForType()
- .parsePartialFrom(rawBytes, extensionRegistry);
- }
- setField(builder, extensions, field, value);
- } else {
- // Use LazyField to load MessageSet lazily.
- LazyField lazyField = new LazyField(
- extension.defaultInstance, extensionRegistry, rawBytes);
- if (builder != null) {
- // TODO(xiangl): it looks like this method can only be invoked by
- // ExtendableBuilder, but I'm not sure. So I double check the type of
- // builder here. It may be useless and need more investigation.
- if (builder instanceof ExtendableBuilder) {
- builder.setField(field, lazyField);
- } else {
- builder.setField(field, lazyField.getValue());
- }
- } else {
- extensions.setField(field, lazyField);
- }
- }
- }
-
public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
setUnknownFields(
UnknownFieldSet.newBuilder(getUnknownFields())
@@ -761,79 +359,18 @@ public abstract class AbstractMessage extends AbstractMessageLite
"getFieldBuilder() called on an unsupported message type.");
}
+ public String toString() {
+ return TextFormat.printToString(this);
+ }
+
/**
* Construct an UninitializedMessageException reporting missing fields in
* the given message.
*/
protected static UninitializedMessageException
newUninitializedMessageException(Message message) {
- return new UninitializedMessageException(findMissingFields(message));
- }
-
- /**
- * Populates {@code this.missingFields} with the full "path" of each
- * missing required field in the given message.
- */
- private static List<String> findMissingFields(
- final MessageOrBuilder message) {
- final List<String> results = new ArrayList<String>();
- findMissingFields(message, "", results);
- return results;
- }
-
- /** Recursive helper implementing {@link #findMissingFields(Message)}. */
- private static void findMissingFields(final MessageOrBuilder message,
- final String prefix,
- final List<String> results) {
- for (final FieldDescriptor field :
- message.getDescriptorForType().getFields()) {
- if (field.isRequired() && !message.hasField(field)) {
- results.add(prefix + field.getName());
- }
- }
-
- for (final Map.Entry<FieldDescriptor, Object> entry :
- message.getAllFields().entrySet()) {
- final FieldDescriptor field = entry.getKey();
- final Object value = entry.getValue();
-
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- if (field.isRepeated()) {
- int i = 0;
- for (final Object element : (List) value) {
- findMissingFields((MessageOrBuilder) element,
- subMessagePrefix(prefix, field, i++),
- results);
- }
- } else {
- if (message.hasField(field)) {
- findMissingFields((MessageOrBuilder) value,
- subMessagePrefix(prefix, field, -1),
- results);
- }
- }
- }
- }
- }
-
- private static String subMessagePrefix(final String prefix,
- final FieldDescriptor field,
- final int index) {
- final StringBuilder result = new StringBuilder(prefix);
- if (field.isExtension()) {
- result.append('(')
- .append(field.getFullName())
- .append(')');
- } else {
- result.append(field.getName());
- }
- if (index != -1) {
- result.append('[')
- .append(index)
- .append(']');
- }
- result.append('.');
- return result.toString();
+ return new UninitializedMessageException(
+ MessageReflection.findMissingFields(message));
}
// ===============================================================
@@ -925,6 +462,5 @@ public abstract class AbstractMessage extends AbstractMessageLite
throws IOException {
return super.mergeDelimitedFrom(input, extensionRegistry);
}
-
}
}