aboutsummaryrefslogtreecommitdiffhomepage
path: root/java/src/main/java/com/google/protobuf/MapField.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/com/google/protobuf/MapField.java')
-rw-r--r--java/src/main/java/com/google/protobuf/MapField.java63
1 files changed, 45 insertions, 18 deletions
diff --git a/java/src/main/java/com/google/protobuf/MapField.java b/java/src/main/java/com/google/protobuf/MapField.java
index 82906d37..b290993c 100644
--- a/java/src/main/java/com/google/protobuf/MapField.java
+++ b/java/src/main/java/com/google/protobuf/MapField.java
@@ -30,9 +30,11 @@
package com.google.protobuf;
+import com.google.protobuf.MapFieldLite.MutatabilityAwareMap;
+
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -51,7 +53,7 @@ import java.util.Map;
* and getList() concurrently in multiple threads. If write-access is needed,
* all access must be synchronized.
*/
-public class MapField<K, V> {
+public class MapField<K, V> implements MutabilityOracle {
/**
* Indicates where the data of this map field is currently stored.
*
@@ -72,8 +74,9 @@ public class MapField<K, V> {
*/
private enum StorageMode {MAP, LIST, BOTH}
+ private volatile boolean isMutable;
private volatile StorageMode mode;
- private Map<K, V> mapData;
+ private MutatabilityAwareMap<K, V> mapData;
private List<Message> listData;
// Convert between a map entry Message and a key-value pair.
@@ -110,20 +113,19 @@ public class MapField<K, V> {
private MapField(
Converter<K, V> converter,
StorageMode mode,
- Map<K, V> mapData,
- List<Message> listData) {
+ Map<K, V> mapData) {
this.converter = converter;
+ this.isMutable = true;
this.mode = mode;
- this.mapData = mapData;
- this.listData = listData;
+ this.mapData = new MutatabilityAwareMap<K, V>(this, mapData);
+ this.listData = null;
}
private MapField(
MapEntry<K, V> defaultEntry,
StorageMode mode,
- Map<K, V> mapData,
- List<Message> listData) {
- this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData, listData);
+ Map<K, V> mapData) {
+ this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData);
}
@@ -131,14 +133,14 @@ public class MapField<K, V> {
public static <K, V> MapField<K, V> emptyMapField(
MapEntry<K, V> defaultEntry) {
return new MapField<K, V>(
- defaultEntry, StorageMode.MAP, Collections.<K, V>emptyMap(), null);
+ 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 HashMap<K, V>(), null);
+ defaultEntry, StorageMode.MAP, new LinkedHashMap<K, V>());
}
@@ -151,7 +153,7 @@ public class MapField<K, V> {
converter.convertMessageToKeyAndValue(message, map);
}
- private List<Message> convertMapToList(Map<K, V> mapData) {
+ private List<Message> convertMapToList(MutatabilityAwareMap<K, V> mapData) {
List<Message> listData = new ArrayList<Message>();
for (Map.Entry<K, V> entry : mapData.entrySet()) {
listData.add(
@@ -161,12 +163,12 @@ public class MapField<K, V> {
return listData;
}
- private Map<K, V> convertListToMap(List<Message> listData) {
- Map<K, V> mapData = new HashMap<K, V>();
+ private MutatabilityAwareMap<K, V> convertListToMap(List<Message> listData) {
+ Map<K, V> mapData = new LinkedHashMap<K, V>();
for (Message item : listData) {
convertMessageToKeyAndValue(item, mapData);
}
- return mapData;
+ return new MutatabilityAwareMap<K, V>(this, mapData);
}
/** Returns the content of this MapField as a read-only Map. */
@@ -199,7 +201,7 @@ public class MapField<K, V> {
}
public void clear() {
- mapData = new HashMap<K, V>();
+ mapData = new MutatabilityAwareMap<K, V>(this, new LinkedHashMap<K, V>());
mode = StorageMode.MAP;
}
@@ -221,7 +223,7 @@ public class MapField<K, V> {
/** Returns a deep copy of this MapField. */
public MapField<K, V> copy() {
return new MapField<K, V>(
- converter, StorageMode.MAP, MapFieldLite.copy(getMap()), null);
+ converter, StorageMode.MAP, MapFieldLite.copy(getMap()));
}
/** Gets the content of this MapField as a read-only List. */
@@ -256,4 +258,29 @@ public class MapField<K, V> {
Message getMapEntryMessageDefaultInstance() {
return converter.getMessageDefaultInstance();
}
+
+ /**
+ * Makes this list immutable. All subsequent modifications will throw an
+ * {@link UnsupportedOperationException}.
+ */
+ 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()
+ */
+ @Override
+ public void ensureMutable() {
+ if (!isMutable()) {
+ throw new UnsupportedOperationException();
+ }
+ }
}