DATACMNS-1108 - Polishing.
Move loop to Set lookup, update Javadoc and remove unused imports. Original Pull Request: #454
This commit is contained in:
@@ -28,9 +28,12 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.spel.EvaluationContextExtensionInformation.ExtensionTypeInformation.PublicMethodAndFieldFilter;
|
||||
import org.springframework.data.spel.ExpressionDependencies.ExpressionDependency;
|
||||
import org.springframework.data.spel.spi.EvaluationContextExtension;
|
||||
import org.springframework.data.spel.spi.Function;
|
||||
import org.springframework.data.util.Streamable;
|
||||
@@ -102,14 +105,13 @@ class EvaluationContextExtensionInformation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@literal true} if this extension provides {@link ExpressionDependencies.ExpressionDependency}.
|
||||
* Return {@literal true} if this extension provides {@link ExpressionDependency}.
|
||||
*
|
||||
* @param dependency the expression dependency.
|
||||
* @return {@literal true} if {@link ExpressionDependencies.ExpressionDependency} is provided by this root object or
|
||||
* the extension itself.
|
||||
* @return {@literal true} if {@link ExpressionDependency} is provided by this root object or the extension itself.
|
||||
* @since 2.4
|
||||
*/
|
||||
public boolean provides(ExpressionDependencies.ExpressionDependency dependency) {
|
||||
public boolean provides(ExpressionDependency dependency) {
|
||||
|
||||
// We don't know, extension declares Object getRootObject
|
||||
if (!rootObjectInformation.isPresent()) {
|
||||
@@ -159,13 +161,13 @@ class EvaluationContextExtensionInformation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@literal true} if this extension provides {@link ExpressionDependencies.ExpressionDependency}.
|
||||
* Return {@literal true} if this extension provides {@link ExpressionDependency}.
|
||||
*
|
||||
* @param dependency the expression dependency.
|
||||
* @return {@literal true} if {@link ExpressionDependencies.ExpressionDependency} is provided by this root object.
|
||||
* @return {@literal true} if {@link ExpressionDependency} is provided by this root object.
|
||||
* @since 2.4
|
||||
*/
|
||||
public boolean provides(ExpressionDependencies.ExpressionDependency dependency) {
|
||||
public boolean provides(ExpressionDependency dependency) {
|
||||
|
||||
if (dependency.isPropertyOrField()) {
|
||||
return properties.containsKey(dependency.getSymbol());
|
||||
@@ -199,12 +201,12 @@ class EvaluationContextExtensionInformation {
|
||||
|
||||
static class PublicMethodAndFieldFilter implements MethodFilter, FieldFilter {
|
||||
|
||||
public static final PublicMethodAndFieldFilter STATIC = new PublicMethodAndFieldFilter(true);
|
||||
public static final PublicMethodAndFieldFilter NON_STATIC = new PublicMethodAndFieldFilter(false);
|
||||
static final PublicMethodAndFieldFilter STATIC = new PublicMethodAndFieldFilter(true);
|
||||
static final PublicMethodAndFieldFilter NON_STATIC = new PublicMethodAndFieldFilter(false);
|
||||
|
||||
private final boolean staticOnly;
|
||||
|
||||
public PublicMethodAndFieldFilter(boolean staticOnly) {
|
||||
PublicMethodAndFieldFilter(boolean staticOnly) {
|
||||
this.staticOnly = staticOnly;
|
||||
}
|
||||
|
||||
@@ -251,7 +253,7 @@ class EvaluationContextExtensionInformation {
|
||||
private static final RootObjectInformation NONE = new RootObjectInformation(Object.class);
|
||||
|
||||
private final Map<String, Method> accessors;
|
||||
private final Collection<Method> methods;
|
||||
private final Methods methods;
|
||||
private final Collection<Field> fields;
|
||||
|
||||
/**
|
||||
@@ -260,12 +262,12 @@ class EvaluationContextExtensionInformation {
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
*/
|
||||
public RootObjectInformation(Class<?> type) {
|
||||
RootObjectInformation(Class<?> type) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
|
||||
this.accessors = new HashMap<>();
|
||||
this.methods = new HashSet<>();
|
||||
this.methods = new Methods();
|
||||
this.fields = new ArrayList<>();
|
||||
|
||||
if (Object.class.equals(type)) {
|
||||
@@ -293,7 +295,7 @@ class EvaluationContextExtensionInformation {
|
||||
* @param target can be {@literal null}.
|
||||
* @return the methods
|
||||
*/
|
||||
public MultiValueMap<String, Function> getFunctions(Optional<Object> target) {
|
||||
MultiValueMap<String, Function> getFunctions(Optional<Object> target) {
|
||||
return target.map(this::getFunctions).orElseGet(LinkedMultiValueMap::new);
|
||||
}
|
||||
|
||||
@@ -307,7 +309,7 @@ class EvaluationContextExtensionInformation {
|
||||
*
|
||||
* @return the properties
|
||||
*/
|
||||
public Map<String, Object> getProperties(Optional<Object> target) {
|
||||
Map<String, Object> getProperties(Optional<Object> target) {
|
||||
|
||||
return target.map(it -> {
|
||||
|
||||
@@ -323,12 +325,17 @@ class EvaluationContextExtensionInformation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this root object information provides {@link ExpressionDependencies.ExpressionDependency}.
|
||||
* Returns whether this root object information provides {@link ExpressionDependency}.
|
||||
*
|
||||
* @param dependency the expression dependency.
|
||||
* @return {@literal true} if {@link ExpressionDependencies.ExpressionDependency} is provided by this root object.
|
||||
* @return {@literal true} if {@link ExpressionDependency} is provided by this root object.
|
||||
* @since 2.4
|
||||
*/
|
||||
public boolean provides(ExpressionDependencies.ExpressionDependency dependency) {
|
||||
boolean provides(ExpressionDependency dependency) {
|
||||
|
||||
if (!dependency.isMethod() && !dependency.isPropertyOrField()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dependency.isPropertyOrField()) {
|
||||
|
||||
@@ -346,14 +353,7 @@ class EvaluationContextExtensionInformation {
|
||||
}
|
||||
|
||||
if (dependency.isMethod()) {
|
||||
|
||||
for (Method method : methods) {
|
||||
if (method.getName().equals(dependency.getSymbol())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return methods.containsMethodName(dependency.getSymbol());
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -369,4 +369,34 @@ class EvaluationContextExtensionInformation {
|
||||
|
||||
return map.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.4
|
||||
* @author Christpoh Strobl
|
||||
*/
|
||||
static class Methods {
|
||||
|
||||
private final Collection<Method> methods;
|
||||
private final Set<String> methodNames;
|
||||
|
||||
Methods() {
|
||||
|
||||
this.methods = new HashSet<>();
|
||||
this.methodNames = new HashSet<>();
|
||||
}
|
||||
|
||||
void add(Method method) {
|
||||
|
||||
methods.add(method);
|
||||
methodNames.add(method.getName());
|
||||
}
|
||||
|
||||
boolean containsMethodName(String name) {
|
||||
return methodNames.contains(name);
|
||||
}
|
||||
|
||||
public Stream<Method> stream() {
|
||||
return methods.stream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.spel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -37,6 +38,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* Value object capturing dependencies to a method or property/field that is referenced from a SpEL expression.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
* @since 2.4
|
||||
*/
|
||||
public class ExpressionDependencies implements Streamable<ExpressionDependencies.ExpressionDependency> {
|
||||
@@ -52,12 +54,47 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
|
||||
/**
|
||||
* Return an empty {@link ExpressionDependencies} object.
|
||||
*
|
||||
* @return the empty dependencies.
|
||||
* @return empty dependencies.
|
||||
*/
|
||||
public static ExpressionDependencies empty() {
|
||||
public static ExpressionDependencies none() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an {@link ExpressionDependencies} object representing the given {@link Collection} of
|
||||
* {@link ExpressionDependency dependencies}.
|
||||
*
|
||||
* @return {@link ExpressionDependencies} holding the given {@link ExpressionDependency dependencies} or
|
||||
* {@link ExpressionDependencies#none() none} if the collection is {@link Collection#isEmpty() empty}.
|
||||
*/
|
||||
public static ExpressionDependencies of(Collection<ExpressionDependency> dependencies) {
|
||||
|
||||
if (dependencies.isEmpty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
return new ExpressionDependencies(new ArrayList<>(new LinkedHashSet<>(dependencies)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an {@link ExpressionDependencies} object representing the merged collection of {@link ExpressionDependency
|
||||
* dependencies} withing the given {@link ExpressionDependencies} collection.
|
||||
*
|
||||
* @return {@link ExpressionDependencies} holding a set of merged {@link ExpressionDependency dependencies} or
|
||||
* {@link ExpressionDependencies#none() none} if the given {@link Iterable} is {@link Collection#isEmpty()
|
||||
* empty}.
|
||||
*/
|
||||
public static ExpressionDependencies merged(Iterable<ExpressionDependencies> dependencies) {
|
||||
|
||||
if (!dependencies.iterator().hasNext()) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
List<ExpressionDependency> dependencySet = new ArrayList<>();
|
||||
dependencies.forEach(it -> dependencySet.addAll(it.dependencies));
|
||||
return ExpressionDependencies.of(dependencySet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover all expression dependencies that are referenced in the {@link SpelNode expression root}.
|
||||
*
|
||||
@@ -65,7 +102,7 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
|
||||
* @return a set of {@link ExpressionDependencies}.
|
||||
*/
|
||||
public static ExpressionDependencies discover(Expression expression) {
|
||||
return expression instanceof SpelExpression ? discover(((SpelExpression) expression).getAST(), true) : empty();
|
||||
return expression instanceof SpelExpression ? discover(((SpelExpression) expression).getAST(), true) : none();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,6 +208,7 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
|
||||
private final int nestLevel;
|
||||
|
||||
private ExpressionDependency(DependencyType type, String symbol, int nestLevel) {
|
||||
|
||||
this.symbol = symbol;
|
||||
this.nestLevel = nestLevel;
|
||||
this.type = type;
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* An {@link EvaluationContextProvider} that assembles an {@link EvaluationContext} from a list of
|
||||
@@ -64,7 +65,7 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class ExtensionAwareEvaluationContextProvider implements EvaluationContextProvider {
|
||||
|
||||
private final Map<Class<?>, EvaluationContextExtensionInformation> extensionInformationCache = new ConcurrentHashMap<>();
|
||||
private final Map<String, EvaluationContextExtensionInformation> extensionInformationCache = new ConcurrentHashMap<>();
|
||||
private final Lazy<? extends Collection<? extends ExtensionIdAware>> extensions;
|
||||
|
||||
private ListableBeanFactory beanFactory;
|
||||
@@ -181,7 +182,7 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex
|
||||
* @return
|
||||
*/
|
||||
EvaluationContextExtensionInformation getOrCreateInformation(Class<? extends EvaluationContextExtension> extension) {
|
||||
return extensionInformationCache.computeIfAbsent(extension,
|
||||
return extensionInformationCache.computeIfAbsent(ClassUtils.getUserClass(extension).getName(),
|
||||
type -> new EvaluationContextExtensionInformation(extension));
|
||||
}
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@ package org.springframework.data.spel.spi;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* SPI to allow adding a set of properties and function definitions accessible via the root of an
|
||||
* {@link EvaluationContext} provided by a {@link ExtensionAwareQueryMethodEvaluationContextProvider}.
|
||||
* {@link EvaluationContext} provided by an
|
||||
* {@link org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider}.
|
||||
* <p>
|
||||
* Extensions can be ordered by following Spring's {@link org.springframework.core.Ordered} conventions.
|
||||
*
|
||||
|
||||
@@ -29,7 +29,7 @@ public interface ExtensionIdAware {
|
||||
* Return the identifier of the extension. The id can be leveraged by users to fully qualify property lookups and thus
|
||||
* overcome ambiguities in case multiple extensions expose properties with the same name.
|
||||
*
|
||||
* @return the extension id, must not be {@literal null}.
|
||||
* @return the extension id, never {@literal null}.
|
||||
*/
|
||||
String getExtensionId();
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ package org.springframework.data.spel.spi;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
|
||||
/**
|
||||
* SPI to resolve a {@link EvaluationContextExtension} to make it accessible via the root of an
|
||||
* {@link EvaluationContext} provided by a {@link ExtensionAwareQueryMethodEvaluationContextProvider}.
|
||||
* {@link EvaluationContext} provided by a
|
||||
* {@link org.springframework.data.repository.query.ExtensionAwareQueryMethodEvaluationContextProvider}.
|
||||
* <p>
|
||||
* Extensions can be ordered by following Spring's {@link org.springframework.core.Ordered} conventions.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user