Browse Source

DATACMNS-867 - Rework utility classes.

Removed the additional methods that reflectively checked for the Stream type and whether a Method instance is a default method. Turned utility classes into interfaces where possible. Make use of Lombok's @UtilityClass where not.

Removed obsolete implementation class in StreamUtils in favor of a lambda.
pull/194/head
Oliver Gierke 9 years ago
parent
commit
1c60ea8d36
  1. 2
      src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java
  2. 4
      src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java
  3. 3
      src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java
  4. 7
      src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java
  5. 4
      src/main/java/org/springframework/data/repository/query/QueryMethod.java
  6. 22
      src/main/java/org/springframework/data/util/CastUtils.java
  7. 7
      src/main/java/org/springframework/data/util/ParsingUtils.java
  8. 73
      src/main/java/org/springframework/data/util/ReflectionUtils.java
  9. 54
      src/main/java/org/springframework/data/util/StreamUtils.java

2
src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java

@ -57,7 +57,7 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor @@ -57,7 +57,7 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor
Method method = invocation.getMethod();
if (!org.springframework.data.util.ReflectionUtils.isDefaultMethod(method)) {
if (!method.isDefault()) {
return invocation.proceed();
}

4
src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java

@ -19,6 +19,7 @@ import java.lang.reflect.Method; @@ -19,6 +19,7 @@ import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Stream;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
@ -28,7 +29,6 @@ import org.springframework.data.repository.util.QueryExecutionConverters; @@ -28,7 +29,6 @@ import org.springframework.data.repository.util.QueryExecutionConverters;
import org.springframework.data.repository.util.ReactiveWrappers;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@ -140,7 +140,7 @@ public abstract class AbstractRepositoryMetadata implements RepositoryMetadata { @@ -140,7 +140,7 @@ public abstract class AbstractRepositoryMetadata implements RepositoryMetadata {
Class<?> rawType = type.getType();
boolean needToUnwrap = Iterable.class.isAssignableFrom(rawType) || rawType.isArray()
|| QueryExecutionConverters.supports(rawType) || ReflectionUtils.isJava8StreamType(rawType);
|| QueryExecutionConverters.supports(rawType) || Stream.class.isAssignableFrom(rawType);
return needToUnwrap ? unwrapWrapperTypes(type.getRequiredComponentType()) : rawType;
}

3
src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java

@ -43,7 +43,6 @@ import org.springframework.data.repository.core.CrudMethods; @@ -43,7 +43,6 @@ import org.springframework.data.repository.core.CrudMethods;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.Streamable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -185,7 +184,7 @@ class DefaultRepositoryInformation implements RepositoryInformation { @@ -185,7 +184,7 @@ class DefaultRepositoryInformation implements RepositoryInformation {
* @return
*/
private boolean isQueryMethodCandidate(Method method) {
return !method.isBridge() && !ReflectionUtils.isDefaultMethod(method) //
return !method.isBridge() && !method.isDefault() //
&& !Modifier.isStatic(method.getModifiers()) //
&& (isQueryAnnotationPresentOn(method) || !isCustomMethod(method) && !isBaseClassMethod(method));
}

7
src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java

@ -364,9 +364,10 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, @@ -364,9 +364,10 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
Class<?> baseClass = information.getRepositoryBaseClass();
Optional<Constructor<?>> constructor = ReflectionUtils.findConstructor(baseClass, constructorArguments);
return constructor.map(it -> (R) BeanUtils.instantiateClass(it, constructorArguments)).orElseThrow(() -> new IllegalStateException(String.format(
"No suitable constructor found on %s to match the given arguments: %s. Make sure you implement a constructor taking these",
baseClass, Arrays.stream(constructorArguments).map(Object::getClass).collect(Collectors.toList()))));
return constructor.map(it -> (R) BeanUtils.instantiateClass(it, constructorArguments))
.orElseThrow(() -> new IllegalStateException(String.format(
"No suitable constructor found on %s to match the given arguments: %s. Make sure you implement a constructor taking these",
baseClass, Arrays.stream(constructorArguments).map(Object::getClass).collect(Collectors.toList()))));
}
/**

4
src/main/java/org/springframework/data/repository/query/QueryMethod.java

@ -19,6 +19,7 @@ import static org.springframework.data.repository.util.ClassUtils.*; @@ -19,6 +19,7 @@ import static org.springframework.data.repository.util.ClassUtils.*;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.stream.Stream;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@ -30,7 +31,6 @@ import org.springframework.data.repository.core.RepositoryMetadata; @@ -30,7 +31,6 @@ import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.util.QueryExecutionConverters;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@ -232,7 +232,7 @@ public class QueryMethod { @@ -232,7 +232,7 @@ public class QueryMethod {
* @since 1.10
*/
public boolean isStreamQuery() {
return ReflectionUtils.isJava8StreamType(unwrappedReturnType);
return Stream.class.isAssignableFrom(unwrappedReturnType);
}
/**

22
src/main/java/org/springframework/data/util/CastUtils.java

@ -1,12 +1,24 @@ @@ -1,12 +1,24 @@
/*
* Copyright 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.
* 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.experimental.UtilityClass;
@UtilityClass
public class CastUtils {
public interface CastUtils {
@SuppressWarnings("unchecked")
public <T> T cast(Object object) {
public static <T> T cast(Object object) {
return (T) object;
}
}

7
src/main/java/org/springframework/data/util/ParsingUtils.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.util;
import lombok.experimental.UtilityClass;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -29,7 +31,8 @@ import org.springframework.util.StringUtils; @@ -29,7 +31,8 @@ import org.springframework.util.StringUtils;
* @author Oliver Gierke
* @since 1.5
*/
public abstract class ParsingUtils {
@UtilityClass
public class ParsingUtils {
private static final String UPPER = "\\p{Lu}|\\P{InBASIC_LATIN}";
private static final String LOWER = "\\p{Ll}";
@ -38,8 +41,6 @@ public abstract class ParsingUtils { @@ -38,8 +41,6 @@ public abstract class ParsingUtils {
private static final Pattern CAMEL_CASE = Pattern.compile(CAMEL_CASE_REGEX);
private ParsingUtils() {}
/**
* Splits up the given camel-case {@link String}.
*

73
src/main/java/org/springframework/data/util/ReflectionUtils.java

@ -17,12 +17,12 @@ package org.springframework.data.util; @@ -17,12 +17,12 @@ package org.springframework.data.util;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.experimental.UtilityClass;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
@ -45,22 +45,8 @@ import org.springframework.util.ReflectionUtils.FieldFilter; @@ -45,22 +45,8 @@ import org.springframework.util.ReflectionUtils.FieldFilter;
* @author Christoph Strobl
* @since 1.5
*/
public abstract class ReflectionUtils {
private static final Class<?> JAVA8_STREAM_TYPE;
static {
Class<?> cls = null;
try {
cls = Class.forName("java.util.stream.Stream");
} catch (ClassNotFoundException ignore) {}
JAVA8_STREAM_TYPE = cls;
}
private ReflectionUtils() {}
@UtilityClass
public class ReflectionUtils {
/**
* Creates an instance of the class with the given fully qualified name or returns the given default instance if the
@ -81,18 +67,6 @@ public abstract class ReflectionUtils { @@ -81,18 +67,6 @@ public abstract class ReflectionUtils {
}
}
/**
* Back-port of Java 8's {@code isDefault()} method on {@link Method}.
*
* @param method must not be {@literal null}.
* @return
*/
public static boolean isDefaultMethod(Method method) {
return ((method.getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == Modifier.PUBLIC)
&& method.getDeclaringClass().isInterface();
}
/**
* A {@link FieldFilter} that has a description.
*
@ -227,21 +201,6 @@ public abstract class ReflectionUtils { @@ -227,21 +201,6 @@ public abstract class ReflectionUtils {
org.springframework.util.ReflectionUtils.setField(field, target, value);
}
/**
* Tests whether the given type is assignable to a Java 8 {@link Stream}.
*
* @param type can be {@literal null}.
* @return
*/
public static boolean isJava8StreamType(Class<?> type) {
if (type == null || JAVA8_STREAM_TYPE == null) {
return false;
}
return JAVA8_STREAM_TYPE.isAssignableFrom(type);
}
/**
* Finds a constructor on the given type that matches the given constructor arguments.
*
@ -276,15 +235,31 @@ public abstract class ReflectionUtils { @@ -276,15 +235,31 @@ public abstract class ReflectionUtils {
return Stream.concat(returnType, parameterTypes);
}
/**
* Returns the {@link Method} with the given name and parameters declared on the given type, if available.
*
* @param type must not be {@literal null}.
* @param name must not be {@literal null} or empty.
* @param parameterTypes must not be {@literal null}.
* @return
* @since 2.0
*/
public static Optional<Method> getMethod(Class<?> type, String name, ResolvableType... parameterTypes) {
List<Class<?>> collect = Arrays.stream(parameterTypes).map(ResolvableType::getRawClass).collect(Collectors.toList());
Assert.notNull(type, "Type must not be null!");
Assert.hasText(name, "Name must not be null or empty!");
Assert.notNull(parameterTypes, "Parameter types must not be null!");
List<Class<?>> collect = Arrays.stream(parameterTypes)//
.map(ResolvableType::getRawClass)//
.collect(Collectors.toList());
Optional<Method> method = Optional.ofNullable(
org.springframework.util.ReflectionUtils.findMethod(type, name, collect.toArray(new Class<?>[collect.size()])));
Method method = org.springframework.util.ReflectionUtils.findMethod(type, name,
collect.toArray(new Class<?>[collect.size()]));
return method.filter(it -> IntStream.range(0, it.getParameterCount())//
.allMatch(index -> ResolvableType.forMethodParameter(it, index).equals(parameterTypes[index])));
return Optional.ofNullable(method)//
.filter(it -> IntStream.range(0, it.getParameterCount())//
.allMatch(index -> ResolvableType.forMethodParameter(it, index).equals(parameterTypes[index])));
}
private static boolean argumentsMatch(Class<?>[] parameterTypes, Object[] arguments) {

54
src/main/java/org/springframework/data/util/StreamUtils.java

@ -1,5 +1,5 @@ @@ -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.
@ -30,9 +30,7 @@ import org.springframework.util.Assert; @@ -30,9 +30,7 @@ import org.springframework.util.Assert;
* @author Oliver Gierke
* @since 1.10
*/
public class StreamUtils {
private StreamUtils() {}
public interface StreamUtils {
/**
* Returns a {@link Stream} backed by the given {@link Iterator}.
@ -51,50 +49,8 @@ public class StreamUtils { @@ -51,50 +49,8 @@ public class StreamUtils {
Spliterator<T> spliterator = Spliterators.spliteratorUnknownSize(iterator, Spliterator.NONNULL);
Stream<T> stream = StreamSupport.stream(spliterator, false);
return iterator instanceof CloseableIterator
? stream.onClose(new CloseableIteratorDisposingRunnable((CloseableIterator<T>) iterator)) : stream;
}
/**
* A {@link Runnable} that closes the given {@link CloseableIterator} in its {@link #run()} method. If the given
* {@code closeable} is {@literal null} the {@link #run()} method effectively becomes a noop.
* <p>
* Can be used in conjunction with streams as close action via:
*
* <pre>
* CloseableIterator<T> result = ...;
* Spliterator<T> spliterator = ...;
*
* return StreamSupport.stream(spliterator, false).onClose(new CloseableIteratorDisposingRunnable(result));
* </pre>
*
* @author Thomas Darimont
* @author Oliver Gierke
* @since 1.10
*/
private static class CloseableIteratorDisposingRunnable implements Runnable {
private CloseableIterator<?> closeable;
/**
* Creates a new {@link CloseableIteratorDisposingRunnable} for the given {@link CloseableIterator}.
*
* @param closeable can be {@literal null}.
*/
public CloseableIteratorDisposingRunnable(CloseableIterator<?> closeable) {
this.closeable = closeable;
}
/*
* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if (closeable != null) {
closeable.close();
}
}
return iterator instanceof CloseableIterator//
? stream.onClose(() -> ((CloseableIterator<T>) iterator).close()) //
: stream;
}
}

Loading…
Cancel
Save