Evolve ValueExpressionParser.
Introduce literal, expression and placeholder variants. Add parser for composite expressions. Closes #2369 Original pull request: #3036
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
|
||||
/**
|
||||
* Composite {@link ValueExpression} consisting of multiple placeholder, SpEL, and literal expressions.
|
||||
*
|
||||
* @param raw
|
||||
* @param expressions
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
record CompositeValueExpression(String raw, List<ValueExpression> expressions) implements ValueExpression {
|
||||
|
||||
@Override
|
||||
public String getExpressionString() {
|
||||
return raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionDependencies getExpressionDependencies() {
|
||||
|
||||
ExpressionDependencies dependencies = ExpressionDependencies.none();
|
||||
|
||||
for (ValueExpression expression : expressions) {
|
||||
ExpressionDependencies dependency = expression.getExpressionDependencies();
|
||||
if (!dependency.equals(ExpressionDependencies.none())) {
|
||||
dependencies = dependencies.mergeWith(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLiteral() {
|
||||
|
||||
for (ValueExpression expression : expressions) {
|
||||
if (!expression.isLiteral()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String evaluate(ValueEvaluationContext context) {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
for (ValueExpression expression : expressions) {
|
||||
builder.append((String) expression.evaluate(context));
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
|
||||
/**
|
||||
* Default {@link ValueEvaluationContext}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
record DefaultValueEvaluationContext(Environment environment,
|
||||
EvaluationContext evaluationContext) implements ValueEvaluationContext {
|
||||
|
||||
@Override
|
||||
public Environment getEnvironment() {
|
||||
return environment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvaluationContext getEvaluationContext() {
|
||||
return evaluationContext();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.expression.ParserContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.SystemPropertyUtils;
|
||||
|
||||
/**
|
||||
* Default {@link ValueExpressionParser} implementation. Instances are thread-safe.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
class DefaultValueExpressionParser implements ValueExpressionParser {
|
||||
|
||||
public static final String PLACEHOLDER_PREFIX = SystemPropertyUtils.PLACEHOLDER_PREFIX;
|
||||
public static final String EXPRESSION_PREFIX = ParserContext.TEMPLATE_EXPRESSION.getExpressionPrefix();
|
||||
public static final char SUFFIX = '}';
|
||||
public static final int PLACEHOLDER_PREFIX_LENGTH = PLACEHOLDER_PREFIX.length();
|
||||
public static final char[] QUOTE_CHARS = { '\'', '"' };
|
||||
|
||||
private final ValueParserConfiguration configuration;
|
||||
|
||||
public DefaultValueExpressionParser(ValueParserConfiguration configuration) {
|
||||
|
||||
Assert.notNull(configuration, "ValueParserConfiguration must not be null");
|
||||
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueExpression parse(String expressionString) {
|
||||
|
||||
int placerholderIndex = expressionString.indexOf(PLACEHOLDER_PREFIX);
|
||||
int expressionIndex = expressionString.indexOf(EXPRESSION_PREFIX);
|
||||
|
||||
if (placerholderIndex == -1 && expressionIndex == -1) {
|
||||
return new LiteralValueExpression(expressionString);
|
||||
}
|
||||
|
||||
if (placerholderIndex != -1 && expressionIndex == -1
|
||||
&& findPlaceholderEndIndex(expressionString, placerholderIndex) != expressionString.length()) {
|
||||
return createPlaceholder(expressionString);
|
||||
}
|
||||
|
||||
if (placerholderIndex == -1
|
||||
&& findPlaceholderEndIndex(expressionString, expressionIndex) != expressionString.length()) {
|
||||
return createExpression(expressionString);
|
||||
}
|
||||
|
||||
return parseComposite(expressionString, placerholderIndex, expressionIndex);
|
||||
}
|
||||
|
||||
private CompositeValueExpression parseComposite(String expressionString, int placerholderIndex, int expressionIndex) {
|
||||
|
||||
List<ValueExpression> expressions = new ArrayList<>(PLACEHOLDER_PREFIX_LENGTH);
|
||||
int startIndex = getStartIndex(placerholderIndex, expressionIndex);
|
||||
|
||||
if (startIndex != 0) {
|
||||
expressions.add(new LiteralValueExpression(expressionString.substring(0, startIndex)));
|
||||
}
|
||||
|
||||
while (startIndex != -1) {
|
||||
|
||||
int endIndex = findPlaceholderEndIndex(expressionString, startIndex);
|
||||
|
||||
if (endIndex == -1) {
|
||||
throw new ParseException(expressionString, startIndex,
|
||||
"No ending suffix '}' for expression starting at character %d: %s".formatted(startIndex,
|
||||
expressionString.substring(startIndex)));
|
||||
}
|
||||
|
||||
int afterClosingParenthesisIndex = endIndex + 1;
|
||||
String part = expressionString.substring(startIndex, afterClosingParenthesisIndex);
|
||||
|
||||
if (part.startsWith(PLACEHOLDER_PREFIX)) {
|
||||
expressions.add(createPlaceholder(part));
|
||||
} else {
|
||||
expressions.add(createExpression(part));
|
||||
}
|
||||
|
||||
placerholderIndex = expressionString.indexOf(PLACEHOLDER_PREFIX, endIndex);
|
||||
expressionIndex = expressionString.indexOf(EXPRESSION_PREFIX, endIndex);
|
||||
|
||||
startIndex = getStartIndex(placerholderIndex, expressionIndex);
|
||||
|
||||
if (startIndex == -1) {
|
||||
// no next expression but we're capturing everything after the expression as literal.
|
||||
expressions.add(new LiteralValueExpression(expressionString.substring(afterClosingParenthesisIndex)));
|
||||
} else {
|
||||
// capture literal after the expression ends and before the next starts.
|
||||
expressions
|
||||
.add(new LiteralValueExpression(expressionString.substring(afterClosingParenthesisIndex, startIndex)));
|
||||
}
|
||||
}
|
||||
|
||||
return new CompositeValueExpression(expressionString, expressions);
|
||||
}
|
||||
|
||||
private static int getStartIndex(int placerholderIndex, int expressionIndex) {
|
||||
return placerholderIndex != -1 && expressionIndex != -1 ? Math.min(placerholderIndex, expressionIndex)
|
||||
: placerholderIndex != -1 ? placerholderIndex : expressionIndex;
|
||||
}
|
||||
|
||||
private PlaceholderExpression createPlaceholder(String part) {
|
||||
return new PlaceholderExpression(part);
|
||||
}
|
||||
|
||||
private ExpressionExpression createExpression(String expression) {
|
||||
|
||||
Expression expr = configuration.getExpressionParser().parseExpression(expression,
|
||||
ParserContext.TEMPLATE_EXPRESSION);
|
||||
ExpressionDependencies dependencies = ExpressionDependencies.discover(expr);
|
||||
return new ExpressionExpression(expr, dependencies);
|
||||
}
|
||||
|
||||
private static int findPlaceholderEndIndex(CharSequence buf, int startIndex) {
|
||||
|
||||
int index = startIndex + PLACEHOLDER_PREFIX_LENGTH;
|
||||
char quotationChar = 0;
|
||||
char nestingLevel = 0;
|
||||
boolean skipEscape = false;
|
||||
|
||||
while (index < buf.length()) {
|
||||
|
||||
char c = buf.charAt(index);
|
||||
|
||||
if (!skipEscape && c == '\\') {
|
||||
skipEscape = true;
|
||||
} else if (skipEscape) {
|
||||
skipEscape = false;
|
||||
} else if (quotationChar == 0) {
|
||||
|
||||
for (char quoteChar : QUOTE_CHARS) {
|
||||
if (quoteChar == c) {
|
||||
quotationChar = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (quotationChar == c) {
|
||||
quotationChar = 0;
|
||||
}
|
||||
|
||||
if (!skipEscape && quotationChar == 0) {
|
||||
|
||||
if (nestingLevel != 0 && c == SUFFIX) {
|
||||
nestingLevel--;
|
||||
} else if (c == '{') {
|
||||
nestingLevel++;
|
||||
} else if (nestingLevel == 0 && c == SUFFIX) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
|
||||
/**
|
||||
* SpEL expression.
|
||||
*
|
||||
* @param expression
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
record ExpressionExpression(Expression expression, ExpressionDependencies dependencies) implements ValueExpression {
|
||||
|
||||
@Override
|
||||
public String getExpressionString() {
|
||||
return expression.getExpressionString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionDependencies getExpressionDependencies() {
|
||||
return dependencies();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLiteral() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(ValueEvaluationContext context) {
|
||||
|
||||
EvaluationContext evaluationContext = context.getEvaluationContext();
|
||||
if (evaluationContext != null) {
|
||||
return expression.getValue(evaluationContext);
|
||||
}
|
||||
return expression.getValue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
/**
|
||||
* Literal expression returning the underlying expression string upon evaluation.
|
||||
*
|
||||
* @param expression
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
record LiteralValueExpression(String expression) implements ValueExpression {
|
||||
|
||||
@Override
|
||||
public String getExpressionString() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLiteral() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String evaluate(ValueEvaluationContext context) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
|
||||
/**
|
||||
* Property placeholder expression evaluated against a {@link Environment}.
|
||||
*
|
||||
* @param expression
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
record PlaceholderExpression(String expression) implements ValueExpression {
|
||||
|
||||
@Override
|
||||
public String getExpressionString() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLiteral() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(ValueEvaluationContext context) {
|
||||
|
||||
Environment environment = context.getEnvironment();
|
||||
if (environment != null) {
|
||||
try {
|
||||
return environment.resolveRequiredPlaceholders(expression);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new EvaluationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Expressions are executed in an evaluation context. It is in this context that references are resolved when
|
||||
* encountered during expression evaluation.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
public interface ValueEvaluationContext {
|
||||
|
||||
/**
|
||||
* Returns a new {@link ValueEvaluationContext}.
|
||||
*
|
||||
* @param environment
|
||||
* @param evaluationContext
|
||||
* @return a new {@link ValueEvaluationContext} for the given environment and evaluation context.
|
||||
*/
|
||||
static ValueEvaluationContext of(Environment environment, EvaluationContext evaluationContext) {
|
||||
return new DefaultValueEvaluationContext(environment, evaluationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Environment} if provided.
|
||||
*
|
||||
* @return the {@link Environment} or {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
Environment getEnvironment();
|
||||
|
||||
/**
|
||||
* Returns the {@link EvaluationContext} if provided.
|
||||
*
|
||||
* @return the {@link EvaluationContext} or {@literal null}.
|
||||
*/
|
||||
@Nullable
|
||||
EvaluationContext getEvaluationContext();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
|
||||
/**
|
||||
* SPI to provide to access a centrally defined potentially shared {@link ValueEvaluationContext}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
public interface ValueEvaluationContextProvider {
|
||||
|
||||
/**
|
||||
* Return a {@link EvaluationContext} built using the given parameter values.
|
||||
*
|
||||
* @param rootObject the root object to set in the {@link EvaluationContext}.
|
||||
* @return
|
||||
*/
|
||||
ValueEvaluationContext getEvaluationContext(Object rootObject);
|
||||
|
||||
/**
|
||||
* Return a tailored {@link EvaluationContext} built using the given parameter values and considering
|
||||
* {@link ExpressionDependencies expression dependencies}. The returned {@link EvaluationContext} may contain a
|
||||
* reduced visibility of methods and properties/fields according to the required {@link ExpressionDependencies
|
||||
* expression dependencies}.
|
||||
*
|
||||
* @param rootObject the root object to set in the {@link EvaluationContext}.
|
||||
* @param dependencies the requested expression dependencies to be available.
|
||||
* @return
|
||||
*/
|
||||
default ValueEvaluationContext getEvaluationContext(Object rootObject, ExpressionDependencies dependencies) {
|
||||
return getEvaluationContext(rootObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* An expression capable of evaluating itself against context objects. Encapsulates the details of a previously parsed
|
||||
* expression string. Provides a common abstraction for expression evaluation.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
public interface ValueExpression {
|
||||
|
||||
/**
|
||||
* Returns the original string used to create this expression (unmodified).
|
||||
*
|
||||
* @return the original expression string.
|
||||
*/
|
||||
String getExpressionString();
|
||||
|
||||
/**
|
||||
* Returns the expression dependencies.
|
||||
*
|
||||
* @return the dependencies the underlying expression requires. Can be {@link ExpressionDependencies#none()}.
|
||||
*/
|
||||
default ExpressionDependencies getExpressionDependencies() {
|
||||
return ExpressionDependencies.none();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the expression is a literal expression (that doesn't actually require evaluation).
|
||||
*
|
||||
* @return {@code true} if the expression is a literal expression; {@code false} if the expression can yield a
|
||||
* different result upon {@link #evaluate(ValueEvaluationContext) evaluation}.
|
||||
*/
|
||||
boolean isLiteral();
|
||||
|
||||
/**
|
||||
* Evaluates this expression using the given evaluation context.
|
||||
*
|
||||
* @return the evaluation result.
|
||||
* @throws EvaluationException if there is a problem during evaluation
|
||||
*/
|
||||
@Nullable
|
||||
Object evaluate(ValueEvaluationContext context) throws EvaluationException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import org.springframework.expression.ParseException;
|
||||
|
||||
/**
|
||||
* Parses expression strings into expressions that can be evaluated. Supports parsing expression, configuration
|
||||
* templates as well as literal strings.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
public interface ValueExpressionParser {
|
||||
|
||||
/**
|
||||
* Creates a new parser to parse expression strings.
|
||||
*
|
||||
* @param configuration the parser context configuration.
|
||||
* @return the parser instance.
|
||||
*/
|
||||
static ValueExpressionParser create(ValueParserConfiguration configuration) {
|
||||
return new DefaultValueExpressionParser(configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the expression string and return an Expression object you can use for repeated evaluation.
|
||||
* <p>
|
||||
* Some examples:
|
||||
*
|
||||
* <pre class="code">
|
||||
* #{3 + 4}
|
||||
* #{name.firstName}
|
||||
* ${key.one}
|
||||
* #{name.lastName}-${key.one}
|
||||
* </pre>
|
||||
*
|
||||
* @param expressionString the raw expression string to parse.
|
||||
* @return an evaluator for the parsed expression.
|
||||
* @throws ParseException an exception occurred during parsing.
|
||||
*/
|
||||
ValueExpression parse(String expressionString) throws ParseException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.expression;
|
||||
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
|
||||
/**
|
||||
* Configuration for {@link ValueExpressionParser}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
public interface ValueParserConfiguration {
|
||||
|
||||
/**
|
||||
* Parser for {@link org.springframework.expression.Expression SpEL expressions}.
|
||||
*
|
||||
* @return for {@link org.springframework.expression.Expression SpEL expressions}.
|
||||
*/
|
||||
ExpressionParser getExpressionParser();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Value Expression implementation.
|
||||
*/
|
||||
@org.springframework.lang.NonNullApi
|
||||
package org.springframework.data.expression;
|
||||
@@ -39,11 +39,11 @@ public class Parameter<T, P extends PersistentProperty<P>> {
|
||||
private final @Nullable String name;
|
||||
private final TypeInformation<T> type;
|
||||
private final MergedAnnotations annotations;
|
||||
private final String key;
|
||||
private final @Nullable String expression;
|
||||
private final @Nullable PersistentEntity<T, P> entity;
|
||||
|
||||
private final Lazy<Boolean> enclosingClassCache;
|
||||
private final Lazy<Boolean> hasSpelExpression;
|
||||
private final Lazy<Boolean> hasExpression;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Parameter} with the given name, {@link TypeInformation} as well as an array of
|
||||
@@ -64,7 +64,7 @@ public class Parameter<T, P extends PersistentProperty<P>> {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.annotations = MergedAnnotations.from(annotations);
|
||||
this.key = getValue(this.annotations);
|
||||
this.expression = getValue(this.annotations);
|
||||
this.entity = entity;
|
||||
|
||||
this.enclosingClassCache = Lazy.of(() -> {
|
||||
@@ -77,7 +77,7 @@ public class Parameter<T, P extends PersistentProperty<P>> {
|
||||
return ClassUtils.isInnerClass(owningType) && type.getType().equals(owningType.getEnclosingClass());
|
||||
});
|
||||
|
||||
this.hasSpelExpression = Lazy.of(() -> StringUtils.hasText(getSpelExpression()));
|
||||
this.hasExpression = Lazy.of(() -> StringUtils.hasText(getValueExpression()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -128,21 +128,62 @@ public class Parameter<T, P extends PersistentProperty<P>> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key to be used when looking up a source data structure to populate the actual parameter value.
|
||||
* Returns the expression to be used when looking up a source data structure to populate the actual parameter value.
|
||||
*
|
||||
* @return
|
||||
* @return the expression to be used when looking up a source data structure.
|
||||
* @deprecated since 3.3, use {@link #getValueExpression()} instead.
|
||||
*/
|
||||
@Nullable
|
||||
public String getSpelExpression() {
|
||||
return key;
|
||||
return getValueExpression();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expression to be used when looking up a source data structure to populate the actual parameter value.
|
||||
*
|
||||
* @return the expression to be used when looking up a source data structure.
|
||||
* @since 3.3
|
||||
*/
|
||||
@Nullable
|
||||
public String getValueExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required expression to be used when looking up a source data structure to populate the actual parameter
|
||||
* value or throws {@link IllegalStateException} if there's no expression.
|
||||
*
|
||||
* @return the expression to be used when looking up a source data structure.
|
||||
* @since 3.3
|
||||
*/
|
||||
public String getRequiredValueExpression() {
|
||||
|
||||
if (!hasValueExpression()) {
|
||||
throw new IllegalStateException("No expression associated with this parameter");
|
||||
}
|
||||
|
||||
return getValueExpression();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the constructor parameter is equipped with a SpEL expression.
|
||||
*
|
||||
* @return
|
||||
* @return {@literal true}} if the parameter is equipped with a SpEL expression.
|
||||
* @deprecated since 3.3, use {@link #hasValueExpression()} instead.
|
||||
*/
|
||||
@Deprecated(since = "3.3")
|
||||
public boolean hasSpelExpression() {
|
||||
return this.hasSpelExpression.get();
|
||||
return hasValueExpression();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the constructor parameter is equipped with a value expression.
|
||||
*
|
||||
* @return {@literal true}} if the parameter is equipped with a value expression.
|
||||
* @since 3.3
|
||||
*/
|
||||
public boolean hasValueExpression() {
|
||||
return this.hasExpression.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,12 +198,12 @@ public class Parameter<T, P extends PersistentProperty<P>> {
|
||||
}
|
||||
|
||||
return Objects.equals(this.name, that.name) && Objects.equals(this.type, that.type)
|
||||
&& Objects.equals(this.key, that.key) && Objects.equals(this.entity, that.entity);
|
||||
&& Objects.equals(this.expression, that.expression) && Objects.equals(this.entity, that.entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, type, key, entity);
|
||||
return Objects.hash(name, type, expression, entity);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,10 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
@@ -44,7 +47,6 @@ import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.KotlinDetector;
|
||||
import org.springframework.core.NativeDetector;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.data.domain.ManagedTypes;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
@@ -52,7 +54,6 @@ import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyPath;
|
||||
import org.springframework.data.mapping.PersistentPropertyPaths;
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
import org.springframework.data.mapping.model.AbstractPersistentProperty;
|
||||
import org.springframework.data.mapping.model.BeanWrapperPropertyAccessorFactory;
|
||||
import org.springframework.data.mapping.model.ClassGeneratingPropertyAccessorFactory;
|
||||
import org.springframework.data.mapping.model.EntityInstantiators;
|
||||
@@ -63,7 +64,6 @@ import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.spel.EvaluationContextProvider;
|
||||
import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider;
|
||||
import org.springframework.data.support.EnvironmentAccessor;
|
||||
import org.springframework.data.util.KotlinReflectionUtils;
|
||||
import org.springframework.data.util.NullableWrapperConverters;
|
||||
import org.springframework.data.util.Optionals;
|
||||
@@ -94,7 +94,8 @@ import org.springframework.util.ReflectionUtils.FieldFilter;
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?, P>, P extends PersistentProperty<P>>
|
||||
implements MappingContext<E, P>, ApplicationEventPublisherAware, ApplicationContextAware, InitializingBean, EnvironmentAware {
|
||||
implements MappingContext<E, P>, ApplicationEventPublisherAware, ApplicationContextAware, BeanFactoryAware,
|
||||
EnvironmentAware, InitializingBean {
|
||||
|
||||
private static final Log LOGGER = LogFactory.getLog(MappingContext.class);
|
||||
|
||||
@@ -105,7 +106,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
private @Nullable ApplicationEventPublisher applicationEventPublisher;
|
||||
private EvaluationContextProvider evaluationContextProvider = EvaluationContextProvider.DEFAULT;
|
||||
private @Nullable EnvironmentAccessor environmentAccessor;
|
||||
private @Nullable Environment environment;
|
||||
|
||||
private ManagedTypes managedTypes = ManagedTypes.empty();
|
||||
|
||||
@@ -134,18 +135,47 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application context. Sets also {@link ApplicationEventPublisher} and {@link Environment} if these weren't
|
||||
* already set.
|
||||
*
|
||||
* @param applicationContext the ApplicationContext object to be used by this object.
|
||||
* @throws BeansException
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
||||
this.evaluationContextProvider = new ExtensionAwareEvaluationContextProvider(applicationContext);
|
||||
setBeanFactory(applicationContext);
|
||||
|
||||
if (applicationEventPublisher == null) {
|
||||
if (this.applicationEventPublisher == null) {
|
||||
this.applicationEventPublisher = applicationContext;
|
||||
}
|
||||
|
||||
if (this.environment == null) {
|
||||
this.environment = applicationContext.getEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param beanFactory owning BeanFactory.
|
||||
* @throws BeansException
|
||||
* @since 3.3
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
|
||||
if (beanFactory instanceof ListableBeanFactory lbf) {
|
||||
this.evaluationContextProvider = new ExtensionAwareEvaluationContextProvider(lbf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param environment the {@code Environment} that this component runs in.
|
||||
* @since 3.3
|
||||
*/
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environmentAccessor = new DelegatingEnvironmentAccessor(environment);
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,7 +183,6 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
*
|
||||
* @param initialEntitySet
|
||||
* @see #setManagedTypes(ManagedTypes)
|
||||
*
|
||||
*/
|
||||
public void setInitialEntitySet(Set<? extends Class<?>> initialEntitySet) {
|
||||
setManagedTypes(ManagedTypes.fromIterable(initialEntitySet));
|
||||
@@ -210,6 +239,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public E getPersistentEntity(Class<?> type) {
|
||||
return getPersistentEntity(TypeInformation.of(type));
|
||||
@@ -416,7 +446,9 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
E entity = createPersistentEntity(userTypeInformation);
|
||||
entity.setEvaluationContextProvider(evaluationContextProvider);
|
||||
entity.setEnvironmentAccessor(environmentAccessor);
|
||||
if (environment != null) {
|
||||
entity.setEnvironment(environment);
|
||||
}
|
||||
|
||||
// Eagerly cache the entity as we might have to find it during recursive lookups.
|
||||
persistentEntities.put(userTypeInformation, Optional.of(entity));
|
||||
@@ -488,10 +520,6 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
|
||||
if(this.environmentAccessor == null) {
|
||||
this.environmentAccessor = new DelegatingEnvironmentAccessor(new StandardEnvironment());
|
||||
}
|
||||
initialize();
|
||||
}
|
||||
|
||||
@@ -594,9 +622,6 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
return;
|
||||
}
|
||||
|
||||
if(property instanceof AbstractPersistentProperty<?> pp) {
|
||||
pp.setEnvironmentAccessor(environmentAccessor);
|
||||
}
|
||||
entity.addPersistentProperty(property);
|
||||
|
||||
if (property.isAssociation()) {
|
||||
@@ -795,31 +820,4 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 3.3
|
||||
*/
|
||||
public static class DelegatingEnvironmentAccessor implements EnvironmentAccessor {
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
static EnvironmentAccessor standard() {
|
||||
return new DelegatingEnvironmentAccessor(new StandardEnvironment());
|
||||
}
|
||||
|
||||
public DelegatingEnvironmentAccessor(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
return environment.getProperty(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolvePlaceholders(String text) {
|
||||
return environment.resolvePlaceholders(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.util.stream.Collectors;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.support.EnvironmentAccessor;
|
||||
import org.springframework.data.util.KotlinReflectionUtils;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.ReflectionUtils;
|
||||
@@ -75,9 +74,6 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
private final Lazy<Boolean> readable;
|
||||
private final boolean immutable;
|
||||
|
||||
|
||||
private @Nullable EnvironmentAccessor environmentAccessor;
|
||||
|
||||
public AbstractPersistentProperty(Property property, PersistentEntity<?, P> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
|
||||
@@ -310,14 +306,6 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
|
||||
return targetType == null ? information.getRequiredActualType() : targetType;
|
||||
}
|
||||
|
||||
protected EnvironmentAccessor getEnvironmentAccessor() {
|
||||
return environmentAccessor;
|
||||
}
|
||||
|
||||
public void setEnvironmentAccessor(EnvironmentAccessor environmentAccessor) {
|
||||
this.environmentAccessor = environmentAccessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
|
||||
@@ -37,8 +37,6 @@ import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.support.EnvironmentAccessor;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.Optionals;
|
||||
import org.springframework.data.util.ReflectionUtils;
|
||||
@@ -198,10 +196,12 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
|
||||
return isTransient.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdProperty() {
|
||||
return isId.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionProperty() {
|
||||
return isVersion.get();
|
||||
}
|
||||
@@ -227,6 +227,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
|
||||
* @param annotationType must not be {@literal null}.
|
||||
* @return {@literal null} if annotation type not found on property.
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public <A extends Annotation> A findAnnotation(Class<A> annotationType) {
|
||||
|
||||
@@ -268,6 +269,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
|
||||
* @param annotationType the annotation type to look up.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
|
||||
return doFindAnnotation(annotationType).isPresent();
|
||||
}
|
||||
|
||||
@@ -30,13 +30,14 @@ import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.annotation.Immutable;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
import org.springframework.data.domain.Persistable;
|
||||
import org.springframework.data.expression.ValueEvaluationContext;
|
||||
import org.springframework.data.mapping.*;
|
||||
import org.springframework.data.spel.EvaluationContextProvider;
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
import org.springframework.data.support.EnvironmentAccessor;
|
||||
import org.springframework.data.support.IsNewStrategy;
|
||||
import org.springframework.data.support.PersistableIsNewStrategy;
|
||||
import org.springframework.data.util.Lazy;
|
||||
@@ -80,7 +81,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
private @Nullable P versionProperty;
|
||||
private PersistentPropertyAccessorFactory propertyAccessorFactory;
|
||||
private EvaluationContextProvider evaluationContextProvider = EvaluationContextProvider.DEFAULT;
|
||||
private @Nullable EnvironmentAccessor environmentAccessor;
|
||||
private @Nullable Environment environment = null;
|
||||
|
||||
private final Lazy<Alias> typeAlias;
|
||||
private final Lazy<IsNewStrategy> isNewStrategy;
|
||||
@@ -148,36 +149,44 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return creator != null && creator.isCreatorParameter(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdProperty(PersistentProperty<?> property) {
|
||||
return idProperty != null && idProperty.equals(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersionProperty(PersistentProperty<?> property) {
|
||||
return versionProperty != null && versionProperty.equals(property);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getType().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public P getIdProperty() {
|
||||
return idProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public P getVersionProperty() {
|
||||
return versionProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIdProperty() {
|
||||
return idProperty != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasVersionProperty() {
|
||||
return versionProperty != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPersistentProperty(P property) {
|
||||
|
||||
Assert.notNull(property, "Property must not be null");
|
||||
@@ -220,9 +229,13 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
this.evaluationContextProvider = provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param environment the {@code Environment} that this component runs in.
|
||||
* @since 3.3
|
||||
*/
|
||||
@Override
|
||||
public void setEnvironmentAccessor(EnvironmentAccessor accessor) {
|
||||
this.environmentAccessor = accessor;
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,6 +261,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
return property;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAssociation(Association<P> association) {
|
||||
|
||||
Assert.notNull(association, "Association must not be null");
|
||||
@@ -283,18 +297,22 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
.filter(it -> it.isAnnotationPresent(annotationType)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getType() {
|
||||
return information.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getTypeAlias() {
|
||||
return typeAlias.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeInformation<T> getTypeInformation() {
|
||||
return information;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWithProperties(PropertyHandler<P> handler) {
|
||||
|
||||
Assert.notNull(handler, "PropertyHandler must not be null");
|
||||
@@ -314,6 +332,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWithAssociations(AssociationHandler<P> handler) {
|
||||
|
||||
Assert.notNull(handler, "Handler must not be null");
|
||||
@@ -323,6 +342,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWithAssociations(SimpleAssociationHandler handler) {
|
||||
|
||||
Assert.notNull(handler, "Handler must not be null");
|
||||
@@ -350,6 +370,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
it -> Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(getType(), it)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify() {
|
||||
|
||||
if (comparator != null) {
|
||||
@@ -449,14 +470,26 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the {@link EnvironmentAccessor} providing access to the current
|
||||
* {@link org.springframework.core.env.Environment}.
|
||||
* Obtain a {@link ValueEvaluationContext} for a {@code rootObject}.
|
||||
*
|
||||
* @return never {@literal null}.
|
||||
* @param rootObject must not be {@literal null}.
|
||||
* @return the evaluation context including all potential extensions.
|
||||
* @since 3.3
|
||||
*/
|
||||
protected EnvironmentAccessor getEnvironmentAccessor() {
|
||||
return environmentAccessor;
|
||||
protected ValueEvaluationContext getValueEvaluationContext(Object rootObject) {
|
||||
return ValueEvaluationContext.of(this.environment, getEvaluationContext(rootObject));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a {@link ValueEvaluationContext} for a {@code rootObject} given {@link ExpressionDependencies}.
|
||||
*
|
||||
* @param rootObject must not be {@literal null}.
|
||||
* @param dependencies must not be {@literal null}.
|
||||
* @return the evaluation context with extensions loaded that satisfy {@link ExpressionDependencies}.
|
||||
* @since 3.3
|
||||
*/
|
||||
protected ValueEvaluationContext getValueEvaluationContext(Object rootObject, ExpressionDependencies dependencies) {
|
||||
return ValueEvaluationContext.of(this.environment, getEvaluationContext(rootObject, dependencies));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -534,6 +567,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(@Nullable Association<P> left, @Nullable Association<P> right) {
|
||||
|
||||
if (left == null) {
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2024 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
|
||||
*
|
||||
* https://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.mapping.model;
|
||||
|
||||
import org.springframework.core.env.EnvironmentCapable;
|
||||
import org.springframework.data.expression.ValueEvaluationContext;
|
||||
import org.springframework.data.expression.ValueEvaluationContextProvider;
|
||||
import org.springframework.data.expression.ValueExpression;
|
||||
import org.springframework.data.expression.ValueExpressionParser;
|
||||
import org.springframework.data.spel.EvaluationContextProvider;
|
||||
import org.springframework.data.spel.ExpressionDependencies;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ConcurrentLruCache;
|
||||
|
||||
/**
|
||||
* Factory to create a ValueExpressionEvaluator
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
public class CachingValueExpressionEvaluatorFactory implements ValueEvaluationContextProvider {
|
||||
|
||||
private final ConcurrentLruCache<String, ValueExpression> expressionCache;
|
||||
private final EnvironmentCapable environmentProvider;
|
||||
private final EvaluationContextProvider evaluationContextProvider;
|
||||
|
||||
public CachingValueExpressionEvaluatorFactory(ExpressionParser expressionParser,
|
||||
EnvironmentCapable environmentProvider, EvaluationContextProvider evaluationContextProvider) {
|
||||
this(expressionParser, environmentProvider, evaluationContextProvider, 256);
|
||||
}
|
||||
|
||||
public CachingValueExpressionEvaluatorFactory(ExpressionParser expressionParser,
|
||||
EnvironmentCapable environmentProvider, EvaluationContextProvider evaluationContextProvider, int cacheSize) {
|
||||
|
||||
Assert.notNull(expressionParser, "ExpressionParser must not be null");
|
||||
|
||||
ValueExpressionParser parser = ValueExpressionParser.create(() -> expressionParser);
|
||||
this.expressionCache = new ConcurrentLruCache<>(cacheSize, parser::parse);
|
||||
this.environmentProvider = environmentProvider;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueEvaluationContext getEvaluationContext(Object rootObject) {
|
||||
return ValueEvaluationContext.of(environmentProvider.getEnvironment(),
|
||||
evaluationContextProvider.getEvaluationContext(rootObject));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueEvaluationContext getEvaluationContext(Object rootObject, ExpressionDependencies dependencies) {
|
||||
return ValueEvaluationContext.of(environmentProvider.getEnvironment(),
|
||||
evaluationContextProvider.getEvaluationContext(rootObject, dependencies));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ValueExpressionEvaluator} using the given {@code source} as root object.
|
||||
*
|
||||
* @param source the root object for evaluating the expression.
|
||||
* @return a new {@link ValueExpressionEvaluator} to evaluate the expression in the context of the given
|
||||
* {@code source} object.
|
||||
*/
|
||||
public ValueExpressionEvaluator create(Object source) {
|
||||
|
||||
return new ValueExpressionEvaluator() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T evaluate(String expression) {
|
||||
ValueExpression valueExpression = expressionCache.get(expression);
|
||||
return (T) valueExpression.evaluate(getEvaluationContext(source, valueExpression.getExpressionDependencies()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,9 @@ import org.springframework.util.Assert;
|
||||
* {@link SpelExpressionParser} and {@link EvaluationContext}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @deprecated since 3.3, use {@link CachingValueExpressionEvaluatorFactory} instead.
|
||||
*/
|
||||
@Deprecated(since = "3.3")
|
||||
public class DefaultSpELExpressionEvaluator implements SpELExpressionEvaluator {
|
||||
|
||||
private final Object source;
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.spel.EvaluationContextProvider;
|
||||
import org.springframework.data.support.EnvironmentAccessor;
|
||||
|
||||
/**
|
||||
* Interface capturing mutator methods for {@link PersistentEntity}s.
|
||||
@@ -29,7 +29,8 @@ import org.springframework.data.support.EnvironmentAccessor;
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface MutablePersistentEntity<T, P extends PersistentProperty<P>> extends PersistentEntity<T, P> {
|
||||
public interface MutablePersistentEntity<T, P extends PersistentProperty<P>>
|
||||
extends PersistentEntity<T, P>, EnvironmentAware {
|
||||
|
||||
/**
|
||||
* Adds a {@link PersistentProperty} to the entity.
|
||||
@@ -68,11 +69,4 @@ public interface MutablePersistentEntity<T, P extends PersistentProperty<P>> ext
|
||||
*/
|
||||
void setEvaluationContextProvider(EvaluationContextProvider provider);
|
||||
|
||||
/**
|
||||
* Sets the {@link EnvironmentAccessor} to be used by the entity.
|
||||
*
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @since 3.3
|
||||
*/
|
||||
void setEnvironmentAccessor(EnvironmentAccessor accessor);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ public class PersistentEntityParameterValueProvider<P extends PersistentProperty
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getParameterValue(Parameter<T, P> parameter) {
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.mapping.model;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.data.spel.EvaluationContextProvider;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
@@ -30,7 +31,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class SpELContext {
|
||||
public class SpELContext implements EvaluationContextProvider {
|
||||
|
||||
private final SpelExpressionParser parser;
|
||||
private final PropertyAccessor accessor;
|
||||
@@ -90,6 +91,7 @@ public class SpELContext {
|
||||
return this.parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvaluationContext getEvaluationContext(Object source) {
|
||||
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext(source);
|
||||
|
||||
@@ -15,21 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* SPI for components that can evaluate Spring EL expressions.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface SpELExpressionEvaluator {
|
||||
@Deprecated(since = "3.3")
|
||||
public interface SpELExpressionEvaluator extends ValueExpressionEvaluator {
|
||||
|
||||
/**
|
||||
* Evaluates the given expression.
|
||||
*
|
||||
* @param expression
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
<T> T evaluate(String expression);
|
||||
}
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.mapping.Parameter;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* {@link ParameterValueProvider} that can be used to front a {@link ParameterValueProvider} delegate to prefer a SpEL
|
||||
@@ -26,43 +24,16 @@ import org.springframework.lang.Nullable;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @deprecated since 3.3, use {@link ValueExpressionParameterValueProvider} instead.
|
||||
*/
|
||||
@Deprecated(since = "3.3")
|
||||
public class SpELExpressionParameterValueProvider<P extends PersistentProperty<P>>
|
||||
implements ParameterValueProvider<P> {
|
||||
|
||||
private final SpELExpressionEvaluator evaluator;
|
||||
private final ConversionService conversionService;
|
||||
private final ParameterValueProvider<P> delegate;
|
||||
extends ValueExpressionParameterValueProvider<P> implements ParameterValueProvider<P> {
|
||||
|
||||
public SpELExpressionParameterValueProvider(SpELExpressionEvaluator evaluator, ConversionService conversionService,
|
||||
ParameterValueProvider<P> delegate) {
|
||||
|
||||
this.evaluator = evaluator;
|
||||
this.conversionService = conversionService;
|
||||
this.delegate = delegate;
|
||||
super(evaluator, conversionService, delegate);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <T> T getParameterValue(Parameter<T, P> parameter) {
|
||||
|
||||
if (!parameter.hasSpelExpression()) {
|
||||
return delegate == null ? null : delegate.getParameterValue(parameter);
|
||||
}
|
||||
|
||||
Object object = evaluator.evaluate(parameter.getSpelExpression());
|
||||
return object == null ? null : potentiallyConvertSpelValue(object, parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to allow to massage the value resulting from the Spel expression evaluation. Default implementation will
|
||||
* leverage the configured {@link ConversionService} to massage the value into the parameter type.
|
||||
*
|
||||
* @param object the value to massage, will never be {@literal null}.
|
||||
* @param parameter the {@link Parameter} we create the value for
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
protected <T> T potentiallyConvertSpelValue(Object object, Parameter<T, P> parameter) {
|
||||
return conversionService.convert(object, parameter.getRawType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2023 the original author or authors.
|
||||
* Copyright 2012-2023 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.
|
||||
@@ -13,18 +13,24 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.support;
|
||||
package org.springframework.data.mapping.model;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 3.3
|
||||
* SPI for components that can evaluate Value expressions.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 3.2
|
||||
*/
|
||||
public interface EnvironmentAccessor extends PlaceholderResolver {
|
||||
public interface ValueExpressionEvaluator {
|
||||
|
||||
/**
|
||||
* Evaluates the given expression.
|
||||
*
|
||||
* @param expression
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
String getProperty(String key);
|
||||
|
||||
<T> T evaluate(String expression);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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
|
||||
*
|
||||
* https://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.mapping.model;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.mapping.Parameter;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ParameterValueProvider} that can be used to front a {@link ParameterValueProvider} delegate to prefer a SpEL
|
||||
* expression evaluation over directly resolving the parameter value with the delegate.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @since 3.3
|
||||
*/
|
||||
public class ValueExpressionParameterValueProvider<P extends PersistentProperty<P>>
|
||||
implements ParameterValueProvider<P> {
|
||||
|
||||
private final ValueExpressionEvaluator evaluator;
|
||||
private final ConversionService conversionService;
|
||||
private final ParameterValueProvider<P> delegate;
|
||||
|
||||
public ValueExpressionParameterValueProvider(ValueExpressionEvaluator evaluator, ConversionService conversionService,
|
||||
ParameterValueProvider<P> delegate) {
|
||||
|
||||
Assert.notNull(evaluator, "ValueExpressionEvaluator must not be null");
|
||||
Assert.notNull(conversionService, "ConversionService must not be null");
|
||||
Assert.notNull(delegate, "Delegate must not be null");
|
||||
|
||||
this.evaluator = evaluator;
|
||||
this.conversionService = conversionService;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <T> T getParameterValue(Parameter<T, P> parameter) {
|
||||
|
||||
if (!parameter.hasValueExpression()) {
|
||||
return delegate.getParameterValue(parameter);
|
||||
}
|
||||
|
||||
// retain compatibility where we accepted bare expressions in @Value
|
||||
String rawExpressionString = parameter.getRequiredValueExpression();
|
||||
String expressionString = rawExpressionString.contains("#{") || rawExpressionString.contains("${")
|
||||
? rawExpressionString
|
||||
: "#{" + rawExpressionString + "}";
|
||||
|
||||
Object object = evaluator.evaluate(expressionString);
|
||||
return object == null ? null : potentiallyConvertExpressionValue(object, parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to allow to massage the value resulting from the Spel expression evaluation. Default implementation will
|
||||
* leverage the configured {@link ConversionService} to massage the value into the parameter type.
|
||||
*
|
||||
* @param object the value to massage, will never be {@literal null}.
|
||||
* @param parameter the {@link Parameter} we create the value for
|
||||
* @return the converted parameter value.
|
||||
* @deprecated since 3.3, use {@link #potentiallyConvertExpressionValue(Object, Parameter)} instead.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated(since = "3.3")
|
||||
protected <T> T potentiallyConvertSpelValue(Object object, Parameter<T, P> parameter) {
|
||||
return conversionService.convert(object, parameter.getRawType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to allow to massage the value resulting from the Spel expression evaluation. Default implementation will
|
||||
* leverage the configured {@link ConversionService} to massage the value into the parameter type.
|
||||
*
|
||||
* @param object the value to massage, will never be {@literal null}.
|
||||
* @param parameter the {@link Parameter} we create the value for
|
||||
* @return the converted parameter value.
|
||||
* @since 3.3
|
||||
*/
|
||||
@Nullable
|
||||
protected <T> T potentiallyConvertExpressionValue(Object object, Parameter<T, P> parameter) {
|
||||
return potentiallyConvertSpelValue(object, parameter);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.util.AnnotationDetectionMethodCallback;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -46,10 +47,29 @@ import org.springframework.util.ReflectionUtils;
|
||||
public class SpelAwareProxyProjectionFactory extends ProxyProjectionFactory implements BeanFactoryAware {
|
||||
|
||||
private final Map<Class<?>, Boolean> typeCache = new ConcurrentHashMap<>();
|
||||
private final SpelExpressionParser parser = new SpelExpressionParser();
|
||||
private final ExpressionParser parser;
|
||||
|
||||
private @Nullable BeanFactory beanFactory;
|
||||
|
||||
/**
|
||||
* Create a new {@link SpelAwareProxyProjectionFactory}.
|
||||
*/
|
||||
public SpelAwareProxyProjectionFactory() {
|
||||
this(new SpelExpressionParser());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link SpelAwareProxyProjectionFactory} for a given {@link ExpressionParser}.
|
||||
*
|
||||
* @param parser the parser to use.
|
||||
* @since 3.3
|
||||
*/
|
||||
public SpelAwareProxyProjectionFactory(ExpressionParser parser) {
|
||||
|
||||
Assert.notNull(parser, "ExpressionParser must not be null");
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
|
||||
@@ -30,9 +30,9 @@ import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParserContext;
|
||||
import org.springframework.expression.common.TemplateParserContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -71,7 +71,7 @@ class SpelEvaluatingMethodInterceptor implements MethodInterceptor {
|
||||
* @param targetInterface must not be {@literal null}.
|
||||
*/
|
||||
public SpelEvaluatingMethodInterceptor(MethodInterceptor delegate, Object target, @Nullable BeanFactory beanFactory,
|
||||
SpelExpressionParser parser, Class<?> targetInterface) {
|
||||
ExpressionParser parser, Class<?> targetInterface) {
|
||||
|
||||
Assert.notNull(delegate, "Delegate MethodInterceptor must not be null");
|
||||
Assert.notNull(target, "Target object must not be null");
|
||||
@@ -105,7 +105,7 @@ class SpelEvaluatingMethodInterceptor implements MethodInterceptor {
|
||||
* @return
|
||||
*/
|
||||
private static Map<Integer, Expression> potentiallyCreateExpressionsForMethodsOnTargetInterface(
|
||||
SpelExpressionParser parser, Class<?> targetInterface) {
|
||||
ExpressionParser parser, Class<?> targetInterface) {
|
||||
|
||||
Map<Integer, Expression> expressions = new HashMap<>();
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* SpEL support.
|
||||
*/
|
||||
@org.springframework.lang.NonNullApi
|
||||
package org.springframework.data.spel;
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023. the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.spel.EvaluationContextProvider;
|
||||
import org.springframework.data.support.EnvironmentAccessor;
|
||||
import org.springframework.expression.BeanResolver;
|
||||
import org.springframework.expression.ConstructorResolver;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.MethodResolver;
|
||||
import org.springframework.expression.OperatorOverloader;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypeComparator;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.TypeLocator;
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2023/11
|
||||
*/
|
||||
public abstract class ExpressionEvaluator {
|
||||
|
||||
private EnvironmentAccessor environmentAccessor;
|
||||
private EvaluationContextProvider evaluationContextProvider;
|
||||
|
||||
public ExpressionEvaluator(EnvironmentAccessor environmentAccessor, EvaluationContextProvider evaluationContextProvider) {
|
||||
this.environmentAccessor = environmentAccessor;
|
||||
this.evaluationContextProvider = evaluationContextProvider;
|
||||
}
|
||||
|
||||
abstract <T> T evaluate(String text, EnvironmentAwareEvaluationContext context);
|
||||
|
||||
public class EnvironmentAwareEvaluationContext implements EvaluationContext, EnvironmentAccessor, EvaluationContextProvider {
|
||||
|
||||
@Override
|
||||
public EvaluationContext getEvaluationContext(Object rootObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolvePlaceholders(String text) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedValue getRootObject() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PropertyAccessor> getPropertyAccessors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConstructorResolver> getConstructorResolvers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MethodResolver> getMethodResolvers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BeanResolver getBeanResolver() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeLocator getTypeLocator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeConverter getTypeConverter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeComparator getTypeComparator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OperatorOverloader getOperatorOverloader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVariable(String name, @Nullable Object value) {
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object lookupVariable(String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user