Make java.util.Collections.Empty{List,Map,Set} work with GWT RPC.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7606 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/rpc/core/java/util/Collections.java b/user/src/com/google/gwt/user/client/rpc/core/java/util/Collections.java
new file mode 100644
index 0000000..56a77d3
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/rpc/core/java/util/Collections.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.user.client.rpc.core.java.util;
+
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Dummy class for nesting the custom serializer.
+ */
+public final class Collections {
+
+ /**
+ * Custom field serializer for {@link java.util.Collections$EmptyList}.
+ */
+ public static final class EmptyList_CustomFieldSerializer {
+
+ @SuppressWarnings({"unused", "unchecked"})
+ public static void deserialize(SerializationStreamReader streamReader,
+ List instance) throws SerializationException {
+ // Handled in instantiate.
+ }
+
+ @SuppressWarnings({"unused", "unchecked"})
+ public static List instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return java.util.Collections.emptyList();
+ }
+
+ @SuppressWarnings({"unused", "unchecked"})
+ public static void serialize(SerializationStreamWriter streamWriter,
+ List instance) throws SerializationException {
+ // Nothing to serialize -- instantiate always returns the same thing
+ }
+ }
+
+ /**
+ * Custom field serializer for {@link java.util.Collections$EmptyMap}.
+ */
+ public static final class EmptyMap_CustomFieldSerializer {
+
+ @SuppressWarnings({"unused", "unchecked"})
+ public static void deserialize(SerializationStreamReader streamReader,
+ Map instance) throws SerializationException {
+ // Handled in instantiate.
+ }
+
+ @SuppressWarnings({"unused", "unchecked"})
+ public static Map instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return java.util.Collections.emptyMap();
+ }
+
+ @SuppressWarnings({"unused", "unchecked"})
+ public static void serialize(SerializationStreamWriter streamWriter,
+ Map instance) throws SerializationException {
+ // Nothing to serialize -- instantiate always returns the same thing
+ }
+ }
+
+ /**
+ * Custom field serializer for {@link java.util.Collections$EmptySet}.
+ */
+ public static final class EmptySet_CustomFieldSerializer {
+
+ @SuppressWarnings({"unused", "unchecked"})
+ public static void deserialize(SerializationStreamReader streamReader,
+ Set instance) throws SerializationException {
+ // Handled in instantiate.
+ }
+
+ @SuppressWarnings({"unused", "unchecked"})
+ public static Set instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return java.util.Collections.emptySet();
+ }
+
+ @SuppressWarnings({"unused", "unchecked"})
+ public static void serialize(SerializationStreamWriter streamWriter,
+ Set instance) throws SerializationException {
+ // Nothing to serialize -- instantiate always returns the same thing
+ }
+ }
+}
diff --git a/user/super/com/google/gwt/emul/java/util/Collections.java b/user/super/com/google/gwt/emul/java/util/Collections.java
index 3df9d3a..36c1031 100644
--- a/user/super/com/google/gwt/emul/java/util/Collections.java
+++ b/user/super/com/google/gwt/emul/java/util/Collections.java
@@ -15,12 +15,101 @@
*/
package java.util;
+import java.io.Serializable;
+
/**
* Utility methods that operate on collections. <a
* href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collections.html">[Sun
* docs]</a>
*/
public class Collections {
+
+ private static final class EmptyList extends AbstractList implements
+ RandomAccess, Serializable {
+ @Override
+ public boolean contains(Object object) {
+ return false;
+ }
+
+ @Override
+ public Object get(int location) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ @Override
+ public int size() {
+ return 0;
+ }
+ }
+
+ private static final class EmptySet extends AbstractSet implements
+ Serializable {
+ @Override
+ public boolean contains(Object object) {
+ return false;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return new Iterator() {
+ public boolean hasNext() {
+ return false;
+ }
+
+ public Object next() {
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ @Override
+ public int size() {
+ return 0;
+ }
+}
+
+ private static final class EmptyMap extends AbstractMap implements
+ Serializable {
+ @Override
+ public boolean containsKey(Object key) {
+ return false;
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return false;
+ }
+
+ @Override
+ public Set entrySet() {
+ return EMPTY_SET;
+ }
+
+ @Override
+ public Object get(Object key) {
+ return null;
+ }
+
+ @Override
+ public Set keySet() {
+ return EMPTY_SET;
+ }
+
+ @Override
+ public int size() {
+ return 0;
+ }
+
+ @Override
+ public Collection values() {
+ return EMPTY_LIST;
+ }
+ }
+
/*
* TODO: make the unmodifiable collections serializable.
*/
@@ -510,13 +599,13 @@
}
@SuppressWarnings("unchecked")
- public static final List EMPTY_LIST = unmodifiableList(new ArrayList());
+ public static final List EMPTY_LIST = new EmptyList();
@SuppressWarnings("unchecked")
- public static final Map EMPTY_MAP = unmodifiableMap(new HashMap());
+ public static final Map EMPTY_MAP = new EmptyMap();
@SuppressWarnings("unchecked")
- public static final Set EMPTY_SET = unmodifiableSet(new HashSet());
+ public static final Set EMPTY_SET = new EmptySet();
private static Comparator<Comparable<Object>> reverseComparator = new Comparator<Comparable<Object>>() {
public int compare(Comparable<Object> o1, Comparable<Object> o2) {
diff --git a/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
index fae04be..2b32fbd 100644
--- a/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
+++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
@@ -18,6 +18,7 @@
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArrayList;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArraysAsList;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmpty;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashMap;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashSet;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashMap;
@@ -34,6 +35,8 @@
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
@@ -191,6 +194,57 @@
});
}
+ public void testEmptyList() {
+ CollectionsTestServiceAsync service = getServiceAsync();
+ delayTestFinishForRpc();
+ service.echo(TestSetFactory.createEmptyList(),
+ new AsyncCallback<List<MarkerTypeEmpty>>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
+
+ public void onSuccess(List<MarkerTypeEmpty> result) {
+ assertNotNull(result);
+ assertTrue(TestSetValidator.isValid(result));
+ finishTest();
+ }
+ });
+ }
+
+ public void testEmptyMap() {
+ CollectionsTestServiceAsync service = getServiceAsync();
+ delayTestFinishForRpc();
+ service.echo(TestSetFactory.createEmptyMap(),
+ new AsyncCallback<Map<MarkerTypeEmpty, MarkerTypeEmpty>>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
+
+ public void onSuccess(Map<MarkerTypeEmpty, MarkerTypeEmpty> result) {
+ assertNotNull(result);
+ assertTrue(TestSetValidator.isValid(result));
+ finishTest();
+ }
+ });
+ }
+
+ public void testEmptySet() {
+ CollectionsTestServiceAsync service = getServiceAsync();
+ delayTestFinishForRpc();
+ service.echo(TestSetFactory.createEmptySet(),
+ new AsyncCallback<Set<MarkerTypeEmpty>>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
+
+ public void onSuccess(Set<MarkerTypeEmpty> result) {
+ assertNotNull(result);
+ assertTrue(TestSetValidator.isValid(result));
+ finishTest();
+ }
+ });
+ }
+
public void testEnumArray() {
CollectionsTestServiceAsync service = getServiceAsync();
final Enum<?>[] expected = TestSetFactory.createEnumArray();
diff --git a/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java
index 671a8ac..4902177 100644
--- a/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java
+++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java
@@ -17,6 +17,7 @@
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArrayList;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArraysAsList;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmpty;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashMap;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashSet;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashMap;
@@ -34,6 +35,8 @@
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
@@ -58,6 +61,18 @@
ArrayList<MarkerTypeArrayList> echo(ArrayList<MarkerTypeArrayList> value)
throws CollectionsTestServiceException;
+ // For Collections.emptyList()
+ List<MarkerTypeEmpty> echo(List<MarkerTypeEmpty> value)
+ throws CollectionsTestServiceException;
+
+ // For Collections.emptyMap()
+ Map<MarkerTypeEmpty, MarkerTypeEmpty> echo(Map<MarkerTypeEmpty,
+ MarkerTypeEmpty> value) throws CollectionsTestServiceException;
+
+ // For Collections.emptySet()
+ Set<MarkerTypeEmpty> echo(Set<MarkerTypeEmpty> value)
+ throws CollectionsTestServiceException;
+
boolean[] echo(boolean[] value) throws CollectionsTestServiceException;
Boolean[] echo(Boolean[] value) throws CollectionsTestServiceException;
diff --git a/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java
index ae55e5c..24221f3 100644
--- a/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java
+++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java
@@ -17,6 +17,7 @@
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArrayList;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArraysAsList;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmpty;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashMap;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashSet;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashMap;
@@ -34,6 +35,8 @@
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
@@ -45,6 +48,18 @@
void echo(ArrayList<MarkerTypeArrayList> value,
AsyncCallback<ArrayList<MarkerTypeArrayList>> callback);
+ // For Collections.emptyList()
+ void echo(List<MarkerTypeEmpty> value,
+ AsyncCallback<List<MarkerTypeEmpty>> callback);
+
+ // For Collections.emptyMap()
+ void echo(Map<MarkerTypeEmpty, MarkerTypeEmpty> value,
+ AsyncCallback<Map<MarkerTypeEmpty, MarkerTypeEmpty>> callback);
+
+ // For Collections.emptySet()
+ void echo(Set<MarkerTypeEmpty> value,
+ AsyncCallback<Set<MarkerTypeEmpty>> callback);
+
void echo(boolean[] value, AsyncCallback<boolean[]> callback);
void echo(Boolean[] value, AsyncCallback<Boolean[]> callback);
diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java b/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
index 069a7fb..5b75365 100644
--- a/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
+++ b/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
@@ -27,6 +27,8 @@
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
@@ -103,6 +105,16 @@
/**
* A single-use marker type to independently check type parameter exposure in
+ * various empty collections.
+ */
+ public static final class MarkerTypeEmpty extends MarkerBase {
+ MarkerTypeEmpty() {
+ super(null);
+ }
+ }
+
+ /**
+ * A single-use marker type to independently check type parameter exposure in
* various collections.
*/
public static enum MarkerTypeEnum {
@@ -394,6 +406,18 @@
new Double(Double.MAX_VALUE), new Double(Double.MIN_VALUE)};
}
+ public static List<MarkerTypeEmpty> createEmptyList() {
+ return java.util.Collections.emptyList();
+ }
+
+ public static Map<MarkerTypeEmpty, MarkerTypeEmpty> createEmptyMap() {
+ return java.util.Collections.emptyMap();
+ }
+
+ public static Set<MarkerTypeEmpty> createEmptySet() {
+ return java.util.Collections.emptySet();
+ }
+
public static Enum<?>[] createEnumArray() {
return new Enum<?>[] {
MarkerTypeEnum.A, MarkerTypeEnum.B, MarkerTypeEnum.C, MarkerTypeEnum.A,};
diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
index 9093b6f7..91e1743 100644
--- a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
+++ b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.user.client.rpc;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmpty;
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.SerializableDoublyLinkedNode;
@@ -248,6 +249,18 @@
return reference.equals(list);
}
+ public static boolean isValid(List<MarkerTypeEmpty> list) {
+ return list != null && list.size() == 0;
+ }
+
+ public static boolean isValid(Map<MarkerTypeEmpty, MarkerTypeEmpty> map) {
+ return map != null && map.size() == 0;
+ }
+
+ public static boolean isValid(Set<MarkerTypeEmpty> set) {
+ return set != null && set.size() == 0;
+ }
+
public static boolean isValid(HashMap<?, ?> expected, HashMap<?, ?> map) {
if (map == null) {
return false;
diff --git a/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java
index dd157c5..2c15ab7 100644
--- a/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java
+++ b/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java
@@ -20,6 +20,7 @@
import com.google.gwt.user.client.rpc.TestSetValidator;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArrayList;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeArraysAsList;
+import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeEmpty;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashMap;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeHashSet;
import com.google.gwt.user.client.rpc.TestSetFactory.MarkerTypeLinkedHashMap;
@@ -38,6 +39,8 @@
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
@@ -267,6 +270,15 @@
return actual;
}
+ public List<MarkerTypeEmpty> echo(List<MarkerTypeEmpty> list)
+ throws CollectionsTestServiceException {
+ if (!TestSetValidator.isValid(list)) {
+ throw new CollectionsTestServiceException();
+ }
+
+ return list;
+ }
+
public long[] echo(long[] actual) throws CollectionsTestServiceException {
long[] expected = TestSetFactory.createPrimitiveLongArray();
if (!TestSetValidator.equals(expected, actual)) {
@@ -287,6 +299,25 @@
return actual;
}
+ public Map<MarkerTypeEmpty, MarkerTypeEmpty> echo(
+ Map<MarkerTypeEmpty, MarkerTypeEmpty> map)
+ throws CollectionsTestServiceException {
+ if (!TestSetValidator.isValid(map)) {
+ throw new CollectionsTestServiceException();
+ }
+
+ return map;
+ }
+
+ public Set<MarkerTypeEmpty> echo(Set<MarkerTypeEmpty> set)
+ throws CollectionsTestServiceException {
+ if (!TestSetValidator.isValid(set)) {
+ throw new CollectionsTestServiceException();
+ }
+
+ return set;
+ }
+
public short[] echo(short[] actual) throws CollectionsTestServiceException {
short[] expected = TestSetFactory.createPrimitiveShortArray();
if (!TestSetValidator.equals(expected, actual)) {