Index: third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapField.java |
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapField.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapField.java |
index 907f0f71120d6b0b29399c0e930ea602231b1aaf..a6109f988f99e0d8c7060cac39c82fd267d58db9 100644 |
--- a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapField.java |
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapField.java |
@@ -30,25 +30,26 @@ |
package com.google.protobuf; |
-import com.google.protobuf.MapFieldLite.MutatabilityAwareMap; |
- |
import java.util.ArrayList; |
+import java.util.Collection; |
import java.util.Collections; |
+import java.util.Iterator; |
import java.util.LinkedHashMap; |
import java.util.List; |
import java.util.Map; |
+import java.util.Set; |
/** |
* Internal representation of map fields in generated messages. |
- * |
+ * |
* This class supports accessing the map field as a {@link Map} to be used in |
* generated API and also supports accessing the field as a {@link List} to be |
* used in reflection API. It keeps track of where the data is currently stored |
- * and do necessary conversions between map and list. |
- * |
+ * and do necessary conversions between map and list. |
+ * |
* This class is a protobuf implementation detail. Users shouldn't use this |
* class directly. |
- * |
+ * |
* THREAD-SAFETY NOTE: Read-only access is thread-safe. Users can call getMap() |
* and getList() concurrently in multiple threads. If write-access is needed, |
* all access must be synchronized. |
@@ -56,21 +57,21 @@ import java.util.Map; |
public class MapField<K, V> implements MutabilityOracle { |
/** |
* Indicates where the data of this map field is currently stored. |
- * |
+ * |
* MAP: Data is stored in mapData. |
* LIST: Data is stored in listData. |
* BOTH: mapData and listData have the same data. |
* |
* When the map field is accessed (through generated API or reflection API), |
* it will shift between these 3 modes: |
- * |
+ * |
* getMap() getList() getMutableMap() getMutableList() |
* MAP MAP BOTH MAP LIST |
* LIST BOTH LIST MAP LIST |
* BOTH BOTH BOTH MAP LIST |
- * |
+ * |
* As the map field changes its mode, the list/map reference returned in a |
- * previous method call may be invalidated. |
+ * previous method call may be invalidated. |
*/ |
private enum StorageMode {MAP, LIST, BOTH} |
@@ -78,26 +79,26 @@ public class MapField<K, V> implements MutabilityOracle { |
private volatile StorageMode mode; |
private MutatabilityAwareMap<K, V> mapData; |
private List<Message> listData; |
- |
+ |
// Convert between a map entry Message and a key-value pair. |
private static interface Converter<K, V> { |
Message convertKeyAndValueToMessage(K key, V value); |
void convertMessageToKeyAndValue(Message message, Map<K, V> map); |
- |
+ |
Message getMessageDefaultInstance(); |
} |
- |
+ |
private static class ImmutableMessageConverter<K, V> implements Converter<K, V> { |
private final MapEntry<K, V> defaultEntry; |
public ImmutableMessageConverter(MapEntry<K, V> defaultEntry) { |
this.defaultEntry = defaultEntry; |
} |
- |
+ |
@Override |
public Message convertKeyAndValueToMessage(K key, V value) { |
return defaultEntry.newBuilderForType().setKey(key).setValue(value).buildPartial(); |
} |
- |
+ |
@Override |
public void convertMessageToKeyAndValue(Message message, Map<K, V> map) { |
MapEntry<K, V> entry = (MapEntry<K, V>) message; |
@@ -109,10 +110,10 @@ public class MapField<K, V> implements MutabilityOracle { |
return defaultEntry; |
} |
} |
- |
+ |
private final Converter<K, V> converter; |
- |
+ |
private MapField( |
Converter<K, V> converter, |
StorageMode mode, |
@@ -123,34 +124,34 @@ public class MapField<K, V> implements MutabilityOracle { |
this.mapData = new MutatabilityAwareMap<K, V>(this, mapData); |
this.listData = null; |
} |
- |
+ |
private MapField( |
MapEntry<K, V> defaultEntry, |
StorageMode mode, |
Map<K, V> mapData) { |
this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData); |
} |
- |
- |
+ |
+ |
/** Returns an immutable empty MapField. */ |
public static <K, V> MapField<K, V> emptyMapField( |
MapEntry<K, V> defaultEntry) { |
return new MapField<K, V>( |
defaultEntry, StorageMode.MAP, Collections.<K, V>emptyMap()); |
} |
- |
- |
+ |
+ |
/** Creates a new mutable empty MapField. */ |
public static <K, V> MapField<K, V> newMapField(MapEntry<K, V> defaultEntry) { |
return new MapField<K, V>( |
defaultEntry, StorageMode.MAP, new LinkedHashMap<K, V>()); |
} |
- |
- |
+ |
+ |
private Message convertKeyAndValueToMessage(K key, V value) { |
return converter.convertKeyAndValueToMessage(key, value); |
} |
- |
+ |
@SuppressWarnings("unchecked") |
private void convertMessageToKeyAndValue(Message message, Map<K, V> map) { |
converter.convertMessageToKeyAndValue(message, map); |
@@ -173,7 +174,7 @@ public class MapField<K, V> implements MutabilityOracle { |
} |
return new MutatabilityAwareMap<K, V>(this, mapData); |
} |
- |
+ |
/** Returns the content of this MapField as a read-only Map. */ |
public Map<K, V> getMap() { |
if (mode == StorageMode.LIST) { |
@@ -186,7 +187,7 @@ public class MapField<K, V> implements MutabilityOracle { |
} |
return Collections.unmodifiableMap(mapData); |
} |
- |
+ |
/** Gets a mutable Map view of this MapField. */ |
public Map<K, V> getMutableMap() { |
if (mode != StorageMode.MAP) { |
@@ -194,20 +195,20 @@ public class MapField<K, V> implements MutabilityOracle { |
mapData = convertListToMap(listData); |
} |
listData = null; |
- mode = StorageMode.MAP; |
+ mode = StorageMode.MAP; |
} |
return mapData; |
} |
- |
+ |
public void mergeFrom(MapField<K, V> other) { |
getMutableMap().putAll(MapFieldLite.copy(other.getMap())); |
} |
- |
+ |
public void clear() { |
mapData = new MutatabilityAwareMap<K, V>(this, new LinkedHashMap<K, V>()); |
mode = StorageMode.MAP; |
} |
- |
+ |
@SuppressWarnings("unchecked") |
@Override |
public boolean equals(Object object) { |
@@ -217,18 +218,18 @@ public class MapField<K, V> implements MutabilityOracle { |
MapField<K, V> other = (MapField<K, V>) object; |
return MapFieldLite.<K, V>equals(getMap(), other.getMap()); |
} |
- |
+ |
@Override |
public int hashCode() { |
return MapFieldLite.<K, V>calculateHashCodeForMap(getMap()); |
} |
- |
+ |
/** Returns a deep copy of this MapField. */ |
public MapField<K, V> copy() { |
return new MapField<K, V>( |
converter, StorageMode.MAP, MapFieldLite.copy(getMap())); |
} |
- |
+ |
/** Gets the content of this MapField as a read-only List. */ |
List<Message> getList() { |
if (mode == StorageMode.MAP) { |
@@ -241,7 +242,7 @@ public class MapField<K, V> implements MutabilityOracle { |
} |
return Collections.unmodifiableList(listData); |
} |
- |
+ |
/** Gets a mutable List view of this MapField. */ |
List<Message> getMutableList() { |
if (mode != StorageMode.LIST) { |
@@ -253,7 +254,7 @@ public class MapField<K, V> implements MutabilityOracle { |
} |
return listData; |
} |
- |
+ |
/** |
* Gets the default instance of the message stored in the list view of this |
* map field. |
@@ -261,7 +262,7 @@ public class MapField<K, V> implements MutabilityOracle { |
Message getMapEntryMessageDefaultInstance() { |
return converter.getMessageDefaultInstance(); |
} |
- |
+ |
/** |
* Makes this list immutable. All subsequent modifications will throw an |
* {@link UnsupportedOperationException}. |
@@ -269,14 +270,14 @@ public class MapField<K, V> implements MutabilityOracle { |
public void makeImmutable() { |
isMutable = false; |
} |
- |
+ |
/** |
* Returns whether this field can be modified. |
*/ |
public boolean isMutable() { |
return isMutable; |
} |
- |
+ |
/* (non-Javadoc) |
* @see com.google.protobuf.MutabilityOracle#ensureMutable() |
*/ |
@@ -286,4 +287,338 @@ public class MapField<K, V> implements MutabilityOracle { |
throw new UnsupportedOperationException(); |
} |
} |
+ |
+ /** |
+ * An internal map that checks for mutability before delegating. |
+ */ |
+ private static class MutatabilityAwareMap<K, V> implements Map<K, V> { |
+ private final MutabilityOracle mutabilityOracle; |
+ private final Map<K, V> delegate; |
+ |
+ MutatabilityAwareMap(MutabilityOracle mutabilityOracle, Map<K, V> delegate) { |
+ this.mutabilityOracle = mutabilityOracle; |
+ this.delegate = delegate; |
+ } |
+ |
+ @Override |
+ public int size() { |
+ return delegate.size(); |
+ } |
+ |
+ @Override |
+ public boolean isEmpty() { |
+ return delegate.isEmpty(); |
+ } |
+ |
+ @Override |
+ public boolean containsKey(Object key) { |
+ return delegate.containsKey(key); |
+ } |
+ |
+ @Override |
+ public boolean containsValue(Object value) { |
+ return delegate.containsValue(value); |
+ } |
+ |
+ @Override |
+ public V get(Object key) { |
+ return delegate.get(key); |
+ } |
+ |
+ @Override |
+ public V put(K key, V value) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.put(key, value); |
+ } |
+ |
+ @Override |
+ public V remove(Object key) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.remove(key); |
+ } |
+ |
+ @Override |
+ public void putAll(Map<? extends K, ? extends V> m) { |
+ mutabilityOracle.ensureMutable(); |
+ delegate.putAll(m); |
+ } |
+ |
+ @Override |
+ public void clear() { |
+ mutabilityOracle.ensureMutable(); |
+ delegate.clear(); |
+ } |
+ |
+ @Override |
+ public Set<K> keySet() { |
+ return new MutatabilityAwareSet<K>(mutabilityOracle, delegate.keySet()); |
+ } |
+ |
+ @Override |
+ public Collection<V> values() { |
+ return new MutatabilityAwareCollection<V>(mutabilityOracle, delegate.values()); |
+ } |
+ |
+ @Override |
+ public Set<java.util.Map.Entry<K, V>> entrySet() { |
+ return new MutatabilityAwareSet<Entry<K, V>>(mutabilityOracle, delegate.entrySet()); |
+ } |
+ |
+ @Override |
+ public boolean equals(Object o) { |
+ return delegate.equals(o); |
+ } |
+ |
+ @Override |
+ public int hashCode() { |
+ return delegate.hashCode(); |
+ } |
+ |
+ @Override |
+ public String toString() { |
+ return delegate.toString(); |
+ } |
+ |
+ /** |
+ * An internal collection that checks for mutability before delegating. |
+ */ |
+ private static class MutatabilityAwareCollection<E> implements Collection<E> { |
+ private final MutabilityOracle mutabilityOracle; |
+ private final Collection<E> delegate; |
+ |
+ MutatabilityAwareCollection(MutabilityOracle mutabilityOracle, Collection<E> delegate) { |
+ this.mutabilityOracle = mutabilityOracle; |
+ this.delegate = delegate; |
+ } |
+ |
+ @Override |
+ public int size() { |
+ return delegate.size(); |
+ } |
+ |
+ @Override |
+ public boolean isEmpty() { |
+ return delegate.isEmpty(); |
+ } |
+ |
+ @Override |
+ public boolean contains(Object o) { |
+ return delegate.contains(o); |
+ } |
+ |
+ @Override |
+ public Iterator<E> iterator() { |
+ return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator()); |
+ } |
+ |
+ @Override |
+ public Object[] toArray() { |
+ return delegate.toArray(); |
+ } |
+ |
+ @Override |
+ public <T> T[] toArray(T[] a) { |
+ return delegate.toArray(a); |
+ } |
+ |
+ @Override |
+ public boolean add(E e) { |
+ // Unsupported operation in the delegate. |
+ throw new UnsupportedOperationException(); |
+ } |
+ |
+ @Override |
+ public boolean remove(Object o) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.remove(o); |
+ } |
+ |
+ @Override |
+ public boolean containsAll(Collection<?> c) { |
+ return delegate.containsAll(c); |
+ } |
+ |
+ @Override |
+ public boolean addAll(Collection<? extends E> c) { |
+ // Unsupported operation in the delegate. |
+ throw new UnsupportedOperationException(); |
+ } |
+ |
+ @Override |
+ public boolean removeAll(Collection<?> c) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.removeAll(c); |
+ } |
+ |
+ @Override |
+ public boolean retainAll(Collection<?> c) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.retainAll(c); |
+ } |
+ |
+ @Override |
+ public void clear() { |
+ mutabilityOracle.ensureMutable(); |
+ delegate.clear(); |
+ } |
+ |
+ @Override |
+ public boolean equals(Object o) { |
+ return delegate.equals(o); |
+ } |
+ |
+ @Override |
+ public int hashCode() { |
+ return delegate.hashCode(); |
+ } |
+ |
+ @Override |
+ public String toString() { |
+ return delegate.toString(); |
+ } |
+ } |
+ |
+ /** |
+ * An internal set that checks for mutability before delegating. |
+ */ |
+ private static class MutatabilityAwareSet<E> implements Set<E> { |
+ private final MutabilityOracle mutabilityOracle; |
+ private final Set<E> delegate; |
+ |
+ MutatabilityAwareSet(MutabilityOracle mutabilityOracle, Set<E> delegate) { |
+ this.mutabilityOracle = mutabilityOracle; |
+ this.delegate = delegate; |
+ } |
+ |
+ @Override |
+ public int size() { |
+ return delegate.size(); |
+ } |
+ |
+ @Override |
+ public boolean isEmpty() { |
+ return delegate.isEmpty(); |
+ } |
+ |
+ @Override |
+ public boolean contains(Object o) { |
+ return delegate.contains(o); |
+ } |
+ |
+ @Override |
+ public Iterator<E> iterator() { |
+ return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator()); |
+ } |
+ |
+ @Override |
+ public Object[] toArray() { |
+ return delegate.toArray(); |
+ } |
+ |
+ @Override |
+ public <T> T[] toArray(T[] a) { |
+ return delegate.toArray(a); |
+ } |
+ |
+ @Override |
+ public boolean add(E e) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.add(e); |
+ } |
+ |
+ @Override |
+ public boolean remove(Object o) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.remove(o); |
+ } |
+ |
+ @Override |
+ public boolean containsAll(Collection<?> c) { |
+ return delegate.containsAll(c); |
+ } |
+ |
+ @Override |
+ public boolean addAll(Collection<? extends E> c) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.addAll(c); |
+ } |
+ |
+ @Override |
+ public boolean retainAll(Collection<?> c) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.retainAll(c); |
+ } |
+ |
+ @Override |
+ public boolean removeAll(Collection<?> c) { |
+ mutabilityOracle.ensureMutable(); |
+ return delegate.removeAll(c); |
+ } |
+ |
+ @Override |
+ public void clear() { |
+ mutabilityOracle.ensureMutable(); |
+ delegate.clear(); |
+ } |
+ |
+ @Override |
+ public boolean equals(Object o) { |
+ return delegate.equals(o); |
+ } |
+ |
+ @Override |
+ public int hashCode() { |
+ return delegate.hashCode(); |
+ } |
+ |
+ @Override |
+ public String toString() { |
+ return delegate.toString(); |
+ } |
+ } |
+ |
+ /** |
+ * An internal iterator that checks for mutability before delegating. |
+ */ |
+ private static class MutatabilityAwareIterator<E> implements Iterator<E> { |
+ private final MutabilityOracle mutabilityOracle; |
+ private final Iterator<E> delegate; |
+ |
+ MutatabilityAwareIterator(MutabilityOracle mutabilityOracle, Iterator<E> delegate) { |
+ this.mutabilityOracle = mutabilityOracle; |
+ this.delegate = delegate; |
+ } |
+ |
+ @Override |
+ public boolean hasNext() { |
+ return delegate.hasNext(); |
+ } |
+ |
+ @Override |
+ public E next() { |
+ return delegate.next(); |
+ } |
+ |
+ @Override |
+ public void remove() { |
+ mutabilityOracle.ensureMutable(); |
+ delegate.remove(); |
+ } |
+ |
+ @Override |
+ public boolean equals(Object obj) { |
+ return delegate.equals(obj); |
+ } |
+ |
+ @Override |
+ public int hashCode() { |
+ return delegate.hashCode(); |
+ } |
+ |
+ @Override |
+ public String toString() { |
+ return delegate.toString(); |
+ } |
+ } |
+ } |
} |