From 9eab7bb11d3a0aa37ad597e8ab1e0f725005a231 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:28:45 +0200 Subject: [PATCH] Introduce null-safe indexing test for custom IndexAccessor --- .../src/test/java/example/Color.java | 21 ++++++++ .../expression/spel/IndexingTests.java | 54 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 spring-expression/src/test/java/example/Color.java diff --git a/spring-expression/src/test/java/example/Color.java b/spring-expression/src/test/java/example/Color.java new file mode 100644 index 0000000000..014857ec70 --- /dev/null +++ b/spring-expression/src/test/java/example/Color.java @@ -0,0 +1,21 @@ +/* + * Copyright 2002-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 example; + +public enum Color { + RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE +} diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java index 452a61bada..bcc4ee2a45 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/IndexingTests.java @@ -33,6 +33,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.TextNode; +import example.Color; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -455,6 +456,58 @@ class IndexingTests { assertThat(expression.getValue(context)).isEqualTo("Jane"); } + @Test + void nullSafeIndexWithCustomIndexAccessor() { + context.addIndexAccessor(new BirdsIndexAccessor()); + context.setVariable("color", Color.RED); + + expression = parser.parseExpression("birds?.[#color]"); + assertThat(expression.getValue(context)).isNull(); + rootContext.birds = new Birds(); + assertThat(expression.getValue(context)).isEqualTo("cardinal"); + } + + static class Birds { + + public String get(Color color) { + return switch (color) { + case RED -> "cardinal"; + case BLUE -> "blue jay"; + default -> throw new RuntimeException("unknown bird color: " + color); + }; + } + } + + static class BirdsIndexAccessor implements IndexAccessor { + + @Override + public Class[] getSpecificTargetClasses() { + return new Class[] { Birds.class }; + } + + @Override + public boolean canRead(EvaluationContext context, Object target, Object index) { + return (target instanceof Birds && index instanceof Color); + } + + @Override + public TypedValue read(EvaluationContext context, Object target, Object index) { + Birds birds = (Birds) target; + Color color = (Color) index; + return new TypedValue(birds.get(color)); + } + + @Override + public boolean canWrite(EvaluationContext context, Object target, Object index) { + return false; + } + + @Override + public void write(EvaluationContext context, Object target, Object index, @Nullable Object newValue) { + throw new UnsupportedOperationException(); + } + } + static class RootContextWithIndexedProperties { public int[] array; public List list; @@ -462,6 +515,7 @@ class IndexingTests { public String string; public Map map; public Person person; + public Birds birds; } }