diff options
author | xiaofeng@google.com <xiaofeng@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2012-09-22 02:40:50 +0000 |
---|---|---|
committer | xiaofeng@google.com <xiaofeng@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2012-09-22 02:40:50 +0000 |
commit | b55a20fa2c669b181f47ea9219b8e74d1263da19 (patch) | |
tree | 3936a0e7c22196587a6d8397372de41434fe2129 /java/src/main/java/com/google/protobuf/FieldSet.java | |
parent | 9ced30caf94bb4e7e9629c199679ff44e8ca7389 (diff) | |
download | protobuf-b55a20fa2c669b181f47ea9219b8e74d1263da19.tar.gz protobuf-b55a20fa2c669b181f47ea9219b8e74d1263da19.tar.bz2 protobuf-b55a20fa2c669b181f47ea9219b8e74d1263da19.zip |
Down-integrate from internal branch
Diffstat (limited to 'java/src/main/java/com/google/protobuf/FieldSet.java')
-rw-r--r-- | java/src/main/java/com/google/protobuf/FieldSet.java | 137 |
1 files changed, 105 insertions, 32 deletions
diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java index a85dbaa6..2663694f 100644 --- a/java/src/main/java/com/google/protobuf/FieldSet.java +++ b/java/src/main/java/com/google/protobuf/FieldSet.java @@ -30,12 +30,14 @@ package com.google.protobuf; +import com.google.protobuf.LazyField.LazyIterator; + +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.io.IOException; /** * A class which represents an arbitrary set of fields of some message type. @@ -68,6 +70,7 @@ final class FieldSet<FieldDescriptorType extends private final SmallSortedMap<FieldDescriptorType, Object> fields; private boolean isImmutable; + private boolean hasLazyField = false; /** Construct a new FieldSet. */ private FieldSet() { @@ -95,7 +98,7 @@ final class FieldSet<FieldDescriptorType extends FieldSet<T> emptySet() { return DEFAULT_INSTANCE; } - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true); /** Make this FieldSet immutable from this point forward. */ @@ -109,7 +112,7 @@ final class FieldSet<FieldDescriptorType extends } /** - * Retuns whether the FieldSet is immutable. This is true if it is the + * Returns whether the FieldSet is immutable. This is true if it is the * {@link #emptySet} or if {@link #makeImmutable} were called. * * @return whether the FieldSet is immutable. @@ -139,6 +142,7 @@ final class FieldSet<FieldDescriptorType extends FieldDescriptorType descriptor = entry.getKey(); clone.setField(descriptor, entry.getValue()); } + clone.hasLazyField = hasLazyField; return clone; } @@ -147,21 +151,52 @@ final class FieldSet<FieldDescriptorType extends /** See {@link Message.Builder#clear()}. */ public void clear() { fields.clear(); + hasLazyField = false; } /** * Get a simple map containing all the fields. */ public Map<FieldDescriptorType, Object> getAllFields() { + if (hasLazyField) { + SmallSortedMap<FieldDescriptorType, Object> result = + SmallSortedMap.newFieldMap(16); + for (int i = 0; i < fields.getNumArrayEntries(); i++) { + cloneFieldEntry(result, fields.getArrayEntryAt(i)); + } + for (Map.Entry<FieldDescriptorType, Object> entry : + fields.getOverflowEntries()) { + cloneFieldEntry(result, entry); + } + if (fields.isImmutable()) { + result.makeImmutable(); + } + return result; + } return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields); } + private void cloneFieldEntry(Map<FieldDescriptorType, Object> map, + Map.Entry<FieldDescriptorType, Object> entry) { + FieldDescriptorType key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof LazyField) { + map.put(key, ((LazyField) value).getValue()); + } else { + map.put(key, value); + } + } + /** * Get an iterator to the field map. This iterator should not be leaked out - * of the protobuf library as it is not protected from mutation when - * fields is not immutable. + * of the protobuf library as it is not protected from mutation when fields + * is not immutable. */ public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() { + if (hasLazyField) { + return new LazyIterator<FieldDescriptorType>( + fields.entrySet().iterator()); + } return fields.entrySet().iterator(); } @@ -185,14 +220,18 @@ final class FieldSet<FieldDescriptorType extends * to the caller to fetch the field's default value. */ public Object getField(final FieldDescriptorType descriptor) { - return fields.get(descriptor); + Object o = fields.get(descriptor); + if (o instanceof LazyField) { + return ((LazyField) o).getValue(); + } + return o; } /** * Useful for implementing * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. */ - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "rawtypes"}) public void setField(final FieldDescriptorType descriptor, Object value) { if (descriptor.isRepeated()) { @@ -204,7 +243,7 @@ final class FieldSet<FieldDescriptorType extends // Wrap the contents in a new list so that the caller cannot change // the list's contents after setting it. final List newList = new ArrayList(); - newList.addAll((List)value); + newList.addAll((List) value); for (final Object element : newList) { verifyType(descriptor.getLiteType(), element); } @@ -213,6 +252,9 @@ final class FieldSet<FieldDescriptorType extends verifyType(descriptor.getLiteType(), value); } + if (value instanceof LazyField) { + hasLazyField = true; + } fields.put(descriptor, value); } @@ -222,6 +264,9 @@ final class FieldSet<FieldDescriptorType extends */ public void clearField(final FieldDescriptorType descriptor) { fields.remove(descriptor); + if (fields.isEmpty()) { + hasLazyField = false; + } } /** @@ -234,7 +279,7 @@ final class FieldSet<FieldDescriptorType extends "getRepeatedField() can only be called on repeated fields."); } - final Object value = fields.get(descriptor); + final Object value = getField(descriptor); if (value == null) { return 0; } else { @@ -253,7 +298,7 @@ final class FieldSet<FieldDescriptorType extends "getRepeatedField() can only be called on repeated fields."); } - final Object value = fields.get(descriptor); + final Object value = getField(descriptor); if (value == null) { throw new IndexOutOfBoundsException(); @@ -275,13 +320,13 @@ final class FieldSet<FieldDescriptorType extends "getRepeatedField() can only be called on repeated fields."); } - final Object list = fields.get(descriptor); + final Object list = getField(descriptor); if (list == null) { throw new IndexOutOfBoundsException(); } verifyType(descriptor.getLiteType(), value); - ((List) list).set(index, value); + ((List<Object>) list).set(index, value); } /** @@ -298,13 +343,13 @@ final class FieldSet<FieldDescriptorType extends verifyType(descriptor.getLiteType(), value); - final Object existingValue = fields.get(descriptor); - List list; + final Object existingValue = getField(descriptor); + List<Object> list; if (existingValue == null) { - list = new ArrayList(); + list = new ArrayList<Object>(); fields.put(descriptor, list); } else { - list = (List) existingValue; + list = (List<Object>) existingValue; } list.add(value); @@ -338,7 +383,8 @@ final class FieldSet<FieldDescriptorType extends break; case MESSAGE: // TODO(kenton): Caller must do type checking here, I guess. - isValid = value instanceof MessageLite; + isValid = + (value instanceof MessageLite) || (value instanceof LazyField); break; } @@ -392,8 +438,16 @@ final class FieldSet<FieldDescriptorType extends } } } else { - if (!((MessageLite) entry.getValue()).isInitialized()) { - return false; + Object value = entry.getValue(); + if (value instanceof MessageLite) { + if (!((MessageLite) value).isInitialized()) { + return false; + } + } else if (value instanceof LazyField) { + return true; + } else { + throw new IllegalArgumentException( + "Wrong object type used with protocol message reflection."); } } } @@ -416,7 +470,8 @@ final class FieldSet<FieldDescriptorType extends } /** - * Like {@link #mergeFrom(Message)}, but merges from another {@link FieldSet}. + * Like {@link Message.Builder#mergeFrom(Message)}, but merges from another + * {@link FieldSet}. */ public void mergeFrom(final FieldSet<FieldDescriptorType> other) { for (int i = 0; i < other.fields.getNumArrayEntries(); i++) { @@ -428,14 +483,17 @@ final class FieldSet<FieldDescriptorType extends } } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "rawtypes"}) private void mergeFromField( final Map.Entry<FieldDescriptorType, Object> entry) { final FieldDescriptorType descriptor = entry.getKey(); - final Object otherValue = entry.getValue(); + Object otherValue = entry.getValue(); + if (otherValue instanceof LazyField) { + otherValue = ((LazyField) otherValue).getValue(); + } if (descriptor.isRepeated()) { - Object value = fields.get(descriptor); + Object value = getField(descriptor); if (value == null) { // Our list is empty, but we still need to make a defensive copy of // the other list since we don't know if the other FieldSet is still @@ -446,7 +504,7 @@ final class FieldSet<FieldDescriptorType extends ((List) value).addAll((List) otherValue); } } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { - Object value = fields.get(descriptor); + Object value = getField(descriptor); if (value == null) { fields.put(descriptor, otherValue); } else { @@ -457,7 +515,6 @@ final class FieldSet<FieldDescriptorType extends ((MessageLite) value).toBuilder(), (MessageLite) otherValue) .build()); } - } else { fields.put(descriptor, otherValue); } @@ -646,7 +703,11 @@ final class FieldSet<FieldDescriptorType extends } } } else { - writeElement(output, type, number, value); + if (value instanceof LazyField) { + writeElement(output, type, number, ((LazyField) value).getValue()); + } else { + writeElement(output, type, number, value); + } } } @@ -686,12 +747,18 @@ final class FieldSet<FieldDescriptorType extends private int getMessageSetSerializedSize( final Map.Entry<FieldDescriptorType, Object> entry) { final FieldDescriptorType descriptor = entry.getKey(); - if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE && - !descriptor.isRepeated() && !descriptor.isPacked()) { - return CodedOutputStream.computeMessageSetExtensionSize( - entry.getKey().getNumber(), (MessageLite) entry.getValue()); + Object value = entry.getValue(); + if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE + && !descriptor.isRepeated() && !descriptor.isPacked()) { + if (value instanceof LazyField) { + return CodedOutputStream.computeLazyFieldMessageSetExtensionSize( + entry.getKey().getNumber(), (LazyField) value); + } else { + return CodedOutputStream.computeMessageSetExtensionSize( + entry.getKey().getNumber(), (MessageLite) value); + } } else { - return computeFieldSize(descriptor, entry.getValue()); + return computeFieldSize(descriptor, value); } } @@ -741,7 +808,6 @@ final class FieldSet<FieldDescriptorType extends case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value); case STRING : return CodedOutputStream.computeStringSizeNoTag ((String )value); case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value); - case MESSAGE : return CodedOutputStream.computeMessageSizeNoTag ((MessageLite)value); case BYTES : return CodedOutputStream.computeBytesSizeNoTag ((ByteString )value); case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value); case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value); @@ -749,6 +815,13 @@ final class FieldSet<FieldDescriptorType extends case SINT32 : return CodedOutputStream.computeSInt32SizeNoTag ((Integer )value); case SINT64 : return CodedOutputStream.computeSInt64SizeNoTag ((Long )value); + case MESSAGE: + if (value instanceof LazyField) { + return CodedOutputStream.computeLazyFieldSizeNoTag((LazyField) value); + } else { + return CodedOutputStream.computeMessageSizeNoTag((MessageLite) value); + } + case ENUM: return CodedOutputStream.computeEnumSizeNoTag( ((Internal.EnumLite) value).getNumber()); |