From 52e6c0c6255977a47ee6647d91fc5e082a8e8160 Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Tue, 5 Jul 2022 10:37:55 +1200 Subject: [PATCH] #2736 - findDto nonsupport setter chain (accessor style setters, both fluid style and non fluid style) --- .../server/dto/DtoMetaBuilder.java | 17 ++- .../server/dto/DtoMetaBuilderTest.java | 84 ++++++++++-- .../io/ebean/xtest/base/DtoQuery2Test.java | 128 +++++++++++++----- 3 files changed, 178 insertions(+), 51 deletions(-) diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/dto/DtoMetaBuilder.java b/ebean-core/src/main/java/io/ebeaninternal/server/dto/DtoMetaBuilder.java index 0632e89f2..43acbf342 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/dto/DtoMetaBuilder.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/dto/DtoMetaBuilder.java @@ -46,20 +46,29 @@ final class DtoMetaBuilder { } static String propertyName(String methodName) { - final String name = methodName.substring(3); - return Character.toLowerCase(name.charAt(0)) + name.substring(1); + if (isTraditionalSetterMethod(methodName)) { + final String name = methodName.substring(3); + return Character.toLowerCase(name.charAt(0)) + name.substring(1); + } else { + // accessor style setter method + return methodName; + } + } + + private static boolean isTraditionalSetterMethod(String methodName) { + return methodName.startsWith("set") && methodName.length() > 3 && Character.isUpperCase(methodName.charAt(3)); } /** * Include a public "setter" method - 1 argument, returns void. */ static boolean includeMethod(Method method) { + String name = method.getName(); final int modifiers = method.getModifiers(); return Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) - && Void.TYPE.equals(method.getReturnType()) && method.getParameterTypes().length == 1 - && method.getName().startsWith("set") && method.getName().length() > 3; + && (!name.equals("wait") && !name.equals("equals")); } private void readConstructors() { diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/dto/DtoMetaBuilderTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/dto/DtoMetaBuilderTest.java index a3cf2a2fd..9448e1a5f 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/dto/DtoMetaBuilderTest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/dto/DtoMetaBuilderTest.java @@ -1,6 +1,5 @@ package io.ebeaninternal.server.dto; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import java.lang.reflect.Method; @@ -12,42 +11,54 @@ import static org.assertj.core.api.Assertions.assertThat; public class DtoMetaBuilderTest { @Test - public void includeMethod() { + void includeMethod() { Map methods = getIncludedMethodsFor(D0.class); assertThat(methods).hasSize(2); - assertThat(methods.get("setName")).isNotNull(); - assertThat(methods.get("setId")).isNotNull(); + assertThat(methods).containsKeys("setId", "setName"); } @Test - public void includeMethod_when_notStrictlySetters() { + void includeMethod_when_notStrictlySetters() { Map methods = getIncludedMethodsFor(D1.class); - assertThat(methods).hasSize(3); - assertThat(methods.get("setNameThen")).isNotNull(); - assertThat(methods.get("setIdFor")).isNotNull(); - assertThat(methods.get("setI")).isNotNull(); + assertThat(methods).hasSize(5); + assertThat(methods).containsKeys("setNameThen", "setIdFor", "setI", "setA", "set"); } @Test - public void propertyType() { + void includeMethod_when_fluidAccessors() { + Map methods = getIncludedMethodsFor(D2FluidAccessors.class); + + assertThat(methods).hasSize(5); + assertThat(methods).containsKeys("nameThen", "idFor", "a", "i", "set"); + } + + @Test + void includeMethod_when_plainAccessors() { + Map methods = getIncludedMethodsFor(D2PlainAccessors.class); + + assertThat(methods).hasSize(5); + assertThat(methods).containsKeys("nameThen", "idFor", "a", "i", "set"); + } + + @Test + void propertyType() { Map methods = getIncludedMethodsFor(D0.class); assertThat(methods).hasSize(2); - Assertions.assertThat(DtoMetaProperty.propertyClass(methods.get("setName"))).isEqualTo(String.class); + assertThat(DtoMetaProperty.propertyClass(methods.get("setName"))).isEqualTo(String.class); assertThat(DtoMetaProperty.propertyClass(methods.get("setId"))).isEqualTo(long.class); assertThat(DtoMetaProperty.propertyType(methods.get("setName"))).isEqualTo(String.class); assertThat(DtoMetaProperty.propertyType(methods.get("setId"))).isEqualTo(long.class); } @Test - public void propertyName() { - - Assertions.assertThat(DtoMetaBuilder.propertyName("setName")).isEqualTo("name"); + void propertyName() { + assertThat(DtoMetaBuilder.propertyName("setName")).isEqualTo("name"); assertThat(DtoMetaBuilder.propertyName("setId")).isEqualTo("id"); assertThat(DtoMetaBuilder.propertyName("setI")).isEqualTo("i"); - assertThat(DtoMetaBuilder.propertyName("setfoo")).isEqualTo("foo"); + assertThat(DtoMetaBuilder.propertyName("setFoo")).isEqualTo("foo"); } @@ -120,4 +131,47 @@ public class DtoMetaBuilderTest { return this; } } + + @SuppressWarnings("unused") + static class D2FluidAccessors { + + public D2FluidAccessors nameThen(String name) { + return this; + } + + public D2FluidAccessors idFor(long id) { + return this; + } + + public D2FluidAccessors i(long val) { + return this; + } + + public D2FluidAccessors set(long val) { + return this; + } + + public D2FluidAccessors a(long val) { + return this; + } + } + + @SuppressWarnings("unused") + static class D2PlainAccessors { + + public void nameThen(String name) { + } + + public void idFor(long id) { + } + + public void i(long val) { + } + + public void set(long val) { + } + + public void a(long val) { + } + } } diff --git a/ebean-test/src/test/java/io/ebean/xtest/base/DtoQuery2Test.java b/ebean-test/src/test/java/io/ebean/xtest/base/DtoQuery2Test.java index 8b86e635c..f702d4c14 100644 --- a/ebean-test/src/test/java/io/ebean/xtest/base/DtoQuery2Test.java +++ b/ebean-test/src/test/java/io/ebean/xtest/base/DtoQuery2Test.java @@ -24,12 +24,36 @@ public class DtoQuery2Test extends BaseTestCase { private static final Logger log = LoggerFactory.getLogger(DtoQuery2Test.class); @Test - public void dto_findList_constructorMatch() { + void dto_findList_fluidAccessors() { + ResetBasicData.reset(); + List list = server().findDto(DCustFluidAccessors.class, "select id, name from o_customer").findList(); + + assertThat(list).isNotEmpty(); + for (DCustFluidAccessors cust: list) { + assertThat(cust.id()).isNotNull(); + assertThat(cust.name()).isNotNull(); + } + } + + @Test + void dto_findList_plainAccessors() { + ResetBasicData.reset(); + + List list = server().findDto(DCustPlainAccessors.class, "select id, name from o_customer").findList(); + + assertThat(list).isNotEmpty(); + for (DCustPlainAccessors cust: list) { + assertThat(cust.id()).isNotNull(); + assertThat(cust.name()).isNotNull(); + } + } + + @Test + void dto_findList_constructorMatch() { ResetBasicData.reset(); DtoQuery dtoQuery = server().findDto(DCust.class, "select id, name from o_customer"); - List list = dtoQuery.findList(); log.info(list.toString()); @@ -37,7 +61,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findIterator_closeWithResources() { + void dto_findIterator_closeWithResources() { ResetBasicData.reset(); int counter = 0; @@ -55,7 +79,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findIterator() { + void dto_findIterator() { ResetBasicData.reset(); final int expectedCount = server().find(Customer.class).findCount(); @@ -80,7 +104,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findStream() { + void dto_findStream() { ResetBasicData.reset(); final int expectedCount = server().find(Customer.class).findCount(); @@ -104,8 +128,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findEach_constructorMatch() { - + void dto_findEach_constructorMatch() { ResetBasicData.reset(); LoggedSql.start(); @@ -118,8 +141,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findEachWhile_constructorMatch() { - + void dto_findEachWhile_constructorMatch() { ResetBasicData.reset(); LoggedSql.start(); @@ -135,8 +157,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findOneEmpty() { - + void dto_findOneEmpty() { ResetBasicData.reset(); Optional rob = server().findDto(DCust.class, "select id, name from o_customer where name = :name") @@ -153,8 +174,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findOne() { - + void dto_findOne() { ResetBasicData.reset(); DCust fiona = server().findDto(DCust.class, "select id, name from o_customer where name = :name") @@ -172,8 +192,7 @@ public class DtoQuery2Test extends BaseTestCase { @Test - public void dto_queryPlanHits() { - + void dto_queryPlanHits() { ResetBasicData.reset(); resetAllMetrics(); @@ -218,8 +237,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findList_relaxedMode() { - + void dto_findList_relaxedMode() { ResetBasicData.reset(); List list = server().findDto(DCust2.class, "select id, '42' as something_we_cannot_map, name from o_customer") @@ -231,8 +249,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findList_relaxedMode_defaultConstructor() { - + void dto_findList_relaxedMode_defaultConstructor() { ResetBasicData.reset(); List list = server().findDto(DCust2.class, "select id, '42' as something_we_cannot_map, name from o_customer") @@ -244,8 +261,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findList_constructorPlusMatch() { - + void dto_findList_constructorPlusMatch() { ResetBasicData.reset(); String sql = "select c.id, c.name, count(o.id) as totalOrders\n" + @@ -263,8 +279,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto_findList_setters() { - + void dto_findList_setters() { ResetBasicData.reset(); DtoQuery dtoQuery = server().findDto(DCust2.class, "select id, name from o_customer"); @@ -275,8 +290,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto3_findList_constructorMatch() { - + void dto3_findList_constructorMatch() { ResetBasicData.reset(); List robs = server().findDto(DCust3.class, "select id, name, 42 as totalOrders from o_customer where name like ?") @@ -290,8 +304,7 @@ public class DtoQuery2Test extends BaseTestCase { } @Test - public void dto3_findList_settersMatch() { - + void dto3_findList_settersMatch() { ResetBasicData.reset(); List robs = server().findDto(DCust3.class, "select id, name from o_customer where name = :name") @@ -305,9 +318,7 @@ public class DtoQuery2Test extends BaseTestCase { public static class DCust { final Integer id; - final String name; - int totalOrders; public DCust(Integer id, String name) { @@ -340,7 +351,6 @@ public class DtoQuery2Test extends BaseTestCase { public static class DCust2 { Integer id; - String name; @Override @@ -368,9 +378,7 @@ public class DtoQuery2Test extends BaseTestCase { public static class DCust3 { Integer id; - String name; - int totalOrders; public DCust3() { @@ -411,4 +419,60 @@ public class DtoQuery2Test extends BaseTestCase { this.name = name; } } + + public static class DCustFluidAccessors { + + Integer id; + String name; + + @Override + public String toString() { + return "id:" + id + " name:" + name; + } + + public Integer id() { + return id; + } + + public DCustFluidAccessors id(Integer id) { + this.id = id; + return this; + } + + public String name() { + return name; + } + + public DCustFluidAccessors name(String name) { + this.name = name; + return this; + } + } + + public static class DCustPlainAccessors { + + Integer id; + String name; + + @Override + public String toString() { + return "id:" + id + " name:" + name; + } + + public Integer id() { + return id; + } + + public void id(Integer id) { + this.id = id; + } + + public String name() { + return name; + } + + public void name(String name) { + this.name = name; + } + } }