From d3c24b70bf9b7ccaaa4d3fd581362cf9728c5e45 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Mon, 25 Sep 2017 15:50:29 -0400 Subject: [PATCH] Be sure to pick up all inherited interfaces and scan those with the @InheritedTable annotation for methods. When doing that, if we encounter the same method name twice prefer the least generic implementation. --- pom.xml | 2 +- .../helenus/config/GetterMethodDetector.java | 5 ++++ .../helenus/mapping/HelenusMappingEntity.java | 25 +++++++++++++++---- .../integration/core/hierarchy/Animal.java | 3 +++ .../test/integration/core/hierarchy/Cat.java | 2 +- .../core/hierarchy/HierarchyTest.java | 1 + .../integration/core/hierarchy/Mammal.java | 25 +++++++++++++++++++ .../test/integration/core/hierarchy/Pig.java | 2 +- 8 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 src/test/java/net/helenus/test/integration/core/hierarchy/Mammal.java diff --git a/pom.xml b/pom.xml index c69d0ba..c99c610 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 net.helenus helenus-core - 2.0.42-SNAPSHOT + 2.0.43-SNAPSHOT jar helenus diff --git a/src/main/java/net/helenus/config/GetterMethodDetector.java b/src/main/java/net/helenus/config/GetterMethodDetector.java index 2d1f908..266a7e7 100644 --- a/src/main/java/net/helenus/config/GetterMethodDetector.java +++ b/src/main/java/net/helenus/config/GetterMethodDetector.java @@ -16,6 +16,7 @@ package net.helenus.config; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.function.Function; import net.helenus.mapping.annotation.Transient; @@ -33,6 +34,10 @@ public enum GetterMethodDetector implements Function { return false; } + if (Modifier.isStatic(method.getModifiers())) { + return false; + } + // Methods marked "Transient" are not mapped, skip them. if (method.getDeclaredAnnotation(Transient.class) != null) { return false; diff --git a/src/main/java/net/helenus/mapping/HelenusMappingEntity.java b/src/main/java/net/helenus/mapping/HelenusMappingEntity.java index 75a967d..f1d57c3 100644 --- a/src/main/java/net/helenus/mapping/HelenusMappingEntity.java +++ b/src/main/java/net/helenus/mapping/HelenusMappingEntity.java @@ -25,6 +25,7 @@ import net.helenus.core.Helenus; import net.helenus.core.annotation.Cacheable; import net.helenus.mapping.annotation.*; import net.helenus.support.HelenusMappingException; +import org.apache.commons.lang3.ClassUtils; public final class HelenusMappingEntity implements HelenusEntity { @@ -52,18 +53,32 @@ public final class HelenusMappingEntity implements HelenusEntity { HelenusSettings settings = Helenus.settings(); - List methods = new ArrayList(); + Map methods = new HashMap(); + for (Method m : iface.getDeclaredMethods()) { + methods.put(m.getName(), m); + } - methods.addAll(Arrays.asList(iface.getDeclaredMethods())); - for (Class c : iface.getInterfaces()) { - methods.addAll(Arrays.asList(c.getDeclaredMethods())); + for (Class c : ClassUtils.getAllInterfaces(iface)) { + if (c.getDeclaredAnnotation(Table.class) != null || c.getDeclaredAnnotation(InheritedTable.class) != null) { + for (Method m : c.getDeclaredMethods()) { + Method o = methods.get(m.getName()); + if (o != null) { + // Prefer overridden method implementation. + if (o.getDeclaringClass().isAssignableFrom(m.getDeclaringClass())) { + methods.put(m.getName(), m); + } + } else { + methods.put(m.getName(), m); + } + } + } } List propsLocal = new ArrayList(); ImmutableMap.Builder propsBuilder = ImmutableMap.builder(); ImmutableMap.Builder methodsBuilder = ImmutableMap.builder(); - for (Method method : methods) { + for (Method method : methods.values()) { if (settings.getGetterMethodDetector().apply(method)) { diff --git a/src/test/java/net/helenus/test/integration/core/hierarchy/Animal.java b/src/test/java/net/helenus/test/integration/core/hierarchy/Animal.java index 3e9cde4..fe6392f 100644 --- a/src/test/java/net/helenus/test/integration/core/hierarchy/Animal.java +++ b/src/test/java/net/helenus/test/integration/core/hierarchy/Animal.java @@ -29,6 +29,9 @@ public interface Animal { @Column(ordinal = 1) boolean eatable(); + @Column + boolean warmBlodded(); + @Transient default Animal me() { return this; diff --git a/src/test/java/net/helenus/test/integration/core/hierarchy/Cat.java b/src/test/java/net/helenus/test/integration/core/hierarchy/Cat.java index aef0582..d0089e0 100644 --- a/src/test/java/net/helenus/test/integration/core/hierarchy/Cat.java +++ b/src/test/java/net/helenus/test/integration/core/hierarchy/Cat.java @@ -20,7 +20,7 @@ import net.helenus.mapping.annotation.Index; import net.helenus.mapping.annotation.Table; @Table("cats") -public interface Cat extends Animal { +public interface Cat extends Mammal { @Column(ordinal = 0) @Index(caseSensitive = false) diff --git a/src/test/java/net/helenus/test/integration/core/hierarchy/HierarchyTest.java b/src/test/java/net/helenus/test/integration/core/hierarchy/HierarchyTest.java index 0fcb039..0aaeceb 100644 --- a/src/test/java/net/helenus/test/integration/core/hierarchy/HierarchyTest.java +++ b/src/test/java/net/helenus/test/integration/core/hierarchy/HierarchyTest.java @@ -53,6 +53,7 @@ public class HierarchyTest extends AbstractEmbeddedCassandraTest { Optional animal = session.select(Cat.class).where(cat::nickname, eq("garfield")).sync().findFirst(); Assert.assertTrue(animal.isPresent()); + Assert.assertTrue(animal.get().warmBlodded()); Assert.assertFalse(animal.get().eatable()); } diff --git a/src/test/java/net/helenus/test/integration/core/hierarchy/Mammal.java b/src/test/java/net/helenus/test/integration/core/hierarchy/Mammal.java new file mode 100644 index 0000000..203ea66 --- /dev/null +++ b/src/test/java/net/helenus/test/integration/core/hierarchy/Mammal.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2015 The Helenus 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 net.helenus.test.integration.core.hierarchy; + +import net.helenus.mapping.annotation.InheritedTable; + +@InheritedTable +public interface Mammal extends Animal { + + default boolean warmBlodded() { return true; } + +} diff --git a/src/test/java/net/helenus/test/integration/core/hierarchy/Pig.java b/src/test/java/net/helenus/test/integration/core/hierarchy/Pig.java index fa569dc..8d12aff 100644 --- a/src/test/java/net/helenus/test/integration/core/hierarchy/Pig.java +++ b/src/test/java/net/helenus/test/integration/core/hierarchy/Pig.java @@ -19,7 +19,7 @@ import net.helenus.mapping.annotation.Column; import net.helenus.mapping.annotation.Table; @Table("pigs") -public interface Pig extends Animal { +public interface Pig extends Mammal { @Column(ordinal = 0) String nickname();