DATAKV-192 - Move codebase to Java8 API.
Make use of stream lambdas in query execution. Remove copy of MetaAnnotationUtils in favor of @AliasFor usage. Original pull request: #26.
This commit is contained in:
committed by
Mark Paluch
parent
871130b9dc
commit
0025c03e5a
@@ -13,14 +13,14 @@ The primary goal of the http://projects.spring.io/spring-data[Spring Data] proje
|
||||
|
||||
## Quick Start
|
||||
|
||||
Download the jar though Maven:
|
||||
Download the jar through Maven:
|
||||
|
||||
[source, xml]
|
||||
----
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-keyvalue</artifactId>
|
||||
<version>0.1.0.BUILD-SNAPSHOT</version>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
----
|
||||
|
||||
|
||||
@@ -88,18 +88,20 @@ template.findAllOf(User.class); <2>
|
||||
[[key-value.keyspaces-custom]]
|
||||
=== Custom KeySpace Annotation
|
||||
|
||||
It is possible to compose own `KeySpace` annotations for a more domain centric usage by annotating one of the attibutes with `@KeySpace`.
|
||||
It is possible to compose own `KeySpace` annotations for a more domain centric usage by annotating one of the attributes with `@AliasFor`.
|
||||
|
||||
NOTE: The composed annotation needs to inherit `@Persistent`.
|
||||
|
||||
[source, java]
|
||||
----
|
||||
@Keyspace
|
||||
@Persistent
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
static @interface CacheCentricAnnotation {
|
||||
|
||||
@KeySpace String cacheRegion() default "";
|
||||
@AliasFor(annotation = KeySpace.class, attribute = "value")
|
||||
String cacheRegion() default "";
|
||||
}
|
||||
|
||||
@CacheCentricAnnotation(cacheRegion = "customers")
|
||||
|
||||
@@ -101,7 +101,7 @@ enum DefaultIdentifierGenerator implements IdentifierGenerator {
|
||||
private static final List<String> SECURE_RANDOM_ALGORITHMS_WINDOWS = Arrays.asList("SHA1PRNG", "Windows-PRNG");
|
||||
|
||||
static List<String> secureRandomAlgorithmNames() {
|
||||
return OPERATING_SYSTEM_NAME.indexOf("win") >= 0 ? SECURE_RANDOM_ALGORITHMS_WINDOWS
|
||||
return OPERATING_SYSTEM_NAME.contains("win") ? SECURE_RANDOM_ALGORITHMS_WINDOWS
|
||||
: SECURE_RANDOM_ALGORITHMS_LINUX_OSX_SOLARIS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -20,6 +20,7 @@ import java.util.NoSuchElementException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple {@link PersistenceExceptionTranslator} implementation for key/value stores that converts the given runtime
|
||||
@@ -34,19 +35,21 @@ public class KeyValuePersistenceExceptionTranslator implements PersistenceExcept
|
||||
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
|
||||
*/
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException e) {
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException exception) {
|
||||
|
||||
if (e == null || e instanceof DataAccessException) {
|
||||
return (DataAccessException) e;
|
||||
Assert.notNull(exception, "Exception must not be null!");
|
||||
|
||||
if (exception instanceof DataAccessException) {
|
||||
return (DataAccessException) exception;
|
||||
}
|
||||
|
||||
if (e instanceof NoSuchElementException || e instanceof IndexOutOfBoundsException
|
||||
|| e instanceof IllegalStateException) {
|
||||
return new DataRetrievalFailureException(e.getMessage(), e);
|
||||
if (exception instanceof NoSuchElementException || exception instanceof IndexOutOfBoundsException
|
||||
|| exception instanceof IllegalStateException) {
|
||||
return new DataRetrievalFailureException(exception.getMessage(), exception);
|
||||
}
|
||||
|
||||
if (e.getClass().getName().startsWith("java")) {
|
||||
return new UncategorizedKeyValueException(e.getMessage(), e);
|
||||
if (exception.getClass().getName().startsWith("java")) {
|
||||
return new UncategorizedKeyValueException(exception.getMessage(), exception);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -219,27 +219,22 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationEventPub
|
||||
|
||||
Assert.notNull(type, "Type to fetch must not be null!");
|
||||
|
||||
return execute(new KeyValueCallback<Iterable<T>>() {
|
||||
return execute(adapter -> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Iterable<T> doInKeyValue(KeyValueAdapter adapter) {
|
||||
Iterable<?> values = adapter.getAllOf(resolveKeySpace(type));
|
||||
|
||||
Iterable<?> values = adapter.getAllOf(resolveKeySpace(type));
|
||||
|
||||
if (values == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
ArrayList<T> filtered = new ArrayList<>();
|
||||
for (Object candidate : values) {
|
||||
if (typeCheck(type, candidate)) {
|
||||
filtered.add((T) candidate);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
if (values == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
ArrayList<T> filtered = new ArrayList<>();
|
||||
for (Object candidate : values) {
|
||||
if (typeCheck(type, candidate)) {
|
||||
filtered.add((T) candidate);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -323,7 +318,7 @@ public class KeyValueTemplate implements KeyValueOperations, ApplicationEventPub
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.beforeDelete(id, keyspace, type));
|
||||
|
||||
T result = execute(adapter -> (T) adapter.delete(id, keyspace, type));
|
||||
T result = execute(adapter -> adapter.delete(id, keyspace, type));
|
||||
|
||||
potentiallyPublishEvent(KeyValueEvent.afterDelete(id, keyspace, type, result));
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -109,18 +109,11 @@ public class SpelPropertyComparator<T> implements Comparator<T> {
|
||||
*/
|
||||
protected String buildExpressionForPath() {
|
||||
|
||||
StringBuilder rawExpression = new StringBuilder(
|
||||
"new org.springframework.util.comparator.NullSafeComparator(new org.springframework.util.comparator.ComparableComparator(), "
|
||||
+ Boolean.toString(this.nullsFirst) + ").compare(");
|
||||
String rawExpression = "new org.springframework.util.comparator.NullSafeComparator(new org.springframework.util.comparator.ComparableComparator(), "
|
||||
+ Boolean.toString(this.nullsFirst) + ").compare(" + "#arg1?." + (path != null ? path.replace(".", "?.") : "")
|
||||
+ "," + "#arg2?." + (path != null ? path.replace(".", "?.") : "") + ")";
|
||||
|
||||
rawExpression.append("#arg1?.");
|
||||
rawExpression.append(path != null ? path.replace(".", "?.") : "");
|
||||
rawExpression.append(",");
|
||||
rawExpression.append("#arg2?.");
|
||||
rawExpression.append(path != null ? path.replace(".", "?.") : "");
|
||||
rawExpression.append(")");
|
||||
|
||||
return rawExpression.toString();
|
||||
return rawExpression;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.keyvalue.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
@@ -60,7 +61,7 @@ class SpelQueryEngine extends QueryEngine<KeyValueAdapter, SpelCriteria, Compara
|
||||
*/
|
||||
@Override
|
||||
public long count(SpelCriteria criteria, String keyspace) {
|
||||
return filterMatchingRange(getAdapter().getAllOf(keyspace), criteria, -1, -1).size();
|
||||
return filterMatchingRange(IterableConverter.toList(getAdapter().getAllOf(keyspace)), criteria, -1, -1).size();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -75,44 +76,35 @@ class SpelQueryEngine extends QueryEngine<KeyValueAdapter, SpelCriteria, Compara
|
||||
return filterMatchingRange(tmp, criteria, offset, rows);
|
||||
}
|
||||
|
||||
private static <S> List<S> filterMatchingRange(Iterable<S> source, SpelCriteria criteria, long offset, int rows) {
|
||||
private static <S> List<S> filterMatchingRange(List<S> source, SpelCriteria criteria, long offset, int rows) {
|
||||
|
||||
List<S> result = new ArrayList<>();
|
||||
Stream<S> stream = source.stream();
|
||||
|
||||
boolean compareOffsetAndRows = 0 < offset || 0 <= rows;
|
||||
int remainingRows = rows;
|
||||
int curPos = 0;
|
||||
|
||||
for (S candidate : source) {
|
||||
|
||||
boolean matches = criteria == null;
|
||||
|
||||
if (!matches) {
|
||||
try {
|
||||
matches = criteria.getExpression().getValue(criteria.getContext(), candidate, Boolean.class);
|
||||
} catch (SpelEvaluationException e) {
|
||||
criteria.getContext().setVariable("it", candidate);
|
||||
matches = criteria.getExpression().getValue(criteria.getContext()) == null ? false
|
||||
: criteria.getExpression().getValue(criteria.getContext(), Boolean.class);
|
||||
}
|
||||
}
|
||||
|
||||
if (matches) {
|
||||
if (compareOffsetAndRows) {
|
||||
if (curPos >= offset && rows > 0) {
|
||||
result.add(candidate);
|
||||
remainingRows--;
|
||||
if (remainingRows <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
curPos++;
|
||||
} else {
|
||||
result.add(candidate);
|
||||
}
|
||||
}
|
||||
if (criteria != null) {
|
||||
stream = stream.filter(it -> evaluateExpression(criteria, it));
|
||||
}
|
||||
if (offset > 0) {
|
||||
stream = stream.skip(offset);
|
||||
}
|
||||
if (rows > 0) {
|
||||
stream = stream.limit(rows);
|
||||
}
|
||||
|
||||
return result;
|
||||
return stream.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
static boolean evaluateExpression(SpelCriteria criteria, Object candidate) {
|
||||
|
||||
boolean matches = false;
|
||||
|
||||
try {
|
||||
matches = criteria.getExpression().getValue(criteria.getContext(), candidate, Boolean.class);
|
||||
} catch (SpelEvaluationException e) {
|
||||
criteria.getContext().setVariable("it", candidate);
|
||||
matches = criteria.getExpression().getValue(criteria.getContext()) == null ? false
|
||||
: criteria.getExpression().getValue(criteria.getContext(), Boolean.class);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,21 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.keyvalue.core.mapping;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
import org.springframework.data.keyvalue.core.mapping.AnnotationBasedKeySpaceResolver.MetaAnnotationUtils.AnnotationDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link AnnotationBasedKeySpaceResolver} looks up {@link Persistent} and checks for presence of either meta or direct
|
||||
@@ -65,346 +56,6 @@ enum AnnotationBasedKeySpaceResolver implements KeySpaceResolver {
|
||||
return AnnotationUtils.getValue(keyspace);
|
||||
}
|
||||
|
||||
AnnotationDescriptor<Persistent> descriptor = MetaAnnotationUtils.findAnnotationDescriptor(type, Persistent.class);
|
||||
|
||||
if (descriptor != null && descriptor.getComposedAnnotation() != null) {
|
||||
|
||||
Annotation composed = descriptor.getComposedAnnotation();
|
||||
|
||||
for (Method method : descriptor.getComposedAnnotationType().getDeclaredMethods()) {
|
||||
|
||||
keyspace = AnnotationUtils.findAnnotation(method, KeySpace.class);
|
||||
|
||||
if (keyspace != null) {
|
||||
return AnnotationUtils.getValue(composed, method.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code MetaAnnotationUtils} is a collection of utility methods that complements the standard support already
|
||||
* available in {@link AnnotationUtils}.
|
||||
* <p>
|
||||
* Whereas {@code AnnotationUtils} provides utilities for <em>getting</em> or <em>finding</em> an annotation,
|
||||
* {@code MetaAnnotationUtils} goes a step further by providing support for determining the <em>root class</em> on
|
||||
* which an annotation is declared, either directly or indirectly via a <em>composed
|
||||
* annotation</em>. This additional information is encapsulated in an {@link AnnotationDescriptor}.
|
||||
* <p>
|
||||
* The additional information provided by an {@code AnnotationDescriptor} is required by the
|
||||
* <em>Spring TestContext Framework</em> in order to be able to support class hierarchy traversals for annotations
|
||||
* such as {@link org.springframework.test.context.ContextConfiguration @ContextConfiguration},
|
||||
* {@link org.springframework.test.context.TestExecutionListeners @TestExecutionListeners}, and
|
||||
* {@link org.springframework.test.context.ActiveProfiles @ActiveProfiles} which offer support for merging and
|
||||
* overriding various <em>inherited</em> annotation attributes (e.g.,
|
||||
* {@link org.springframework.test.context.ContextConfiguration#inheritLocations}).
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.0
|
||||
* @see AnnotationUtils
|
||||
* @see AnnotationDescriptor
|
||||
*/
|
||||
static abstract class MetaAnnotationUtils {
|
||||
|
||||
private MetaAnnotationUtils() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the {@link AnnotationDescriptor} for the supplied {@code annotationType} on the supplied {@link Class},
|
||||
* traversing its annotations and superclasses if no annotation can be found on the given class itself.
|
||||
* <p>
|
||||
* This method explicitly handles class-level annotations which are not declared as
|
||||
* {@linkplain java.lang.annotation.Inherited inherited} <em>as
|
||||
* well as meta-annotations</em>.
|
||||
* <p>
|
||||
* The algorithm operates as follows:
|
||||
* <ol>
|
||||
* <li>Search for the annotation on the given class and return a corresponding {@code AnnotationDescriptor} if
|
||||
* found.
|
||||
* <li>Recursively search through all annotations that the given class declares.
|
||||
* <li>Recursively search through the superclass hierarchy of the given class.
|
||||
* </ol>
|
||||
* <p>
|
||||
* In this context, the term <em>recursively</em> means that the search process continues by returning to step #1
|
||||
* with the current annotation or superclass as the class to look for annotations on.
|
||||
* <p>
|
||||
* If the supplied {@code clazz} is an interface, only the interface itself will be checked; the inheritance
|
||||
* hierarchy for interfaces will not be traversed.
|
||||
*
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param annotationType the type of annotation to look for
|
||||
* @return the corresponding annotation descriptor if the annotation was found; otherwise {@code null}
|
||||
* @see AnnotationUtils#findAnnotationDeclaringClass(Class, Class)
|
||||
* @see #findAnnotationDescriptorForTypes(Class, Class...)
|
||||
*/
|
||||
public static <T extends Annotation> AnnotationDescriptor<T> findAnnotationDescriptor(Class<?> clazz,
|
||||
Class<T> annotationType) {
|
||||
return findAnnotationDescriptor(clazz, new HashSet<>(), annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the search algorithm for {@link #findAnnotationDescriptor(Class, Class)}, avoiding endless recursion by
|
||||
* tracking which annotations have already been <em>visited</em>.
|
||||
*
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param visited the set of annotations that have already been visited
|
||||
* @param annotationType the type of annotation to look for
|
||||
* @return the corresponding annotation descriptor if the annotation was found; otherwise {@code null}
|
||||
*/
|
||||
private static <T extends Annotation> AnnotationDescriptor<T> findAnnotationDescriptor(Class<?> clazz,
|
||||
Set<Annotation> visited, Class<T> annotationType) {
|
||||
|
||||
Assert.notNull(annotationType, "Annotation type must not be null");
|
||||
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Declared locally?
|
||||
if (AnnotationUtils.isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||
return new AnnotationDescriptor<>(clazz, clazz.getAnnotation(annotationType));
|
||||
}
|
||||
|
||||
// Declared on a composed annotation (i.e., as a meta-annotation)?
|
||||
for (Annotation composedAnnotation : clazz.getDeclaredAnnotations()) {
|
||||
if (!AnnotationUtils.isInJavaLangAnnotationPackage(composedAnnotation) && visited.add(composedAnnotation)) {
|
||||
AnnotationDescriptor<T> descriptor = findAnnotationDescriptor(composedAnnotation.annotationType(), visited,
|
||||
annotationType);
|
||||
if (descriptor != null) {
|
||||
return new AnnotationDescriptor<>(clazz, descriptor.getDeclaringClass(), composedAnnotation,
|
||||
descriptor.getAnnotation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Declared on a superclass?
|
||||
return findAnnotationDescriptor(clazz.getSuperclass(), visited, annotationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the {@link UntypedAnnotationDescriptor} for the first {@link Class} in the inheritance hierarchy of the
|
||||
* specified {@code clazz} (including the specified {@code clazz} itself) which declares at least one of the
|
||||
* specified {@code annotationTypes}.
|
||||
* <p>
|
||||
* This method traverses the annotations and superclasses of the specified {@code clazz} if no annotation can be
|
||||
* found on the given class itself.
|
||||
* <p>
|
||||
* This method explicitly handles class-level annotations which are not declared as
|
||||
* {@linkplain java.lang.annotation.Inherited inherited} <em>as
|
||||
* well as meta-annotations</em>.
|
||||
* <p>
|
||||
* The algorithm operates as follows:
|
||||
* <ol>
|
||||
* <li>Search for a local declaration of one of the annotation types on the given class and return a corresponding
|
||||
* {@code UntypedAnnotationDescriptor} if found.
|
||||
* <li>Recursively search through all annotations that the given class declares.
|
||||
* <li>Recursively search through the superclass hierarchy of the given class.
|
||||
* </ol>
|
||||
* <p>
|
||||
* In this context, the term <em>recursively</em> means that the search process continues by returning to step #1
|
||||
* with the current annotation or superclass as the class to look for annotations on.
|
||||
* <p>
|
||||
* If the supplied {@code clazz} is an interface, only the interface itself will be checked; the inheritance
|
||||
* hierarchy for interfaces will not be traversed.
|
||||
*
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param annotationTypes the types of annotations to look for
|
||||
* @return the corresponding annotation descriptor if one of the annotations was found; otherwise {@code null}
|
||||
* @see AnnotationUtils#findAnnotationDeclaringClassForTypes(java.util.List, Class)
|
||||
* @see #findAnnotationDescriptor(Class, Class)
|
||||
*/
|
||||
public static UntypedAnnotationDescriptor findAnnotationDescriptorForTypes(Class<?> clazz,
|
||||
Class<? extends Annotation>... annotationTypes) {
|
||||
return findAnnotationDescriptorForTypes(clazz, new HashSet<>(), annotationTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the search algorithm for {@link #findAnnotationDescriptorForTypes(Class, Class...)}, avoiding endless
|
||||
* recursion by tracking which annotations have already been <em>visited</em>.
|
||||
*
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param visited the set of annotations that have already been visited
|
||||
* @param annotationTypes the types of annotations to look for
|
||||
* @return the corresponding annotation descriptor if one of the annotations was found; otherwise {@code null}
|
||||
*/
|
||||
private static UntypedAnnotationDescriptor findAnnotationDescriptorForTypes(Class<?> clazz,
|
||||
Set<Annotation> visited, Class<? extends Annotation>... annotationTypes) {
|
||||
|
||||
assertNonEmptyAnnotationTypeArray(annotationTypes, "The list of annotation types must not be empty");
|
||||
|
||||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Declared locally?
|
||||
for (Class<? extends Annotation> annotationType : annotationTypes) {
|
||||
if (AnnotationUtils.isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||
return new UntypedAnnotationDescriptor(clazz, clazz.getAnnotation(annotationType));
|
||||
}
|
||||
}
|
||||
|
||||
// Declared on a composed annotation (i.e., as a meta-annotation)?
|
||||
for (Annotation composedAnnotation : clazz.getDeclaredAnnotations()) {
|
||||
if (!AnnotationUtils.isInJavaLangAnnotationPackage(composedAnnotation) && visited.add(composedAnnotation)) {
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
composedAnnotation.annotationType(), visited, annotationTypes);
|
||||
if (descriptor != null) {
|
||||
return new UntypedAnnotationDescriptor(clazz, descriptor.getDeclaringClass(), composedAnnotation,
|
||||
descriptor.getAnnotation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Declared on a superclass?
|
||||
return findAnnotationDescriptorForTypes(clazz.getSuperclass(), visited, annotationTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Descriptor for an {@link Annotation}, including the {@linkplain #getDeclaringClass() class} on which the
|
||||
* annotation is <em>declared</em> as well as the actual {@linkplain #getAnnotation() annotation} instance.
|
||||
* <p>
|
||||
* If the annotation is used as a meta-annotation, the descriptor also includes the
|
||||
* {@linkplain #getComposedAnnotation() composed annotation} on which the annotation is present. In such cases, the
|
||||
* <em>root declaring class</em> is not directly annotated with the annotation but rather indirectly via the
|
||||
* composed annotation.
|
||||
* <p>
|
||||
* Given the following example, if we are searching for the {@code @Transactional} annotation <em>on</em> the
|
||||
* {@code TransactionalTests} class, then the properties of the {@code AnnotationDescriptor} would be as follows.
|
||||
* <ul>
|
||||
* <li>rootDeclaringClass: {@code TransactionalTests} class object</li>
|
||||
* <li>declaringClass: {@code TransactionalTests} class object</li>
|
||||
* <li>composedAnnotation: {@code null}</li>
|
||||
* <li>annotation: instance of the {@code Transactional} annotation</li>
|
||||
* </ul>
|
||||
*
|
||||
* <pre style="code">
|
||||
* @Transactional
|
||||
* @ContextConfiguration({ "/test-datasource.xml", "/repository-config.xml" })
|
||||
* public class TransactionalTests {}
|
||||
* </pre>
|
||||
* <p>
|
||||
* Given the following example, if we are searching for the {@code @Transactional} annotation <em>on</em> the
|
||||
* {@code UserRepositoryTests} class, then the properties of the {@code AnnotationDescriptor} would be as follows.
|
||||
* <ul>
|
||||
* <li>rootDeclaringClass: {@code UserRepositoryTests} class object</li>
|
||||
* <li>declaringClass: {@code RepositoryTests} class object</li>
|
||||
* <li>composedAnnotation: instance of the {@code RepositoryTests} annotation</li>
|
||||
* <li>annotation: instance of the {@code Transactional} annotation</li>
|
||||
* </ul>
|
||||
*
|
||||
* <pre style="code">
|
||||
* @Transactional
|
||||
* @ContextConfiguration({ "/test-datasource.xml", "/repository-config.xml" })
|
||||
* @Retention(RetentionPolicy.RUNTIME)
|
||||
* public @interface RepositoryTests {
|
||||
* }
|
||||
*
|
||||
* @RepositoryTests
|
||||
* public class UserRepositoryTests {}
|
||||
* </pre>
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.0
|
||||
*/
|
||||
public static class AnnotationDescriptor<T extends Annotation> {
|
||||
|
||||
private final Class<?> rootDeclaringClass;
|
||||
private final Class<?> declaringClass;
|
||||
private final Annotation composedAnnotation;
|
||||
private final T annotation;
|
||||
private final AnnotationAttributes annotationAttributes;
|
||||
|
||||
public AnnotationDescriptor(Class<?> rootDeclaringClass, T annotation) {
|
||||
this(rootDeclaringClass, rootDeclaringClass, null, annotation);
|
||||
}
|
||||
|
||||
public AnnotationDescriptor(Class<?> rootDeclaringClass, Class<?> declaringClass, Annotation composedAnnotation,
|
||||
T annotation) {
|
||||
Assert.notNull(rootDeclaringClass, "rootDeclaringClass must not be null");
|
||||
Assert.notNull(annotation, "annotation must not be null");
|
||||
|
||||
this.rootDeclaringClass = rootDeclaringClass;
|
||||
this.declaringClass = declaringClass;
|
||||
this.composedAnnotation = composedAnnotation;
|
||||
this.annotation = annotation;
|
||||
this.annotationAttributes = AnnotatedElementUtils.findMergedAnnotationAttributes(rootDeclaringClass,
|
||||
annotation.annotationType(), false, false);
|
||||
}
|
||||
|
||||
public Class<?> getRootDeclaringClass() {
|
||||
return this.rootDeclaringClass;
|
||||
}
|
||||
|
||||
public Class<?> getDeclaringClass() {
|
||||
return this.declaringClass;
|
||||
}
|
||||
|
||||
public T getAnnotation() {
|
||||
return this.annotation;
|
||||
}
|
||||
|
||||
public Class<? extends Annotation> getAnnotationType() {
|
||||
return this.annotation.annotationType();
|
||||
}
|
||||
|
||||
public AnnotationAttributes getAnnotationAttributes() {
|
||||
return this.annotationAttributes;
|
||||
}
|
||||
|
||||
public Annotation getComposedAnnotation() {
|
||||
return this.composedAnnotation;
|
||||
}
|
||||
|
||||
public Class<? extends Annotation> getComposedAnnotationType() {
|
||||
return this.composedAnnotation == null ? null : this.composedAnnotation.annotationType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a textual representation of this {@code AnnotationDescriptor}.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this)//
|
||||
.append("rootDeclaringClass", rootDeclaringClass)//
|
||||
.append("declaringClass", declaringClass)//
|
||||
.append("composedAnnotation", composedAnnotation)//
|
||||
.append("annotation", annotation)//
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <em>Untyped</em> extension of {@code AnnotationDescriptor} that is used to describe the declaration of one of
|
||||
* several candidate annotation types where the actual annotation type cannot be predetermined.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.0
|
||||
*/
|
||||
public static class UntypedAnnotationDescriptor extends AnnotationDescriptor<Annotation> {
|
||||
|
||||
public UntypedAnnotationDescriptor(Class<?> rootDeclaringClass, Annotation annotation) {
|
||||
this(rootDeclaringClass, rootDeclaringClass, null, annotation);
|
||||
}
|
||||
|
||||
public UntypedAnnotationDescriptor(Class<?> rootDeclaringClass, Class<?> declaringClass,
|
||||
Annotation composedAnnotation, Annotation annotation) {
|
||||
super(rootDeclaringClass, declaringClass, composedAnnotation, annotation);
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertNonEmptyAnnotationTypeArray(Class<?>[] annotationTypes, String message) {
|
||||
if (ObjectUtils.isEmpty(annotationTypes)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
|
||||
for (Class<?> clazz : annotationTypes) {
|
||||
if (!Annotation.class.isAssignableFrom(clazz)) {
|
||||
throw new IllegalArgumentException("Array elements must be of type Annotation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2017 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.
|
||||
@@ -48,8 +48,9 @@ public class BasicKeyValuePersistentEntity<T, P extends KeyValuePersistentProper
|
||||
|
||||
String keySpace = AnnotationBasedKeySpaceResolver.INSTANCE.resolveKeySpace(type);
|
||||
|
||||
if (StringUtils.hasText(keySpace))
|
||||
if (StringUtils.hasText(keySpace)) {
|
||||
return keySpace;
|
||||
}
|
||||
|
||||
return (fallback == null ? DEFAULT_FALLBACK_RESOLVER : fallback).resolveKeySpace(type);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
* Copyright 2014-2017 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.
|
||||
@@ -35,6 +35,7 @@ import org.springframework.data.repository.config.AnnotationRepositoryConfigurat
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationSource;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* {@link RepositoryConfigurationExtension} for {@link KeyValueRepository}.
|
||||
@@ -80,7 +81,7 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor
|
||||
*/
|
||||
@Override
|
||||
protected Collection<Class<?>> getIdentifyingTypes() {
|
||||
return Collections.<Class<?>> singleton(KeyValueRepository.class);
|
||||
return Collections.singleton(KeyValueRepository.class);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -109,9 +110,10 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor
|
||||
|
||||
AnnotationMetadata metadata = config.getEnableAnnotationMetadata();
|
||||
|
||||
Map<String, Object> queryCreatorAnnotationAttributes = metadata.getAnnotationAttributes(QueryCreatorType.class.getName());
|
||||
Map<String, Object> queryCreatorAnnotationAttributes = metadata
|
||||
.getAnnotationAttributes(QueryCreatorType.class.getName());
|
||||
|
||||
if (queryCreatorAnnotationAttributes == null) {
|
||||
if (CollectionUtils.isEmpty(queryCreatorAnnotationAttributes)) {
|
||||
return SpelQueryCreator.class;
|
||||
}
|
||||
|
||||
@@ -130,7 +132,8 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor
|
||||
|
||||
AnnotationMetadata metadata = config.getEnableAnnotationMetadata();
|
||||
|
||||
Map<String, Object> queryCreatorAnnotationAttributes = metadata.getAnnotationAttributes(QueryCreatorType.class.getName());
|
||||
Map<String, Object> queryCreatorAnnotationAttributes = metadata
|
||||
.getAnnotationAttributes(QueryCreatorType.class.getName());
|
||||
|
||||
if (queryCreatorAnnotationAttributes == null) {
|
||||
return KeyValuePartTreeQuery.class;
|
||||
@@ -163,7 +166,8 @@ public abstract class KeyValueRepositoryConfigurationExtension extends Repositor
|
||||
AbstractBeanDefinition beanDefinition = getDefaultKeyValueTemplateBeanDefinition(configurationSource);
|
||||
|
||||
if (beanDefinition != null) {
|
||||
registerIfNotAlreadyRegistered(beanDefinition, registry, keyValueTemplateName.get(), configurationSource.getSource());
|
||||
registerIfNotAlreadyRegistered(beanDefinition, registry, keyValueTemplateName.get(),
|
||||
configurationSource.getSource());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public class KeyValuePartTreeQuery implements RepositoryQuery {
|
||||
query.setRows(instance.getRows());
|
||||
}
|
||||
|
||||
query.setSort(sort == null || sort.isUnsorted() ? instance.getSort() : sort);
|
||||
query.setSort(sort.isUnsorted() ? instance.getSort() : sort);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
@@ -154,12 +154,7 @@ public class SimpleKeyValueRepository<T, ID> implements KeyValueRepository<T, ID
|
||||
List<T> result = new ArrayList<>();
|
||||
|
||||
for (ID id : ids) {
|
||||
|
||||
Optional<T> candidate = findById(id);
|
||||
|
||||
if (candidate.isPresent()) {
|
||||
result.add(candidate.get());
|
||||
}
|
||||
findById(id).ifPresent(result::add);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.keyvalue;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
|
||||
/**
|
||||
* Custom composed {@link Persistent} annotation using {@link KeySpace} on name attribute.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Persistent
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
public @interface CustomKeySpaceAnnotation {
|
||||
|
||||
@KeySpace
|
||||
String name() default "";
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2017 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.
|
||||
@@ -18,10 +18,13 @@ package org.springframework.data.keyvalue;
|
||||
import org.springframework.data.keyvalue.annotation.KeySpace;
|
||||
|
||||
/**
|
||||
* Class that inherits its {@link KeySpace} from a super class annotated with a custom {@link CustomKeySpaceAnnotation} annotation.
|
||||
* Class that inherits its {@link KeySpace} from a super class annotated with a custom {@link CustomKeySpaceAnnotation}
|
||||
* annotation.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class SubclassOfTypeWithCustomComposedKeySpaceAnnotation extends TypeWithCustomComposedKeySpaceAnnotation {
|
||||
public class SubclassOfTypeWithCustomComposedKeySpaceAnnotation
|
||||
extends TypeWithCustomComposedKeySpaceAnnotationUsingAliasFor {
|
||||
|
||||
public SubclassOfTypeWithCustomComposedKeySpaceAnnotation(String name) {
|
||||
super(name);
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.keyvalue;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* A {@link Persistent} type with {@link CustomKeySpaceAnnotation}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@CustomKeySpaceAnnotation(name = "aliased")
|
||||
public class TypeWithCustomComposedKeySpaceAnnotation {
|
||||
|
||||
@Id String id;
|
||||
String name;
|
||||
|
||||
public TypeWithCustomComposedKeySpaceAnnotation(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.id);
|
||||
result = prime * result + ObjectUtils.nullSafeHashCode(this.name);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof TypeWithCustomComposedKeySpaceAnnotation)) {
|
||||
return false;
|
||||
}
|
||||
TypeWithCustomComposedKeySpaceAnnotation other = (TypeWithCustomComposedKeySpaceAnnotation) obj;
|
||||
if (!ObjectUtils.nullSafeEquals(this.id, other.id)) {
|
||||
return false;
|
||||
}
|
||||
if (!ObjectUtils.nullSafeEquals(this.name, other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public class KeyValuePersistenceExceptionTranslatorUnitTests {
|
||||
instanceOf(DataRetrievalFailureException.class));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-525
|
||||
@Test(expected = IllegalArgumentException.class) // DATACMNS-525, DATAKV-192
|
||||
public void translateExeptionShouldReturnNullWhenGivenNull() {
|
||||
assertThat(translator.translateExceptionIfPossible(null), nullValue());
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.util.Optional;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
@@ -261,12 +262,13 @@ public class KeyValueTemplateTests {
|
||||
|
||||
}
|
||||
|
||||
@KeySpace
|
||||
@Persistent
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
static @interface ExplicitKeySpace {
|
||||
@interface ExplicitKeySpace {
|
||||
|
||||
@KeySpace
|
||||
@AliasFor(annotation = KeySpace.class, value = "value")
|
||||
String name() default "";
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.springframework.data.keyvalue.core;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -35,7 +34,6 @@ import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
@@ -43,7 +41,6 @@ import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.keyvalue.SubclassOfTypeWithCustomComposedKeySpaceAnnotation;
|
||||
import org.springframework.data.keyvalue.TypeWithCustomComposedKeySpaceAnnotation;
|
||||
import org.springframework.data.keyvalue.TypeWithCustomComposedKeySpaceAnnotationUsingAliasFor;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent;
|
||||
import org.springframework.data.keyvalue.core.event.KeyValueEvent.AfterDeleteEvent;
|
||||
@@ -70,11 +67,9 @@ public class KeyValueTemplateUnitTests {
|
||||
|
||||
private static final Foo FOO_ONE = new Foo("one");
|
||||
private static final Foo FOO_TWO = new Foo("two");
|
||||
private static final TypeWithCustomComposedKeySpaceAnnotation ALIASED = new TypeWithCustomComposedKeySpaceAnnotation(
|
||||
"super");
|
||||
private static final TypeWithCustomComposedKeySpaceAnnotationUsingAliasFor ALIASED_USING_ALIAS_FOR = new TypeWithCustomComposedKeySpaceAnnotationUsingAliasFor(
|
||||
"super");
|
||||
private static final SubclassOfTypeWithCustomComposedKeySpaceAnnotation SUBCLASS_OF_ALIASED = new SubclassOfTypeWithCustomComposedKeySpaceAnnotation(
|
||||
private static final SubclassOfTypeWithCustomComposedKeySpaceAnnotation SUBCLASS_OF_ALIASED_USING_ALIAS_FOR = new SubclassOfTypeWithCustomComposedKeySpaceAnnotation(
|
||||
"sub");
|
||||
private static final KeyValueQuery<String> STRING_QUERY = new KeyValueQuery<>("foo == 'two'");
|
||||
|
||||
@@ -300,34 +295,35 @@ public class KeyValueTemplateUnitTests {
|
||||
@Test // DATACMNS-525
|
||||
public void insertShouldRespectTypeAlias() {
|
||||
|
||||
template.insert("1", ALIASED);
|
||||
template.insert("1", ALIASED_USING_ALIAS_FOR);
|
||||
|
||||
verify(adapterMock, times(1)).put("1", ALIASED, "aliased");
|
||||
verify(adapterMock, times(1)).put("1", ALIASED_USING_ALIAS_FOR, "aliased");
|
||||
}
|
||||
|
||||
@Test // DATACMNS-525
|
||||
public void insertShouldRespectTypeAliasOnSubClass() {
|
||||
|
||||
template.insert("1", SUBCLASS_OF_ALIASED);
|
||||
template.insert("1", SUBCLASS_OF_ALIASED_USING_ALIAS_FOR);
|
||||
|
||||
verify(adapterMock, times(1)).put("1", SUBCLASS_OF_ALIASED, "aliased");
|
||||
verify(adapterMock, times(1)).put("1", SUBCLASS_OF_ALIASED_USING_ALIAS_FOR, "aliased");
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test // DATACMNS-525
|
||||
public void findAllOfShouldRespectTypeAliasAndFilterNonMatchingTypes() {
|
||||
|
||||
Collection foo = Arrays.asList(ALIASED, SUBCLASS_OF_ALIASED);
|
||||
Collection foo = Arrays.asList(ALIASED_USING_ALIAS_FOR, SUBCLASS_OF_ALIASED_USING_ALIAS_FOR);
|
||||
when(adapterMock.getAllOf("aliased")).thenReturn(foo);
|
||||
|
||||
assertThat(template.findAll(SUBCLASS_OF_ALIASED.getClass()), containsInAnyOrder(SUBCLASS_OF_ALIASED));
|
||||
assertThat(template.findAll(SUBCLASS_OF_ALIASED_USING_ALIAS_FOR.getClass()),
|
||||
containsInAnyOrder(SUBCLASS_OF_ALIASED_USING_ALIAS_FOR));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-525
|
||||
public void insertSouldRespectTypeAliasAndFilterNonMatching() {
|
||||
|
||||
template.insert("1", ALIASED);
|
||||
assertThat(template.findById("1", SUBCLASS_OF_ALIASED.getClass()), is(Optional.empty()));
|
||||
template.insert("1", ALIASED_USING_ALIAS_FOR);
|
||||
assertThat(template.findById("1", SUBCLASS_OF_ALIASED_USING_ALIAS_FOR.getClass()), is(Optional.empty()));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class) // DATACMNS-525
|
||||
@@ -359,7 +355,7 @@ public class KeyValueTemplateUnitTests {
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void shouldNotPublishEventsWhenEventsToPublishIsSetToEmptyList() {
|
||||
|
||||
template.setEventTypesToPublish(Collections.<Class<? extends KeyValueEvent>> emptySet());
|
||||
template.setEventTypesToPublish(Collections.emptySet());
|
||||
|
||||
template.insert("1", FOO_ONE);
|
||||
|
||||
@@ -371,7 +367,7 @@ public class KeyValueTemplateUnitTests {
|
||||
|
||||
template.insert("1", FOO_ONE);
|
||||
|
||||
verify(publisherMock, atLeastOnce()).publishEvent(Matchers.any(KeyValueEvent.class));
|
||||
verify(publisherMock, atLeastOnce()).publishEvent(any());
|
||||
}
|
||||
|
||||
@Test // DATAKV-91, DATAKV-104
|
||||
@@ -400,7 +396,7 @@ public class KeyValueTemplateUnitTests {
|
||||
|
||||
assertThat(captor.getValue().getKey(), is("1"));
|
||||
assertThat(captor.getValue().getKeyspace(), is(Foo.class.getName()));
|
||||
assertThat(captor.getValue().getPayload(), is((Object) FOO_ONE));
|
||||
assertThat(captor.getValue().getPayload(), is(FOO_ONE));
|
||||
}
|
||||
|
||||
@Test // DATAKV-91, DATAKV-104, DATAKV-187
|
||||
|
||||
@@ -35,8 +35,8 @@ public class SpelPropertyComperatorUnitTests {
|
||||
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
private static final SomeType ONE = new SomeType("one", Integer.valueOf(1), 1);
|
||||
private static final SomeType TWO = new SomeType("two", Integer.valueOf(2), 2);
|
||||
private static final SomeType ONE = new SomeType("one", 1, 1);
|
||||
private static final SomeType TWO = new SomeType("two", 2, 2);
|
||||
private static final WrapperType WRAPPER_ONE = new WrapperType("w-one", ONE);
|
||||
private static final WrapperType WRAPPER_TWO = new WrapperType("w-two", TWO);
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.keyvalue.core;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -52,11 +52,6 @@ public class AnnotationBasedKeySpaceResolverUnitTests {
|
||||
assertThat(resolver.resolveKeySpace(EntityWithDefaultKeySpace.class), is("daenerys"));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-525
|
||||
public void shouldResolveKeySpaceCorrectly() {
|
||||
assertThat(resolver.resolveKeySpace(EntityWithSetKeySpace.class), is("viserys"));
|
||||
}
|
||||
|
||||
@Test // DATAKV-105
|
||||
public void shouldReturnNullWhenNoKeySpaceFoundOnComposedPersistentAnnotation() {
|
||||
assertThat(resolver.resolveKeySpace(TypeWithInhteritedPersistentAnnotationNotHavingKeySpace.class), nullValue());
|
||||
@@ -92,40 +87,24 @@ public class AnnotationBasedKeySpaceResolverUnitTests {
|
||||
assertThat(resolver.resolveKeySpace(EntityWithInheritedKeySpaceUsingAliasFor.class), is("viserys"));
|
||||
}
|
||||
|
||||
@PersistentAnnotationWithExplicitKeySpace
|
||||
@PersistentAnnotationWithExplicitKeySpaceUsingAliasFor
|
||||
static class EntityWithDefaultKeySpace {
|
||||
|
||||
}
|
||||
|
||||
@PersistentAnnotationWithExplicitKeySpace(firstname = "viserys")
|
||||
static class EntityWithSetKeySpace {
|
||||
|
||||
}
|
||||
|
||||
static class EntityWithInheritedKeySpace extends EntityWithSetKeySpace {
|
||||
|
||||
}
|
||||
|
||||
@PersistentAnnotationWithExplicitKeySpace(firstname = "viserys")
|
||||
@PersistentAnnotationWithExplicitKeySpaceUsingAliasFor(firstname = "viserys")
|
||||
static class EntityWithSetKeySpaceUsingAliasFor {
|
||||
|
||||
}
|
||||
|
||||
static class EntityWithInheritedKeySpace extends EntityWithSetKeySpaceUsingAliasFor {
|
||||
|
||||
}
|
||||
|
||||
static class EntityWithInheritedKeySpaceUsingAliasFor extends EntityWithSetKeySpaceUsingAliasFor {
|
||||
|
||||
}
|
||||
|
||||
@Persistent
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
static @interface PersistentAnnotationWithExplicitKeySpace {
|
||||
|
||||
@KeySpace
|
||||
String firstname() default "daenerys";
|
||||
|
||||
String lastnamne() default "targaryen";
|
||||
}
|
||||
|
||||
@Persistent
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
|
||||
@@ -17,9 +17,6 @@ package org.springframework.data.keyvalue.repository;
|
||||
|
||||
import static org.hamcrest.core.Is.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.data.keyvalue.repository.query;
|
||||
import static org.hamcrest.core.IsNot.*;
|
||||
import static org.hamcrest.core.IsSame.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -314,7 +314,7 @@ public class SpelQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
private Evaluation evaluate(String methodName, Object... args) throws Exception {
|
||||
return new Evaluation((SpelExpression) createQueryForMethodWithArgs(methodName, args).getCriteria());
|
||||
return new Evaluation(createQueryForMethodWithArgs(methodName, args).getCriteria());
|
||||
}
|
||||
|
||||
private KeyValueQuery<SpelExpression> createQueryForMethodWithArgs(String methodName, Object... args)
|
||||
|
||||
@@ -70,7 +70,7 @@ public class KeyValueQuerydslUtilsUnitTests {
|
||||
OrderSpecifier<?>[] specifiers = toOrderSpecifier(sort, builder);
|
||||
|
||||
assertThat(specifiers,
|
||||
IsArrayContainingInOrder.<OrderSpecifier<?>> arrayContaining(QPerson.person.firstname.asc()));
|
||||
IsArrayContainingInOrder.arrayContaining(QPerson.person.firstname.asc()));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-525
|
||||
@@ -81,7 +81,7 @@ public class KeyValueQuerydslUtilsUnitTests {
|
||||
OrderSpecifier<?>[] specifiers = toOrderSpecifier(sort, builder);
|
||||
|
||||
assertThat(specifiers,
|
||||
IsArrayContainingInOrder.<OrderSpecifier<?>> arrayContaining(QPerson.person.firstname.desc()));
|
||||
IsArrayContainingInOrder.arrayContaining(QPerson.person.firstname.desc()));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-525
|
||||
@@ -91,7 +91,7 @@ public class KeyValueQuerydslUtilsUnitTests {
|
||||
|
||||
OrderSpecifier<?>[] specifiers = toOrderSpecifier(sort, builder);
|
||||
|
||||
assertThat(specifiers, IsArrayContainingInOrder.<OrderSpecifier<?>> arrayContaining(QPerson.person.firstname.desc(),
|
||||
assertThat(specifiers, IsArrayContainingInOrder.arrayContaining(QPerson.person.firstname.desc(),
|
||||
QPerson.person.age.asc()));
|
||||
}
|
||||
|
||||
@@ -103,6 +103,6 @@ public class KeyValueQuerydslUtilsUnitTests {
|
||||
OrderSpecifier<?>[] specifiers = toOrderSpecifier(sort, builder);
|
||||
|
||||
assertThat(specifiers,
|
||||
IsArrayContainingInOrder.<OrderSpecifier<?>> arrayContaining(QPerson.person.firstname.desc().nullsLast()));
|
||||
IsArrayContainingInOrder.arrayContaining(QPerson.person.firstname.desc().nullsLast()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class QuerydslKeyValueRepositoryUnitTests extends AbstractRepositoryUnitT
|
||||
assertThat(page1.getContent(), hasSize(1));
|
||||
assertThat(page1.hasNext(), is(true));
|
||||
|
||||
Page<Person> page2 = ((QPersonRepository) repository).findAll(QPerson.person.age.eq(CERSEI.getAge()),
|
||||
Page<Person> page2 = repository.findAll(QPerson.person.age.eq(CERSEI.getAge()),
|
||||
page1.nextPageable());
|
||||
|
||||
assertThat(page2.getTotalElements(), is(2L));
|
||||
|
||||
Reference in New Issue
Block a user