DATACMNS-485 - Fixed false negative type alias detection in MappingContextTypeInformationMapper.

MappingContextTypeInformationMapper now considers the raw type only for type alias conflict detection.
This commit is contained in:
Oliver Gierke
2014-04-14 21:49:25 +02:00
parent e13fc294bb
commit 64caad04a3
2 changed files with 58 additions and 3 deletions

View File

@@ -21,6 +21,7 @@ import java.util.Map.Entry;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@@ -90,12 +91,31 @@ public class MappingContextTypeInformationMapper implements TypeInformationMappe
return;
}
if (typeMap.containsValue(alias)) {
TypeInformation<?> toStore = ClassTypeInformation.from(key.getType());
Object existingAlias = typeMap.get(toStore);
// Reject second alias for same type
if (existingAlias != null && !alias.equals(existingAlias)) {
throw new IllegalArgumentException(String.format(
"Detected mapping ambiguity! String %s cannot be mapped to more than one type!", alias));
"Trying to register alias '%s', but found already registered alias '%s' for type %s!", alias, existingAlias,
toStore));
}
typeMap.put(key, alias);
// Reject second type for same alias
if (typeMap.containsValue(alias)) {
for (Entry<TypeInformation<?>, Object> entry : typeMap.entrySet()) {
if (entry.getValue().equals(alias) && !entry.getKey().equals(toStore)) {
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()));
}
}
}
typeMap.put(toStore, alias);
}
/*

View File

@@ -27,6 +27,7 @@ import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.SampleMappingContext;
import org.springframework.data.mapping.context.SamplePersistentProperty;
import org.springframework.data.util.AnnotatedTypeScanner;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
@@ -98,8 +99,42 @@ public class MappingContextTypeInformationMapperUnitTests {
assertThat(mapper.resolveTypeFrom("foo"), is((TypeInformation) from(Entity.class)));
}
/**
* @see DATACMNS-485
*/
@Test
@SuppressWarnings("unchecked")
public void createsTypeMapperForGenericTypesWithDifferentBindings() {
AnnotatedTypeScanner scanner = new AnnotatedTypeScanner(TypeAlias.class);
SampleMappingContext context = new SampleMappingContext();
context.setInitialEntitySet(scanner.findTypes(getClass().getPackage().getName()));
context.initialize();
new MappingContextTypeInformationMapper(context);
}
@TypeAlias("foo")
static class Entity {
}
@TypeAlias("genericType")
static class GenericType<T> {
}
@TypeAlias("concreteWrapper")
static class ConcreteWrapper {
GenericType<String> stringGeneric;
GenericType<Integer> integerGeneric;
}
@TypeAlias("genericWrapper")
static class GenericWrapper<T> {
GenericType<T> genericGeneric;
}
}