DATACMNS-38 - Prevent StackOverflow on self referencing objects.
Various improvements and additional test cases for the TypeInformation abstraction. Introduced ParameterizedTypeInformation in-between class to take the parent into account when calculating equals(…) and hashCode(). We're also shortcutting TypeInformation creation if the parent's underlying type equals the one we shall create a new TypeInformation for. Slightly modified the parsing algorithm when adding PersistentEntity objects. We now eagerly add them to the cache to prevent endless recursive adding.
This commit is contained in:
@@ -162,6 +162,10 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
try {
|
||||
final E entity = createPersistentEntity(typeInformation);
|
||||
|
||||
// Eagerly cache the entity as we might have to find it during recursive lookups.
|
||||
persistentEntities.put(entity.getTypeInformation(), entity);
|
||||
|
||||
BeanInfo info = Introspector.getBeanInfo(type);
|
||||
|
||||
final Map<String, PropertyDescriptor> descriptors = new HashMap<String, PropertyDescriptor>();
|
||||
@@ -196,8 +200,6 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
if (nestedType != null) {
|
||||
addPersistentEntity(nestedType);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}, new ReflectionUtils.FieldFilter() {
|
||||
public boolean matches(Field field) {
|
||||
@@ -212,9 +214,6 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
applicationEventPublisher.publishEvent(new MappingContextEvent<E, P>(entity, typeInformation));
|
||||
}
|
||||
|
||||
// Cache
|
||||
persistentEntities.put(entity.getTypeInformation(), (E) entity);
|
||||
|
||||
return entity;
|
||||
} catch (IntrospectionException e) {
|
||||
throw new MappingException(e.getMessage(), e);
|
||||
@@ -270,7 +269,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
protected abstract P createPersistentProperty(Field field, PropertyDescriptor descriptor, E owner);
|
||||
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
public void afterPropertiesSet() {
|
||||
for (Class<?> initialEntity : initialEntitySet) {
|
||||
addPersistentEntity(initialEntity);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.repository;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.repository.support;
|
||||
|
||||
import org.springframework.data.repository.RepositoryProxy;
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package org.springframework.data.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Special {@link TypeDiscoverer} handling {@link GenericArrayType}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ArrayTypeDiscoverer<S> extends TypeDiscoverer<S> {
|
||||
|
||||
private GenericArrayType type;
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* @param parent
|
||||
* @param parent
|
||||
*/
|
||||
protected ArrayTypeDiscoverer(GenericArrayType type, TypeDiscoverer<?> parent) {
|
||||
super(type, null, parent);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#getType()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<S> getType() {
|
||||
|
||||
return (Class<S>) Array.newInstance(resolveType(type.getGenericComponentType()), 0).getClass();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#getComponentType()
|
||||
*/
|
||||
@Override
|
||||
public TypeInformation<?> getComponentType() {
|
||||
|
||||
Type componentType = type.getGenericComponentType();
|
||||
return createInfo(componentType);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.util;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@@ -15,6 +30,13 @@ public class ClassTypeInformation<S> extends TypeDiscoverer<S> {
|
||||
|
||||
private final Class<S> type;
|
||||
|
||||
/**
|
||||
* Simple factory method to easily create new instances of {@link ClassTypeInformation}.
|
||||
*
|
||||
* @param <S>
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
public static <S> TypeInformation<S> from(Class<S> type) {
|
||||
return new ClassTypeInformation<S>(type);
|
||||
}
|
||||
@@ -25,16 +47,13 @@ public class ClassTypeInformation<S> extends TypeDiscoverer<S> {
|
||||
* @param type
|
||||
*/
|
||||
public ClassTypeInformation(Class<S> type) {
|
||||
this(type, GenericTypeResolver.getTypeVariableMap(type), null);
|
||||
this(type, GenericTypeResolver.getTypeVariableMap(type));
|
||||
}
|
||||
|
||||
ClassTypeInformation(Class<S> type, TypeDiscoverer<?> parent) {
|
||||
this(type, null, parent);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes") ClassTypeInformation(Class<S> type, Map<TypeVariable, Type> typeVariableMap,
|
||||
TypeDiscoverer<?> parent) {
|
||||
super(type, typeVariableMap, parent);
|
||||
@SuppressWarnings("rawtypes")
|
||||
ClassTypeInformation(Class<S> type, Map<TypeVariable, Type> typeVariableMap) {
|
||||
super(type, typeVariableMap);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@@ -68,27 +87,4 @@ public class ClassTypeInformation<S> extends TypeDiscoverer<S> {
|
||||
Class<?> componentType = type.getComponentType();
|
||||
return componentType.isArray() ? resolveArrayType(componentType) : componentType;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClassTypeInformation<?> that = (ClassTypeInformation<?>) obj;
|
||||
return this.type.equals(that.type);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
return result += 31 * type.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Special {@link TypeDiscoverer} handling {@link GenericArrayType}s.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class GenericArrayTypeInformation<S> extends ParameterizedTypeInformation<S> {
|
||||
|
||||
private GenericArrayType type;
|
||||
|
||||
/**
|
||||
* Creates a new {@link GenericArrayTypeInformation} for the given {@link GenericArrayTypeInformation} and
|
||||
* {@link TypeDiscoverer}.
|
||||
*
|
||||
* @param type
|
||||
* @param parent
|
||||
*/
|
||||
protected GenericArrayTypeInformation(GenericArrayType type, TypeDiscoverer<?> parent) {
|
||||
super(type, parent);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#getType()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<S> getType() {
|
||||
|
||||
return (Class<S>) Array.newInstance(resolveType(type.getGenericComponentType()), 0).getClass();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#getComponentType()
|
||||
*/
|
||||
@Override
|
||||
public TypeInformation<?> getComponentType() {
|
||||
|
||||
Type componentType = type.getGenericComponentType();
|
||||
return createInfo(componentType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.util;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Base class for all types that include parameterization of some kind. Crucial as we have to take note of the parent
|
||||
* class we will have to resolve generic parameters against.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class ParameterizedTypeInformation<T> extends TypeDiscoverer<T> {
|
||||
|
||||
private final TypeDiscoverer<?> parent;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link ParameterizedTypeInformation} for the given {@link Type} and parent {@link TypeDiscoverer}.
|
||||
*
|
||||
* @param type must not be {@literal null}
|
||||
* @param parent must not be {@literal null}
|
||||
*/
|
||||
public ParameterizedTypeInformation(Type type, TypeDiscoverer<?> parent) {
|
||||
super(type, null);
|
||||
Assert.notNull(parent);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Considers the parent's type variable map before invoking the super class method.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected Map<TypeVariable, Type> getTypeVariableMap() {
|
||||
|
||||
return parent != null ? parent.getTypeVariableMap() : super.getTypeVariableMap();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#createInfo(java.lang.reflect.Type)
|
||||
*/
|
||||
@Override
|
||||
protected TypeInformation<?> createInfo(Type fieldType) {
|
||||
if (parent.getType().equals(fieldType)) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
return super.createInfo(fieldType);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.getClass().equals(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ParameterizedTypeInformation<?> that = (ParameterizedTypeInformation<?>) obj;
|
||||
return this.parent == null ? that.parent == null : this.parent.equals(that.parent);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.util.TypeDiscoverer#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode() + 31 * ObjectUtils.nullSafeHashCode(parent);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.util;
|
||||
|
||||
import static org.springframework.util.ObjectUtils.*;
|
||||
@@ -28,23 +43,19 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final Map<TypeVariable, Type> typeVariableMap;
|
||||
private final Map<String, TypeInformation<?>> fieldTypes = new ConcurrentHashMap<String, TypeInformation<?>>();
|
||||
private final TypeDiscoverer<?> parent;
|
||||
|
||||
/**
|
||||
* Creates a ne {@link TypeDiscoverer} for the given type, type variable map and parent.
|
||||
*
|
||||
* @param type must not be null.
|
||||
* @param type must not be null.
|
||||
* @param typeVariableMap
|
||||
* @param parent
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected TypeDiscoverer(Type type, Map<TypeVariable, Type> typeVariableMap,
|
||||
TypeDiscoverer<?> parent) {
|
||||
protected TypeDiscoverer(Type type, Map<TypeVariable, Type> typeVariableMap) {
|
||||
|
||||
Assert.notNull(type);
|
||||
this.type = type;
|
||||
this.typeVariableMap = typeVariableMap;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,9 +65,9 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private Map<TypeVariable, Type> getTypeVariableMap() {
|
||||
protected Map<TypeVariable, Type> getTypeVariableMap() {
|
||||
|
||||
return parent != null ? parent.getTypeVariableMap() : typeVariableMap;
|
||||
return typeVariableMap;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,10 +82,14 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
if (fieldType.equals(this.type)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
if (fieldType instanceof Class) {
|
||||
return new ClassTypeInformation((Class<?>) fieldType);
|
||||
}
|
||||
|
||||
if (fieldType instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) fieldType;
|
||||
return new TypeDiscoverer(parameterizedType, null, this);
|
||||
return new ParameterizedTypeInformation(parameterizedType, this);
|
||||
}
|
||||
|
||||
if (fieldType instanceof TypeVariable) {
|
||||
@@ -82,12 +97,8 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
return new TypeVariableTypeInformation(variable, type, this);
|
||||
}
|
||||
|
||||
if (fieldType instanceof Class) {
|
||||
return new ClassTypeInformation((Class<?>) fieldType, this);
|
||||
}
|
||||
|
||||
if (fieldType instanceof GenericArrayType) {
|
||||
return new ArrayTypeDiscoverer((GenericArrayType) fieldType, this);
|
||||
return new GenericArrayTypeInformation((GenericArrayType) fieldType, this);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException();
|
||||
@@ -145,7 +156,7 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
|
||||
String head = fieldname.substring(0, separatorIndex);
|
||||
TypeInformation<?> info = fieldTypes.get(head);
|
||||
return info.getProperty(fieldname.substring(separatorIndex + 1));
|
||||
return info == null ? null : info.getProperty(fieldname.substring(separatorIndex + 1));
|
||||
}
|
||||
|
||||
private TypeInformation<?> getPropertyInformation(String fieldname) {
|
||||
@@ -237,9 +248,8 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
boolean typeEqual = nullSafeEquals(this.type, that.type);
|
||||
boolean typeVariableMapEqual = nullSafeEquals(this.typeVariableMap,
|
||||
that.typeVariableMap);
|
||||
boolean parentEqual = nullSafeEquals(this.parent, that.parent);
|
||||
|
||||
return typeEqual && typeVariableMapEqual && parentEqual;
|
||||
return typeEqual && typeVariableMapEqual;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -253,7 +263,6 @@ class TypeDiscoverer<S> implements TypeInformation<S> {
|
||||
int result = 17;
|
||||
result += nullSafeHashCode(type);
|
||||
result += nullSafeHashCode(typeVariableMap);
|
||||
result += nullSafeHashCode(parent);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.util;
|
||||
|
||||
import static org.springframework.util.ObjectUtils.*;
|
||||
@@ -14,7 +29,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class TypeVariableTypeInformation<T> extends TypeDiscoverer<T> {
|
||||
class TypeVariableTypeInformation<T> extends ParameterizedTypeInformation<T> {
|
||||
|
||||
private final TypeVariable<?> variable;
|
||||
private final Type owningType;
|
||||
@@ -29,7 +44,7 @@ class TypeVariableTypeInformation<T> extends TypeDiscoverer<T> {
|
||||
*/
|
||||
public TypeVariableTypeInformation(TypeVariable<?> variable, Type owningType, TypeDiscoverer<?> parent) {
|
||||
|
||||
super(variable, null, parent);
|
||||
super(variable, parent);
|
||||
Assert.notNull(variable);
|
||||
this.variable = variable;
|
||||
this.owningType = owningType;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.util;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
@@ -109,6 +124,15 @@ public class ClassTypeInformationUnitTests {
|
||||
assertEquals(Map.class, map.getType());
|
||||
assertEquals(Calendar.class, map.getMapValueType().getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void typeInfoDoesNotEqualForGenericTypesWithDifferentParent() {
|
||||
|
||||
TypeInformation<ConcreteWrapper> first = ClassTypeInformation.from(ConcreteWrapper.class);
|
||||
TypeInformation<AnotherConcreteWrapper> second = ClassTypeInformation.from(AnotherConcreteWrapper.class);
|
||||
|
||||
assertFalse(first.getProperty("wrapped").equals(second.getProperty("wrapped")));
|
||||
}
|
||||
|
||||
static class StringMapContainer extends MapContainer<String> {
|
||||
|
||||
@@ -171,4 +195,8 @@ public class ClassTypeInformationUnitTests {
|
||||
static class ConcreteWrapper extends GenericWrapper<String> {
|
||||
|
||||
}
|
||||
|
||||
static class AnotherConcreteWrapper extends GenericWrapper<Long> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.util;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ParameterizedTypeInformation}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class ParameterizedTypeUnitTests {
|
||||
|
||||
@Test
|
||||
public void considersTypeInformationsWithDifferingParentsNotEqual() {
|
||||
|
||||
TypeDiscoverer<String> stringParent = new TypeDiscoverer<String>(String.class, null);
|
||||
TypeDiscoverer<Object> objectParent = new TypeDiscoverer<Object>(Object.class, null);
|
||||
|
||||
ParameterizedTypeInformation<Object> first = new ParameterizedTypeInformation<Object>(Object.class, stringParent);
|
||||
ParameterizedTypeInformation<Object> second = new ParameterizedTypeInformation<Object>(Object.class, objectParent);
|
||||
|
||||
assertFalse(first.equals(second));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void considersTypeInformationsWithSameParentsNotEqual() {
|
||||
|
||||
TypeDiscoverer<String> stringParent = new TypeDiscoverer<String>(String.class, null);
|
||||
|
||||
ParameterizedTypeInformation<Object> first = new ParameterizedTypeInformation<Object>(Object.class, stringParent);
|
||||
ParameterizedTypeInformation<Object> second = new ParameterizedTypeInformation<Object>(Object.class, stringParent);
|
||||
|
||||
assertTrue(first.equals(second));
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,96 @@
|
||||
/*
|
||||
* Copyright 2011 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.
|
||||
* 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 org.springframework.data.util;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link TypeDiscoverer}.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TypeDiscovererUnitTests {
|
||||
|
||||
@Mock
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<TypeVariable, Type> firstMap;
|
||||
|
||||
@Mock
|
||||
@SuppressWarnings("rawtypes")
|
||||
Map<TypeVariable, Type> secondMap;
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullType() {
|
||||
new TypeDiscoverer<Object>(null, null, null);
|
||||
new TypeDiscoverer<Object>(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotEqualIfTypesDiffer() {
|
||||
|
||||
TypeDiscoverer<Object> objectTypeInfo = new TypeDiscoverer<Object>(Object.class, null);
|
||||
TypeDiscoverer<String> stringTypeInfo = new TypeDiscoverer<String>(String.class, null);
|
||||
|
||||
assertFalse(objectTypeInfo.equals(stringTypeInfo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotEqualIfTypeVariableMapsDiffer() {
|
||||
|
||||
assertFalse(firstMap.equals(secondMap));
|
||||
|
||||
TypeDiscoverer<Object> first = new TypeDiscoverer<Object>(Object.class, firstMap);
|
||||
TypeDiscoverer<Object> second = new TypeDiscoverer<Object>(Object.class, secondMap);
|
||||
|
||||
assertFalse(first.equals(second));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dealsWithTypesReferencingThemselves() {
|
||||
|
||||
TypeInformation<SelfReferencing> information = new ClassTypeInformation<SelfReferencing>(SelfReferencing.class);
|
||||
TypeInformation<?> first = information.getProperty("parent").getMapValueType();
|
||||
TypeInformation<?> second = first.getProperty("map").getMapValueType();
|
||||
assertEquals(first, second);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dealsWithTypesReferencingThemselvesInAMap() {
|
||||
|
||||
TypeInformation<SelfReferencingMap> information = new ClassTypeInformation<SelfReferencingMap>(
|
||||
SelfReferencingMap.class);
|
||||
TypeInformation<?> mapValueType = information.getProperty("map").getMapValueType();
|
||||
assertEquals(mapValueType, information);
|
||||
}
|
||||
|
||||
class SelfReferencing {
|
||||
|
||||
Map<String, SelfReferencingMap> parent;
|
||||
}
|
||||
|
||||
class SelfReferencingMap {
|
||||
Map<String, SelfReferencingMap> map;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user