You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/01/21 19:03:57 UTC
[isis] branch master updated: ISIS-2944: fixes non-public member support detection when inherited without overriding
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new 43d196c ISIS-2944: fixes non-public member support detection when inherited without overriding
43d196c is described below
commit 43d196ca69f5e20ea05e13c527aedcd3347c28c7
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Jan 21 20:03:44 2022 +0100
ISIS-2944: fixes non-public member support detection when inherited
without overriding
- reason type.getDeclaredMethods() cannot detect non overridden
inherited methods
---
.../commons/internal/reflection/_ClassCache.java | 12 ++-
.../internal/reflection/ClassCacheTest.java | 99 ++++++++++++++++++++++
.../DomainModelTest_usingGoodDomain.java | 22 ++---
.../model/good/ProperMemberSupportDiscovery.java | 14 ++-
4 files changed, 130 insertions(+), 17 deletions(-)
diff --git a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_ClassCache.java b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_ClassCache.java
index 3e30047..ef03c66 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_ClassCache.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_ClassCache.java
@@ -64,6 +64,13 @@ public final class _ClassCache implements AutoCloseable {
return _Context.computeIfAbsent(_ClassCache.class, _ClassCache::new);
}
+ /**
+ * JUnit support.
+ */
+ public static void invalidate() {
+ _Context.put(_ClassCache.class, new _ClassCache(), true);
+ }
+
public void add(final Class<?> type) {
inspectType(type);
}
@@ -197,11 +204,12 @@ public final class _ClassCache implements AutoCloseable {
val publicConstr = type.getConstructors();
val declaredFields = type.getDeclaredFields();
- val declaredMethods = type.getDeclaredMethods();
+ val declaredMethods = //type.getDeclaredMethods(); ... cannot detect non overridden inherited methods
+ Can.ofStream(_Reflect.streamAllMethods(type, true));
val model = new ClassModel(
Can.ofArray(declaredFields),
- Can.ofArray(declaredMethods));
+ declaredMethods);
for(val constr : publicConstr) {
model.publicConstructorsByKey.put(ConstructorKey.of(type, constr), constr);
diff --git a/commons/src/test/java/org/apache/isis/commons/internal/reflection/ClassCacheTest.java b/commons/src/test/java/org/apache/isis/commons/internal/reflection/ClassCacheTest.java
new file mode 100644
index 0000000..7281bd9
--- /dev/null
+++ b/commons/src/test/java/org/apache/isis/commons/internal/reflection/ClassCacheTest.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.isis.commons.internal.reflection;
+
+import java.lang.reflect.Method;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.base._NullSafe;
+
+import lombok.val;
+
+class ClassCacheTest {
+
+ static abstract class AbstractBase {
+ void commonAction(){}
+ }
+
+ static class Concrete extends AbstractBase {
+ void specificAction(){}
+ }
+
+ static class ConcreteOverride extends AbstractBase {
+ @Override void commonAction(){}
+ void specificAction(){}
+ }
+
+ private _ClassCache classCache;
+
+ @BeforeEach
+ void setup() {
+ _ClassCache.invalidate();
+ classCache = _ClassCache.getInstance();
+ }
+
+ @Test
+ void inhertitedMethodWhenUsingReflectionUtility() {
+ val declaredMethods = Can.ofStream(
+ _NullSafe.stream(_Reflect.streamAllMethods(Concrete.class, true)));
+ assertContainsMethod(declaredMethods, "commonAction");
+ assertContainsMethod(declaredMethods, "specificAction");
+ }
+
+ @Test
+ void inhertitedMethod() {
+ val declaredMethods = Can.ofStream(
+ classCache.streamPublicOrDeclaredMethods(Concrete.class));
+ assertContainsMethod(declaredMethods, "commonAction");
+ assertContainsMethod(declaredMethods, "specificAction");
+ }
+
+ @Test
+ void inhertitedMethodWhenOverride() {
+ val declaredMethods = Can.ofStream(
+ classCache.streamPublicOrDeclaredMethods(ConcreteOverride.class));
+ assertContainsMethod(declaredMethods, "commonAction");
+ assertContainsMethod(declaredMethods, "specificAction");
+ }
+
+ // -- HELPER
+
+ private void assertContainsMethod(final Can<Method> declaredMethods, final String methodName) {
+
+ final long methodCount =
+ declaredMethods.stream()
+ .filter(m->m.getName().equals(methodName))
+ // using filter over peek here, because peek is unreliable with 'count()' terminal
+ .filter(m->{
+ assertNotNull(m);
+ return true;
+ })
+ .count();
+
+ assertTrue(methodCount>0);
+ }
+
+
+}
diff --git a/regressiontests/stable-domainmodel/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java b/regressiontests/stable-domainmodel/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
index 874b719..bc7ecee 100644
--- a/regressiontests/stable-domainmodel/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
+++ b/regressiontests/stable-domainmodel/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
@@ -580,7 +580,7 @@ class DomainModelTest_usingGoodDomain {
@SuppressWarnings("unchecked")
@ParameterizedTest
@ValueSource(classes = {
- //FIXME ProperMemberSupportDiscovery.WhenEncapsulationEnabled.class,
+ ProperMemberSupportDiscovery.WhenEncapsulationEnabled.class,
ProperMemberSupportDiscovery.WhenAnnotationRequired.class,
//FIXME ProperMemberSupportDiscovery.WhenAnnotationOptional.class
})
@@ -650,8 +650,8 @@ class DomainModelTest_usingGoodDomain {
val actualChoices =
pendingArgsThen.getObservableParamChoices(0).getValue().map(ManagedObject::getPojo);
assertEquals(
- actualChoices,
- Can.of("my choice"));
+ Can.of("my choice"),
+ actualChoices);
});
@@ -666,8 +666,8 @@ class DomainModelTest_usingGoodDomain {
val actualChoices =
pendingArgsThen.getObservableParamChoices(1).getValue().map(ManagedObject::getPojo);
assertEquals(
- actualChoices,
- Can.of("my search arg=hello"));
+ Can.of("my search arg=hello"),
+ actualChoices);
});
@@ -679,14 +679,14 @@ class DomainModelTest_usingGoodDomain {
pendingArgsWhen->{},
pendingArgsThen->{
assertEquals(
- pendingArgsThen.getObservableParamValidation(0).getValue(),
- "my validation-0");
+ "my validation-0",
+ pendingArgsThen.getObservableParamValidation(0).getValue());
assertEquals(
- pendingArgsThen.getObservableParamValidation(1).getValue(),
- "my validation-1");
+ "my validation-1",
+ pendingArgsThen.getObservableParamValidation(1).getValue());
assertEquals(
- pendingArgsThen.validateParameterSetForAction().getReason(),
- "my validation");
+ "my validation",
+ pendingArgsThen.validateParameterSetForAction().getReason());
});
// namedEmail(): String = "my email"
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupportDiscovery.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupportDiscovery.java
index 0bc149f..863518b 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupportDiscovery.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/model/good/ProperMemberSupportDiscovery.java
@@ -91,7 +91,8 @@ public class ProperMemberSupportDiscovery {
// -- ACTION
- protected abstract void placeOrder(String x, String y);
+ //FIXME should be allowed without annotation ...
+ //protected abstract void placeOrder(String x, String y);
@MemberSupport protected String namedPlaceOrder() { return "my name"; }
@MemberSupport protected String describedPlaceOrder() { return "my description"; }
@@ -110,9 +111,14 @@ public class ProperMemberSupportDiscovery {
@MemberSupport protected java.util.Collection<String> autoComplete1PlaceOrder(
final String y,
@MinLength(3) final String search) {
- return List.of("my search");
+ return List.of("my search arg=" + search);
}
+ @MemberSupport protected String validate0PlaceOrder(final String x) { return "my validation-0";}
+ @MemberSupport protected String validate1PlaceOrder(final String y) { return "my validation-1";}
+ @MemberSupport protected String validatePlaceOrder(final String x, final String y) { return "my validation";}
+
+
// -- PROPERTY
@MemberSupport protected String namedEmail() { return "my email";}
@@ -127,7 +133,7 @@ public class ProperMemberSupportDiscovery {
// -- COLLECTION
- @MemberSupport protected String namedOrders() { return "my oders"; }
+ @MemberSupport protected String namedOrders() { return "my orders"; }
@MemberSupport protected String describedOrders() { return "my orders described"; }
@MemberSupport protected boolean hideOrders() { return true;}
@MemberSupport protected String disableOrders() { return "my orders disabled"; }
@@ -179,7 +185,7 @@ public class ProperMemberSupportDiscovery {
// annotation required, otherwise not picked up as action
@Action
- @Override
+ //@Override
protected void placeOrder(final String x, final String y) {
}