Merge branch '6.1.x'
This commit is contained in:
commit
1aea01687a
|
@ -64,8 +64,9 @@ import org.springframework.lang.Nullable;
|
||||||
* read-only access to properties via {@link DataBindingPropertyAccessor}. Similarly,
|
* read-only access to properties via {@link DataBindingPropertyAccessor}. Similarly,
|
||||||
* {@link SimpleEvaluationContext#forReadWriteDataBinding()} enables read and write access
|
* {@link SimpleEvaluationContext#forReadWriteDataBinding()} enables read and write access
|
||||||
* to properties. Alternatively, configure custom accessors via
|
* to properties. Alternatively, configure custom accessors via
|
||||||
* {@link SimpleEvaluationContext#forPropertyAccessors} and potentially activate method
|
* {@link SimpleEvaluationContext#forPropertyAccessors}, potentially
|
||||||
* resolution and/or a type converter through the builder.
|
* {@linkplain Builder#withAssignmentDisabled() disable assignment}, and optionally
|
||||||
|
* activate method resolution and/or a type converter through the builder.
|
||||||
*
|
*
|
||||||
* <p>Note that {@code SimpleEvaluationContext} is typically not configured
|
* <p>Note that {@code SimpleEvaluationContext} is typically not configured
|
||||||
* with a default root object. Instead it is meant to be created once and
|
* with a default root object. Instead it is meant to be created once and
|
||||||
|
@ -268,9 +269,8 @@ public final class SimpleEvaluationContext implements EvaluationContext {
|
||||||
* ({@code ++}), and decrement ({@code --}) operators are disabled.
|
* ({@code ++}), and decrement ({@code --}) operators are disabled.
|
||||||
* @return {@code true} if assignment is enabled; {@code false} otherwise
|
* @return {@code true} if assignment is enabled; {@code false} otherwise
|
||||||
* @since 5.3.38
|
* @since 5.3.38
|
||||||
* @see #forPropertyAccessors(PropertyAccessor...)
|
|
||||||
* @see #forReadOnlyDataBinding()
|
* @see #forReadOnlyDataBinding()
|
||||||
* @see #forReadWriteDataBinding()
|
* @see Builder#withAssignmentDisabled()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isAssignmentEnabled() {
|
public boolean isAssignmentEnabled() {
|
||||||
|
@ -279,15 +279,18 @@ public final class SimpleEvaluationContext implements EvaluationContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@code SimpleEvaluationContext} for the specified {@link PropertyAccessor}
|
* Create a {@code SimpleEvaluationContext} for the specified {@link PropertyAccessor}
|
||||||
* delegates: typically a custom {@code PropertyAccessor} specific to a use case
|
* delegates: typically a custom {@code PropertyAccessor} specific to a use case —
|
||||||
* (e.g. attribute resolution in a custom data structure), potentially combined with
|
* for example, for attribute resolution in a custom data structure — potentially
|
||||||
* a {@link DataBindingPropertyAccessor} if property dereferences are needed as well.
|
* combined with a {@link DataBindingPropertyAccessor} if property dereferences are
|
||||||
* <p>Assignment is enabled within expressions evaluated by the context created via
|
* needed as well.
|
||||||
* this factory method.
|
* <p>By default, assignment is enabled within expressions evaluated by the context
|
||||||
|
* created via this factory method; however, assignment can be disabled via
|
||||||
|
* {@link Builder#withAssignmentDisabled()}.
|
||||||
* @param accessors the accessor delegates to use
|
* @param accessors the accessor delegates to use
|
||||||
* @see DataBindingPropertyAccessor#forReadOnlyAccess()
|
* @see DataBindingPropertyAccessor#forReadOnlyAccess()
|
||||||
* @see DataBindingPropertyAccessor#forReadWriteAccess()
|
* @see DataBindingPropertyAccessor#forReadWriteAccess()
|
||||||
* @see #isAssignmentEnabled()
|
* @see #isAssignmentEnabled()
|
||||||
|
* @see Builder#withAssignmentDisabled()
|
||||||
*/
|
*/
|
||||||
public static Builder forPropertyAccessors(PropertyAccessor... accessors) {
|
public static Builder forPropertyAccessors(PropertyAccessor... accessors) {
|
||||||
for (PropertyAccessor accessor : accessors) {
|
for (PropertyAccessor accessor : accessors) {
|
||||||
|
@ -296,7 +299,7 @@ public final class SimpleEvaluationContext implements EvaluationContext {
|
||||||
"ReflectivePropertyAccessor. Consider using DataBindingPropertyAccessor or a custom subclass.");
|
"ReflectivePropertyAccessor. Consider using DataBindingPropertyAccessor or a custom subclass.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Builder(true, accessors);
|
return new Builder(accessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -307,22 +310,26 @@ public final class SimpleEvaluationContext implements EvaluationContext {
|
||||||
* @see DataBindingPropertyAccessor#forReadOnlyAccess()
|
* @see DataBindingPropertyAccessor#forReadOnlyAccess()
|
||||||
* @see #forPropertyAccessors
|
* @see #forPropertyAccessors
|
||||||
* @see #isAssignmentEnabled()
|
* @see #isAssignmentEnabled()
|
||||||
|
* @see Builder#withAssignmentDisabled()
|
||||||
*/
|
*/
|
||||||
public static Builder forReadOnlyDataBinding() {
|
public static Builder forReadOnlyDataBinding() {
|
||||||
return new Builder(false, DataBindingPropertyAccessor.forReadOnlyAccess());
|
return new Builder(DataBindingPropertyAccessor.forReadOnlyAccess()).withAssignmentDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@code SimpleEvaluationContext} for read-write access to
|
* Create a {@code SimpleEvaluationContext} for read-write access to
|
||||||
* public properties via {@link DataBindingPropertyAccessor}.
|
* public properties via {@link DataBindingPropertyAccessor}.
|
||||||
* <p>Assignment is enabled within expressions evaluated by the context created via
|
* <p>By default, assignment is enabled within expressions evaluated by the context
|
||||||
* this factory method.
|
* created via this factory method. Assignment can be disabled via
|
||||||
|
* {@link Builder#withAssignmentDisabled()}; however, it is preferable to use
|
||||||
|
* {@link #forReadOnlyDataBinding()} if you desire read-only access.
|
||||||
* @see DataBindingPropertyAccessor#forReadWriteAccess()
|
* @see DataBindingPropertyAccessor#forReadWriteAccess()
|
||||||
* @see #forPropertyAccessors
|
* @see #forPropertyAccessors
|
||||||
* @see #isAssignmentEnabled()
|
* @see #isAssignmentEnabled()
|
||||||
|
* @see Builder#withAssignmentDisabled()
|
||||||
*/
|
*/
|
||||||
public static Builder forReadWriteDataBinding() {
|
public static Builder forReadWriteDataBinding() {
|
||||||
return new Builder(true, DataBindingPropertyAccessor.forReadWriteAccess());
|
return new Builder(DataBindingPropertyAccessor.forReadWriteAccess());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -343,15 +350,24 @@ public final class SimpleEvaluationContext implements EvaluationContext {
|
||||||
@Nullable
|
@Nullable
|
||||||
private TypedValue rootObject;
|
private TypedValue rootObject;
|
||||||
|
|
||||||
private final boolean assignmentEnabled;
|
private boolean assignmentEnabled = true;
|
||||||
|
|
||||||
|
|
||||||
private Builder(boolean assignmentEnabled, PropertyAccessor... accessors) {
|
private Builder(PropertyAccessor... accessors) {
|
||||||
this.assignmentEnabled = assignmentEnabled;
|
|
||||||
this.propertyAccessors = Arrays.asList(accessors);
|
this.propertyAccessors = Arrays.asList(accessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable assignment within expressions evaluated by this evaluation context.
|
||||||
|
* @since 5.3.38
|
||||||
|
* @see SimpleEvaluationContext#isAssignmentEnabled()
|
||||||
|
*/
|
||||||
|
public Builder withAssignmentDisabled() {
|
||||||
|
this.assignmentEnabled = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the specified {@link IndexAccessor} delegates.
|
* Register the specified {@link IndexAccessor} delegates.
|
||||||
* @param indexAccessors the index accessors to use
|
* @param indexAccessors the index accessors to use
|
||||||
|
|
|
@ -211,6 +211,52 @@ class SimpleEvaluationContextTests {
|
||||||
assertIncrementAndDecrementWritesForIndexedStructures(context);
|
assertIncrementAndDecrementWritesForIndexedStructures(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void forPropertyAccessorsWithAssignmentDisabled() {
|
||||||
|
SimpleEvaluationContext context = SimpleEvaluationContext
|
||||||
|
.forPropertyAccessors(new CompilableMapAccessor(false), DataBindingPropertyAccessor.forReadOnlyAccess())
|
||||||
|
.withIndexAccessors(colorsIndexAccessor)
|
||||||
|
.withAssignmentDisabled()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assertCommonReadOnlyModeBehavior(context);
|
||||||
|
|
||||||
|
// WRITE -- via assignment operator
|
||||||
|
|
||||||
|
// Variable
|
||||||
|
assertAssignmentDisabled(context, "#myVar = 'rejected'");
|
||||||
|
|
||||||
|
// Property
|
||||||
|
assertAssignmentDisabled(context, "name = 'rejected'");
|
||||||
|
assertAssignmentDisabled(context, "map.yellow = 'rejected'");
|
||||||
|
assertIncrementDisabled(context, "count++");
|
||||||
|
assertIncrementDisabled(context, "++count");
|
||||||
|
assertDecrementDisabled(context, "count--");
|
||||||
|
assertDecrementDisabled(context, "--count");
|
||||||
|
|
||||||
|
// Array Index
|
||||||
|
assertAssignmentDisabled(context, "array[0] = 'rejected'");
|
||||||
|
assertIncrementDisabled(context, "numbers[0]++");
|
||||||
|
assertIncrementDisabled(context, "++numbers[0]");
|
||||||
|
assertDecrementDisabled(context, "numbers[0]--");
|
||||||
|
assertDecrementDisabled(context, "--numbers[0]");
|
||||||
|
|
||||||
|
// List Index
|
||||||
|
assertAssignmentDisabled(context, "list[0] = 'rejected'");
|
||||||
|
|
||||||
|
// Map Index -- key as String
|
||||||
|
assertAssignmentDisabled(context, "map['red'] = 'rejected'");
|
||||||
|
|
||||||
|
// Map Index -- key as pseudo property name
|
||||||
|
assertAssignmentDisabled(context, "map[yellow] = 'rejected'");
|
||||||
|
|
||||||
|
// String Index
|
||||||
|
assertAssignmentDisabled(context, "name[0] = 'rejected'");
|
||||||
|
|
||||||
|
// Object Index
|
||||||
|
assertAssignmentDisabled(context, "['name'] = 'rejected'");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void assertReadWriteMode(SimpleEvaluationContext context) {
|
private void assertReadWriteMode(SimpleEvaluationContext context) {
|
||||||
// Variables can always be set programmatically within an EvaluationContext.
|
// Variables can always be set programmatically within an EvaluationContext.
|
||||||
|
|
Loading…
Reference in New Issue