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/05/04 11:11:33 UTC
[isis] branch master updated: ISIS-2642: simplify TypeOfFacet
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 50010e7 ISIS-2642: simplify TypeOfFacet utilities
50010e7 is described below
commit 50010e7305aeade689bb7c5166fcd2463d7e8a27
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue May 4 13:11:17 2021 +0200
ISIS-2642: simplify TypeOfFacet utilities
---
.../isis/commons/internal/collections/_Arrays.java | 8 +-
.../commons/internal/collections/_Collections.java | 83 ++++++++++-----
.../commons/internal/collections/_ArraysTest.java | 6 +-
.../metamodel/_testing/_ServiceInjectorLegacy.java | 3 +-
.../metamodel/commons/CanonicalParameterUtil.java | 6 +-
.../isis/core/metamodel/facets/FacetedMethod.java | 36 +++----
.../facets/actcoll/typeof/TypeOfFacet.java | 111 ++++++++-------------
.../action/ActionAnnotationFacetFactory.java | 13 +--
.../ActionAnnotationFacetFactoryTest_TypeOf.java | 2 +-
9 files changed, 130 insertions(+), 138 deletions(-)
diff --git a/commons/src/main/java/org/apache/isis/commons/internal/collections/_Arrays.java b/commons/src/main/java/org/apache/isis/commons/internal/collections/_Arrays.java
index 390ac89..589f400 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/collections/_Arrays.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/collections/_Arrays.java
@@ -326,14 +326,14 @@ public final class _Arrays {
/**
* Returns the inferred element type of the specified array type
* @param arrayType - type of the array for which to infer the element type
- * @return inferred type or null if inference fails
+ * @return optionally the inferred type, based on whether inference is possible
*/
- public static @Nullable Class<?> inferComponentTypeIfAny(
+ public static Optional<Class<?>> inferComponentType(
final @Nullable Class<?> arrayType) {
if(!isArrayType(arrayType)) {
- return null;
+ return Optional.empty();
}
- return arrayType.getComponentType();
+ return Optional.ofNullable(arrayType.getComponentType());
}
// -- ACCESSOR
diff --git a/commons/src/main/java/org/apache/isis/commons/internal/collections/_Collections.java b/commons/src/main/java/org/apache/isis/commons/internal/collections/_Collections.java
index 4b6d359..62d239f 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/collections/_Collections.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/collections/_Collections.java
@@ -20,6 +20,8 @@
package org.apache.isis.commons.internal.collections;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -43,7 +45,9 @@ import javax.annotation.Nullable;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.base._With;
+import org.apache.isis.commons.internal.reflection._Generics;
+import lombok.NonNull;
import lombok.val;
/**
@@ -68,11 +72,11 @@ public final class _Collections {
* @param cls
* @return whether {@code cls} implements the java.util.Collection interface
*/
- public static boolean isCollectionType(@Nullable final Class<?> cls) {
+ public static boolean isCollectionType(final @Nullable Class<?> cls) {
return cls!=null ? java.util.Collection.class.isAssignableFrom(cls) : false;
}
- public static boolean isCanType(@Nullable final Class<?> cls) {
+ public static boolean isCanType(final @Nullable Class<?> cls) {
return cls!=null ? Can.class.isAssignableFrom(cls) : false;
}
@@ -106,7 +110,7 @@ public final class _Collections {
* @param list
* @return null if {@code list} is null
*/
- public static <T> Collection<T> asUnmodifiableCollection(@Nullable final List<T> list) {
+ public static <T> Collection<T> asUnmodifiableCollection(final @Nullable List<T> list) {
if(list==null) {
return null;
}
@@ -119,7 +123,7 @@ public final class _Collections {
*
* @param list
*/
- public static <T> List<T> asUnmodifiableList(@Nullable final List<T> list) {
+ public static <T> List<T> asUnmodifiableList(final @Nullable List<T> list) {
if(list==null) {
return null;
}
@@ -135,7 +139,7 @@ public final class _Collections {
* @param list
* @return null if {@code list} is null
*/
- public static <T> Set<T> asUnmodifiableSet(@Nullable final List<T> list) {
+ public static <T> Set<T> asUnmodifiableSet(final @Nullable List<T> list) {
if(list==null) {
return null;
}
@@ -154,7 +158,7 @@ public final class _Collections {
* @param list
* @return null if {@code list} is null
*/
- public static <T> SortedSet<T> asUnmodifiableSortedSet(@Nullable final List<T> list) {
+ public static <T> SortedSet<T> asUnmodifiableSortedSet(final @Nullable List<T> list) {
if(list==null) {
return null;
}
@@ -272,6 +276,31 @@ public final class _Collections {
// -- ELEMENT TYPE INFERENCE
+
+ public static Optional<Class<?>> inferElementType(final @NonNull Parameter param) {
+ final Class<?> parameterType = param.getType();
+ final Class<?> declaringType = param.getDeclaringExecutable().getDeclaringClass();
+ final Type genericParameterType = param.getParameterizedType();
+
+ //TODO use _Generics instead
+ return inferElementType(parameterType, genericParameterType);
+ }
+
+ public static Optional<Class<?>> inferElementType(final @NonNull Method method) {
+
+ val returnType = method.getReturnType();
+
+ if (_Collections.isCollectionType(returnType)
+ || _Collections.isCanType(returnType)) {
+
+ return _Generics.streamGenericTypeArgumentsOfMethodReturnType(method)
+ .findFirst();
+ }
+
+ return Optional.empty();
+ }
+
+
/**
* If the {@code collectionType} represents a collection then returns returns the inferred element type of the
* specified {@code genericType}
@@ -279,18 +308,18 @@ public final class _Collections {
* @param genericType as associated with {@code collectionType} (as available for fields or method parameters)
* @return inferred type or null if inference fails
*/
- public static @Nullable Class<?> inferElementTypeIfAny(
- @Nullable final Class<?> collectionType,
- @Nullable final Type genericType) {
+ private static Optional<Class<?>> inferElementType(
+ final @Nullable Class<?> collectionType,
+ final @Nullable Type genericType) {
if(collectionType == null || genericType==null) {
- return null;
+ return Optional.empty();
}
if(!isCollectionType(collectionType) && !isCanType(collectionType)) {
- return null;
+ return Optional.empty();
}
-
+
if(genericType instanceof ParameterizedType) {
final ParameterizedType parameterizedType = (ParameterizedType) genericType;
final Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
@@ -298,21 +327,19 @@ public final class _Collections {
// handle e.g. List<Sometype>
final Type actualTypeArgument = actualTypeArguments[0];
if(actualTypeArgument instanceof Class) {
- final Class<?> actualType = (Class<?>) actualTypeArgument;
- return actualType;
+ return Optional.of((Class<?>) actualTypeArgument);
}
// also handle e.g. List<Sometype<T>>
if(actualTypeArgument instanceof ParameterizedType) {
final Type innerParameterizedType = ((ParameterizedType) actualTypeArgument).getRawType();
if(innerParameterizedType instanceof Class) {
- final Class<?> actualType = (Class<?>) innerParameterizedType;
- return actualType;
+ return Optional.of((Class<?>) innerParameterizedType);
}
}
}
}
- return null;
+ return Optional.empty();
}
/**
@@ -322,15 +349,14 @@ public final class _Collections {
* based on whether parameter is a (collection or array) and has an infer-able element type
*/
public static Optional<Class<?>> inferElementTypeFromArrayOrCollection(
- @Nullable final Class<?> collectionType,
- @Nullable final Type genericType) {
+ final @Nullable Class<?> collectionType,
+ final @Nullable Type genericType) {
- val fromArray = Optional.ofNullable(_Arrays.inferComponentTypeIfAny(collectionType));
+ val fromArray = _Arrays.inferComponentType(collectionType);
if(fromArray.isPresent()) {
return fromArray;
}
- val fromCollection = Optional.ofNullable(_Collections.inferElementTypeIfAny(collectionType, genericType));
- return fromCollection;
+ return _Collections.inferElementType(collectionType, genericType);
}
/**
@@ -339,17 +365,18 @@ public final class _Collections {
* @param field
* @return inferred type or null if inference fails
*/
- public static @Nullable Class<?> inferElementTypeIfAny(@Nullable final Field field) {
+ public static Optional<Class<?>> inferElementType(final @Nullable Field field) {
if(field==null) {
return null;
}
- return inferElementTypeIfAny(field.getType(), field.getGenericType());
+ return inferElementType(field.getType(), field.getGenericType());
}
// -- TO STRING
- public static String toStringJoining(@Nullable Collection<?> collection, String delimiter) {
- _With.requires(delimiter, "delimiter");
+ public static String toStringJoining(
+ final @Nullable Collection<?> collection,
+ final @NonNull String delimiter) {
return _NullSafe.stream(collection)
.map(x->""+x)
.collect(Collectors.joining(delimiter));
@@ -359,4 +386,8 @@ public final class _Collections {
return toStringJoining(collection, "\n");
}
+
+
+
+
}
diff --git a/commons/src/test/java/org/apache/isis/commons/internal/collections/_ArraysTest.java b/commons/src/test/java/org/apache/isis/commons/internal/collections/_ArraysTest.java
index d8ff778..cd0dfb6 100644
--- a/commons/src/test/java/org/apache/isis/commons/internal/collections/_ArraysTest.java
+++ b/commons/src/test/java/org/apache/isis/commons/internal/collections/_ArraysTest.java
@@ -333,9 +333,9 @@ class _ArraysTest {
*/
@Test
void testInferComponentTypeIfAny() {
- assertEquals(null, _Arrays.inferComponentTypeIfAny(null));
- assertEquals(int.class, _Arrays.inferComponentTypeIfAny(int[].class));
- assertEquals(Integer.class, _Arrays.inferComponentTypeIfAny(Integer[].class));
+ assertEquals(null, _Arrays.inferComponentType(null).orElse(null));
+ assertEquals(int.class, _Arrays.inferComponentType(int[].class).orElse(null));
+ assertEquals(Integer.class, _Arrays.inferComponentType(Integer[].class).orElse(null));
}
/**
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_ServiceInjectorLegacy.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_ServiceInjectorLegacy.java
index 1696435..0099720 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_ServiceInjectorLegacy.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_ServiceInjectorLegacy.java
@@ -130,7 +130,8 @@ final class _ServiceInjectorLegacy implements ServiceInjector {
}
// inject matching services into a field of type Collection<T> if a generic type T is present
- final Class<?> elementType = _Collections.inferElementTypeIfAny(field);
+ final Class<?> elementType = _Collections.inferElementType(field)
+ .orElse(null);
if(elementType!=null) {
injectToField_nonScalar(targetPojo, field, elementType, onNotResolvable);
return;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/CanonicalParameterUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/CanonicalParameterUtil.java
index f5c9f62..c9569f4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/CanonicalParameterUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/CanonicalParameterUtil.java
@@ -109,12 +109,12 @@ public final class CanonicalParameterUtil {
}
if(_Arrays.isArrayType(parameterType)) {
- final Class<?> componentType = _Arrays.inferComponentTypeIfAny(parameterType);
- if(componentType==null) {
+ final Class<?> elementType = _Arrays.inferComponentType(parameterType).orElse(null);
+ if(elementType==null) {
return obj;
}
@SuppressWarnings("rawtypes") final List list = (List)obj;
- return _Arrays.toArray(_Casts.uncheckedCast(list), componentType);
+ return _Arrays.toArray(_Casts.uncheckedCast(list), elementType);
}
// allow no side effects on Collection arguments
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
index 215ba02..38488c8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
@@ -107,39 +107,35 @@ public class FacetedMethod extends TypedHolderDefault implements IdentifiedHolde
final Class<?> declaringType,
final Method actionMethod) {
- final Class<?>[] parameterTypes = actionMethod.getParameterTypes();
- final Type[] genericParameterTypes = actionMethod.getGenericParameterTypes();
- final List<FacetedMethodParameter> actionParams = _Lists.newArrayList();
-
- for (int paramNum = 0; paramNum < parameterTypes.length; paramNum++) {
-
- final Class<?> parameterType = parameterTypes[paramNum];
- final Type genericParameterType = genericParameterTypes[paramNum];
-
+ final List<FacetedMethodParameter> actionParams = _Lists.newArrayList(actionMethod.getParameterCount());
+
+ for(val param : actionMethod.getParameters()) {
+
+ final Class<?> parameterType = param.getType();
+ final Type genericParameterType = param.getParameterizedType();
+
final FeatureType featureType =
_Collections.inferElementTypeFromArrayOrCollection(parameterType, genericParameterType).isPresent()
? FeatureType.ACTION_PARAMETER_COLLECTION
: FeatureType.ACTION_PARAMETER_SCALAR;
- final FacetedMethodParameter fmp = new FacetedMethodParameter(featureType, declaringType, actionMethod, parameterType);
- actionParams.add(fmp);
+ val facetedMethodParam =
+ new FacetedMethodParameter(featureType, declaringType, actionMethod, parameterType);
+ actionParams.add(facetedMethodParam);
// this is based on similar logic to ActionAnnotationFacetFactory#processTypeOf
if(featureType == FeatureType.ACTION_PARAMETER_COLLECTION) {
final CollectionSemanticsFacet semanticsFacet =
- CollectionSemanticsFacetDefault.forParamType(parameterType, fmp);
+ CollectionSemanticsFacetDefault.forParamType(parameterType, facetedMethodParam);
FacetUtil.addFacet(semanticsFacet);
- TypeOfFacet typeOfFacet = TypeOfFacet.Util
- .inferFromParameterType(fmp, parameterType, genericParameterType);
-
-
- // copy over (corresponds to similar code for OneToManyAssociation in FacetMethodsBuilder).
- if(typeOfFacet != null ) {
+ TypeOfFacet.inferFromParameterType(facetedMethodParam, param)
+ .ifPresent(typeOfFacet->{
+ // copy over (corresponds to similar code for OneToManyAssociation in FacetMethodsBuilder).
FacetUtil.addFacet(typeOfFacet);
- fmp.setType(typeOfFacet.value());
- }
+ facetedMethodParam.setType(typeOfFacet.value());
+ });
}
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
index 78ae0f7..8652e10 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
@@ -20,12 +20,12 @@
package org.apache.isis.core.metamodel.facets.actcoll.typeof;
import java.lang.reflect.Method;
-import java.lang.reflect.Type;
+import java.lang.reflect.Parameter;
+import java.util.Optional;
import org.apache.isis.applib.annotation.Collection;
import org.apache.isis.commons.internal.collections._Arrays;
import org.apache.isis.commons.internal.collections._Collections;
-import org.apache.isis.commons.internal.reflection._Generics;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
import org.apache.isis.core.metamodel.facets.SingleClassValueFacet;
@@ -41,80 +41,49 @@ import lombok.val;
*/
public interface TypeOfFacet extends SingleClassValueFacet {
- public static class Util {
- private Util(){}
+ // -- FACTORIES
+
+ static TypeOfFacet inferredFromArray(
+ final FacetHolder holder,
+ final Class<?> elementType) {
+ return new TypeOfFacetInferredFromArray(elementType, holder);
+ }
+
+ static TypeOfFacet inferredFromGenerics(
+ final FacetHolder holder,
+ final Class<?> elementType) {
+ return new TypeOfFacetInferredFromGenerics(elementType, holder);
+ }
+
+ static Optional<TypeOfFacet> inferFromParameterType(
+ final FacetHolder holder,
+ final Parameter param) {
- public static TypeOfFacet inferFromParameterType(
- final FacetHolder holder,
- final Class<?> parameterType,
- final Type genericParameterType) {
+ val paramType = param.getType();
- TypeOfFacet typeOfFacet = inferFromGenericParamType(holder, parameterType, genericParameterType);
-
- if(typeOfFacet == null ) {
- if (_Arrays.isArrayType(parameterType)) {
- typeOfFacet = inferFromArrayType(holder, parameterType);
- }
- }
-
- return typeOfFacet;
+ if (_Arrays.isArrayType(paramType)) {
+ return _Arrays.inferComponentType(paramType)
+ .map(elementType->inferredFromArray(holder, elementType));
}
- public static TypeOfFacet inferFromMethodReturnType(
- final FacetHolder holder,
- final Class<?> methodOwner,
- final Method method) {
-
- // infer from return type
- val returnType = method.getReturnType();
- TypeOfFacet typeOfFacet = inferFromArrayType(holder, returnType);
-
- // infer from generic return type
- if(typeOfFacet == null) {
- typeOfFacet = inferFromGenericReturnType(methodOwner, method, holder);
- }
-
- return typeOfFacet;
- }
+ return _Collections.inferElementType(param)
+ .map(elementType->inferredFromGenerics(holder, elementType));
+ }
+
+ static Optional<TypeOfFacet> inferFromMethodReturnType(
+ final FacetHolder holder,
+ final Method method) {
-
- private static TypeOfFacet inferFromGenericReturnType(
- final Class<?> cls,
- final Method method,
- final FacetHolder holder) {
-
- final Class<?> methodReturnType = method.getReturnType();
- if (!_Collections.isCollectionType(methodReturnType)
- && !_Collections.isCanType(methodReturnType)) {
- return null;
- }
-
- return _Generics.streamGenericTypeArgumentsOfMethodReturnType(method)
- .findFirst()
- .map(elementType->new TypeOfFacetInferredFromGenerics(elementType, holder))
- .orElse(null);
- }
-
- private static TypeOfFacet inferFromArrayType(
- final FacetHolder holder,
- final Class<?> type) {
-
- final Class<?> elementType = _Arrays.inferComponentTypeIfAny(type);
- return elementType != null
- ? new TypeOfFacetInferredFromArray(elementType, holder)
- : null;
- }
-
- private static TypeOfFacet inferFromGenericParamType(
- final FacetHolder holder,
- final Class<?> parameterType,
- final Type genericParameterType) {
-
- Class<?> elementType = _Collections.inferElementTypeIfAny(parameterType, genericParameterType);
-
- return elementType != null
- ? new TypeOfFacetInferredFromGenerics(elementType, holder)
- : null;
+ val returnType = method.getReturnType();
+
+ if (_Arrays.isArrayType(returnType)) {
+ return _Arrays.inferComponentType(returnType)
+ .map(elementType->inferredFromArray(holder, elementType));
}
+
+ return _Collections.inferElementType(method)
+ .map(elementType->inferredFromGenerics(holder, elementType));
}
+
+
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
index 7c86e10..fdc9260 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
@@ -253,17 +253,12 @@ extends FacetFactoryAbstract {
}
// check for @Action(typeOf=...)
- TypeOfFacet typeOfFacet = actionIfAny
+ val typeOfFacet = actionIfAny
.map(Action::typeOf)
.filter(typeOf -> typeOf != null && typeOf != Object.class)
- .map(typeOf -> new TypeOfFacetForActionAnnotation(typeOf, facetedMethod))
- .orElse(null);
-
- // infer from generic return type
- if(typeOfFacet == null) {
- val cls = processMethodContext.getCls();
- typeOfFacet = TypeOfFacet.Util.inferFromMethodReturnType(facetedMethod, cls, method);
- }
+ .<TypeOfFacet>map(typeOf -> new TypeOfFacetForActionAnnotation(typeOf, facetedMethod))
+ // else infer from generic type arg if any
+ .orElseGet(()->TypeOfFacet.inferFromMethodReturnType(facetedMethod, method).orElse(null));
super.addFacet(typeOfFacet);
}
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_TypeOf.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_TypeOf.java
index 13bf011..0d45ff6 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_TypeOf.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_TypeOf.java
@@ -169,7 +169,7 @@ public class ActionAnnotationFacetFactoryTest_TypeOf extends ActionAnnotationFac
// then
final TypeOfFacet facet = facetedMethod.getFacet(TypeOfFacet.class);
Assert.assertNotNull(facet);
- Assert.assertTrue(facet instanceof TypeOfFacetInferredFromGenerics);
+ Assert.assertEquals(TypeOfFacetInferredFromGenerics.class, facet.getClass());
assertThat(facet.value(), classEqualTo(Order.class));
}