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 2021/09/03 08:58:01 UTC
[isis] branch master updated: ISIS-2774: simplify Evaluator
utilities
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 e13e0a6 ISIS-2774: simplify Evaluator utilities
e13e0a6 is described below
commit e13e0a608f1264cbfe5d56e14b36f583da99d1db
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Sep 3 10:57:51 2021 +0200
ISIS-2774: simplify Evaluator utilities
also has some validation fixes for navigable parent
also simplifies TitleFacet testing
---
.../isis/applib/spec/AbstractSpecification.java | 4 +-
.../isis/applib/spec/AbstractSpecification2.java | 4 +-
.../{_MethodCache.java => _ClassCache.java} | 30 ++-
.../isis/commons/internal/reflection/_Reflect.java | 60 ++---
.../isis/core/metamodel/commons/MethodUtil.java | 11 +-
.../isis/core/metamodel/facets/Annotations.java | 242 ---------------------
.../isis/core/metamodel/facets/Evaluators.java | 196 +++++++++++++++++
.../metamodel/facets/FacetFactoryAbstract.java | 6 +-
.../navparent/NavigableParentFacetAbstract.java | 4 +-
.../NavigableParentAnnotationFacetFactory.java | 80 ++++---
...va => NavigableParentFacetViaGetterMethod.java} | 9 +-
.../annotation/TitleAnnotationFacetFactory.java | 49 ++---
.../annotation/TitleFacetViaTitleAnnotation.java | 35 ++-
...tionEnforcesMetamodelContributionValidator.java | 6 +-
.../core/metamodel/methods/MethodFinderUtils.java | 6 +-
.../classsubstitutor/ClassSubstitutorAbstract.java | 4 +-
.../specloader/specimpl/FacetedMethodsBuilder.java | 4 +-
.../TitleAnnotationFacetFactoryTest.java | 14 +-
.../TitleFacetViaTitleAnnotationTest.java | 30 +--
.../navparent/NavigableParentFacetMethodTest.java | 6 +-
.../NavigableParentAnnotationFacetFactoryTest.java | 6 +-
21 files changed, 389 insertions(+), 417 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/spec/AbstractSpecification.java b/api/applib/src/main/java/org/apache/isis/applib/spec/AbstractSpecification.java
index 27db496..57c4caa 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/spec/AbstractSpecification.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/spec/AbstractSpecification.java
@@ -22,7 +22,7 @@ package org.apache.isis.applib.spec;
import java.lang.reflect.Method;
import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.commons.internal.reflection._MethodCache;
+import org.apache.isis.commons.internal.reflection._ClassCache;
import lombok.val;
@@ -56,7 +56,7 @@ public abstract class AbstractSpecification<T> implements Specification {
private static Class<?> findExpectedType(final Class<?> fromClass) {
- val methodCache = _MethodCache.getInstance();
+ val methodCache = _ClassCache.getInstance();
for (Class<?> c = fromClass; c != Object.class; c = c.getSuperclass()) {
diff --git a/api/applib/src/main/java/org/apache/isis/applib/spec/AbstractSpecification2.java b/api/applib/src/main/java/org/apache/isis/applib/spec/AbstractSpecification2.java
index 653e1a3..a1fd2a1 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/spec/AbstractSpecification2.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/spec/AbstractSpecification2.java
@@ -24,7 +24,7 @@ import java.lang.reflect.Method;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.services.i18n.TranslatableString;
import org.apache.isis.commons.internal.base._Casts;
-import org.apache.isis.commons.internal.reflection._MethodCache;
+import org.apache.isis.commons.internal.reflection._ClassCache;
import lombok.val;
@@ -58,7 +58,7 @@ public abstract class AbstractSpecification2<T> implements Specification2 {
private static Class<?> findExpectedType(final Class<?> fromClass) {
- val methodCache = _MethodCache.getInstance();
+ val methodCache = _ClassCache.getInstance();
for (Class<?> c = fromClass; c != Object.class; c = c.getSuperclass()) {
diff --git a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_MethodCache.java b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_ClassCache.java
similarity index 87%
rename from commons/src/main/java/org/apache/isis/commons/internal/reflection/_MethodCache.java
rename to commons/src/main/java/org/apache/isis/commons/internal/reflection/_ClassCache.java
index 675d7a6..e587945 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_MethodCache.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_ClassCache.java
@@ -51,10 +51,10 @@ import lombok.val;
* @since 2.0
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class _MethodCache implements AutoCloseable {
+public final class _ClassCache implements AutoCloseable {
- public static _MethodCache getInstance() {
- return _Context.computeIfAbsent(_MethodCache.class, _MethodCache::new);
+ public static _ClassCache getInstance() {
+ return _Context.computeIfAbsent(_ClassCache.class, _ClassCache::new);
}
public void add(final Class<?> type) {
@@ -83,10 +83,10 @@ public final class _MethodCache implements AutoCloseable {
}
public Stream<Method> streamPublicOrDeclaredMethods(final Class<?> type) {
- val methods = inspectType(type);
+ val classModel = inspectType(type);
return Stream.concat(
- methods.publicMethodsByKey.values().stream(),
- methods.nonPublicDeclaredMethodsByKey.values().stream());
+ classModel.publicMethodsByKey.values().stream(),
+ classModel.nonPublicDeclaredMethodsByKey.values().stream());
}
public Stream<Method> streamDeclaredMethods(final Class<?> type) {
@@ -106,11 +106,11 @@ public final class _MethodCache implements AutoCloseable {
final String attributeName,
final Predicate<Method> filter) {
- val methods = inspectType(type);
+ val classModel = inspectType(type);
- synchronized(methods.declaredMethodsByAttribute) {
- return methods.declaredMethodsByAttribute
- .computeIfAbsent(attributeName, key->methods.declaredMethods.filter(filter))
+ synchronized(classModel.declaredMethodsByAttribute) {
+ return classModel.declaredMethodsByAttribute
+ .computeIfAbsent(attributeName, key->classModel.declaredMethods.filter(filter))
.stream();
}
}
@@ -118,14 +118,14 @@ public final class _MethodCache implements AutoCloseable {
// -- IMPLEMENATION DETAILS
@RequiredArgsConstructor
- private static class Methods {
+ private static class ClassModel {
private final Map<MethodKey, Method> publicMethodsByKey = new HashMap<>();
private final Map<MethodKey, Method> nonPublicDeclaredMethodsByKey = new HashMap<>();
private final Can<Method> declaredMethods;
private final Map<String, Can<Method>> declaredMethodsByAttribute = new HashMap<>();
}
- private final Map<Class<?>, Methods> inspectedTypes = new HashMap<>();
+ private final Map<Class<?>, ClassModel> inspectedTypes = new HashMap<>();
@AllArgsConstructor(staticName = "of") @EqualsAndHashCode
private static final class MethodKey {
@@ -136,10 +136,8 @@ public final class _MethodCache implements AutoCloseable {
public static MethodKey of(final Class<?> type, final Method method) {
return MethodKey.of(type, method.getName(), _Arrays.emptyToNull(method.getParameterTypes()));
}
-
}
-
@Override
public void close() throws Exception {
synchronized(inspectedTypes) {
@@ -149,14 +147,14 @@ public final class _MethodCache implements AutoCloseable {
// -- HELPER
- private Methods inspectType(final Class<?> type) {
+ private ClassModel inspectType(final Class<?> type) {
synchronized(inspectedTypes) {
return inspectedTypes.computeIfAbsent(type, __->{
val declaredMethods = type.getDeclaredMethods();
- val methods = new Methods(Can.ofArray(declaredMethods));
+ val methods = new ClassModel(Can.ofArray(declaredMethods));
for(val method : declaredMethods) {
methods.nonPublicDeclaredMethodsByKey.put(MethodKey.of(type, method), method);
diff --git a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
index 9ab17f4..31dec7d 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
@@ -34,17 +34,15 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
-import java.util.Spliterator;
-import java.util.Spliterators;
-import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.Nullable;
+import org.springframework.util.ClassUtils;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.functional.Result;
@@ -266,52 +264,38 @@ public final class _Reflect {
// -- SUPER CLASSES
+ public enum TypeHierarchyPolicy {
+ EXCLUDE,
+ INCLUDE;
+ public boolean isIncludeTypeHierarchy() {
+ return this == TypeHierarchyPolicy.INCLUDE;
+ }
+ }
+
public enum InterfacePolicy {
- INCLUDE,
- EXCLUDE
+ EXCLUDE,
+ INCLUDE;
+ public boolean isIncludeInterfaces() {
+ return this == InterfacePolicy.INCLUDE;
+ }
}
/**
* Stream all types of given {@code type}, up the super class hierarchy starting with self
* @param type (nullable)
- * @param interfacePolicy - whether to include all interfaces implemented by given {@code type}.
+ * @param interfacePolicy - whether to include all interfaces implemented by given {@code type} at the end
* @return non-null
*/
public static Stream<Class<?>> streamTypeHierarchy(
final @Nullable Class<?> type,
- final InterfacePolicy interfacePolicy) {
-
- val includeInterfaces = interfacePolicy == InterfacePolicy.INCLUDE;
-
- // https://stackoverflow.com/questions/40240450/java8-streaming-a-class-hierarchy?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
- // Java 9+ will allow ...
- // return Stream.iterate(type, Objects::nonNull, Class::getSuperclass);
-
- return StreamSupport.stream(
- new Spliterators.AbstractSpliterator<Class<?>>(Long.MAX_VALUE,
- Spliterator.ORDERED|Spliterator.IMMUTABLE|Spliterator.NONNULL) {
- Class<?> current = type;
- @Override
- public boolean tryAdvance(final Consumer<? super Class<?>> action) {
- if(current == null) return false;
- action.accept(current);
- if(includeInterfaces) {
- for(Class<?> subIface : current.getInterfaces()) {
- recur(subIface, action);
- }
- }
- current = current.getSuperclass();
- return true;
- }
+ final @NonNull InterfacePolicy interfacePolicy) {
- private void recur(final Class<?> iface, final Consumer<? super Class<?>> action) {
- action.accept(iface);
- for(Class<?> subIface : iface.getInterfaces()) {
- recur(subIface, action);
- }
- }
+ return interfacePolicy.isIncludeInterfaces()
+ ? Stream.concat(
+ Stream.<Class<?>>iterate(type, Objects::nonNull, Class::getSuperclass),
+ ClassUtils.getAllInterfacesForClassAsSet(type).stream())
+ : Stream.iterate(type, Objects::nonNull, Class::getSuperclass);
- }, false);
}
// -- ANNOTATIONS
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/MethodUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/MethodUtil.java
index cbe22fb..2373263 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/MethodUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/MethodUtil.java
@@ -47,11 +47,16 @@ public class MethodUtil {
return Modifier.isStatic(modifiers);
}
- public static boolean isPublic(Member method) {
+ public static boolean isPublic(final Member method) {
final int modifiers = method.getModifiers();
return Modifier.isPublic(modifiers);
}
+ public static boolean isNoArg(final Method method) {
+ return method.getParameterCount() == 0;
+ }
+
+
@UtilityClass
public static class Predicates {
@@ -148,7 +153,7 @@ public class MethodUtil {
* @return whether the method under test matches the given constraints
*/
public static Predicate<Method> prefixed(
- String prefix, Class<?> returnType, CanBeVoid canBeVoid, int paramCount) {
+ final String prefix, final Class<?> returnType, final CanBeVoid canBeVoid, final int paramCount) {
return method -> {
@@ -172,7 +177,7 @@ public class MethodUtil {
}
- public static Predicate<Method> getter(Class<?> returnType) {
+ public static Predicate<Method> getter(final Class<?> returnType) {
return prefixed(MethodLiteralConstants.GET_PREFIX, returnType, CanBeVoid.FALSE, 0);
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
deleted file mode 100644
index cb210ab..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * 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.core.metamodel.facets;
-
-import java.beans.IntrospectionException;
-import java.lang.annotation.Annotation;
-import java.lang.invoke.MethodHandle;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-
-import org.apache.isis.applib.exceptions.unrecoverable.MetaModelException;
-import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.commons.internal.reflection._MethodCache;
-import org.apache.isis.commons.internal.reflection._Reflect;
-import org.apache.isis.core.metamodel.commons.MethodUtil;
-import org.apache.isis.core.metamodel.commons.ThrowableExtensions;
-
-import lombok.Getter;
-import lombok.val;
-import lombok.experimental.UtilityClass;
-import lombok.extern.log4j.Log4j2;
-
-@UtilityClass
-@Log4j2
-public final class Annotations {
-
-
- /**
- * Searches for all no-arg methods or fields with a specified title, returning an
- * {@link Evaluator} object that wraps either. Will search up hierarchy also,
- * including implemented interfaces.
- */
- public static <T extends Annotation> List<Evaluator<T>> getEvaluators(
- final Class<?> cls,
- final Class<T> annotationClass) {
- final List<Evaluator<T>> evaluators = _Lists.newArrayList();
- visitEvaluators(cls, annotationClass, evaluators::add);
-
- // search implemented interfaces
- final Class<?>[] interfaces = cls.getInterfaces();
- for (final Class<?> iface : interfaces) {
- visitEvaluators(iface, annotationClass, evaluators::add);
- }
-
- return evaluators;
- }
-
- /**
- * Starting from the current class {@code cls}, we search down the inheritance
- * hierarchy (super class, super super class, ...), until we find
- * the first class that has at least a field or no-arg method with {@code annotationClass} annotation.
- * <br/>
- * In this hierarchy traversal, implemented interfaces are not processed.
- * @param cls
- * @param annotationClass
- * @param filter
- * @return list of {@link Evaluator} that wraps each annotated member found on the class where
- * the search stopped, or an empty list if no such {@code annotationClass} annotation found.
- *
- * @since 2.0
- */
- public static <T extends Annotation> List<Evaluator<T>> firstEvaluatorsInHierarchyHaving(
- final Class<?> cls,
- final Class<T> annotationClass,
- final Predicate<Evaluator<T>> filter) {
-
- final List<Evaluator<T>> evaluators = _Lists.newArrayList();
- visitEvaluatorsWhile(cls, annotationClass, __->evaluators.isEmpty(), evaluator->{
- if(filter.test(evaluator)) {
- evaluators.add(evaluator);
- }
- });
-
- return evaluators;
- }
-
- private static <T extends Annotation> void visitEvaluators(
- final Class<?> cls,
- final Class<T> annotationClass,
- final Consumer<Evaluator<T>> visitor) {
- visitEvaluatorsWhile(cls, annotationClass, __->true, visitor);
- }
-
- private static <T extends Annotation> void visitEvaluatorsWhile(
- final Class<?> cls,
- final Class<T> annotationClass,
- final Predicate<Class<?>> filter,
- final Consumer<Evaluator<T>> visitor) {
-
- if(!filter.test(cls))
- return; // stop visitation
-
- visitMethodEvaluators(cls, annotationClass, visitor);
- visitFieldEvaluators(cls, annotationClass, visitor);
-
- // search super-classes
- final Class<?> superclass = cls.getSuperclass();
- if (superclass != null) {
- visitEvaluatorsWhile(superclass, annotationClass, filter, visitor);
- }
-
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private static <T extends Annotation> void visitMethodEvaluators(
- final Class<?> cls,
- final Class<T> annotationClass,
- final Consumer<Evaluator<T>> visitor) {
-
- val methodCache = _MethodCache.getInstance();
-
- methodCache
- .streamDeclaredMethods(cls)
- .filter(MethodUtil::isNotStatic)
- .filter(method->method.getParameterTypes().length == 0)
- .forEach(method->{
- final Annotation annotation = method.getAnnotation(annotationClass);
- if(annotation != null) {
- visitor.accept(new MethodEvaluator(method, annotation));
- }
- });
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private static <T extends Annotation> void visitFieldEvaluators(
- final Class<?> cls,
- final Class<T> annotationClass,
- final Consumer<Evaluator<T>> visitor) {
-
- for (final Field field: cls.getDeclaredFields()) {
- final Annotation annotation = field.getAnnotation(annotationClass);
- if(annotation != null) {
- visitor.accept(new FieldEvaluator(field, annotation));
- }
- }
- }
-
- public static abstract class Evaluator<T extends Annotation> {
- private final T annotation;
- private MethodHandle mh;
-
- protected Evaluator(final T annotation) {
- this.annotation = annotation;
- }
-
- public T getAnnotation() {
- return annotation;
- }
-
- protected abstract MethodHandle createMethodHandle() throws IllegalAccessException;
- protected abstract String name();
-
- public Object value(final Object obj) {
- if(mh==null) {
- try {
- mh = createMethodHandle();
- } catch (IllegalAccessException e) {
- throw new MetaModelException("illegal access of " + name(), e);
- }
- }
-
- try {
- return mh.invoke(obj);
- } catch (Throwable e) {
- return ThrowableExtensions.handleInvocationException(e, name());
- }
-
- }
- }
-
- public static class MethodEvaluator<T extends Annotation> extends Evaluator<T> {
- @Getter private final Method method;
-
- MethodEvaluator(final Method method, final T annotation) {
- super(annotation);
- this.method = method;
- }
-
- @Override
- protected String name() {
- return method.getName();
- }
-
- @Override
- protected MethodHandle createMethodHandle() throws IllegalAccessException {
- return _Reflect.handleOf(method);
- }
- }
-
- public static class FieldEvaluator<T extends Annotation> extends Evaluator<T> {
- @Getter private final Field field;
-
- FieldEvaluator(final Field field, final T annotation) {
- super(annotation);
- this.field = field;
- }
-
- @Override
- protected String name() {
- return field.getName();
- }
-
- @Override
- protected MethodHandle createMethodHandle() throws IllegalAccessException {
- return _Reflect.handleOfGetterOn(field);
- }
-
- public Optional<Method> getGetter(final Class<?> originatingClass) {
- try {
- return Optional.ofNullable(
- _Reflect.getGetter(originatingClass, field.getName()) );
- } catch (IntrospectionException e) {
- log.warn("failed reflective introspection on {} field {}",
- originatingClass, field.getName(), e);
- }
- return Optional.empty();
- }
-
- }
-
-}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Evaluators.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Evaluators.java
new file mode 100644
index 0000000..2571ed1
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Evaluators.java
@@ -0,0 +1,196 @@
+/*
+ * 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.core.metamodel.facets;
+
+import java.beans.IntrospectionException;
+import java.lang.annotation.Annotation;
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.apache.isis.applib.exceptions.unrecoverable.MetaModelException;
+import org.apache.isis.commons.internal.reflection._ClassCache;
+import org.apache.isis.commons.internal.reflection._Reflect;
+import org.apache.isis.commons.internal.reflection._Reflect.InterfacePolicy;
+import org.apache.isis.commons.internal.reflection._Reflect.TypeHierarchyPolicy;
+import org.apache.isis.core.metamodel.commons.MethodUtil;
+import org.apache.isis.core.metamodel.commons.ThrowableExtensions;
+
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.val;
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+public final class Evaluators {
+
+ /**
+ * Streams all fields and no-arg methods having a specified annotationType,
+ * each wrapped with an {@link Evaluator} object.
+ */
+ public static <T extends Annotation> Stream<Evaluator<T>> streamEvaluators(
+ final @NonNull Class<?> cls,
+ final @NonNull Class<T> annotationType,
+ final @NonNull TypeHierarchyPolicy typeHierarchyPolicy,
+ final @NonNull InterfacePolicy interfacePolicy) {
+
+ return typeHierarchyPolicy.isIncludeTypeHierarchy()
+ ? _Reflect
+ .streamTypeHierarchy(cls, interfacePolicy)
+ .flatMap(type->streamAnnotatedMemberEvaluators(type, annotationType))
+ : streamAnnotatedMemberEvaluators(cls, annotationType);
+ }
+
+ // -- HELPER
+
+ private static <T extends Annotation> Stream<Evaluator<T>> streamAnnotatedMemberEvaluators(
+ final Class<?> cls,
+ final Class<T> annotationType) {
+
+ return Stream.concat(
+ streamMethodEvaluators(cls, annotationType),
+ streamFieldEvaluators(cls, annotationType));
+ }
+
+ private static <T extends Annotation> Stream<Evaluator<T>> streamMethodEvaluators(
+ final Class<?> cls,
+ final Class<T> annotationType) {
+
+ val methodCache = _ClassCache.getInstance();
+
+ return methodCache
+ .streamDeclaredMethods(cls)
+ .filter(MethodUtil::isNotStatic)
+ .filter(MethodUtil::isNoArg)
+ .map(method->MethodEvaluator.create(method, annotationType))
+ .flatMap(Optional::stream);
+ }
+
+ private static <T extends Annotation> Stream<Evaluator<T>> streamFieldEvaluators(
+ final Class<?> cls,
+ final Class<T> annotationType) {
+
+ return Stream.<Field>of(cls.getDeclaredFields())
+ .map(field->FieldEvaluator.create(field, annotationType))
+ .flatMap(Optional::stream);
+ }
+
+ // -- EVALUATOR
+
+ public static abstract class Evaluator<T extends Annotation> {
+ @Getter private final T annotation;
+ private MethodHandle mh;
+
+ protected Evaluator(final T annotation) {
+ this.annotation = annotation;
+ }
+
+ protected abstract MethodHandle createMethodHandle() throws IllegalAccessException;
+ public abstract String name();
+
+ public Object value(final Object obj) {
+ if(mh==null) {
+ try {
+ mh = createMethodHandle();
+ } catch (IllegalAccessException e) {
+ throw new MetaModelException("illegal access of " + name(), e);
+ }
+ }
+
+ try {
+ return mh.invoke(obj);
+ } catch (Throwable e) {
+ return ThrowableExtensions.handleInvocationException(e, name());
+ }
+
+ }
+ }
+
+ public static class MethodEvaluator<T extends Annotation> extends Evaluator<T> {
+
+ static <T extends Annotation> Optional<MethodEvaluator<T>> create(
+ final Method method,
+ final Class<T> annotationType) {
+
+ return Optional.ofNullable(method.getAnnotation(annotationType))
+ .map(annot->new MethodEvaluator<>(method, annot));
+ }
+
+ @Getter private final Method method;
+
+ MethodEvaluator(final Method method, final T annotation) {
+ super(annotation);
+ this.method = method;
+ }
+
+ @Override
+ public String name() {
+ return method.getName() + "()";
+ }
+
+ @Override
+ protected MethodHandle createMethodHandle() throws IllegalAccessException {
+ return _Reflect.handleOf(method);
+ }
+ }
+
+ public static class FieldEvaluator<T extends Annotation> extends Evaluator<T> {
+
+ static <T extends Annotation> Optional<FieldEvaluator<T>> create(
+ final Field field,
+ final Class<T> annotationType) {
+
+ return Optional.ofNullable(field.getAnnotation(annotationType))
+ .map(annot->new FieldEvaluator<>(field, annot));
+ }
+
+ @Getter private final Field field;
+
+ FieldEvaluator(final Field field, final T annotation) {
+ super(annotation);
+ this.field = field;
+ }
+
+ @Override
+ public String name() {
+ return field.getName();
+ }
+
+ @Override
+ protected MethodHandle createMethodHandle() throws IllegalAccessException {
+ return _Reflect.handleOfGetterOn(field);
+ }
+
+ public Optional<Method> getGetter(final Class<?> originatingClass) {
+ try {
+ return Optional.ofNullable(
+ _Reflect.getGetter(originatingClass, field.getName()) );
+ } catch (IntrospectionException e) {
+ log.warn("failed reflective introspection on {} field {}",
+ originatingClass, field.getName(), e);
+ }
+ return Optional.empty();
+ }
+
+ }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactoryAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactoryAbstract.java
index 7236837..f930307 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactoryAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactoryAbstract.java
@@ -24,7 +24,7 @@ import java.util.Optional;
import org.springframework.lang.Nullable;
import org.apache.isis.commons.collections.ImmutableEnumSet;
-import org.apache.isis.commons.internal.reflection._MethodCache;
+import org.apache.isis.commons.internal.reflection._ClassCache;
import org.apache.isis.core.metamodel.context.HasMetaModelContext;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.facetapi.Facet;
@@ -42,14 +42,14 @@ implements FacetFactory, HasMetaModelContext {
@Getter(onMethod_ = {@Override}) private final ImmutableEnumSet<FeatureType> featureTypes;
- @Getter(AccessLevel.PROTECTED) private final _MethodCache methodCache;
+ @Getter(AccessLevel.PROTECTED) private final _ClassCache methodCache;
public FacetFactoryAbstract(
final MetaModelContext metaModelContext,
final ImmutableEnumSet<FeatureType> featureTypes) {
this.metaModelContext = metaModelContext;
this.featureTypes = featureTypes;
- this.methodCache = _MethodCache.getInstance();
+ this.methodCache = _ClassCache.getInstance();
}
@Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/NavigableParentFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/NavigableParentFacetAbstract.java
index a66e856..ea51d34 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/NavigableParentFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/NavigableParentFacetAbstract.java
@@ -23,7 +23,9 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-public abstract class NavigableParentFacetAbstract extends FacetAbstract implements NavigableParentFacet {
+public abstract class NavigableParentFacetAbstract
+extends FacetAbstract
+implements NavigableParentFacet {
private static final Class<? extends Facet> type() {
return NavigableParentFacet.class;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactory.java
index d5718eb..e3c789f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactory.java
@@ -20,22 +20,26 @@
package org.apache.isis.core.metamodel.facets.object.navparent.annotation;
import java.lang.reflect.Method;
-import java.util.List;
+import java.util.Optional;
import javax.inject.Inject;
import org.apache.isis.applib.annotation.PropertyLayout;
-import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.reflection._Reflect.InterfacePolicy;
+import org.apache.isis.commons.internal.reflection._Reflect.TypeHierarchyPolicy;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
import org.apache.isis.core.metamodel.facetapi.FeatureType;
import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
-import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.Evaluators;
import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
-import org.apache.isis.core.metamodel.facets.object.navparent.method.NavigableParentFacetMethod;
+import org.apache.isis.core.metamodel.facets.object.navparent.NavigableParentFacet;
+import org.apache.isis.core.metamodel.facets.object.navparent.method.NavigableParentFacetViaGetterMethod;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
import org.apache.isis.core.metamodel.specloader.validator.ValidationFailure;
+import lombok.val;
import lombok.extern.log4j.Log4j2;
/**
@@ -66,28 +70,29 @@ implements MetaModelRefiner {
// That's the one we use to
// resolve the current domain-object's navigable parent.
- final List<Annotations.Evaluator<PropertyLayout>> evaluators =
- Annotations.firstEvaluatorsInHierarchyHaving(cls, PropertyLayout.class,
- NavigableParentAnnotationFacetFactory::isNavigableParentFlagSet);
+ final Optional<Evaluators.Evaluator<PropertyLayout>> evaluators =
+ Evaluators.streamEvaluators(cls,
+ PropertyLayout.class,
+ TypeHierarchyPolicy.INCLUDE,
+ InterfacePolicy.EXCLUDE)
+ .filter(NavigableParentAnnotationFacetFactory::isNavigableParentFlagSet)
+ .findFirst();
- if (_NullSafe.isEmpty(evaluators)) {
+ if (evaluators.isEmpty()) {
return; // no parent resolvable
- } else if (evaluators.size()>1) {
- // code should not be reached, since case should be handled by meta-data validation
- throw new RuntimeException("unable to determine navigable parent due to ambiguity");
}
- final Annotations.Evaluator<PropertyLayout> parentEvaluator = evaluators.get(0);
+ final Evaluators.Evaluator<PropertyLayout> parentEvaluator = evaluators.get();
final Method method;
// find method that provides the parent ...
- if(parentEvaluator instanceof Annotations.MethodEvaluator) {
+ if(parentEvaluator instanceof Evaluators.MethodEvaluator) {
// we have a @Parent annotated method
- method = ((Annotations.MethodEvaluator<PropertyLayout>) parentEvaluator).getMethod();
- } else if(parentEvaluator instanceof Annotations.FieldEvaluator) {
+ method = ((Evaluators.MethodEvaluator<PropertyLayout>) parentEvaluator).getMethod();
+ } else if(parentEvaluator instanceof Evaluators.FieldEvaluator) {
// we have a @Parent annotated field (useful if one uses lombok's @Getter on a field)
- method = ((Annotations.FieldEvaluator<PropertyLayout>) parentEvaluator).getGetter(cls).orElse(null);
+ method = ((Evaluators.FieldEvaluator<PropertyLayout>) parentEvaluator).getGetter(cls).orElse(null);
if(method==null)
return; // code should not be reached, since case should be handled by meta-data validation
@@ -96,20 +101,20 @@ implements MetaModelRefiner {
}
try {
- addFacet(new NavigableParentFacetMethod(method, facetHolder));
+ addFacet(new NavigableParentFacetViaGetterMethod(method, facetHolder));
} catch (IllegalAccessException e) {
log.warn("failed to create NavigableParentFacetMethod method:{} holder:{}",
method, facetHolder, e);
}
}
- private static boolean isNavigableParentFlagSet(final Annotations.Evaluator<PropertyLayout> evaluator){
+ private static boolean isNavigableParentFlagSet(final Evaluators.Evaluator<PropertyLayout> evaluator){
return evaluator.getAnnotation().navigable().isParent();
}
/**
- * For detailed behavioral specification see
+ * For detailed behavior see
* <a href="https://issues.apache.org/jira/browse/ISIS-1816">ISIS-1816</a>.
*/
@Override
@@ -117,33 +122,46 @@ implements MetaModelRefiner {
programmingModel.addVisitingValidatorSkipManagedBeans(spec->{
- final Class<?> cls = spec.getCorrespondingClass();
+ val cls = spec.getCorrespondingClass();
- final List<Annotations.Evaluator<PropertyLayout>> evaluators =
- Annotations.firstEvaluatorsInHierarchyHaving(cls, PropertyLayout.class,
- NavigableParentAnnotationFacetFactory::isNavigableParentFlagSet);
+ if(!spec.lookupFacet(NavigableParentFacet.class).isPresent()) {
+ return; // skip check
+ }
+
+ val evaluators =
+ Evaluators.streamEvaluators(cls,
+ PropertyLayout.class,
+ TypeHierarchyPolicy.EXCLUDE,
+ InterfacePolicy.INCLUDE)
+ .filter(NavigableParentAnnotationFacetFactory::isNavigableParentFlagSet)
+ .collect(Can.toCan());
- if (_NullSafe.isEmpty(evaluators)) {
+ if (evaluators.isEmpty()) {
return; // no conflict, continue validation processing
- } else if (evaluators.size()>1) {
+ } else if (evaluators.isCardinalityMultiple()) {
+
+ val conflictingEvaluatorNames = evaluators.map(Evaluators.Evaluator::name).toList();
ValidationFailure.raiseFormatted(
spec,
"%s: conflict for determining a strategy for retrieval of (navigable) parent for class, "
- + "contains multiple annotations '@%s' having navigable=PARENT, while at most one is allowed.",
+ + "contains multiple annotations '@%s' having navigable=PARENT, "
+ + "while at most one is allowed.\n\tConflicting members: %s",
spec.getFeatureIdentifier().getClassName(),
- PropertyLayout.class.getName());
+ PropertyLayout.class.getName(),
+ conflictingEvaluatorNames.toString()
+ );
return; // continue validation processing
}
- final Annotations.Evaluator<PropertyLayout> parentEvaluator = evaluators.get(0);
+ final Evaluators.Evaluator<PropertyLayout> parentEvaluator = evaluators.getSingletonOrFail();
- if(parentEvaluator instanceof Annotations.FieldEvaluator) {
+ if(parentEvaluator instanceof Evaluators.FieldEvaluator) {
// we have a @Parent annotated field (useful if one uses lombok's @Getter on a field)
- final Annotations.FieldEvaluator<PropertyLayout> fieldEvaluator =
- (Annotations.FieldEvaluator<PropertyLayout>) parentEvaluator;
+ final Evaluators.FieldEvaluator<PropertyLayout> fieldEvaluator =
+ (Evaluators.FieldEvaluator<PropertyLayout>) parentEvaluator;
if(!fieldEvaluator.getGetter(cls).isPresent()) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/method/NavigableParentFacetMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/method/NavigableParentFacetViaGetterMethod.java
similarity index 85%
rename from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/method/NavigableParentFacetMethod.java
rename to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/method/NavigableParentFacetViaGetterMethod.java
index e80ca8c..7aa65d9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/method/NavigableParentFacetMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/navparent/method/NavigableParentFacetViaGetterMethod.java
@@ -32,17 +32,20 @@ import org.apache.isis.core.metamodel.facets.object.navparent.NavigableParentFac
* @since 2.0
*
*/
-public class NavigableParentFacetMethod extends NavigableParentFacetAbstract {
+public class NavigableParentFacetViaGetterMethod
+extends NavigableParentFacetAbstract {
private final MethodHandle methodHandle;
- public NavigableParentFacetMethod(final Method method, final FacetHolder holder) throws IllegalAccessException {
+ public NavigableParentFacetViaGetterMethod(
+ final Method method,
+ final FacetHolder holder) throws IllegalAccessException {
super(holder);
this.methodHandle = _Reflect.handleOf(method);
}
@Override
- public Object navigableParent(Object object) {
+ public Object navigableParent(final Object object) {
try {
return methodHandle.invoke(object);
} catch (final Throwable ex) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java
index 6e614e8..75262e2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java
@@ -19,7 +19,6 @@
package org.apache.isis.core.metamodel.facets.object.title.annotation;
-import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@@ -30,10 +29,9 @@ import org.apache.isis.applib.annotation.Title;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.core.metamodel.context.MetaModelContext;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
import org.apache.isis.core.metamodel.facetapi.FeatureType;
import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
-import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.Evaluators;
import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
import org.apache.isis.core.metamodel.facets.fallback.FallbackFacetFactory;
import org.apache.isis.core.metamodel.facets.object.title.TitleFacet;
@@ -41,6 +39,10 @@ import org.apache.isis.core.metamodel.facets.object.title.methods.TitleFacetViaM
import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
import org.apache.isis.core.metamodel.specloader.validator.ValidationFailure;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.val;
+
public class TitleAnnotationFacetFactory
extends FacetFactoryAbstract
implements MetaModelRefiner {
@@ -56,35 +58,28 @@ implements MetaModelRefiner {
*/
@Override
public void process(final ProcessClassContext processClassContext) {
- final Class<?> cls = processClassContext.getCls();
- final FacetHolder facetHolder = processClassContext.getFacetHolder();
-
- final var evaluators = Annotations.getEvaluators(cls, Title.class);
- if (evaluators.isEmpty()) {
- return;
- }
-
- sort(evaluators);
- final var titleComponents =
- Can.ofCollection(evaluators)
- .map(TitleFacetViaTitleAnnotation.TitleComponent::of);
+ val cls = processClassContext.getCls();
+ val facetHolder = processClassContext.getFacetHolder();
- addFacet(new TitleFacetViaTitleAnnotation(titleComponents, facetHolder));
+ addFacetIfPresent(TitleFacetViaTitleAnnotation.create(cls, facetHolder));
}
- public static void sort(final List<Annotations.Evaluator<Title>> evaluators) {
- Collections.sort(evaluators, new Comparator<Annotations.Evaluator<Title>>() {
- Comparator<String> comparator = new SequenceComparator();
+ // static comparator memoization
+ @Getter(lazy = true, value = AccessLevel.PACKAGE)
+ private static final Comparator<Evaluators.Evaluator<Title>> sequenceComparator =
+ new Comparator<Evaluators.Evaluator<Title>>() {
+ final Comparator<String> comparator = new SequenceComparator();
+
+ @Override
+ public int compare(final Evaluators.Evaluator<Title> o1, final Evaluators.Evaluator<Title> o2) {
+ final Title a1 = o1.getAnnotation();
+ final Title a2 = o2.getAnnotation();
+ return comparator.compare(a1.sequence(), a2.sequence());
+ }
+ };
- @Override
- public int compare(final Annotations.Evaluator<Title> o1, final Annotations.Evaluator<Title> o2) {
- final Title a1 = o1.getAnnotation();
- final Title a2 = o2.getAnnotation();
- return comparator.compare(a1.sequence(), a2.sequence());
- }
- });
- }
+ @Deprecated //FIXME[ISI-2774] I believe we have sequence comparators already else where (dewey order)
static class SequenceComparator implements Comparator<String> {
@Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java
index d6fcdbb..f54e30a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java
@@ -21,6 +21,7 @@ package org.apache.isis.core.metamodel.facets.object.title.annotation;
import java.lang.reflect.Method;
import java.util.List;
+import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
@@ -29,10 +30,13 @@ import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.functions._Predicates;
+import org.apache.isis.commons.internal.reflection._Reflect.InterfacePolicy;
+import org.apache.isis.commons.internal.reflection._Reflect.TypeHierarchyPolicy;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.Annotations;
-import org.apache.isis.core.metamodel.facets.Annotations.MethodEvaluator;
+import org.apache.isis.core.metamodel.facets.Evaluators;
+import org.apache.isis.core.metamodel.facets.Evaluators.MethodEvaluator;
import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.object.title.TitleFacet;
import org.apache.isis.core.metamodel.facets.object.title.TitleFacetAbstract;
import org.apache.isis.core.metamodel.spec.ManagedObject;
@@ -46,11 +50,30 @@ public class TitleFacetViaTitleAnnotation
extends TitleFacetAbstract
implements ImperativeFacet {
+ public static Optional<TitleFacet> create(
+ final @NonNull Class<?> cls,
+ final @NonNull FacetHolder holder){
+
+ val titleComponents = Evaluators.streamEvaluators(cls,
+ Title.class,
+ TypeHierarchyPolicy.EXCLUDE,
+ InterfacePolicy.INCLUDE)
+ .sorted(TitleAnnotationFacetFactory.getSequenceComparator())
+ .map(TitleFacetViaTitleAnnotation.TitleComponent::of)
+ .collect(Can.toCan());
+
+ if (titleComponents.isEmpty()) {
+ return Optional.empty();
+ }
+
+ return Optional.of(new TitleFacetViaTitleAnnotation(titleComponents, holder));
+ }
+
@Getter private final Can<TitleComponent> components;
@Getter(onMethod_ = {@Override}) private final @NonNull Can<Method> methods;
- public TitleFacetViaTitleAnnotation(final Can<TitleComponent> components, final FacetHolder holder) {
+ protected TitleFacetViaTitleAnnotation(final Can<TitleComponent> components, final FacetHolder holder) {
super(holder);
this.components = components;
@@ -151,7 +174,7 @@ implements ImperativeFacet {
public static class TitleComponent {
- public static TitleComponent of(final Annotations.Evaluator<Title> titleEvaluator) {
+ public static TitleComponent of(final Evaluators.Evaluator<Title> titleEvaluator) {
final Title annotation = titleEvaluator.getAnnotation();
final String prepend = annotation != null ? annotation.prepend() : " ";
final String append = annotation != null ? annotation.append() : "";
@@ -161,13 +184,13 @@ implements ImperativeFacet {
@Getter private final String prepend;
@Getter private final String append;
- @Getter private final Annotations.Evaluator<Title> titleEvaluator;
+ @Getter private final Evaluators.Evaluator<Title> titleEvaluator;
private final int abbreviateTo;
private TitleComponent(
final String prepend,
final String append,
- final Annotations.Evaluator<Title> titleEvaluator,
+ final Evaluators.Evaluator<Title> titleEvaluator,
final int abbreviateTo) {
super();
this.prepend = prepend;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/DomainIncludeAnnotationEnforcesMetamodelContributionValidator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/DomainIncludeAnnotationEnforcesMetamodelContributionValidator.java
index d68313a..2a6d572 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/DomainIncludeAnnotationEnforcesMetamodelContributionValidator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/DomainIncludeAnnotationEnforcesMetamodelContributionValidator.java
@@ -32,7 +32,7 @@ import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.collections._Sets;
import org.apache.isis.commons.internal.reflection._Annotations;
-import org.apache.isis.commons.internal.reflection._MethodCache;
+import org.apache.isis.commons.internal.reflection._ClassCache;
import org.apache.isis.commons.internal.reflection._Reflect;
import org.apache.isis.core.metamodel.commons.MethodUtil;
import org.apache.isis.core.metamodel.context.MetaModelContext;
@@ -54,12 +54,12 @@ import lombok.val;
public class DomainIncludeAnnotationEnforcesMetamodelContributionValidator
extends MetaModelVisitingValidatorAbstract {
- private final _MethodCache methodCache;
+ private final _ClassCache methodCache;
@Inject
public DomainIncludeAnnotationEnforcesMetamodelContributionValidator(final MetaModelContext mmc) {
super(mmc);
- this.methodCache = _MethodCache.getInstance();
+ this.methodCache = _ClassCache.getInstance();
}
@Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/MethodFinderUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/MethodFinderUtils.java
index 82575d3..126c7e9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/MethodFinderUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/methods/MethodFinderUtils.java
@@ -29,7 +29,7 @@ import java.util.stream.Stream;
import org.apache.isis.applib.services.i18n.TranslatableString;
import org.apache.isis.commons.collections.Can;
-import org.apache.isis.commons.internal.reflection._MethodCache;
+import org.apache.isis.commons.internal.reflection._ClassCache;
import org.apache.isis.commons.internal.reflection._Reflect;
import org.apache.isis.core.metamodel.commons.MethodUtil;
import org.apache.isis.core.metamodel.facetapi.MethodRemover;
@@ -66,7 +66,7 @@ public final class MethodFinderUtils {
final Class<?> expectedReturnType,
final Class<?>[] paramTypes) {
- val methodCache = _MethodCache.getInstance();
+ val methodCache = _ClassCache.getInstance();
val method = options.getEncapsulationPolicy().isEncapsulatedMembersSupported()
? methodCache.lookupPublicOrDeclaredMethod(type, name, paramTypes)
@@ -361,7 +361,7 @@ public final class MethodFinderUtils {
public static Stream<Method> streamMethods(
final MethodFinderOptions options,
final Class<?> type) {
- val methodCache = _MethodCache.getInstance();
+ val methodCache = _ClassCache.getInstance();
return options.getEncapsulationPolicy().isEncapsulatedMembersSupported()
? methodCache.streamPublicOrDeclaredMethods(type)
: methodCache.streamPublicMethods(type)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorAbstract.java
index fe36f56..1da9cde 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorAbstract.java
@@ -25,7 +25,7 @@ import java.util.Set;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.commons.internal.collections._Sets;
import org.apache.isis.commons.internal.proxy._ProxyFactoryService;
-import org.apache.isis.commons.internal.reflection._MethodCache;
+import org.apache.isis.commons.internal.reflection._ClassCache;
import org.apache.isis.core.metamodel.commons.ClassUtil;
import lombok.NonNull;
@@ -33,7 +33,7 @@ import lombok.val;
public abstract class ClassSubstitutorAbstract implements ClassSubstitutor {
- private final _MethodCache methodCache = _MethodCache.getInstance();
+ private final _ClassCache methodCache = _ClassCache.getInstance();
@Override
public final Substitution getSubstitution(@NonNull final Class<?> cls) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/FacetedMethodsBuilder.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
index 8b6207d..1ac1895 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
@@ -42,7 +42,7 @@ import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.collections._Sets;
import org.apache.isis.commons.internal.reflection._Annotations;
-import org.apache.isis.commons.internal.reflection._MethodCache;
+import org.apache.isis.commons.internal.reflection._ClassCache;
import org.apache.isis.commons.internal.reflection._Reflect;
import org.apache.isis.core.metamodel.commons.CanBeVoid;
import org.apache.isis.core.metamodel.commons.MethodUtil;
@@ -143,7 +143,7 @@ implements HasMetaModelContext {
this.isMemberAnnotationsRequired =
introspectionPolicy().getMemberAnnotationPolicy().isMemberAnnotationsRequired();
- val methodCache = _MethodCache.getInstance();
+ val methodCache = _ClassCache.getInstance();
val methodsRemaining = introspectionPolicy().getEncapsulationPolicy().isEncapsulatedMembersSupported()
? methodCache.streamPublicOrDeclaredMethods(introspectedClass)
: methodCache.streamPublicMethods(introspectedClass);
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java
index f614d09..6af1bed 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java
@@ -36,7 +36,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import org.apache.isis.applib.annotation.Title;
import org.apache.isis.core.metamodel.facetapi.Facet;
import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
-import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.Evaluators;
import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessClassContext;
import org.apache.isis.core.metamodel.facets.object.title.TitleFacet;
import org.apache.isis.core.metamodel.facets.object.title.annotation.TitleAnnotationFacetFactory;
@@ -86,8 +86,8 @@ extends AbstractFacetFactoryJUnit4TestCase {
final List<Method> titleMethods = Arrays.asList(Customer.class.getMethod("someTitle"));
for (int i = 0; i < titleMethods.size(); i++) {
- final Annotations.MethodEvaluator<Title> titleEvaluator =
- (Annotations.MethodEvaluator<Title>) titleFacetViaTitleAnnotation.getComponents().getElseFail(i)
+ final Evaluators.MethodEvaluator<Title> titleEvaluator =
+ (Evaluators.MethodEvaluator<Title>) titleFacetViaTitleAnnotation.getComponents().getElseFail(i)
.getTitleEvaluator();
Assert.assertEquals(titleMethods.get(i),
@@ -114,7 +114,7 @@ extends AbstractFacetFactoryJUnit4TestCase {
}
- @Ignore // to re-instate
+ @Ignore //FIXME[ISI-2774] to re-instate
@Test
public void testTitleAnnotatedMethodsPickedUpOnClass() throws Exception {
@@ -130,8 +130,8 @@ extends AbstractFacetFactoryJUnit4TestCase {
//final List<TitleComponent> components = titleFacetViaTitleAnnotation.getComponents();
for (int i = 0; i < titleMethods.size(); i++) {
- final Annotations.MethodEvaluator<Title> titleEvaluator =
- (Annotations.MethodEvaluator<Title>) titleFacetViaTitleAnnotation.getComponents().getElseFail(i)
+ final Evaluators.MethodEvaluator<Title> titleEvaluator =
+ (Evaluators.MethodEvaluator<Title>) titleFacetViaTitleAnnotation.getComponents().getElseFail(i)
.getTitleEvaluator();
Assert.assertEquals(titleMethods.get(i),
@@ -206,7 +206,7 @@ extends AbstractFacetFactoryJUnit4TestCase {
}
- @Ignore // to re-instate
+ @Ignore //FIXME[ISI-2774] to re-instate
@Test
public void titleAnnotatedMethodsSomeOfWhichReturnNulls() throws Exception {
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleFacetViaTitleAnnotationTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleFacetViaTitleAnnotationTest.java
index 0bdde4d..1eb93d4 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleFacetViaTitleAnnotationTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleFacetViaTitleAnnotationTest.java
@@ -16,11 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.isis.core.metamodel.facets.object.ident.title.annotation;
-import java.util.List;
-
import org.jmock.Expectations;
import org.jmock.Sequence;
import org.jmock.auto.Mock;
@@ -32,20 +29,15 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import org.apache.isis.applib.annotation.Title;
-import org.apache.isis.commons.collections.Can;
import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2;
import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2.Mode;
import org.apache.isis.core.metamodel._testing.MetaModelContext_forTesting;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.Annotations;
-import org.apache.isis.core.metamodel.facets.object.title.annotation.TitleAnnotationFacetFactory;
import org.apache.isis.core.metamodel.facets.object.title.annotation.TitleFacetViaTitleAnnotation;
import org.apache.isis.core.metamodel.objectmanager.ObjectManager;
import org.apache.isis.core.metamodel.spec.ManagedObject;
-import lombok.val;
-
public class TitleFacetViaTitleAnnotationTest {
@Rule
@@ -95,14 +87,12 @@ public class TitleFacetViaTitleAnnotationTest {
@Test
public void testTitle() throws Exception {
- final List<Annotations.Evaluator<Title>> evaluatorList = Annotations
- .getEvaluators(NormalDomainObject.class, Title.class);
- TitleAnnotationFacetFactory.sort(evaluatorList);
+ final TitleFacetViaTitleAnnotation facet =
+ (TitleFacetViaTitleAnnotation) TitleFacetViaTitleAnnotation
+ .create(NormalDomainObject.class, mockFacetHolder)
+ .orElse(null);
- val components = Can.ofCollection(evaluatorList)
- .map(TitleFacetViaTitleAnnotation.TitleComponent::of);
- final TitleFacetViaTitleAnnotation facet = new TitleFacetViaTitleAnnotation(components, mockFacetHolder);
final NormalDomainObject normalPojo = new NormalDomainObject();
final Sequence sequence = context.sequence("in-title-element-order");
context.checking(new Expectations() {
@@ -132,13 +122,13 @@ public class TitleFacetViaTitleAnnotationTest {
@Test
public void titleThrowsException() {
- final List<Annotations.Evaluator<Title>> evaluators = Annotations
- .getEvaluators(DomainObjectWithProblemInItsAnnotatedTitleMethod.class, Title.class);
+ final TitleFacetViaTitleAnnotation facet =
+ (TitleFacetViaTitleAnnotation) TitleFacetViaTitleAnnotation
+ .create(DomainObjectWithProblemInItsAnnotatedTitleMethod.class, mockFacetHolder)
+ .orElse(null);
- val components = Can.ofCollection(evaluators)
- .map(TitleFacetViaTitleAnnotation.TitleComponent::of);
- final TitleFacetViaTitleAnnotation facet = new TitleFacetViaTitleAnnotation(components, mockFacetHolder);
- final DomainObjectWithProblemInItsAnnotatedTitleMethod screwedPojo = new DomainObjectWithProblemInItsAnnotatedTitleMethod();
+ final DomainObjectWithProblemInItsAnnotatedTitleMethod screwedPojo =
+ new DomainObjectWithProblemInItsAnnotatedTitleMethod();
context.checking(new Expectations() {
{
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/navparent/NavigableParentFacetMethodTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/navparent/NavigableParentFacetMethodTest.java
index 453c08d..0aa0475 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/navparent/NavigableParentFacetMethodTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/navparent/NavigableParentFacetMethodTest.java
@@ -29,7 +29,7 @@ import org.junit.Before;
import org.junit.Test;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.object.navparent.method.NavigableParentFacetMethod;
+import org.apache.isis.core.metamodel.facets.object.navparent.method.NavigableParentFacetViaGetterMethod;
import org.apache.isis.core.metamodel.spec.ManagedObject;
import static org.hamcrest.CoreMatchers.is;
@@ -40,7 +40,7 @@ public class NavigableParentFacetMethodTest {
private final Mockery mockery = new JUnit4Mockery();
- private NavigableParentFacetMethod facet;
+ private NavigableParentFacetViaGetterMethod facet;
private FacetHolder mockFacetHolder;
private ManagedObject mockOwningAdapter;
@@ -60,7 +60,7 @@ public class NavigableParentFacetMethodTest {
mockFacetHolder = mockery.mock(FacetHolder.class);
mockOwningAdapter = mockery.mock(ManagedObject.class);
final Method navigableParentMethod = DomainObjectWithProblemInNavigableParentMethod.class.getMethod("parent");
- facet = new NavigableParentFacetMethod(navigableParentMethod, mockFacetHolder);
+ facet = new NavigableParentFacetViaGetterMethod(navigableParentMethod, mockFacetHolder);
mockery.checking(new Expectations() {
{
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactoryTest.java
index a109572..a5ae96f 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/navparent/annotation/NavigableParentAnnotationFacetFactoryTest.java
@@ -32,7 +32,7 @@ import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessClassContext;
import org.apache.isis.core.metamodel.facets.object.navparent.NavigableParentFacet;
import org.apache.isis.core.metamodel.facets.object.navparent.annotation.NavigableParentTestSamples.DomainObjectA;
-import org.apache.isis.core.metamodel.facets.object.navparent.method.NavigableParentFacetMethod;
+import org.apache.isis.core.metamodel.facets.object.navparent.method.NavigableParentFacetViaGetterMethod;
import org.apache.isis.core.metamodel.spec.ManagedObject;
public class NavigableParentAnnotationFacetFactoryTest
@@ -70,9 +70,9 @@ extends AbstractFacetFactoryJUnit4TestCase {
final Facet facet = facetedMethod.getFacet(NavigableParentFacet.class);
Assert.assertNotNull(facet);
- Assert.assertTrue(facet instanceof NavigableParentFacetMethod);
+ Assert.assertTrue(facet instanceof NavigableParentFacetViaGetterMethod);
- final NavigableParentFacetMethod navigableParentFacetMethod = (NavigableParentFacetMethod) facet;
+ final NavigableParentFacetViaGetterMethod navigableParentFacetMethod = (NavigableParentFacetViaGetterMethod) facet;
final Method parentMethod = domainClass.getMethod(parentMethodName);
Assert.assertEquals(