From 88c640ee3cb0c7b7865fdf3c7cf22ca8ce983953 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 29 May 2015 11:53:51 +0100 Subject: [PATCH] Fix logic error in BeanPath relating to lists of beans There was a counting error affecting bean paths like nested[0].foo[1].bar (needed to reset a counter to 0). Tests seem fine and I added a couple of new ones for that use case. Fixes gh-3065 --- .../boot/bind/RelaxedDataBinder.java | 8 ++-- .../boot/bind/BindingPreparationTests.java | 47 +++++++++++++++++++ .../boot/bind/RelaxedDataBinderTests.java | 42 +++++++++++++++++ 3 files changed, 92 insertions(+), 5 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java index 60425e5fa31..16f458e1f61 100644 --- a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java +++ b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java @@ -461,12 +461,11 @@ public class RelaxedDataBinder extends DataBinder { } private String extractIndexedPaths(String path, List nodes) { - int begin = 0; int startRef = path.indexOf("["); String current = path; while (startRef >= 0) { - if (startRef > begin) { - nodes.addAll(splitPath(current.substring(begin, startRef))); + if (startRef > 0) { + nodes.addAll(splitPath(current.substring(0, startRef))); } int endRef = current.indexOf("]", startRef); if (endRef > 0) { @@ -478,8 +477,7 @@ public class RelaxedDataBinder extends DataBinder { nodes.add(new MapIndexNode(sub)); } } - begin = endRef + 1; - current = current.substring(begin); + current = current.substring(endRef + 1); startRef = current.indexOf("["); } return current; diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/BindingPreparationTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/BindingPreparationTests.java index fef12d3d39e..0ddf1e78c2b 100644 --- a/spring-boot/src/test/java/org/springframework/boot/bind/BindingPreparationTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/bind/BindingPreparationTests.java @@ -62,6 +62,28 @@ public class BindingPreparationTests { assertNotNull(wrapper.getPropertyValue("nested[foo]")); } + @Test + public void testListOfBeansWithList() throws Exception { + TargetWithNestedListOfBeansWithList target = new TargetWithNestedListOfBeansWithList(); + BeanWrapperImpl wrapper = new BeanWrapperImpl(target); + wrapper.setAutoGrowNestedPaths(true); + RelaxedDataBinder binder = new RelaxedDataBinder(target); + binder.normalizePath(wrapper, "nested[0].list[1]"); + assertNotNull(wrapper.getPropertyValue("nested")); + assertNotNull(wrapper.getPropertyValue("nested[0].list[1]")); + } + + @Test + public void testListOfBeansWithListAndNoPeriod() throws Exception { + TargetWithNestedListOfBeansWithList target = new TargetWithNestedListOfBeansWithList(); + BeanWrapperImpl wrapper = new BeanWrapperImpl(target); + wrapper.setAutoGrowNestedPaths(true); + RelaxedDataBinder binder = new RelaxedDataBinder(target); + binder.normalizePath(wrapper, "nested[0]list[1]"); + assertNotNull(wrapper.getPropertyValue("nested")); + assertNotNull(wrapper.getPropertyValue("nested[0].list[1]")); + } + @Test public void testAutoGrowWithFuzzyNameCapitals() throws Exception { TargetWithNestedMap target = new TargetWithNestedMap(); @@ -259,6 +281,31 @@ public class BindingPreparationTests { } } + public static class TargetWithNestedListOfBeansWithList { + private List nested; + + public List getNested() { + return this.nested; + } + + public void setNested(List nested) { + this.nested = nested; + } + } + + public static class TargetWithList { + private List list; + + public List getList() { + return this.list; + } + + public void setList(List list) { + this.list = list; + } + + } + public static class TargetWithNestedMapOfBean { private Map nested; diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java index f0c05c9aabd..9404c16d83f 100644 --- a/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/bind/RelaxedDataBinderTests.java @@ -231,6 +231,20 @@ public class RelaxedDataBinderTests { assertEquals("[bar, foo]", target.getNested().toString()); } + @Test + public void testBindNestedListOfBean() throws Exception { + TargetWithNestedListOfBean target = new TargetWithNestedListOfBean(); + bind(target, "nested[0].foo: bar\nnested[1].foo: foo"); + assertEquals("bar", target.getNested().get(0).getFoo()); + } + + @Test + public void testBindNestedListOfBeanWithList() throws Exception { + TargetWithNestedListOfBeanWithList target = new TargetWithNestedListOfBeanWithList(); + bind(target, "nested[0].nested[0].foo: bar\nnested[1].nested[0].foo: foo"); + assertEquals("bar", target.getNested().get(0).getNested().get(0).getFoo()); + } + @Test public void testBindNestedListCommaDelimitedOnly() throws Exception { TargetWithNestedList target = new TargetWithNestedList(); @@ -764,6 +778,34 @@ public class RelaxedDataBinderTests { } + public static class TargetWithNestedListOfBean { + + private List nested; + + public List getNested() { + return this.nested; + } + + public void setNested(List nested) { + this.nested = nested; + } + + } + + public static class TargetWithNestedListOfBeanWithList { + + private List nested; + + public List getNested() { + return this.nested; + } + + public void setNested(List nested) { + this.nested = nested; + } + + } + public static class TargetWithReadOnlyNestedList { private final List nested = new ArrayList();