From 165c0595e390c8d81b11b2108978c4363ad2ec57 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 15 Apr 2014 07:41:18 +0200 Subject: [PATCH] DATACMNS-485 - API improvements to in TypeInformationMapper area. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default implementations of the TypeInformation Mapper interfaces now work with ClassTypeInformation where possible to express they only map raw types effectively. Added TypeInformation.getRawTypeInformation() to easily turn whatever TypeInformation into the raw type representation. Changed ClassTypeInformation.from(…) to return ClassTypeInformations directly. --- .../ConfigurableTypeInformationMapper.java | 12 +++--- .../MappingContextTypeInformationMapper.java | 33 ++++++++--------- .../convert/SimpleTypeInformationMapper.java | 8 ++-- .../data/util/ClassTypeInformation.java | 37 ++++++++++++------- .../data/util/TypeDiscoverer.java | 9 +++++ .../data/util/TypeInformation.java | 8 ++++ 6 files changed, 66 insertions(+), 41 deletions(-) diff --git a/src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java b/src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java index befbc77de..ea4b105e0 100644 --- a/src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java +++ b/src/main/java/org/springframework/data/convert/ConfigurableTypeInformationMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-12 the original author or authors. + * Copyright 2011-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ import org.springframework.util.Assert; */ public class ConfigurableTypeInformationMapper implements TypeInformationMapper { - private final Map, Object> typeMap; + private final Map, Object> typeMap; /** * Creates a new {@link ConfigurableTypeMapper} for the given type map. @@ -44,10 +44,10 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper public ConfigurableTypeInformationMapper(Map, String> sourceTypeMap) { Assert.notNull(sourceTypeMap); - this.typeMap = new HashMap, Object>(sourceTypeMap.size()); + this.typeMap = new HashMap, Object>(sourceTypeMap.size()); for (Entry, String> entry : sourceTypeMap.entrySet()) { - TypeInformation key = ClassTypeInformation.from(entry.getKey()); + ClassTypeInformation key = ClassTypeInformation.from(entry.getKey()); String value = entry.getValue(); if (typeMap.containsValue(value)) { @@ -71,13 +71,13 @@ public class ConfigurableTypeInformationMapper implements TypeInformationMapper * (non-Javadoc) * @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.lang.Object) */ - public TypeInformation resolveTypeFrom(Object alias) { + public ClassTypeInformation resolveTypeFrom(Object alias) { if (alias == null) { return null; } - for (Entry, Object> entry : typeMap.entrySet()) { + for (Entry, Object> entry : typeMap.entrySet()) { if (entry.getValue().equals(alias)) { return entry.getKey(); } diff --git a/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java b/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java index 15fcde8f5..4bfc15287 100644 --- a/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java +++ b/src/main/java/org/springframework/data/convert/MappingContextTypeInformationMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ import org.springframework.util.Assert; */ public class MappingContextTypeInformationMapper implements TypeInformationMapper { - private final Map, Object> typeMap; + private final Map, Object> typeMap; private final MappingContext, ?> mappingContext; /** @@ -47,11 +47,11 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe Assert.notNull(mappingContext); - this.typeMap = new HashMap, Object>(); + this.typeMap = new HashMap, Object>(); this.mappingContext = mappingContext; for (PersistentEntity entity : mappingContext.getPersistentEntities()) { - safelyAddToCache(entity.getTypeInformation(), entity.getTypeAlias()); + safelyAddToCache(entity.getTypeInformation().getRawTypeInformation(), entity.getTypeAlias()); } } @@ -74,7 +74,7 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe } Object alias = entity.getTypeAlias(); - safelyAddToCache(type, alias); + safelyAddToCache(type.getRawTypeInformation(), alias); return alias; } @@ -85,50 +85,49 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe * @param key must not be {@literal null}. * @param alias can be {@literal null}. */ - private void safelyAddToCache(TypeInformation key, Object alias) { + private void safelyAddToCache(ClassTypeInformation key, Object alias) { if (alias == null) { return; } - TypeInformation toStore = ClassTypeInformation.from(key.getType()); - Object existingAlias = typeMap.get(toStore); + Object existingAlias = typeMap.get(key); // Reject second alias for same type if (existingAlias != null && !alias.equals(existingAlias)) { throw new IllegalArgumentException(String.format( "Trying to register alias '%s', but found already registered alias '%s' for type %s!", alias, existingAlias, - toStore)); + key)); } // Reject second type for same alias if (typeMap.containsValue(alias)) { - for (Entry, Object> entry : typeMap.entrySet()) { - if (entry.getValue().equals(alias) && !entry.getKey().equals(toStore)) { + for (Entry, Object> entry : typeMap.entrySet()) { + if (entry.getValue().equals(alias) && !entry.getKey().equals(key)) { throw new IllegalArgumentException(String.format( - "Detected existing type mapping of %s to alias '%s' but attempted to bind the same alias to %s!", - toStore, alias, entry.getKey())); + "Detected existing type mapping of %s to alias '%s' but attempted to bind the same alias to %s!", key, + alias, entry.getKey())); } } } - typeMap.put(toStore, alias); + typeMap.put(key, alias); } /* * (non-Javadoc) * @see org.springframework.data.convert.TypeInformationMapper#resolveTypeFrom(java.lang.Object) */ - public TypeInformation resolveTypeFrom(Object alias) { + public ClassTypeInformation resolveTypeFrom(Object alias) { if (alias == null) { return null; } - for (Entry, Object> entry : typeMap.entrySet()) { + for (Entry, Object> entry : typeMap.entrySet()) { if (entry.getValue().equals(alias)) { return entry.getKey(); } @@ -136,7 +135,7 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe for (PersistentEntity entity : mappingContext.getPersistentEntities()) { if (alias.equals(entity.getTypeAlias())) { - return entity.getTypeInformation(); + return entity.getTypeInformation().getRawTypeInformation(); } } diff --git a/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java b/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java index 6beb8270e..4e0097ba4 100644 --- a/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java +++ b/src/main/java/org/springframework/data/convert/SimpleTypeInformationMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 the original author or authors. + * Copyright 2011-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ import org.springframework.util.StringUtils; public class SimpleTypeInformationMapper implements TypeInformationMapper { public static final SimpleTypeInformationMapper INSTANCE = new SimpleTypeInformationMapper(); - private static final Map> cache = new ConcurrentHashMap>(); + private static final Map> cache = new ConcurrentHashMap>(); /** * Returns the {@link TypeInformation} that shall be used when the given {@link String} value is found as type hint. @@ -44,7 +44,7 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper { * @return the type to be used for the given {@link String} representation or {@literal null} if nothing found or the * class cannot be loaded. */ - public TypeInformation resolveTypeFrom(Object alias) { + public ClassTypeInformation resolveTypeFrom(Object alias) { if (!(alias instanceof String)) { return null; @@ -56,7 +56,7 @@ public class SimpleTypeInformationMapper implements TypeInformationMapper { return null; } - TypeInformation information = cache.get(value); + ClassTypeInformation information = cache.get(value); if (information != null) { return information; diff --git a/src/main/java/org/springframework/data/util/ClassTypeInformation.java b/src/main/java/org/springframework/data/util/ClassTypeInformation.java index 319e4aad2..1d56725d6 100644 --- a/src/main/java/org/springframework/data/util/ClassTypeInformation.java +++ b/src/main/java/org/springframework/data/util/ClassTypeInformation.java @@ -40,18 +40,18 @@ import org.springframework.util.ClassUtils; @SuppressWarnings({ "unchecked", "rawtypes" }) public class ClassTypeInformation extends TypeDiscoverer { - public static final TypeInformation COLLECTION = new ClassTypeInformation(Collection.class); - public static final TypeInformation LIST = new ClassTypeInformation(List.class); - public static final TypeInformation SET = new ClassTypeInformation(Set.class); - public static final TypeInformation MAP = new ClassTypeInformation(Map.class); - public static final TypeInformation OBJECT = new ClassTypeInformation(Object.class); + public static final ClassTypeInformation COLLECTION = new ClassTypeInformation(Collection.class); + public static final ClassTypeInformation LIST = new ClassTypeInformation(List.class); + public static final ClassTypeInformation SET = new ClassTypeInformation(Set.class); + public static final ClassTypeInformation MAP = new ClassTypeInformation(Map.class); + public static final ClassTypeInformation OBJECT = new ClassTypeInformation(Object.class); - private static final Map, Reference>> CACHE = Collections - .synchronizedMap(new WeakHashMap, Reference>>()); + private static final Map, Reference>> CACHE = Collections + .synchronizedMap(new WeakHashMap, Reference>>()); static { - for (TypeInformation info : Arrays.asList(COLLECTION, LIST, SET, MAP, OBJECT)) { - CACHE.put(info.getType(), new WeakReference>(info)); + for (ClassTypeInformation info : Arrays.asList(COLLECTION, LIST, SET, MAP, OBJECT)) { + CACHE.put(info.getType(), new WeakReference>(info)); } } @@ -64,19 +64,19 @@ public class ClassTypeInformation extends TypeDiscoverer { * @param type must not be {@literal null}. * @return */ - public static TypeInformation from(Class type) { + public static ClassTypeInformation from(Class type) { Assert.notNull(type, "Type must not be null!"); - Reference> cachedReference = CACHE.get(type); + Reference> cachedReference = CACHE.get(type); TypeInformation cachedTypeInfo = cachedReference == null ? null : cachedReference.get(); if (cachedTypeInfo != null) { - return (TypeInformation) cachedTypeInfo; + return (ClassTypeInformation) cachedTypeInfo; } - TypeInformation result = new ClassTypeInformation(type); - CACHE.put(type, new WeakReference>(result)); + ClassTypeInformation result = new ClassTypeInformation(type); + CACHE.put(type, new WeakReference>(result)); return result; } @@ -116,6 +116,15 @@ public class ClassTypeInformation extends TypeDiscoverer { return type; } + /* + * (non-Javadoc) + * @see org.springframework.data.util.TypeDiscoverer#getRawTypeInformation() + */ + @Override + public ClassTypeInformation getRawTypeInformation() { + return this; + } + /* * (non-Javadoc) * @see org.springframework.data.util.TypeDiscoverer#isAssignableFrom(org.springframework.data.util.TypeInformation) diff --git a/src/main/java/org/springframework/data/util/TypeDiscoverer.java b/src/main/java/org/springframework/data/util/TypeDiscoverer.java index 18be3d871..c1534721d 100644 --- a/src/main/java/org/springframework/data/util/TypeDiscoverer.java +++ b/src/main/java/org/springframework/data/util/TypeDiscoverer.java @@ -270,6 +270,15 @@ class TypeDiscoverer implements TypeInformation { return this.resolvedType; } + /* + * (non-Javadoc) + * @see org.springframework.data.util.TypeInformation#getRawTypeInformation() + */ + @Override + public ClassTypeInformation getRawTypeInformation() { + return ClassTypeInformation.from(getType()).getRawTypeInformation(); + } + /* * (non-Javadoc) * @see org.springframework.data.util.TypeInformation#getActualType() diff --git a/src/main/java/org/springframework/data/util/TypeInformation.java b/src/main/java/org/springframework/data/util/TypeInformation.java index 869cc2ce6..a71275904 100644 --- a/src/main/java/org/springframework/data/util/TypeInformation.java +++ b/src/main/java/org/springframework/data/util/TypeInformation.java @@ -82,6 +82,14 @@ public interface TypeInformation { */ Class getType(); + /** + * Returns a {@link ClassTypeInformation} to represent the {@link TypeInformation} of the raw type of the current + * instance. + * + * @return + */ + ClassTypeInformation getRawTypeInformation(); + /** * Transparently returns the {@link java.util.Map} value type if the type is a {@link java.util.Map}, returns the * component type if the type {@link #isCollectionLike()} or the simple type if none of this applies.