DATACMNS-867 - Second draft.
This commit is contained in:
@@ -35,7 +35,7 @@ public class AnnotationDetectionMethodCallbackUnitTests {
|
||||
@Test // DATACMNS-452
|
||||
public void findsMethodWithAnnotation() throws Exception {
|
||||
|
||||
AnnotationDetectionMethodCallback<Value> callback = new AnnotationDetectionMethodCallback<Value>(Value.class);
|
||||
AnnotationDetectionMethodCallback<Value> callback = new AnnotationDetectionMethodCallback<>(Value.class);
|
||||
ReflectionUtils.doWithMethods(Sample.class, callback);
|
||||
|
||||
assertThat(callback.hasFoundAnnotation()).isTrue();
|
||||
@@ -52,7 +52,7 @@ public class AnnotationDetectionMethodCallbackUnitTests {
|
||||
exception.expectMessage("getValue");
|
||||
exception.expectMessage("getOtherValue");
|
||||
|
||||
AnnotationDetectionMethodCallback<Value> callback = new AnnotationDetectionMethodCallback<Value>(Value.class, true);
|
||||
AnnotationDetectionMethodCallback<Value> callback = new AnnotationDetectionMethodCallback<>(Value.class, true);
|
||||
ReflectionUtils.doWithMethods(Multiple.class, callback);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.util.ClassTypeInformation.*;
|
||||
import static org.springframework.data.util.OptionalAssert.*;
|
||||
|
||||
import javaslang.collection.Traversable;
|
||||
|
||||
@@ -45,26 +46,25 @@ public class ClassTypeInformationUnitTests {
|
||||
|
||||
assertThat(discoverer.getType()).isEqualTo(ConcreteType.class);
|
||||
|
||||
TypeInformation<?> content = discoverer.getProperty("content");
|
||||
OptionalAssert<TypeInformation<?>> assertThat = assertOptional(discoverer.getProperty("content"));
|
||||
|
||||
assertThat(content.getType()).isEqualTo(String.class);
|
||||
assertThat(content.getComponentType()).isNull();
|
||||
assertThat(content.getMapValueType()).isNull();
|
||||
assertThat.value(it -> it.getType()).isEqualTo(String.class);
|
||||
assertThat.flatMap(it -> it.getComponentType()).isNotPresent();
|
||||
assertThat.flatMap(it -> it.getMapValueType()).isNotPresent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversTypeForNestedGenericField() {
|
||||
|
||||
TypeInformation<ConcreteWrapper> discoverer = ClassTypeInformation.from(ConcreteWrapper.class);
|
||||
|
||||
assertThat(discoverer.getType()).isEqualTo(ConcreteWrapper.class);
|
||||
TypeInformation<?> wrapper = discoverer.getProperty("wrapped");
|
||||
assertThat(wrapper.getType()).isEqualTo(GenericType.class);
|
||||
TypeInformation<?> content = wrapper.getProperty("content");
|
||||
|
||||
assertThat(content.getType()).isEqualTo(String.class);
|
||||
assertThat(discoverer.getProperty("wrapped").getProperty("content").getType()).isEqualTo(String.class);
|
||||
assertThat(discoverer.getProperty("wrapped.content").getType()).isEqualTo(String.class);
|
||||
assertOptional(discoverer.getProperty("wrapped")).andAssert(inner -> {
|
||||
inner.value(it -> it.getType()).isEqualTo(GenericType.class);
|
||||
inner.flatMap(it -> it.getProperty("content")).value(it -> it.getType()).isEqualTo(String.class);
|
||||
});
|
||||
|
||||
assertOptional(discoverer.getProperty("wrapped.content")).value(it -> it.getType()).isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -72,7 +72,7 @@ public class ClassTypeInformationUnitTests {
|
||||
public void discoversBoundType() {
|
||||
|
||||
TypeInformation<GenericTypeWithBound> information = ClassTypeInformation.from(GenericTypeWithBound.class);
|
||||
assertThat(information.getProperty("person").getType()).isEqualTo(Person.class);
|
||||
assertOptional(information.getProperty("person")).value(it -> it.getType()).isEqualTo(Person.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -80,7 +80,7 @@ public class ClassTypeInformationUnitTests {
|
||||
|
||||
TypeInformation<SpecialGenericTypeWithBound> information = ClassTypeInformation
|
||||
.from(SpecialGenericTypeWithBound.class);
|
||||
assertThat(information.getProperty("person").getType()).isEqualTo(SpecialPerson.class);
|
||||
assertOptional(information.getProperty("person")).value(it -> it.getType()).isEqualTo(SpecialPerson.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -88,43 +88,52 @@ public class ClassTypeInformationUnitTests {
|
||||
public void discoversBoundTypeForNested() {
|
||||
|
||||
TypeInformation<AnotherGenericType> information = ClassTypeInformation.from(AnotherGenericType.class);
|
||||
assertThat(information.getProperty("nested").getType()).isEqualTo(GenericTypeWithBound.class);
|
||||
assertThat(information.getProperty("nested.person").getType()).isEqualTo(Person.class);
|
||||
|
||||
assertOptional(information.getProperty("nested")).value(it -> it.getType()).isEqualTo(GenericTypeWithBound.class);
|
||||
assertOptional(information.getProperty("nested.person")).value(it -> it.getType()).isEqualTo(Person.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversArraysAndCollections() {
|
||||
|
||||
TypeInformation<StringCollectionContainer> information = ClassTypeInformation.from(StringCollectionContainer.class);
|
||||
|
||||
TypeInformation<?> property = information.getProperty("array");
|
||||
assertThat(property.getComponentType().getType()).isEqualTo(String.class);
|
||||
OptionalAssert<TypeInformation<?>> optional = assertOptional(information.getProperty("array"));
|
||||
|
||||
Class<?> type = property.getType();
|
||||
assertThat(type).isEqualTo(String[].class);
|
||||
assertThat(type.isArray()).isTrue();
|
||||
optional.flatMap(it -> it.getComponentType()).value(it -> it.getType()).isEqualTo(String.class);
|
||||
optional.value(it -> it.getType()).satisfies(it -> {
|
||||
assertThat(it).isEqualTo(String[].class);
|
||||
assertThat(it.isArray()).isTrue();
|
||||
});
|
||||
|
||||
property = information.getProperty("foo");
|
||||
assertThat(property.getType()).isEqualTo(Collection[].class);
|
||||
assertThat(property.getComponentType().getType()).isEqualTo(Collection.class);
|
||||
assertThat(property.getComponentType().getComponentType().getType()).isEqualTo(String.class);
|
||||
optional = assertOptional(information.getProperty("foo"));
|
||||
|
||||
property = information.getProperty("rawSet");
|
||||
assertThat(property.getType()).isEqualTo(Set.class);
|
||||
assertThat(property.getComponentType().getType()).isEqualTo(Object.class);
|
||||
assertThat(property.getMapValueType()).isNull();
|
||||
optional.value(it -> it.getType()).isEqualTo(Collection[].class);
|
||||
optional.flatMap(it -> it.getComponentType()).andAssert(it -> {
|
||||
it.value(inner -> inner.getType()).isEqualTo(Collection.class);
|
||||
it.flatMap(inner -> inner.getComponentType()).value(inner -> inner.getType()).isEqualTo(String.class);
|
||||
});
|
||||
|
||||
optional = assertOptional(information.getProperty("rawSet"));
|
||||
|
||||
optional.value(it -> it.getType()).isEqualTo(Set.class);
|
||||
optional.flatMap(it -> it.getComponentType()).value(it -> it.getType()).isEqualTo(Object.class);
|
||||
optional.flatMap(it -> it.getMapValueType()).isNotPresent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversMapValueType() {
|
||||
|
||||
TypeInformation<StringMapContainer> information = ClassTypeInformation.from(StringMapContainer.class);
|
||||
TypeInformation<?> genericMap = information.getProperty("genericMap");
|
||||
assertThat(genericMap.getType()).isEqualTo(Map.class);
|
||||
assertThat(genericMap.getMapValueType().getType()).isEqualTo(String.class);
|
||||
OptionalAssert<TypeInformation<?>> assertion = assertOptional(information.getProperty("genericMap"));
|
||||
|
||||
TypeInformation<?> map = information.getProperty("map");
|
||||
assertThat(map.getType()).isEqualTo(Map.class);
|
||||
assertThat(map.getMapValueType().getType()).isEqualTo(Calendar.class);
|
||||
assertion.value(it -> it.getType()).isEqualTo(Map.class);
|
||||
assertion.flatMap(it -> it.getMapValueType()).value(it -> it.getType()).isEqualTo(String.class);
|
||||
|
||||
assertion = assertOptional(information.getProperty("map"));
|
||||
|
||||
assertion.value(it -> it.getType()).isEqualTo(Map.class);
|
||||
assertion.flatMap(it -> it.getMapValueType()).value(it -> it.getType()).isEqualTo(Calendar.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -141,13 +150,8 @@ public class ClassTypeInformationUnitTests {
|
||||
|
||||
TypeInformation<PropertyGetter> from = ClassTypeInformation.from(PropertyGetter.class);
|
||||
|
||||
TypeInformation<?> property = from.getProperty("_name");
|
||||
assertThat(property).isNotNull();
|
||||
assertThat(property.getType()).isEqualTo(String.class);
|
||||
|
||||
property = from.getProperty("name");
|
||||
assertThat(property).isNotNull();
|
||||
assertThat(property.getType()).isEqualTo(byte[].class);
|
||||
assertOptional(from.getProperty("_name")).value(it -> it.getType()).isEqualTo(String.class);
|
||||
assertOptional(from.getProperty("name")).value(it -> it.getType()).isEqualTo(byte[].class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-77
|
||||
@@ -162,16 +166,18 @@ public class ClassTypeInformationUnitTests {
|
||||
|
||||
TypeInformation<ClassWithWildCardBound> information = ClassTypeInformation.from(ClassWithWildCardBound.class);
|
||||
|
||||
TypeInformation<?> property = information.getProperty("wildcard");
|
||||
assertThat(property.isCollectionLike()).isTrue();
|
||||
assertThat(property.getComponentType().getType()).isEqualTo(String.class);
|
||||
OptionalAssert<TypeInformation<?>> assertion = assertOptional(information.getProperty("wildcard"));
|
||||
|
||||
property = information.getProperty("complexWildcard");
|
||||
assertThat(property.isCollectionLike()).isTrue();
|
||||
assertion.value(it -> it.isCollectionLike()).isEqualTo(true);
|
||||
assertion.flatMap(it -> it.getComponentType()).value(it -> it.getType()).isEqualTo(String.class);
|
||||
|
||||
TypeInformation<?> component = property.getComponentType();
|
||||
assertThat(component.isCollectionLike()).isTrue();
|
||||
assertThat(component.getComponentType().getType()).isEqualTo(String.class);
|
||||
assertion = assertOptional(information.getProperty("complexWildcard"));
|
||||
|
||||
assertion.value(it -> it.isCollectionLike()).isEqualTo(true);
|
||||
assertion.flatMap(it -> it.getComponentType()).andAssert(it -> {
|
||||
it.value(inner -> inner.isCollectionLike()).isEqualTo(true);
|
||||
it.flatMap(inner -> inner.getComponentType()).value(inner -> inner.getType()).isEqualTo(String.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -258,8 +264,9 @@ public class ClassTypeInformationUnitTests {
|
||||
public void returnsComponentTypeForMultiDimensionalArrayCorrectly() {
|
||||
|
||||
TypeInformation<?> information = from(String[][].class);
|
||||
|
||||
assertThat(information.getType()).isEqualTo(String[][].class);
|
||||
assertThat(information.getComponentType().getType()).isEqualTo(String[].class);
|
||||
assertOptional(information.getComponentType()).value(it -> it.getType()).isEqualTo(String[].class);
|
||||
assertThat(information.getActualType().getActualType().getType()).isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@@ -268,10 +275,8 @@ public class ClassTypeInformationUnitTests {
|
||||
public void findsGetterOnInterface() {
|
||||
|
||||
TypeInformation<Product> information = from(Product.class);
|
||||
TypeInformation<?> categoryIdInfo = information.getProperty("category.id");
|
||||
|
||||
assertThat(categoryIdInfo).isNotNull();
|
||||
assertThat(categoryIdInfo).isEqualTo((TypeInformation) from(Long.class));
|
||||
assertOptional(information.getProperty("category.id")).hasValue(from(Long.class));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class) // DATACMNS-387
|
||||
@@ -280,27 +285,32 @@ public class ClassTypeInformationUnitTests {
|
||||
}
|
||||
|
||||
@Test // DATACMNS-422
|
||||
public void returnsNullForRawTypesOnly() {
|
||||
public void returnsEmptyOptionalForRawTypesOnly() {
|
||||
|
||||
assertThat(from(MyRawIterable.class).getComponentType()).isNull();
|
||||
assertThat(from(MyIterable.class).getComponentType()).isNotNull();
|
||||
assertThat(from(MyRawIterable.class).getComponentType()).isNotPresent();
|
||||
assertThat(from(MyIterable.class).getComponentType()).isPresent();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-440
|
||||
public void detectsSpecialMapAsMapValueType() {
|
||||
|
||||
TypeInformation<SuperGenerics> information = ClassTypeInformation.from(SuperGenerics.class);
|
||||
OptionalAssert<TypeInformation<?>> assertion = assertOptional(
|
||||
ClassTypeInformation.from(SuperGenerics.class).getProperty("seriously"));
|
||||
|
||||
TypeInformation<?> propertyInformation = information.getProperty("seriously");
|
||||
assertThat(propertyInformation.getType()).isEqualTo(SortedMap.class);
|
||||
assertion//
|
||||
// Type
|
||||
.andAssert(inner -> inner.value(it -> it.getType()).isEqualTo(SortedMap.class))//
|
||||
|
||||
TypeInformation<?> mapValueType = propertyInformation.getMapValueType();
|
||||
assertThat(mapValueType.getType()).isEqualTo(SortedMap.class);
|
||||
assertThat(mapValueType.getComponentType().getType()).isEqualTo(String.class);
|
||||
// Map value type
|
||||
.andAssert(inner -> inner.flatMap(it -> it.getMapValueType()).andAssert(value -> {
|
||||
value.value(it -> it.getType()).isEqualTo(SortedMap.class);
|
||||
value.flatMap(it -> it.getComponentType()).value(it -> it.getType()).isEqualTo(String.class);
|
||||
|
||||
TypeInformation<?> nestedValueType = mapValueType.getMapValueType();
|
||||
assertThat(nestedValueType.getType()).isEqualTo(List.class);
|
||||
assertThat(nestedValueType.getComponentType().getType()).isEqualTo(Person.class);
|
||||
// Nested value type
|
||||
}).flatMap(it -> it.getMapValueType()).andAssert(nestedValue -> {
|
||||
nestedValue.value(it -> it.getType()).isEqualTo(List.class);
|
||||
nestedValue.flatMap(it -> it.getComponentType()).value(it -> it.getType()).isEqualTo(Person.class);
|
||||
}));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-446
|
||||
@@ -313,33 +323,33 @@ public class ClassTypeInformationUnitTests {
|
||||
public void resolvesNestedGenericsToConcreteType() {
|
||||
|
||||
ClassTypeInformation<ConcreteRoot> rootType = from(ConcreteRoot.class);
|
||||
TypeInformation<?> subsPropertyType = rootType.getProperty("subs");
|
||||
TypeInformation<?> subsElementType = subsPropertyType.getActualType();
|
||||
TypeInformation<?> subSubType = subsElementType.getProperty("subSub");
|
||||
|
||||
assertThat(subSubType.getType()).isEqualTo(ConcreteSubSub.class);
|
||||
assertOptional(rootType.getProperty("subs"))//
|
||||
.map(it -> it.getActualType())//
|
||||
.flatMap(it -> it.getProperty("subSub"))//
|
||||
.value(it -> it.getType()).isEqualTo(ConcreteSubSub.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-594
|
||||
public void considersGenericsOfTypeBounds() {
|
||||
|
||||
ClassTypeInformation<ConcreteRootIntermediate> customer = ClassTypeInformation.from(ConcreteRootIntermediate.class);
|
||||
TypeInformation<?> leafType = customer.getProperty("intermediate.content.intermediate.content");
|
||||
|
||||
assertThat(leafType.getType()).isEqualTo(Leaf.class);
|
||||
assertOptional(ClassTypeInformation.from(ConcreteRootIntermediate.class)
|
||||
.getProperty("intermediate.content.intermediate.content"))//
|
||||
.value(it -> it.getType()).isEqualTo(Leaf.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-783, DATACMNS-853
|
||||
public void specializesTypeUsingTypeVariableContext() {
|
||||
|
||||
ClassTypeInformation<Foo> root = ClassTypeInformation.from(Foo.class);
|
||||
TypeInformation<?> property = root.getProperty("abstractBar");
|
||||
|
||||
TypeInformation<?> specialized = property.specialize(ClassTypeInformation.from(Bar.class));
|
||||
|
||||
assertThat(specialized.getType()).isEqualTo(Bar.class);
|
||||
assertThat(specialized.getProperty("field").getType()).isEqualTo(Character.class);
|
||||
assertThat(specialized.getProperty("anotherField").getType()).isEqualTo(Integer.class);
|
||||
assertOptional(root.getProperty("abstractBar"))//
|
||||
.map(it -> it.specialize(ClassTypeInformation.from(Bar.class)))//
|
||||
.andAssert(inner -> {
|
||||
inner.value(it -> it.getType()).isEqualTo(Bar.class);
|
||||
inner.flatMap(it -> it.getProperty("field")).value(it -> it.getType()).isEqualTo(Character.class);
|
||||
inner.flatMap(it -> it.getProperty("anotherField")).value(it -> it.getType()).isEqualTo(Integer.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // DATACMNS-783
|
||||
@@ -347,10 +357,9 @@ public class ClassTypeInformationUnitTests {
|
||||
public void usesTargetTypeDirectlyIfNoGenericsAreInvolved() {
|
||||
|
||||
ClassTypeInformation<Foo> root = ClassTypeInformation.from(Foo.class);
|
||||
TypeInformation<?> property = root.getProperty("object");
|
||||
|
||||
ClassTypeInformation<?> from = ClassTypeInformation.from(Bar.class);
|
||||
assertThat(property.specialize(from)).isEqualTo((TypeInformation) from);
|
||||
|
||||
assertOptional(root.getProperty("object")).value(it -> it.specialize(from)).isEqualTo(from);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-855
|
||||
@@ -358,14 +367,17 @@ public class ClassTypeInformationUnitTests {
|
||||
public void specializedTypeEqualsAndHashCode() {
|
||||
|
||||
ClassTypeInformation<Foo> root = ClassTypeInformation.from(Foo.class);
|
||||
TypeInformation<?> property = root.getProperty("abstractBar");
|
||||
|
||||
TypeInformation left = property.specialize(ClassTypeInformation.from(Bar.class));
|
||||
TypeInformation right = property.specialize(ClassTypeInformation.from(Bar.class));
|
||||
OptionalAssert<TypeInformation<?>> assertion = assertOptional(root.getProperty("abstractBar"));
|
||||
|
||||
assertThat(left).isEqualTo(right);
|
||||
assertThat(right).isEqualTo(left);
|
||||
assertThat(left.hashCode()).isEqualTo(right.hashCode());
|
||||
assertion
|
||||
.map(it -> Pair.of(it.specialize(ClassTypeInformation.from(Bar.class)),
|
||||
it.specialize(ClassTypeInformation.from(Bar.class))))//
|
||||
.hasValueSatisfying(pair -> {
|
||||
assertThat(pair.getFirst()).isEqualTo(pair.getSecond());
|
||||
assertThat(pair.getSecond()).isEqualTo(pair.getFirst());
|
||||
assertThat(pair.getFirst().hashCode()).isEqualTo(pair.getSecond().hashCode());
|
||||
});
|
||||
}
|
||||
|
||||
@Test // DATACMNS-896
|
||||
@@ -373,7 +385,7 @@ public class ClassTypeInformationUnitTests {
|
||||
|
||||
ClassTypeInformation<Concrete> information = ClassTypeInformation.from(Concrete.class);
|
||||
|
||||
assertThat(information.getProperty("field").getType()).isEqualTo(Nested.class);
|
||||
assertOptional(information.getProperty("field")).value(it -> it.getType()).isEqualTo(Nested.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-940
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.util.OptionalAssert.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -33,26 +33,32 @@ public class DataCmns511Tests {
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void detectsEqualTypeVariableTypeInformationInstances() {
|
||||
|
||||
TypeInformation<AbstractRole> firstRoleType = ClassTypeInformation.from(AbstractRole.class);
|
||||
TypeInformation<?> firstCreatedBy = firstRoleType.getProperty("createdBy");
|
||||
TypeInformation<?> secondRoleType = firstCreatedBy.getProperty("roles").getActualType();
|
||||
TypeInformation secondCreatedBy = secondRoleType.getProperty("createdBy");
|
||||
TypeInformation<?> thirdRoleType = secondCreatedBy.getProperty("roles").getActualType();
|
||||
TypeInformation thirdCreatedBy = thirdRoleType.getProperty("createdBy");
|
||||
OptionalAssert<TypeInformation<?>> assertion = assertOptional(
|
||||
ClassTypeInformation.from(AbstractRole.class).getProperty("createdBy"));
|
||||
|
||||
assertThat(secondCreatedBy).isEqualTo(thirdCreatedBy);
|
||||
assertThat(secondCreatedBy.hashCode()).isEqualTo(thirdCreatedBy.hashCode());
|
||||
assertion.flatMap(it -> it.getProperty("roles"))//
|
||||
.map(it -> it.getActualType())//
|
||||
.flatMap(it -> it.getProperty("createdBy"))//
|
||||
.andAssert(second -> {
|
||||
|
||||
OptionalAssert<TypeInformation<?>> third = second.flatMap(it -> it.getProperty("roles"))//
|
||||
.map(it -> it.getActualType())//
|
||||
.flatMap(it -> it.getProperty("createdBy"));
|
||||
|
||||
second.isEqualTo(third);
|
||||
second.value(it -> it.hashCode()).isEqualTo(third.getActual().hashCode());
|
||||
});
|
||||
}
|
||||
|
||||
static class AbstractRole<USER extends AbstractUser<USER, ROLE>, ROLE extends AbstractRole<USER, ROLE>> extends
|
||||
AuditingEntity<USER> {
|
||||
static class AbstractRole<USER extends AbstractUser<USER, ROLE>, ROLE extends AbstractRole<USER, ROLE>>
|
||||
extends AuditingEntity<USER> {
|
||||
|
||||
String name;
|
||||
}
|
||||
|
||||
static abstract class AbstractUser<USER extends AbstractUser<USER, ROLE>, ROLE extends AbstractRole<USER, ROLE>> {
|
||||
|
||||
Set<ROLE> roles = new HashSet<ROLE>();
|
||||
Set<ROLE> roles = new HashSet<>();
|
||||
}
|
||||
|
||||
static abstract class AuditingEntity<USER extends AbstractUser<USER, ?>> {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2016 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 lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.assertj.core.api.AbstractObjectAssert;
|
||||
import org.assertj.core.api.Assertions;
|
||||
|
||||
/**
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class OptionalAssert<T> extends org.assertj.core.api.OptionalAssert<T> {
|
||||
|
||||
public OptionalAssert(Optional<T> actual) {
|
||||
super(actual);
|
||||
}
|
||||
|
||||
public static <T> OptionalAssert<T> assertOptional(Optional<T> optional) {
|
||||
return new OptionalAssert<T>(optional);
|
||||
}
|
||||
|
||||
public Optional<T> getActual() {
|
||||
return actual;
|
||||
}
|
||||
|
||||
public <S> OptionalAssert<S> flatMap(Function<T, Optional<S>> function) {
|
||||
|
||||
Assertions.assertThat(actual).isPresent();
|
||||
|
||||
return assertOptional(actual.flatMap(function));
|
||||
}
|
||||
|
||||
public <S> OptionalAssert<S> map(Function<T, S> function) {
|
||||
|
||||
Assertions.assertThat(actual).isPresent();
|
||||
|
||||
return assertOptional(actual.map(function));
|
||||
}
|
||||
|
||||
public <S> AbstractObjectAssert<?, S> value(Function<T, S> function) {
|
||||
|
||||
Assertions.assertThat(actual).isPresent();
|
||||
|
||||
return Assertions.assertThat(actual.map(function).orElseThrow(() -> new IllegalStateException()));
|
||||
}
|
||||
|
||||
public OptionalAssert<T> isEqualTo(OptionalAssert<?> other) {
|
||||
|
||||
Assertions.assertThat(actual).isEqualTo(other.actual);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public OptionalAssert<T> andAssert(Consumer<OptionalAssert<T>> consumer) {
|
||||
|
||||
consumer.accept(this);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.util;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.util.ClassTypeInformation.*;
|
||||
import static org.springframework.data.util.OptionalAssert.*;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -27,6 +28,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -55,8 +57,8 @@ public class ParameterizedTypeUnitTests {
|
||||
@Test
|
||||
public void considersTypeInformationsWithDifferingParentsNotEqual() {
|
||||
|
||||
TypeDiscoverer<String> stringParent = new TypeDiscoverer<String>(String.class, EMPTY_MAP);
|
||||
TypeDiscoverer<Object> objectParent = new TypeDiscoverer<Object>(Object.class, EMPTY_MAP);
|
||||
TypeDiscoverer<String> stringParent = new TypeDiscoverer<>(String.class, EMPTY_MAP);
|
||||
TypeDiscoverer<Object> objectParent = new TypeDiscoverer<>(Object.class, EMPTY_MAP);
|
||||
|
||||
ParameterizedTypeInformation<Object> first = new ParameterizedTypeInformation<>(one, stringParent, EMPTY_MAP);
|
||||
ParameterizedTypeInformation<Object> second = new ParameterizedTypeInformation<>(one, objectParent, EMPTY_MAP);
|
||||
@@ -67,7 +69,7 @@ public class ParameterizedTypeUnitTests {
|
||||
@Test
|
||||
public void considersTypeInformationsWithSameParentsNotEqual() {
|
||||
|
||||
TypeDiscoverer<String> stringParent = new TypeDiscoverer<String>(String.class, EMPTY_MAP);
|
||||
TypeDiscoverer<String> stringParent = new TypeDiscoverer<>(String.class, EMPTY_MAP);
|
||||
|
||||
ParameterizedTypeInformation<Object> first = new ParameterizedTypeInformation<>(one, stringParent, EMPTY_MAP);
|
||||
ParameterizedTypeInformation<Object> second = new ParameterizedTypeInformation<>(one, stringParent, EMPTY_MAP);
|
||||
@@ -79,19 +81,23 @@ public class ParameterizedTypeUnitTests {
|
||||
public void resolvesMapValueTypeCorrectly() {
|
||||
|
||||
TypeInformation<Foo> type = ClassTypeInformation.from(Foo.class);
|
||||
TypeInformation<?> propertyType = type.getProperty("param");
|
||||
assertThat(propertyType.getProperty("value").getType()).isEqualTo(String.class);
|
||||
assertThat(propertyType.getMapValueType().getType()).isEqualTo(String.class);
|
||||
Optional<TypeInformation<?>> propertyType = type.getProperty("param");
|
||||
|
||||
OptionalAssert<TypeInformation<?>> assertion = assertOptional(propertyType);
|
||||
|
||||
assertion.flatMap(it -> it.getProperty("value")).value(it -> it.getType()).isEqualTo(String.class);
|
||||
assertion.flatMap(it -> it.getMapValueType()).value(it -> it.getType()).isEqualTo(String.class);
|
||||
|
||||
propertyType = type.getProperty("param2");
|
||||
assertThat(propertyType.getProperty("value").getType()).isEqualTo(String.class);
|
||||
assertThat(propertyType.getMapValueType().getType()).isEqualTo(Locale.class);
|
||||
|
||||
assertion.flatMap(it -> it.getProperty("value")).value(it -> it.getType()).isEqualTo(String.class);
|
||||
assertion.flatMap(it -> it.getMapValueType()).value(it -> it.getType()).isEqualTo(String.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-446
|
||||
public void createsToStringRepresentation() {
|
||||
|
||||
assertThat(from(Foo.class).getProperty("param").toString())
|
||||
assertOptional(from(Foo.class).getProperty("param")).value(it -> it.toString())
|
||||
.isEqualTo("org.springframework.data.util.ParameterizedTypeUnitTests$Localized<java.lang.String>");
|
||||
}
|
||||
|
||||
@@ -99,37 +105,47 @@ public class ParameterizedTypeUnitTests {
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void hashCodeShouldBeConsistentWithEqualsForResolvedTypes() {
|
||||
|
||||
TypeInformation first = from(First.class).getProperty("property");
|
||||
TypeInformation second = from(Second.class).getProperty("property");
|
||||
Optional<TypeInformation<?>> first = from(First.class).getProperty("property");
|
||||
Optional<TypeInformation<?>> second = from(Second.class).getProperty("property");
|
||||
|
||||
assertThat(first).isEqualTo(second);
|
||||
assertThat(first.hashCode()).isEqualTo(second.hashCode());
|
||||
|
||||
assertThat(first).hasValueSatisfying(left -> {
|
||||
assertThat(second).hasValueSatisfying(right -> {
|
||||
assertThat(left.hashCode()).isEqualTo(right.hashCode());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test // DATACMNS-485
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void getActualTypeShouldNotUnwrapParameterizedTypes() {
|
||||
|
||||
TypeInformation type = from(First.class).getProperty("property");
|
||||
assertThat(type.getActualType()).isEqualTo(type);
|
||||
Optional<TypeInformation<?>> type = from(First.class).getProperty("property");
|
||||
|
||||
assertOptional(type).map(it -> it.getActualType()).isEqualTo(type);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-697
|
||||
public void usesLocalGenericInformationOfFields() {
|
||||
|
||||
TypeInformation<NormalizedProfile> information = ClassTypeInformation.from(NormalizedProfile.class);
|
||||
TypeInformation<?> valueType = information.getProperty("education2.data").getComponentType();
|
||||
assertThat(valueType.getProperty("value").getType()).isEqualTo(Education.class);
|
||||
|
||||
assertOptional(information.getProperty("education2.data"))//
|
||||
.flatMap(it -> it.getComponentType())//
|
||||
.flatMap(it -> it.getProperty("value"))//
|
||||
.value(it -> it.getType())//
|
||||
.isEqualTo(Education.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-899
|
||||
public void returnsNullMapValueTypeForNonMapProperties() {
|
||||
public void returnsEmptyOptionalMapValueTypeForNonMapProperties() {
|
||||
|
||||
TypeInformation<?> valueType = ClassTypeInformation.from(Bar.class).getProperty("param");
|
||||
TypeInformation<?> mapValueType = valueType.getMapValueType();
|
||||
OptionalAssert<TypeInformation<?>> assertion = assertOptional(
|
||||
ClassTypeInformation.from(Bar.class).getProperty("param"));
|
||||
|
||||
assertThat(valueType).isInstanceOf(ParameterizedTypeInformation.class);
|
||||
assertThat(mapValueType).isNull();
|
||||
assertion.hasValueSatisfying(it -> assertThat(it).isInstanceOf(ParameterizedTypeInformation.class));
|
||||
assertion.flatMap(it -> it.getMapValueType()).isEmpty();
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -47,14 +48,14 @@ public class TypeDiscovererUnitTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullType() {
|
||||
new TypeDiscoverer<Object>(null, null);
|
||||
new TypeDiscoverer<>(null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotEqualIfTypesDiffer() {
|
||||
|
||||
TypeDiscoverer<Object> objectTypeInfo = new TypeDiscoverer<Object>(Object.class, EMPTY_MAP);
|
||||
TypeDiscoverer<String> stringTypeInfo = new TypeDiscoverer<String>(String.class, EMPTY_MAP);
|
||||
TypeDiscoverer<Object> objectTypeInfo = new TypeDiscoverer<>(Object.class, EMPTY_MAP);
|
||||
TypeDiscoverer<String> stringTypeInfo = new TypeDiscoverer<>(String.class, EMPTY_MAP);
|
||||
|
||||
assertThat(objectTypeInfo.equals(stringTypeInfo)).isFalse();
|
||||
}
|
||||
@@ -64,8 +65,8 @@ public class TypeDiscovererUnitTests {
|
||||
|
||||
assertThat(firstMap.equals(secondMap)).isFalse();
|
||||
|
||||
TypeDiscoverer<Object> first = new TypeDiscoverer<Object>(Object.class, firstMap);
|
||||
TypeDiscoverer<Object> second = new TypeDiscoverer<Object>(Object.class, secondMap);
|
||||
TypeDiscoverer<Object> first = new TypeDiscoverer<>(Object.class, firstMap);
|
||||
TypeDiscoverer<Object> second = new TypeDiscoverer<>(Object.class, secondMap);
|
||||
|
||||
assertThat(first.equals(second)).isFalse();
|
||||
}
|
||||
@@ -74,8 +75,9 @@ public class TypeDiscovererUnitTests {
|
||||
public void dealsWithTypesReferencingThemselves() {
|
||||
|
||||
TypeInformation<SelfReferencing> information = from(SelfReferencing.class);
|
||||
TypeInformation<?> first = information.getProperty("parent").getMapValueType();
|
||||
TypeInformation<?> second = first.getProperty("map").getMapValueType();
|
||||
Optional<TypeInformation<?>> first = information.getProperty("parent").flatMap(it -> it.getMapValueType());
|
||||
Optional<TypeInformation<?>> second = first.flatMap(it -> it.getProperty("map"))
|
||||
.flatMap(it -> it.getMapValueType());
|
||||
|
||||
assertThat(second).isEqualTo(first);
|
||||
}
|
||||
@@ -84,27 +86,35 @@ public class TypeDiscovererUnitTests {
|
||||
public void dealsWithTypesReferencingThemselvesInAMap() {
|
||||
|
||||
TypeInformation<SelfReferencingMap> information = from(SelfReferencingMap.class);
|
||||
TypeInformation<?> mapValueType = information.getProperty("map").getMapValueType();
|
||||
Optional<TypeInformation<?>> property = information.getProperty("map");
|
||||
|
||||
assertThat(information).isEqualTo(mapValueType);
|
||||
assertThat(property).hasValueSatisfying(it -> {
|
||||
assertThat(it.getMapValueType()).hasValue(information);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsComponentAndValueTypesForMapExtensions() {
|
||||
|
||||
TypeInformation<?> discoverer = new TypeDiscoverer<Object>(CustomMap.class, EMPTY_MAP);
|
||||
TypeInformation<?> discoverer = new TypeDiscoverer<>(CustomMap.class, EMPTY_MAP);
|
||||
|
||||
assertThat(discoverer.getMapValueType().getType()).isEqualTo(Locale.class);
|
||||
assertThat(discoverer.getComponentType().getType()).isEqualTo(String.class);
|
||||
assertThat(discoverer.getMapValueType()).hasValueSatisfying(it -> {
|
||||
assertThat(it.getType()).isEqualTo(Locale.class);
|
||||
});
|
||||
|
||||
assertThat(discoverer.getComponentType()).hasValueSatisfying(it -> {
|
||||
assertThat(it.getType()).isEqualTo(String.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsComponentTypeForCollectionExtension() {
|
||||
|
||||
TypeDiscoverer<CustomCollection> discoverer = new TypeDiscoverer<CustomCollection>(CustomCollection.class,
|
||||
firstMap);
|
||||
TypeDiscoverer<CustomCollection> discoverer = new TypeDiscoverer<>(CustomCollection.class, firstMap);
|
||||
|
||||
assertThat(discoverer.getComponentType().getType()).isEqualTo(String.class);
|
||||
assertThat(discoverer.getComponentType()).hasValueSatisfying(it -> {
|
||||
assertThat(it.getType()).isEqualTo(String.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -112,49 +122,56 @@ public class TypeDiscovererUnitTests {
|
||||
|
||||
TypeDiscoverer<String[]> discoverer = new TypeDiscoverer<String[]>(String[].class, EMPTY_MAP);
|
||||
|
||||
assertThat(discoverer.getComponentType().getType()).isEqualTo(String.class);
|
||||
assertThat(discoverer.getComponentType()).hasValueSatisfying(it -> {
|
||||
assertThat(it.getType()).isEqualTo(String.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test // DATACMNS-57
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void discoveresConstructorParameterTypesCorrectly() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
TypeDiscoverer<GenericConstructors> discoverer = new TypeDiscoverer<GenericConstructors>(GenericConstructors.class,
|
||||
firstMap);
|
||||
TypeDiscoverer<GenericConstructors> discoverer = new TypeDiscoverer<>(GenericConstructors.class, firstMap);
|
||||
Constructor<GenericConstructors> constructor = GenericConstructors.class.getConstructor(List.class, Locale.class);
|
||||
List<TypeInformation<?>> types = discoverer.getParameterTypes(constructor);
|
||||
|
||||
assertThat(types).hasSize(2);
|
||||
assertThat(types.get(0).getType()).isEqualTo(List.class);
|
||||
assertThat(types.get(0).getComponentType().getType()).isEqualTo(String.class);
|
||||
assertThat(types.get(0).getComponentType()).hasValueSatisfying(it -> {
|
||||
assertThat(it.getType()).isEqualTo(String.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void returnsNullForComponentAndValueTypesForRawMaps() {
|
||||
|
||||
TypeDiscoverer<Map> discoverer = new TypeDiscoverer<Map>(Map.class, EMPTY_MAP);
|
||||
TypeDiscoverer<Map> discoverer = new TypeDiscoverer<>(Map.class, EMPTY_MAP);
|
||||
|
||||
assertThat(discoverer.getComponentType()).isNull();
|
||||
assertThat(discoverer.getMapValueType()).isNull();
|
||||
assertThat(discoverer.getComponentType()).isEmpty();
|
||||
assertThat(discoverer.getMapValueType()).isEmpty();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-167
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void doesNotConsiderTypeImplementingIterableACollection() {
|
||||
|
||||
TypeDiscoverer<Person> discoverer = new TypeDiscoverer<Person>(Person.class, EMPTY_MAP);
|
||||
TypeDiscoverer<Person> discoverer = new TypeDiscoverer<>(Person.class, EMPTY_MAP);
|
||||
TypeInformation reference = from(Address.class);
|
||||
|
||||
TypeInformation<?> addresses = discoverer.getProperty("addresses");
|
||||
Optional<TypeInformation<?>> addresses = discoverer.getProperty("addresses");
|
||||
|
||||
assertThat(addresses.isCollectionLike()).isFalse();
|
||||
assertThat(addresses.getComponentType()).isEqualTo(reference);
|
||||
assertThat(addresses).hasValueSatisfying(it -> {
|
||||
assertThat(it.isCollectionLike()).isFalse();
|
||||
assertThat(it.getComponentType()).hasValue(reference);
|
||||
});
|
||||
|
||||
TypeInformation<?> adressIterable = discoverer.getProperty("addressIterable");
|
||||
Optional<TypeInformation<?>> adressIterable = discoverer.getProperty("addressIterable");
|
||||
|
||||
assertThat(adressIterable.isCollectionLike()).isTrue();
|
||||
assertThat(adressIterable.getComponentType()).isEqualTo(reference);
|
||||
assertThat(adressIterable).hasValueSatisfying(it -> {
|
||||
assertThat(it.isCollectionLike()).isTrue();
|
||||
assertThat(it.getComponentType()).hasValue(reference);
|
||||
});
|
||||
}
|
||||
|
||||
class Person {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.springframework.data.util;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.AbstractObjectAssert;
|
||||
import org.assertj.core.api.Assertions;
|
||||
|
||||
public class TypeInformationAssert extends AbstractAssert<TypeInformationAssert, TypeInformation<?>> {
|
||||
|
||||
/**
|
||||
* @param actual
|
||||
* @param selfType
|
||||
*/
|
||||
public TypeInformationAssert(TypeInformation<?> actual) {
|
||||
super(actual, TypeInformationAssert.class);
|
||||
}
|
||||
|
||||
public static TypeInformationAssert assertThat(TypeInformation<?> information) {
|
||||
return new TypeInformationAssert(information);
|
||||
}
|
||||
|
||||
public TypeInformationAssert hasComponentType(Class<?> type) {
|
||||
|
||||
Assertions.assertThat(actual.getComponentType()).hasValueSatisfying(it -> {
|
||||
Assertions.assertThat(it.getType()).isEqualTo(type);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbstractObjectAssert<?, TypeInformation<?>> hasProperty(String property) {
|
||||
|
||||
Optional<TypeInformation<?>> property2 = actual.getProperty(property);
|
||||
|
||||
return Assertions.assertThat(property2.orElseGet(() -> {
|
||||
failWithMessage("Property %s not found!", property);
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user