Revision: 8394
Author: [email protected]
Date: Tue Jul 20 05:31:21 2010
Log: Allow RPC for unmodifiable collections

Review at http://gwt-code-reviews.appspot.com/620805

Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=8394

Modified:
/trunk/user/src/com/google/gwt/user/client/rpc/core/java/util/Collections.java /trunk/user/src/com/google/gwt/user/client/rpc/core/java/util/TreeSet_CustomFieldSerializer.java
 /trunk/user/super/com/google/gwt/emul/java/util/Collections.java
 /trunk/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java
 /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
 /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java
/trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java
 /trunk/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
 /trunk/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
/trunk/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java

=======================================
--- /trunk/user/src/com/google/gwt/user/client/rpc/core/java/util/Collections.java Tue Jun 22 06:26:45 2010 +++ /trunk/user/src/com/google/gwt/user/client/rpc/core/java/util/Collections.java Tue Jul 20 05:31:21 2010
@@ -19,9 +19,18 @@
 import com.google.gwt.user.client.rpc.SerializationStreamReader;
 import com.google.gwt.user.client.rpc.SerializationStreamWriter;

+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;

 /**
  * Dummy class for nesting the custom serializer.
@@ -122,4 +131,210 @@
       streamWriter.writeObject(instance.get(0));
     }
   }
-}
+
+  /**
+ * Custom field serializer for {...@link java.util.Collections$SingletonMap}.
+   */
+  public static final class SingletonMap_CustomFieldSerializer {
+
+    @SuppressWarnings({"unused", "unchecked"})
+    public static void deserialize(SerializationStreamReader streamReader,
+        Map instance) throws SerializationException {
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Map instantiate(SerializationStreamReader streamReader)
+        throws SerializationException {
+      Object key = streamReader.readObject();
+      Object value = streamReader.readObject();
+      return java.util.Collections.singletonMap(key, value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void serialize(SerializationStreamWriter streamWriter,
+        Map instance) throws SerializationException {
+      Map.Entry entry = (Map.Entry) instance.entrySet().iterator().next();
+      streamWriter.writeObject(entry.getKey());
+      streamWriter.writeObject(entry.getValue());
+    }
+  }
+
+  /**
+ * Custom field serializer for {...@link java.util.Collections$UnmodifiableCollection}.
+   */
+  public static final class UnmodifiableCollection_CustomFieldSerializer {
+
+    @SuppressWarnings({"unused", "unchecked"})
+    public static void deserialize(SerializationStreamReader streamReader,
+        Collection instance) throws SerializationException {
+    }
+
+    @SuppressWarnings("unchecked")
+ public static Collection instantiate(SerializationStreamReader streamReader)
+        throws SerializationException {
+      Collection collection = new ArrayList();
+ Collection_CustomFieldSerializerBase.deserialize(streamReader, collection);
+      return java.util.Collections.unmodifiableCollection(collection);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void serialize(SerializationStreamWriter streamWriter,
+        Collection instance) throws SerializationException {
+ Collection_CustomFieldSerializerBase.serialize(streamWriter, instance);
+    }
+  }
+
+  /**
+ * Custom field serializer for {...@link java.util.Collections$UnmodifiableList}.
+   */
+  public static final class UnmodifiableList_CustomFieldSerializer {
+
+    @SuppressWarnings({"unused", "unchecked"})
+    public static void deserialize(SerializationStreamReader streamReader,
+        List instance) throws SerializationException {
+    }
+
+    @SuppressWarnings("unchecked")
+    public static List instantiate(SerializationStreamReader streamReader)
+        throws SerializationException {
+      ArrayList list = new ArrayList();
+      Collection_CustomFieldSerializerBase.deserialize(streamReader, list);
+      return java.util.Collections.unmodifiableList(list);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void serialize(SerializationStreamWriter streamWriter,
+        List instance) throws SerializationException {
+ Collection_CustomFieldSerializerBase.serialize(streamWriter, instance);
+    }
+  }
+
+  /**
+ * Custom field serializer for {...@link java.util.Collections$UnmodifiableMap}.
+   */
+  public static final class UnmodifiableMap_CustomFieldSerializer {
+
+    @SuppressWarnings({"unused", "unchecked"})
+    public static void deserialize(SerializationStreamReader streamReader,
+        Map instance) throws SerializationException {
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Map instantiate(SerializationStreamReader streamReader)
+        throws SerializationException {
+      HashMap map = new HashMap();
+      Map_CustomFieldSerializerBase.deserialize(streamReader, map);
+      return java.util.Collections.unmodifiableMap(map);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void serialize(SerializationStreamWriter streamWriter,
+        Map instance) throws SerializationException {
+      Map_CustomFieldSerializerBase.serialize(streamWriter, instance);
+    }
+  }
+
+  /**
+ * Custom field serializer for {...@link java.util.Collections$UnmodifiableRandomAccessList}.
+   */
+ public static final class UnmodifiableRandomAccessList_CustomFieldSerializer {
+
+    @SuppressWarnings({"unused", "unchecked"})
+    public static void deserialize(SerializationStreamReader streamReader,
+        List instance) throws SerializationException {
+    }
+
+    @SuppressWarnings("unchecked")
+    public static List instantiate(SerializationStreamReader streamReader)
+        throws SerializationException {
+      ArrayList list = new ArrayList();
+      Collection_CustomFieldSerializerBase.deserialize(streamReader, list);
+      return java.util.Collections.unmodifiableList(list);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void serialize(SerializationStreamWriter streamWriter,
+        List instance) throws SerializationException {
+ Collection_CustomFieldSerializerBase.serialize(streamWriter, instance);
+    }
+  }
+
+  /**
+ * Custom field serializer for {...@link java.util.Collections$UnmodifiableSet}.
+   */
+  public static final class UnmodifiableSet_CustomFieldSerializer {
+
+    @SuppressWarnings({"unused", "unchecked"})
+    public static void deserialize(SerializationStreamReader streamReader,
+        Set instance) throws SerializationException {
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Set instantiate(SerializationStreamReader streamReader)
+        throws SerializationException {
+      HashSet set = new HashSet();
+      Collection_CustomFieldSerializerBase.deserialize(streamReader, set);
+      return java.util.Collections.unmodifiableSet(set);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void serialize(SerializationStreamWriter streamWriter,
+        Set instance) throws SerializationException {
+ Collection_CustomFieldSerializerBase.serialize(streamWriter, instance);
+    }
+  }
+
+  /**
+ * Custom field serializer for {...@link java.util.Collections$UnmodifiableSortedMap}.
+   */
+  public static final class UnmodifiableSortedMap_CustomFieldSerializer {
+
+    @SuppressWarnings({"unused", "unchecked"})
+    public static void deserialize(SerializationStreamReader streamReader,
+        SortedMap instance) throws SerializationException {
+    }
+
+    @SuppressWarnings("unchecked")
+ public static SortedMap instantiate(SerializationStreamReader streamReader)
+        throws SerializationException {
+      Comparator comparator = (Comparator) streamReader.readObject();
+      TreeMap map = new TreeMap(comparator);
+      Map_CustomFieldSerializerBase.deserialize(streamReader, map);
+      return java.util.Collections.unmodifiableSortedMap(map);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void serialize(SerializationStreamWriter streamWriter,
+        SortedMap instance) throws SerializationException {
+      streamWriter.writeObject(instance.comparator());
+      Map_CustomFieldSerializerBase.serialize(streamWriter, instance);
+    }
+  }
+
+  /**
+ * Custom field serializer for {...@link java.util.Collections$UnmodifiableSortedSet}.
+   */
+  public static final class UnmodifiableSortedSet_CustomFieldSerializer {
+
+    @SuppressWarnings({"unused", "unchecked"})
+    public static void deserialize(SerializationStreamReader streamReader,
+        SortedSet instance) throws SerializationException {
+    }
+
+    @SuppressWarnings("unchecked")
+ public static SortedSet instantiate(SerializationStreamReader streamReader)
+        throws SerializationException {
+      Comparator comparator = (Comparator) streamReader.readObject();
+      TreeSet set = new TreeSet(comparator);
+      Collection_CustomFieldSerializerBase.deserialize(streamReader, set);
+      return java.util.Collections.unmodifiableSortedSet(set);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static void serialize(SerializationStreamWriter streamWriter,
+        SortedSet instance) throws SerializationException {
+      streamWriter.writeObject(instance.comparator());
+ Collection_CustomFieldSerializerBase.serialize(streamWriter, instance);
+    }
+  }
+}
=======================================
--- /trunk/user/src/com/google/gwt/user/client/rpc/core/java/util/TreeSet_CustomFieldSerializer.java Wed Oct 28 09:10:53 2009 +++ /trunk/user/src/com/google/gwt/user/client/rpc/core/java/util/TreeSet_CustomFieldSerializer.java Tue Jul 20 05:31:21 2010
@@ -23,7 +23,7 @@
 import java.util.TreeSet;

 /**
- * Custom field serializer for {...@link java.util.TreeMap}.
+ * Custom field serializer for {...@link java.util.TreeSet}.
  */
 @SuppressWarnings("unchecked")
 public class TreeSet_CustomFieldSerializer {
=======================================
--- /trunk/user/super/com/google/gwt/emul/java/util/Collections.java Mon Apr 19 10:54:02 2010 +++ /trunk/user/super/com/google/gwt/emul/java/util/Collections.java Tue Jul 20 05:31:21 2010
@@ -134,12 +134,122 @@
     }
   }

-  /*
-   * TODO: make the unmodifiable collections serializable.
+  /**
+   * A Map containing exactly one key/value pair, used to implement
+   * the singletonMap(K key, V value) method.  The map is unmodifiable
+   * and attempt to modify it directly, by iterators, or using the
+   * sets returned from keySet(), entrySet(), or values() will fail
+   * with an UnsupportedOperationException.  Null keys and values are
+   * allowed.
    */
+ private static final class SingletonMap<K, V> extends AbstractMap<K, V> implements Serializable {
+    Set<Map.Entry<K, V>> entrySet = null;
+    final K key;
+    Set<K> keySet = null;
+    final V value;
+    Set<V> valueSet = null;
+
+    public SingletonMap(K key, V value) {
+      this.key = key;
+      this.value = value;
+    }
+
+    public void clear() {
+      throw new UnsupportedOperationException();
+    }
+
+    public boolean containsKey(Object key) {
+      return Utility.equalsWithNullCheck(this.key, key);
+    }
+
+    public boolean containsValue(Object value) {
+      return Utility.equalsWithNullCheck(this.value, value);
+    }
+
+    public Set<Map.Entry<K, V>> entrySet() {
+      if (entrySet == null) {
+        HashSet set = new HashSet();
+        set.add(new AbstractMapEntry<K, V>() {
+          public K getKey() {
+            return key;
+          }
+
+          public V getValue() {
+            return value;
+          }
+
+          public V setValue(V value) {
+            throw new UnsupportedOperationException();
+          }
+        });
+        entrySet = unmodifiableSet(set);
+      }
+      return entrySet;
+    }
+
+    public boolean equals(Object o) {
+      if (!(o instanceof Map)) {
+        return false;
+      }
+      Map other = (Map) o;
+      return other.size() == 1
+        && other.containsKey(key)
+        && Utility.equalsWithNullCheck(other.get(key), value);
+    }
+
+    public V get(Object key) {
+      return Utility.equalsWithNullCheck(this.key, key) ? value : null;
+    }
+
+    public boolean isEmpty() {
+      return false;
+    }
+
+    public Set<K> keySet() {
+      if (keySet == null) {
+        HashSet<K> set = new HashSet<K>();
+        set.add(key);
+        keySet = unmodifiableSet(set);
+      }
+      return keySet;
+    }
+
+    public V put(K key, V value) {
+      throw new UnsupportedOperationException();
+    }
+
+    public void putAll(Map<? extends K, ? extends V> t) {
+      if (t.size() > 0) {
+        throw new UnsupportedOperationException();
+      }
+    }
+
+    public V remove(Object key) {
+      if (Utility.equalsWithNullCheck(this.key, key)) {
+        throw new UnsupportedOperationException();
+      }
+      return null;
+    }
+
+    public int size() {
+      return 1;
+    }
+
+    public Collection<V> values() {
+      if (valueSet == null) {
+        HashSet<V> set = new HashSet<V>();
+        set.add(value);
+        valueSet = unmodifiableSet(set);
+      }
+      return valueSet;
+    }
+  }

   static class UnmodifiableCollection<T> implements Collection<T> {
-    protected final Collection<? extends T> coll;
+    protected Collection<? extends T> coll;
+
+    public UnmodifiableCollection() {
+    }

     public UnmodifiableCollection(Collection<? extends T> coll) {
       this.coll = coll;
@@ -203,8 +313,11 @@
   }

static class UnmodifiableList<T> extends UnmodifiableCollection<T> implements
-      List<T> {
-    private final List<? extends T> list;
+      List<T>, Serializable {
+    private List<? extends T> list;
+
+    public UnmodifiableList() {
+    }

     public UnmodifiableList(List<? extends T> list) {
       super(list);
@@ -267,7 +380,7 @@
     }
   }

-  static class UnmodifiableMap<K, V> implements Map<K, V> {
+  static class UnmodifiableMap<K, V> implements Map<K, V>, Serializable {

     static class UnmodifiableEntrySet<K, V> extends
         UnmodifiableSet<Map.Entry<K, V>> {
@@ -373,9 +486,12 @@

     private transient UnmodifiableSet<Map.Entry<K, V>> entrySet;
     private transient UnmodifiableSet<K> keySet;
-    private final Map<? extends K, ? extends V> map;
+    private Map<? extends K, ? extends V> map;
     private transient UnmodifiableCollection<V> values;

+    public UnmodifiableMap() {
+    }
+
     public UnmodifiableMap(Map<? extends K, ? extends V> map) {
       this.map = map;
     }
@@ -454,14 +570,22 @@
   }

   static class UnmodifiableRandomAccessList<T> extends UnmodifiableList<T>
-      implements RandomAccess {
+      implements RandomAccess, Serializable {
+
+    public UnmodifiableRandomAccessList() {
+    }
+
     public UnmodifiableRandomAccessList(List<? extends T> list) {
       super(list);
     }
   }

static class UnmodifiableSet<T> extends UnmodifiableCollection<T> implements
-      Set<T> {
+      Set<T>, Serializable {
+
+    public UnmodifiableSet() {
+    }
+
     public UnmodifiableSet(Set<? extends T> set) {
       super(set);
     }
@@ -478,10 +602,13 @@
   }

   static class UnmodifiableSortedMap<K, V> extends UnmodifiableMap<K, V>
-      implements SortedMap<K, V> {
+      implements SortedMap<K, V>, Serializable {

     private SortedMap<K, ? extends V> sortedMap;

+    public UnmodifiableSortedMap() {
+    }
+
     public UnmodifiableSortedMap(SortedMap<K, ? extends V> sortedMap) {
       super(sortedMap);
       this.sortedMap = sortedMap;
@@ -523,9 +650,12 @@
   }

static class UnmodifiableSortedSet<E> extends UnmodifiableSet<E> implements
-      SortedSet<E> {
+      SortedSet<E>, Serializable {
     private SortedSet<E> sortedSet;

+    public UnmodifiableSortedSet() {
+    }
+
     @SuppressWarnings("unchecked")
     public UnmodifiableSortedSet(SortedSet<? extends E> sortedSet) {
       super(sortedSet);
@@ -939,9 +1069,7 @@
   }

   public static <K, V> Map<K, V> singletonMap(K key, V value) {
-    Map<K, V> map = new HashMap<K, V>(1);
-    map.put(key, value);
-    return unmodifiableMap(map);
+    return new SingletonMap<K, V>(key, value);
   }

   public static <T> void sort(List<T> target) {
=======================================
--- /trunk/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java Thu Dec 17 20:58:44 2009 +++ /trunk/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java Tue Jul 20 05:31:21 2010
@@ -17,6 +17,7 @@

 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -155,6 +156,116 @@
     Collections.reverse(b);
     assertEquals(b, createRandomList());
   }
+
+  public void testSingletonMap() {
+    Map<String, Integer> map = Collections.singletonMap("two", 2);
+    assertEquals(1, map.size());
+    assertFalse(map.isEmpty());
+    assertEquals(Integer.valueOf(2), map.get("two"));
+    assertTrue(map.containsKey("two"));
+    assertFalse(map.containsKey("three"));
+    assertTrue(map.containsValue(2));
+    assertFalse(map.containsValue(3));
+
+    try {
+      map.clear();
+      fail();
+    } catch (UnsupportedOperationException e) {
+    }
+
+    try {
+      map.put("three", 3);
+      fail();
+    } catch (UnsupportedOperationException e) {
+    }
+
+    try {
+      HashMap<String, Integer> m = new HashMap<String, Integer>();
+      map.putAll(m);
+    } catch (UnsupportedOperationException e) {
+      fail();
+    }
+
+    try {
+      HashMap<String, Integer> m = new HashMap<String, Integer>();
+      m.put("three", 3);
+      map.putAll(m);
+      fail();
+    } catch (UnsupportedOperationException e) {
+    }
+
+    try {
+      map.remove("three");
+    } catch (UnsupportedOperationException e) {
+      fail();
+    }
+
+    try {
+      map.remove("two");
+      fail();
+    } catch (UnsupportedOperationException e) {
+    }
+
+    // Test equals, hashCode, keySet, entrySet and values against a
+    // HashMap
+    HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
+    hashMap.put("two", 2);
+    assertEquals(hashMap, map);
+    assertEquals(hashMap.hashCode(), map.hashCode());
+    assertEquals(hashMap.keySet(), map.keySet());
+    assertEquals(hashMap.entrySet(), map.entrySet());
+
+    Collection<Integer> values = map.values();
+    assertNotNull(values);
+    assertEquals(1, values.size());
+    assertEquals(Integer.valueOf(2), values.iterator().next());
+    try {
+      values.add(3);
+      fail();
+    } catch (UnsupportedOperationException e) {
+    }
+
+    // null key
+    map = Collections.singletonMap(null, 2);
+    assertEquals(1, map.size());
+    assertFalse(map.isEmpty());
+    assertEquals(Integer.valueOf(2), map.get(null));
+    assertTrue(map.containsKey(null));
+    assertFalse(map.containsKey("three"));
+    assertTrue(map.containsValue(2));
+    assertFalse(map.containsValue(3));
+
+    // null value
+    map = Collections.singletonMap("null", null);
+    assertEquals(1, map.size());
+    assertFalse(map.isEmpty());
+    assertNull(map.get("null"));
+    assertTrue(map.containsKey("null"));
+    assertFalse(map.containsKey("three"));
+    assertTrue(map.containsValue(null));
+    assertFalse(map.containsValue(3));
+
+    // null key and value
+    map = Collections.singletonMap(null, null);
+    assertEquals(1, map.size());
+    assertFalse(map.isEmpty());
+    assertNull(map.get(null));
+    assertTrue(map.containsKey(null));
+    assertFalse(map.containsKey("three"));
+    assertTrue(map.containsValue(null));
+    assertFalse(map.containsValue(3));
+
+    // Equality for maps with a null value
+ Map<Integer, String> map2 = Collections.singletonMap(Integer.valueOf(2), null);
+    HashMap<Integer, String> hashMap2 = new HashMap<Integer, String>();
+    assertFalse(map2.equals(hashMap2));
+    hashMap2.put(Integer.valueOf(1), null);
+    assertFalse(map2.equals(hashMap2));
+    hashMap2.put(Integer.valueOf(2), null);
+    assertFalse(map2.equals(hashMap2));
+    hashMap2.remove(Integer.valueOf(1));
+    assertTrue(map2.equals(hashMap2));
+  }

   public void testSort() {
     List<String> a = createSortedList();
=======================================
--- /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java Mon Apr 19 10:54:02 2010 +++ /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java Tue Jul 20 05:31:21 2010
@@ -25,12 +25,14 @@
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeSingleton;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeMap;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeSet;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeUnmodifiable;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeVector;
import com.google.gwt.user.client.rpc.core.java.util.LinkedHashMap_CustomFieldSerializer;

 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -581,6 +583,23 @@
           }
         });
   }
+
+  public void testSingletonMap() {
+    CollectionsTestServiceAsync service = getServiceAsync();
+    delayTestFinishForRpc();
+    service.echoSingletonMap(TestSetFactory.createSingletonMap(),
+        new AsyncCallback<Map<Integer, MarkerTypeSingleton>>() {
+          public void onFailure(Throwable caught) {
+            TestSetValidator.rethrowException(caught);
+          }
+
+          public void onSuccess(Map<Integer, MarkerTypeSingleton> result) {
+            assertNotNull(result);
+            assertTrue(TestSetValidator.isValidSingletonMap(result));
+            finishTest();
+          }
+        });
+  }

   public void testSqlDateArray() {
     CollectionsTestServiceAsync service = getServiceAsync();
@@ -706,6 +725,125 @@
           });
     }
   }
+
+  public void testUnmodifiableCollection() {
+    CollectionsTestServiceAsync service = getServiceAsync();
+    delayTestFinishForRpc();
+ service.echoUnmodifiableCollection(TestSetFactory.createUnmodifiableCollection(),
+        new AsyncCallback<Collection<MarkerTypeUnmodifiable>>() {
+          public void onFailure(Throwable caught) {
+            TestSetValidator.rethrowException(caught);
+          }
+
+ public void onSuccess(Collection<MarkerTypeUnmodifiable> result) {
+            assertNotNull(result);
+ assertTrue(TestSetValidator.isValidUnmodifiableCollection(result));
+            finishTest();
+          }
+        });
+  }
+
+  public void testUnmodifiableList() {
+    CollectionsTestServiceAsync service = getServiceAsync();
+    delayTestFinishForRpc();
+    service.echoUnmodifiableList(TestSetFactory.createUnmodifiableList(),
+        new AsyncCallback<List<MarkerTypeUnmodifiable>>() {
+          public void onFailure(Throwable caught) {
+            TestSetValidator.rethrowException(caught);
+          }
+
+          public void onSuccess(List<MarkerTypeUnmodifiable> result) {
+            assertNotNull(result);
+            assertTrue(TestSetValidator.isValidUnmodifiableList(result));
+            finishTest();
+          }
+        });
+  }
+
+  public void testUnmodifiableMap() {
+    CollectionsTestServiceAsync service = getServiceAsync();
+    delayTestFinishForRpc();
+    service.echoUnmodifiableMap(TestSetFactory.createUnmodifiableMap(),
+        new AsyncCallback<Map<Integer, MarkerTypeUnmodifiable>>() {
+          public void onFailure(Throwable caught) {
+            TestSetValidator.rethrowException(caught);
+          }
+
+ public void onSuccess(Map<Integer, MarkerTypeUnmodifiable> result) {
+            assertNotNull(result);
+            assertTrue(TestSetValidator.isValidUnmodifiableMap(result));
+            finishTest();
+          }
+        });
+  }
+
+  public void testUnmodifiableRandomAccessList() {
+    CollectionsTestServiceAsync service = getServiceAsync();
+    delayTestFinishForRpc();
+ service.echoUnmodifiableList(TestSetFactory.createUnmodifiableRandomAccessList(),
+        new AsyncCallback<List<MarkerTypeUnmodifiable>>() {
+          public void onFailure(Throwable caught) {
+            TestSetValidator.rethrowException(caught);
+          }
+
+          public void onSuccess(List<MarkerTypeUnmodifiable> result) {
+            assertNotNull(result);
+ assertTrue(TestSetValidator.isValidUnmodifiableRandomAccessList(result));
+            finishTest();
+          }
+        });
+  }
+
+  public void testUnmodifiableSet() {
+    CollectionsTestServiceAsync service = getServiceAsync();
+    delayTestFinishForRpc();
+    service.echoUnmodifiableSet(TestSetFactory.createUnmodifiableSet(),
+        new AsyncCallback<Set<MarkerTypeUnmodifiable>>() {
+          public void onFailure(Throwable caught) {
+            TestSetValidator.rethrowException(caught);
+          }
+
+          public void onSuccess(Set<MarkerTypeUnmodifiable> result) {
+            assertNotNull(result);
+            assertTrue(TestSetValidator.isValidUnmodifiableSet(result));
+            finishTest();
+          }
+        });
+  }
+
+  public void testUnmodifiableSortedMap() {
+    CollectionsTestServiceAsync service = getServiceAsync();
+    delayTestFinishForRpc();
+ service.echoUnmodifiableMap(TestSetFactory.createUnmodifiableSortedMap(),
+        new AsyncCallback<Map<Integer, MarkerTypeUnmodifiable>>() {
+          public void onFailure(Throwable caught) {
+            TestSetValidator.rethrowException(caught);
+          }
+
+ public void onSuccess(Map<Integer, MarkerTypeUnmodifiable> result) {
+            assertNotNull(result);
+ assertTrue(TestSetValidator.isValidUnmodifiableSortedMap(result));
+            finishTest();
+          }
+        });
+  }
+
+  public void testUnmodifiableSortedSet() {
+    CollectionsTestServiceAsync service = getServiceAsync();
+    delayTestFinishForRpc();
+ service.echoUnmodifiableSet(TestSetFactory.createUnmodifiableSortedSet(),
+        new AsyncCallback<Set<MarkerTypeUnmodifiable>>() {
+          public void onFailure(Throwable caught) {
+            TestSetValidator.rethrowException(caught);
+          }
+
+          public void onSuccess(Set<MarkerTypeUnmodifiable> result) {
+            assertNotNull(result);
+ assertTrue(TestSetValidator.isValidUnmodifiableSortedSet(result));
+            finishTest();
+          }
+        });
+  }

   public void testVector() {
     CollectionsTestServiceAsync service = getServiceAsync();
=======================================
--- /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java Mon Apr 19 10:54:02 2010 +++ /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java Tue Jul 20 05:31:21 2010
@@ -25,11 +25,13 @@
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeSingleton;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeMap;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeSet;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeUnmodifiable;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeVector;

 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -156,4 +158,25 @@
   // For Collections.singletonList()
List<MarkerTypeSingleton> echoSingletonList(List<MarkerTypeSingleton> value)
       throws CollectionsTestServiceException;
-}
+
+  // For Collections.singletonMap()
+ Map<Integer, MarkerTypeSingleton> echoSingletonMap(Map<Integer, MarkerTypeSingleton> value)
+      throws CollectionsTestServiceException;
+
+  // For Collections.unmodifiableCollection()
+ Collection<MarkerTypeUnmodifiable> echoUnmodifiableCollection(Collection<MarkerTypeUnmodifiable> value)
+      throws CollectionsTestServiceException;
+
+  // For Collections.unmodifiableList()
+ List<MarkerTypeUnmodifiable> echoUnmodifiableList(List<MarkerTypeUnmodifiable> value)
+      throws CollectionsTestServiceException;
+
+  // For Collections.unmodifiableMap()
+  Map<Integer, MarkerTypeUnmodifiable> echoUnmodifiableMap(
+      Map<Integer, MarkerTypeUnmodifiable> value)
+      throws CollectionsTestServiceException;
+
+  // For Collections.unmodifiableSet()
+ Set<MarkerTypeUnmodifiable> echoUnmodifiableSet(Set<MarkerTypeUnmodifiable> value)
+      throws CollectionsTestServiceException;
+}
=======================================
--- /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java Mon Apr 19 10:54:02 2010 +++ /trunk/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java Tue Jul 20 05:31:21 2010
@@ -25,11 +25,13 @@
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeSingleton;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeMap;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeSet;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeUnmodifiable;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeVector;

 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -137,4 +139,24 @@
   // For Collections.singletonList()
   void echoSingletonList(List<MarkerTypeSingleton> value,
       AsyncCallback<List<MarkerTypeSingleton>> callback);
-}
+
+  // For Collections.singletonMap()
+  void echoSingletonMap(Map<Integer, MarkerTypeSingleton> value,
+      AsyncCallback<Map<Integer, MarkerTypeSingleton>> callback);
+
+  // For Collections.unmodifiableCollection()
+  void echoUnmodifiableCollection(Collection<MarkerTypeUnmodifiable> value,
+      AsyncCallback<Collection<MarkerTypeUnmodifiable>> callback);
+
+  // For Collections.unmodifiableList()
+  void echoUnmodifiableList(List<MarkerTypeUnmodifiable> value,
+      AsyncCallback<List<MarkerTypeUnmodifiable>> callback);
+
+  // For Collections.unmodifiableMap()
+  void echoUnmodifiableMap(Map<Integer, MarkerTypeUnmodifiable> value,
+      AsyncCallback<Map<Integer, MarkerTypeUnmodifiable>> callback);
+
+  // For Collections.unmodifiableSet()
+  void echoUnmodifiableSet(Set<MarkerTypeUnmodifiable> value,
+      AsyncCallback<Set<MarkerTypeUnmodifiable>> callback);
+}
=======================================
--- /trunk/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java Mon Jun 7 09:38:44 2010 +++ /trunk/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java Tue Jul 20 05:31:21 2010
@@ -20,15 +20,19 @@
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.TreeSet;
 import java.util.Vector;
@@ -190,6 +194,16 @@
       super("singleton");
     }
   }
+
+  /**
+ * A single-use marker type to independently check type parameter exposure in
+   * unmodifiable collections.
+   */
+  public static final class MarkerTypeUnmodifiable extends MarkerBase {
+    MarkerTypeUnmodifiable() {
+      super("unmodifiable");
+    }
+  }

   /**
* A single-use marker type to independently check type parameter exposure in
@@ -587,6 +601,10 @@
   public static List<MarkerTypeSingleton> createSingletonList() {
     return java.util.Collections.singletonList(new MarkerTypeSingleton());
   }
+
+  public static Map<Integer, MarkerTypeSingleton> createSingletonMap() {
+ return java.util.Collections.singletonMap(2, new MarkerTypeSingleton());
+  }

   public static java.sql.Date[] createSqlDateArray() {
     return new java.sql.Date[] {
@@ -643,6 +661,50 @@
     set.add(new MarkerTypeTreeSet("w00t"));
     return set;
   }
+
+ public static Collection<MarkerTypeUnmodifiable> createUnmodifiableCollection() { + List<MarkerTypeUnmodifiable> list = new LinkedList<MarkerTypeUnmodifiable>();
+    list.add(new MarkerTypeUnmodifiable());
+    return java.util.Collections.unmodifiableCollection(list);
+  }
+
+  public static List<MarkerTypeUnmodifiable> createUnmodifiableList() {
+ List<MarkerTypeUnmodifiable> list = new LinkedList<MarkerTypeUnmodifiable>();
+    list.add(new MarkerTypeUnmodifiable());
+    return java.util.Collections.unmodifiableList(list);
+  }
+
+ public static Map<Integer, MarkerTypeUnmodifiable> createUnmodifiableMap() {
+    Map<Integer, MarkerTypeUnmodifiable> map =
+      new HashMap<Integer, MarkerTypeUnmodifiable>();
+    map.put(1, new MarkerTypeUnmodifiable());
+    return java.util.Collections.unmodifiableMap(map);
+  }
+
+ public static Map<Integer, MarkerTypeUnmodifiable> createUnmodifiableSortedMap() {
+    SortedMap<Integer, MarkerTypeUnmodifiable> map =
+      new TreeMap<Integer, MarkerTypeUnmodifiable>();
+    map.put(1, new MarkerTypeUnmodifiable());
+    return java.util.Collections.unmodifiableSortedMap(map);
+  }
+
+ public static List<MarkerTypeUnmodifiable> createUnmodifiableRandomAccessList() { + List<MarkerTypeUnmodifiable> list = new ArrayList<MarkerTypeUnmodifiable>();
+    list.add(new MarkerTypeUnmodifiable());
+    return java.util.Collections.unmodifiableList(list);
+  }
+
+  public static Set<MarkerTypeUnmodifiable> createUnmodifiableSet() {
+ Set<MarkerTypeUnmodifiable> set = new HashSet<MarkerTypeUnmodifiable>();
+    set.add(new MarkerTypeUnmodifiable());
+    return java.util.Collections.unmodifiableSet(set);
+  }
+
+  public static Set<MarkerTypeUnmodifiable> createUnmodifiableSortedSet() {
+ SortedSet<MarkerTypeUnmodifiable> set = new TreeSet<MarkerTypeUnmodifiable>();
+    set.add(new MarkerTypeUnmodifiable());
+    return java.util.Collections.unmodifiableSortedSet(set);
+  }

   public static Vector<MarkerTypeVector> createVector() {
     Vector<MarkerTypeVector> vector = new Vector<MarkerTypeVector>();
=======================================
--- /trunk/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java Mon Apr 19 10:54:02 2010 +++ /trunk/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java Tue Jul 20 05:31:21 2010
@@ -19,6 +19,7 @@
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeSingleton;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeMap;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeSet;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeUnmodifiable; import com.google.gwt.user.client.rpc.TestSetFactory.SerializableDoublyLinkedNode; import com.google.gwt.user.client.rpc.TestSetFactory.SerializableGraphWithCFS; import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg;
@@ -30,6 +31,7 @@
 import static junit.framework.Assert.assertSame;

 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -37,7 +39,10 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.RandomAccess;
 import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.TreeSet;
 import java.util.Vector;
@@ -550,6 +555,27 @@
     }
     return true;
   }
+
+ public static boolean isValidSingletonMap(Map<Integer, MarkerTypeSingleton> map) {
+    if (map == null || map.size() != 1) {
+      return false;
+    }
+    try {
+      map.put(3, new MarkerTypeSingleton());
+      return false;
+    } catch (UnsupportedOperationException e) {
+    }
+    Object value = map.get(2);
+    // Perform instanceof check in case RPC did the wrong thing
+    if (!(value instanceof MarkerTypeSingleton)) {
+      return false;
+    }
+    MarkerTypeSingleton singleton = (MarkerTypeSingleton) value;
+    if (!"singleton".equals(singleton.getValue())) {
+      return false;
+    }
+    return true;
+  }

   public static boolean isValidTrivialCyclicGraph(
       SerializableDoublyLinkedNode actual) {
@@ -577,6 +603,169 @@

     return true;
   }
+
+ public static boolean isValidUnmodifiableCollection(Collection<MarkerTypeUnmodifiable> collection) {
+    if (collection == null || collection.size() != 1) {
+      return false;
+    }
+    try {
+      collection.add(new MarkerTypeUnmodifiable());
+      return false;
+    } catch (UnsupportedOperationException e) {
+    }
+
+    Object value = collection.iterator().next();
+    // Perform instanceof check in case RPC did the wrong thing
+    if (!(value instanceof MarkerTypeUnmodifiable)) {
+      return false;
+    }
+    MarkerTypeUnmodifiable v = (MarkerTypeUnmodifiable) value;
+    if (!"unmodifiable".equals(v.getValue())) {
+      return false;
+    }
+    return true;
+  }
+
+ public static boolean isValidUnmodifiableList(List<MarkerTypeUnmodifiable> list) {
+    if (list == null || list.size() != 1) {
+      return false;
+    }
+    try {
+      list.add(new MarkerTypeUnmodifiable());
+      return false;
+    } catch (UnsupportedOperationException e) {
+    }
+
+    Object value = list.get(0);
+    // Perform instanceof check in case RPC did the wrong thing
+    if (!(value instanceof MarkerTypeUnmodifiable)) {
+      return false;
+    }
+    MarkerTypeUnmodifiable v = (MarkerTypeUnmodifiable) value;
+    if (!"unmodifiable".equals(v.getValue())) {
+      return false;
+    }
+    return true;
+  }
+
+ public static boolean isValidUnmodifiableMap(Map<Integer, MarkerTypeUnmodifiable> map) {
+    if (map == null || map.size() != 1) {
+      return false;
+    }
+    try {
+      map.put(2, new MarkerTypeUnmodifiable());
+      return false;
+    } catch (UnsupportedOperationException e) {
+    }
+
+    Object value = map.get(1);
+    // Perform instanceof check in case RPC did the wrong thing
+    if (!(value instanceof MarkerTypeUnmodifiable)) {
+      return false;
+    }
+    MarkerTypeUnmodifiable v = (MarkerTypeUnmodifiable) value;
+    if (!"unmodifiable".equals(v.getValue())) {
+      return false;
+    }
+    return true;
+  }
+
+ public static boolean isValidUnmodifiableRandomAccessList(List<MarkerTypeUnmodifiable> list) {
+    if (list == null || list.size() != 1) {
+      return false;
+    }
+    if (!(list instanceof RandomAccess)) {
+      return false;
+    }
+    try {
+      list.add(new MarkerTypeUnmodifiable());
+      return false;
+    } catch (UnsupportedOperationException e) {
+    }
+
+    Object value = list.get(0);
+    // Perform instanceof check in case RPC did the wrong thing
+    if (!(value instanceof MarkerTypeUnmodifiable)) {
+      return false;
+    }
+    MarkerTypeUnmodifiable v = (MarkerTypeUnmodifiable) value;
+    if (!"unmodifiable".equals(v.getValue())) {
+      return false;
+    }
+    return true;
+  }
+
+ public static boolean isValidUnmodifiableSet(Set<MarkerTypeUnmodifiable> set) {
+    if (set == null || set.size() != 1) {
+      return false;
+    }
+    try {
+      set.add(new MarkerTypeUnmodifiable());
+      return false;
+    } catch (UnsupportedOperationException e) {
+    }
+
+    Object value = set.iterator().next();
+    // Perform instanceof check in case RPC did the wrong thing
+    if (!(value instanceof MarkerTypeUnmodifiable)) {
+      return false;
+    }
+    MarkerTypeUnmodifiable v = (MarkerTypeUnmodifiable) value;
+    if (!"unmodifiable".equals(v.getValue())) {
+      return false;
+    }
+    return true;
+  }
+
+ public static boolean isValidUnmodifiableSortedMap(Map<Integer, MarkerTypeUnmodifiable> map) {
+    if (map == null || map.size() != 1) {
+      return false;
+    }
+    if (!(map instanceof SortedMap<?, ?>)) {
+      return false;
+    }
+    try {
+      map.put(2, new MarkerTypeUnmodifiable());
+      return false;
+    } catch (UnsupportedOperationException e) {
+    }
+
+    Object value = map.get(1);
+    // Perform instanceof check in case RPC did the wrong thing
+    if (!(value instanceof MarkerTypeUnmodifiable)) {
+      return false;
+    }
+    MarkerTypeUnmodifiable v = (MarkerTypeUnmodifiable) value;
+    if (!"unmodifiable".equals(v.getValue())) {
+      return false;
+    }
+    return true;
+  }
+
+ public static boolean isValidUnmodifiableSortedSet(Set<MarkerTypeUnmodifiable> set) {
+    if (set == null || set.size() != 1) {
+      return false;
+    }
+    if (!(set instanceof SortedSet<?>)) {
+      return false;
+    }
+    try {
+      set.add(new MarkerTypeUnmodifiable());
+      return false;
+    } catch (UnsupportedOperationException e) {
+    }
+
+    Object value = set.iterator().next();
+    // Perform instanceof check in case RPC did the wrong thing
+    if (!(value instanceof MarkerTypeUnmodifiable)) {
+      return false;
+    }
+    MarkerTypeUnmodifiable v = (MarkerTypeUnmodifiable) value;
+    if (!"unmodifiable".equals(v.getValue())) {
+      return false;
+    }
+    return true;
+  }

   /**
* Wrap an exception in RuntimeException if necessary so it doesn't have to be
=======================================
--- /trunk/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java Mon Apr 19 10:54:02 2010 +++ /trunk/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java Tue Jul 20 05:31:21 2010
@@ -28,12 +28,14 @@
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeSingleton;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeMap;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeTreeSet;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeUnmodifiable;
 import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeVector;

 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -435,6 +437,51 @@
     if (!TestSetValidator.isValidSingletonList(value)) {
       throw new CollectionsTestServiceException();
     }
+
+    return value;
+  }
+
+  public Map<Integer, MarkerTypeSingleton> echoSingletonMap(
+ Map<Integer, MarkerTypeSingleton> value) throws CollectionsTestServiceException {
+    if (!TestSetValidator.isValidSingletonMap(value)) {
+      throw new CollectionsTestServiceException();
+    }
+
+    return value;
+  }
+
+  public Collection<MarkerTypeUnmodifiable> echoUnmodifiableCollection(
+ Collection<MarkerTypeUnmodifiable> value) throws CollectionsTestServiceException {
+    if (!TestSetValidator.isValidUnmodifiableCollection(value)) {
+      throw new CollectionsTestServiceException();
+    }
+
+    return value;
+  }
+
+  public List<MarkerTypeUnmodifiable> echoUnmodifiableList(
+ List<MarkerTypeUnmodifiable> value) throws CollectionsTestServiceException {
+    if (!TestSetValidator.isValidUnmodifiableList(value)) {
+      throw new CollectionsTestServiceException();
+    }
+
+    return value;
+  }
+
+  public Map<Integer, MarkerTypeUnmodifiable> echoUnmodifiableMap(
+ Map<Integer, MarkerTypeUnmodifiable> value) throws CollectionsTestServiceException {
+    if (!TestSetValidator.isValidUnmodifiableMap(value)) {
+      throw new CollectionsTestServiceException();
+    }
+
+    return value;
+  }
+
+  public Set<MarkerTypeUnmodifiable> echoUnmodifiableSet(
+ Set<MarkerTypeUnmodifiable> value) throws CollectionsTestServiceException {
+    if (!TestSetValidator.isValidUnmodifiableSet(value)) {
+      throw new CollectionsTestServiceException();
+    }

     return value;
   }

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to