No more system type adapters.

This commit is contained in:
Jesse Wilson 2011-11-20 18:03:46 +00:00
parent 3f5caea95e
commit 777e17c723
3 changed files with 49 additions and 91 deletions

View File

@ -518,10 +518,6 @@ public final class GsonBuilder {
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/ */
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) { public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
return registerTypeAdapter(type, typeAdapter, false);
}
private GsonBuilder registerTypeAdapter(Type type, Object typeAdapter, boolean isSystem) {
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?> $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof JsonDeserializer<?>
|| typeAdapter instanceof InstanceCreator<?> || typeAdapter instanceof InstanceCreator<?>
@ -531,13 +527,13 @@ public final class GsonBuilder {
"Cannot register type adapters for " + type); "Cannot register type adapters for " + type);
} }
if (typeAdapter instanceof InstanceCreator<?>) { if (typeAdapter instanceof InstanceCreator<?>) {
registerInstanceCreator(type, (InstanceCreator<?>) typeAdapter, isSystem); registerInstanceCreator(type, (InstanceCreator<?>) typeAdapter);
} }
if (typeAdapter instanceof JsonSerializer<?>) { if (typeAdapter instanceof JsonSerializer<?>) {
registerSerializer(type, (JsonSerializer<?>) typeAdapter, isSystem); registerSerializer(type, (JsonSerializer<?>) typeAdapter);
} }
if (typeAdapter instanceof JsonDeserializer<?>) { if (typeAdapter instanceof JsonDeserializer<?>) {
registerDeserializer(type, (JsonDeserializer<?>) typeAdapter, isSystem); registerDeserializer(type, (JsonDeserializer<?>) typeAdapter);
} }
if (typeAdapter instanceof TypeAdapter.Factory) { if (typeAdapter instanceof TypeAdapter.Factory) {
typeAdapterFactories.add((TypeAdapter.Factory) typeAdapter); typeAdapterFactories.add((TypeAdapter.Factory) typeAdapter);
@ -551,14 +547,14 @@ public final class GsonBuilder {
* takes a type instead of a Class object, it can be used to register a specific handler for a * takes a type instead of a Class object, it can be used to register a specific handler for a
* generic type corresponding to a raw type. * generic type corresponding to a raw type.
* *
* @param <T> the type for which instance creator is being registered *
* @param typeOfT The Type definition for T * @param typeOfT The Type definition for T
* @param instanceCreator the instance creator for T * @param instanceCreator the instance creator for T
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/ */
private <T> GsonBuilder registerInstanceCreator(Type typeOfT, private <T> GsonBuilder registerInstanceCreator(Type typeOfT,
InstanceCreator<? extends T> instanceCreator, boolean isSystem) { InstanceCreator<? extends T> instanceCreator) {
instanceCreators.register(typeOfT, instanceCreator, isSystem); instanceCreators.register(typeOfT, instanceCreator);
return this; return this;
} }
@ -567,14 +563,13 @@ public final class GsonBuilder {
* method if you want to register different serializers for different generic types corresponding * method if you want to register different serializers for different generic types corresponding
* to a raw type. * to a raw type.
* *
* @param <T> the type for which the serializer is being registered *
* @param typeOfT The type definition for T * @param typeOfT The type definition for T
* @param serializer the custom serializer * @param serializer the custom serializer
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/ */
private <T> GsonBuilder registerSerializer(Type typeOfT, JsonSerializer<T> serializer, private <T> GsonBuilder registerSerializer(Type typeOfT, JsonSerializer<T> serializer) {
boolean isSystem) { serializers.register(typeOfT, serializer);
serializers.register(typeOfT, serializer, isSystem);
return this; return this;
} }
@ -583,14 +578,13 @@ public final class GsonBuilder {
* method if you want to register different deserializers for different generic types * method if you want to register different deserializers for different generic types
* corresponding to a raw type. * corresponding to a raw type.
* *
* @param <T> the type for which the deserializer is being registered *
* @param typeOfT The type definition for T * @param typeOfT The type definition for T
* @param deserializer the custom deserializer * @param deserializer the custom deserializer
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/ */
private <T> GsonBuilder registerDeserializer(Type typeOfT, JsonDeserializer<T> deserializer, private <T> GsonBuilder registerDeserializer(Type typeOfT, JsonDeserializer<T> deserializer) {
boolean isSystem) { deserializers.register(typeOfT, new JsonDeserializerExceptionWrapper<T>(deserializer));
deserializers.register(typeOfT, new JsonDeserializerExceptionWrapper<T>(deserializer), isSystem);
return this; return this;
} }
@ -612,41 +606,36 @@ public final class GsonBuilder {
* @since 1.7 * @since 1.7
*/ */
public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) { public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
return registerTypeHierarchyAdapter(baseType, typeAdapter, false);
}
private GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter,
boolean isSystem) {
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?> $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?>); || typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?>);
if (typeAdapter instanceof InstanceCreator<?>) { if (typeAdapter instanceof InstanceCreator<?>) {
registerInstanceCreatorForTypeHierarchy(baseType, (InstanceCreator<?>) typeAdapter, isSystem); registerInstanceCreatorForTypeHierarchy(baseType, (InstanceCreator<?>) typeAdapter);
} }
if (typeAdapter instanceof JsonSerializer<?>) { if (typeAdapter instanceof JsonSerializer<?>) {
registerSerializerForTypeHierarchy(baseType, (JsonSerializer<?>) typeAdapter, isSystem); registerSerializerForTypeHierarchy(baseType, (JsonSerializer<?>) typeAdapter);
} }
if (typeAdapter instanceof JsonDeserializer<?>) { if (typeAdapter instanceof JsonDeserializer<?>) {
registerDeserializerForTypeHierarchy(baseType, (JsonDeserializer<?>) typeAdapter, isSystem); registerDeserializerForTypeHierarchy(baseType, (JsonDeserializer<?>) typeAdapter);
} }
return this; return this;
} }
private <T> GsonBuilder registerInstanceCreatorForTypeHierarchy(Class<?> classOfT, private <T> GsonBuilder registerInstanceCreatorForTypeHierarchy(Class<?> classOfT,
InstanceCreator<? extends T> instanceCreator, boolean isSystem) { InstanceCreator<? extends T> instanceCreator) {
instanceCreators.registerForTypeHierarchy(classOfT, instanceCreator, isSystem); instanceCreators.registerForTypeHierarchy(classOfT, instanceCreator);
return this; return this;
} }
private <T> GsonBuilder registerSerializerForTypeHierarchy(Class<?> classOfT, private <T> GsonBuilder registerSerializerForTypeHierarchy(Class<?> classOfT,
JsonSerializer<T> serializer, boolean isSystem) { JsonSerializer<T> serializer) {
serializers.registerForTypeHierarchy(classOfT, serializer, isSystem); serializers.registerForTypeHierarchy(classOfT, serializer);
return this; return this;
} }
private <T> GsonBuilder registerDeserializerForTypeHierarchy(Class<?> classOfT, private <T> GsonBuilder registerDeserializerForTypeHierarchy(Class<?> classOfT,
JsonDeserializer<T> deserializer, boolean isSystem) { JsonDeserializer<T> deserializer) {
deserializers.registerForTypeHierarchy(classOfT, deserializers.registerForTypeHierarchy(classOfT,
new JsonDeserializerExceptionWrapper<T>(deserializer), isSystem); new JsonDeserializerExceptionWrapper<T>(deserializer));
return this; return this;
} }
@ -736,7 +725,7 @@ public final class GsonBuilder {
private static <T> void registerIfAbsent(Class<?> type, private static <T> void registerIfAbsent(Class<?> type,
ParameterizedTypeHandlerMap<T> adapters, T adapter) { ParameterizedTypeHandlerMap<T> adapters, T adapter) {
if (!adapters.hasSpecificHandlerFor(type)) { if (!adapters.hasSpecificHandlerFor(type)) {
adapters.register(type, adapter, false); adapters.register(type, adapter);
} }
} }
} }

View File

@ -37,28 +37,24 @@ public final class ParameterizedTypeHandlerMap<T> {
private static final Logger logger = private static final Logger logger =
Logger.getLogger(ParameterizedTypeHandlerMap.class.getName()); Logger.getLogger(ParameterizedTypeHandlerMap.class.getName());
/**
* Map that is meant for storing default type adapters /** Map that is meant for storing default type adapters */
*/
private final Map<Type, T> systemMap = new HashMap<Type, T>();
private final Map<Type, T> userMap = new HashMap<Type, T>(); private final Map<Type, T> userMap = new HashMap<Type, T>();
/**
* List of default type hierarchy adapters /** List of default type hierarchy adapters */
*/
private final List<Pair<Class<?>, T>> systemTypeHierarchyList = new ArrayList<Pair<Class<?>, T>>();
private final List<Pair<Class<?>, T>> userTypeHierarchyList = new ArrayList<Pair<Class<?>, T>>(); private final List<Pair<Class<?>, T>> userTypeHierarchyList = new ArrayList<Pair<Class<?>, T>>();
private boolean modifiable = true; private boolean modifiable = true;
public synchronized void registerForTypeHierarchy(Class<?> typeOfT, T value, boolean isSystem) { public synchronized void registerForTypeHierarchy(Class<?> typeOfT, T value) {
Pair<Class<?>, T> pair = new Pair<Class<?>, T>(typeOfT, value); Pair<Class<?>, T> pair = new Pair<Class<?>, T>(typeOfT, value);
registerForTypeHierarchy(pair, isSystem); registerForTypeHierarchy(pair);
} }
public synchronized void registerForTypeHierarchy(Pair<Class<?>, T> pair, boolean isSystem) { public synchronized void registerForTypeHierarchy(Pair<Class<?>, T> pair) {
if (!modifiable) { if (!modifiable) {
throw new IllegalStateException("Attempted to modify an unmodifiable map."); throw new IllegalStateException("Attempted to modify an unmodifiable map.");
} }
List<Pair<Class<?>, T>> typeHierarchyList = isSystem ? systemTypeHierarchyList : userTypeHierarchyList; List<Pair<Class<?>, T>> typeHierarchyList = userTypeHierarchyList;
int index = getIndexOfSpecificHandlerForTypeHierarchy(pair.first, typeHierarchyList); int index = getIndexOfSpecificHandlerForTypeHierarchy(pair.first, typeHierarchyList);
if (index >= 0) { if (index >= 0) {
logger.log(Level.WARNING, "Overriding the existing type handler for {0}", pair.first); logger.log(Level.WARNING, "Overriding the existing type handler for {0}", pair.first);
@ -85,14 +81,14 @@ public final class ParameterizedTypeHandlerMap<T> {
return -1; return -1;
} }
public synchronized void register(Type typeOfT, T value, boolean isSystem) { public synchronized void register(Type typeOfT, T value) {
if (!modifiable) { if (!modifiable) {
throw new IllegalStateException("Attempted to modify an unmodifiable map."); throw new IllegalStateException("Attempted to modify an unmodifiable map.");
} }
if (hasSpecificHandlerFor(typeOfT)) { if (hasSpecificHandlerFor(typeOfT)) {
logger.log(Level.WARNING, "Overriding the existing type handler for {0}", typeOfT); logger.log(Level.WARNING, "Overriding the existing type handler for {0}", typeOfT);
} }
Map<Type, T> map = isSystem ? systemMap : userMap; Map<Type, T> map = userMap;
map.put(typeOfT, value); map.put(typeOfT, value);
} }
@ -102,12 +98,7 @@ public final class ParameterizedTypeHandlerMap<T> {
} }
for (Map.Entry<Type, T> entry : other.userMap.entrySet()) { for (Map.Entry<Type, T> entry : other.userMap.entrySet()) {
if (!userMap.containsKey(entry.getKey())) { if (!userMap.containsKey(entry.getKey())) {
register(entry.getKey(), entry.getValue(), false); register(entry.getKey(), entry.getValue());
}
}
for (Map.Entry<Type, T> entry : other.systemMap.entrySet()) {
if (!systemMap.containsKey(entry.getKey())) {
register(entry.getKey(), entry.getValue(), true);
} }
} }
// Quite important to traverse the typeHierarchyList from stack bottom first since // Quite important to traverse the typeHierarchyList from stack bottom first since
@ -116,14 +107,7 @@ public final class ParameterizedTypeHandlerMap<T> {
Pair<Class<?>, T> entry = other.userTypeHierarchyList.get(i); Pair<Class<?>, T> entry = other.userTypeHierarchyList.get(i);
int index = getIndexOfSpecificHandlerForTypeHierarchy(entry.first, userTypeHierarchyList); int index = getIndexOfSpecificHandlerForTypeHierarchy(entry.first, userTypeHierarchyList);
if (index < 0) { if (index < 0) {
registerForTypeHierarchy(entry, false); registerForTypeHierarchy(entry);
}
}
for (int i = other.systemTypeHierarchyList.size()-1; i >= 0; --i) {
Pair<Class<?>, T> entry = other.systemTypeHierarchyList.get(i);
int index = getIndexOfSpecificHandlerForTypeHierarchy(entry.first, systemTypeHierarchyList);
if (index < 0) {
registerForTypeHierarchy(entry, true);
} }
} }
} }
@ -141,10 +125,6 @@ public final class ParameterizedTypeHandlerMap<T> {
return handler; return handler;
} }
} }
handler = systemMap.get(type);
if (handler != null) {
return handler;
}
Class<?> rawClass = $Gson$Types.getRawType(type); Class<?> rawClass = $Gson$Types.getRawType(type);
if (rawClass != type) { if (rawClass != type) {
handler = getHandlerFor(rawClass, systemOnly); handler = getHandlerFor(rawClass, systemOnly);
@ -165,16 +145,11 @@ public final class ParameterizedTypeHandlerMap<T> {
} }
} }
} }
for (Pair<Class<?>, T> entry : systemTypeHierarchyList) {
if (entry.first.isAssignableFrom(type)) {
return entry.second;
}
}
return null; return null;
} }
public synchronized boolean hasSpecificHandlerFor(Type type) { public synchronized boolean hasSpecificHandlerFor(Type type) {
return userMap.containsKey(type) || systemMap.containsKey(type); return userMap.containsKey(type);
} }
private static <T> int getIndexOfSpecificHandlerForTypeHierarchy( private static <T> int getIndexOfSpecificHandlerForTypeHierarchy(
@ -194,9 +169,7 @@ public final class ParameterizedTypeHandlerMap<T> {
// TODO (inder): Performance optimization. We can probably just share the // TODO (inder): Performance optimization. We can probably just share the
// systemMap and systemTypeHierarchyList instead of making copies // systemMap and systemTypeHierarchyList instead of making copies
copy.systemMap.putAll(systemMap);
copy.userMap.putAll(userMap); copy.userMap.putAll(userMap);
copy.systemTypeHierarchyList.addAll(systemTypeHierarchyList);
copy.userTypeHierarchyList.addAll(userTypeHierarchyList); copy.userTypeHierarchyList.addAll(userTypeHierarchyList);
return copy; return copy;
} }
@ -205,12 +178,8 @@ public final class ParameterizedTypeHandlerMap<T> {
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder("{userTypeHierarchyList:{"); StringBuilder sb = new StringBuilder("{userTypeHierarchyList:{");
appendList(sb, userTypeHierarchyList); appendList(sb, userTypeHierarchyList);
sb.append("},systemTypeHierarchyList:{");
appendList(sb, systemTypeHierarchyList);
sb.append("},userMap:{"); sb.append("},userMap:{");
appendMap(sb, userMap); appendMap(sb, userMap);
sb.append("},systemMap:{");
appendMap(sb, systemMap);
sb.append("}"); sb.append("}");
return sb.toString(); return sb.toString();
} }

View File

@ -46,7 +46,7 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
public void testHasGenericButNotSpecific() throws Exception { public void testHasGenericButNotSpecific() throws Exception {
Type specificType = new TypeToken<List<String>>() {}.getType(); Type specificType = new TypeToken<List<String>>() {}.getType();
String handler = "blah"; String handler = "blah";
paramMap.register(List.class, handler, false); paramMap.register(List.class, handler);
assertFalse(paramMap.hasSpecificHandlerFor(specificType)); assertFalse(paramMap.hasSpecificHandlerFor(specificType));
assertTrue(paramMap.hasSpecificHandlerFor(List.class)); assertTrue(paramMap.hasSpecificHandlerFor(List.class));
@ -58,7 +58,7 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
public void testHasSpecificType() throws Exception { public void testHasSpecificType() throws Exception {
Type specificType = new TypeToken<List<String>>() {}.getType(); Type specificType = new TypeToken<List<String>>() {}.getType();
String handler = "blah"; String handler = "blah";
paramMap.register(specificType, handler, false); paramMap.register(specificType, handler);
assertTrue(paramMap.hasSpecificHandlerFor(specificType)); assertTrue(paramMap.hasSpecificHandlerFor(specificType));
assertFalse(paramMap.hasSpecificHandlerFor(List.class)); assertFalse(paramMap.hasSpecificHandlerFor(List.class));
@ -70,8 +70,8 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
public void testTypeOverridding() throws Exception { public void testTypeOverridding() throws Exception {
String handler1 = "blah1"; String handler1 = "blah1";
String handler2 = "blah2"; String handler2 = "blah2";
paramMap.register(String.class, handler1, false); paramMap.register(String.class, handler1);
paramMap.register(String.class, handler2, false); paramMap.register(String.class, handler2);
assertTrue(paramMap.hasSpecificHandlerFor(String.class)); assertTrue(paramMap.hasSpecificHandlerFor(String.class));
assertEquals(handler2, paramMap.getHandlerFor(String.class, false)); assertEquals(handler2, paramMap.getHandlerFor(String.class, false));
@ -80,44 +80,44 @@ public class ParameterizedTypeHandlerMapTest extends TestCase {
public void testMakeUnmodifiable() throws Exception { public void testMakeUnmodifiable() throws Exception {
paramMap.makeUnmodifiable(); paramMap.makeUnmodifiable();
try { try {
paramMap.register(String.class, "blah", false); paramMap.register(String.class, "blah");
fail("Can not register handlers when map is unmodifiable"); fail("Can not register handlers when map is unmodifiable");
} catch (IllegalStateException expected) { } } catch (IllegalStateException expected) { }
} }
public void testTypeHierarchy() { public void testTypeHierarchy() {
paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false); paramMap.registerForTypeHierarchy(Base.class, "baseHandler");
String handler = paramMap.getHandlerFor(Sub.class, false); String handler = paramMap.getHandlerFor(Sub.class, false);
assertEquals("baseHandler", handler); assertEquals("baseHandler", handler);
} }
public void testTypeHierarchyMultipleHandlers() { public void testTypeHierarchyMultipleHandlers() {
paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false); paramMap.registerForTypeHierarchy(Base.class, "baseHandler");
paramMap.registerForTypeHierarchy(Sub.class, "subHandler", false); paramMap.registerForTypeHierarchy(Sub.class, "subHandler");
String handler = paramMap.getHandlerFor(SubOfSub.class, false); String handler = paramMap.getHandlerFor(SubOfSub.class, false);
assertEquals("subHandler", handler); assertEquals("subHandler", handler);
} }
public void testTypeHierarchyRegisterIfAbsent() { public void testTypeHierarchyRegisterIfAbsent() {
paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false); paramMap.registerForTypeHierarchy(Base.class, "baseHandler");
ParameterizedTypeHandlerMap<String> otherMap = new ParameterizedTypeHandlerMap<String>(); ParameterizedTypeHandlerMap<String> otherMap = new ParameterizedTypeHandlerMap<String>();
otherMap.registerForTypeHierarchy(Base.class, "baseHandler2", false); otherMap.registerForTypeHierarchy(Base.class, "baseHandler2");
paramMap.registerIfAbsent(otherMap); paramMap.registerIfAbsent(otherMap);
String handler = paramMap.getHandlerFor(Base.class, false); String handler = paramMap.getHandlerFor(Base.class, false);
assertEquals("baseHandler", handler); assertEquals("baseHandler", handler);
} }
public void testReplaceExistingTypeHierarchyHandler() { public void testReplaceExistingTypeHierarchyHandler() {
paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false); paramMap.registerForTypeHierarchy(Base.class, "baseHandler");
paramMap.registerForTypeHierarchy(Base.class, "base2Handler", false); paramMap.registerForTypeHierarchy(Base.class, "base2Handler");
String handler = paramMap.getHandlerFor(Base.class, false); String handler = paramMap.getHandlerFor(Base.class, false);
assertEquals("base2Handler", handler); assertEquals("base2Handler", handler);
} }
public void testHidingExistingTypeHierarchyHandlerIsDisallowed() { public void testHidingExistingTypeHierarchyHandlerIsDisallowed() {
paramMap.registerForTypeHierarchy(Sub.class, "subHandler", false); paramMap.registerForTypeHierarchy(Sub.class, "subHandler");
try { try {
paramMap.registerForTypeHierarchy(Base.class, "baseHandler", false); paramMap.registerForTypeHierarchy(Base.class, "baseHandler");
fail("A handler that hides an existing type hierarchy handler is not allowed"); fail("A handler that hides an existing type hierarchy handler is not allowed");
} catch (IllegalArgumentException expected) { } catch (IllegalArgumentException expected) {
} }