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 2020/01/19 09:55:59 UTC
[isis] branch master updated: ISIS-2158: polishing
class-substitutor API
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 6f8dc36 ISIS-2158: polishing class-substitutor API
6f8dc36 is described below
commit 6f8dc368e06129d5fb8edce9c056d67fcc7c1fd5
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sun Jan 19 10:55:49 2020 +0100
ISIS-2158: polishing class-substitutor API
---
...jectSpecIdFacetDerivedFromClassNameFactory.java | 4 +-
.../classsubstitutor/ClassSubstitutor.java | 70 +++++++++++++++-------
.../classsubstitutor/ClassSubstitutorAbstract.java | 10 ++--
.../ClassSubstitutorForCollections.java | 12 ++--
.../classsubstitutor/ClassSubstitutorRegistry.java | 31 ++++++++--
.../specloader/SpecificationLoaderDefault.java | 10 ++--
.../specloader/specimpl/FacetedMethodsBuilder.java | 4 +-
.../ClassSubstitutorTest_getClass.java | 6 +-
.../JdoDiscriminatorAnnotationFacetFactory.java | 4 +-
9 files changed, 98 insertions(+), 53 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
index 4d9c8b3..2e2eaae 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
@@ -72,10 +72,10 @@ implements MetaModelRefiner, ObjectSpecIdFacetFactory {
}
val cls = processClassContext.getCls();
val substitute = classSubstitutorRegistry.getSubstitution(cls);
- if(substitute.isIgnore()) {
+ if(substitute.isNeverIntrospect()) {
return;
}
- val objectSpecIdFacet = createObjectSpecIdFacet(facetHolder, substitute.replace(cls));
+ val objectSpecIdFacet = createObjectSpecIdFacet(facetHolder, substitute.apply(cls));
FacetUtil.addFacet(objectSpecIdFacet);
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutor.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutor.java
index 9253fb4..99f2145 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutor.java
@@ -20,6 +20,7 @@
package org.apache.isis.core.metamodel.services.classsubstitutor;
import java.io.Serializable;
+import java.util.function.UnaryOperator;
import javax.annotation.Nullable;
@@ -41,48 +42,71 @@ public interface ClassSubstitutor {
* @since 2.0
*/
@Value(staticConstructor = "of")
- static class Substitution implements Serializable {
+ static class Substitution implements UnaryOperator<Class<?>>, Serializable {
private static final long serialVersionUID = 1L;
- private static final Substitution NOP = Substitution.of(Type.DO_NOT_REPLACE, null);
- private static final Substitution IGNORE = Substitution.of(Type.IGNORE_CLASS, null);
+ private static final Substitution PASSTHROUGH = Substitution.of(Type.PASSTHROUGH, null);
+ private static final Substitution NEVER_REPLACE_CLASS = Substitution.of(Type.NEVER_REPLACE_CLASS, null);
+ private static final Substitution NEVER_INTROSPECT_CLASS = Substitution.of(Type.NEVER_INTROSPECT_CLASS, null);
private static enum Type {
- DO_NOT_REPLACE,
- IGNORE_CLASS,
+ PASSTHROUGH,
+ NEVER_REPLACE_CLASS,
+ NEVER_INTROSPECT_CLASS,
REPLACE_WITH_OTHER_CLASS,
}
@NonNull Type type;
@Nullable Class<?> replacement;
+ // -- FACTORIES
+
+ /**
+ * The result type to be used for a ClassSubstitutor that does not feel responsible
+ * for the (operand-) class, hence acts as a pass-through when aggregating.
+ */
+ public static Substitution passThrough() {
+ return PASSTHROUGH;
+ }
+
/**
- * for framework internal use only, not required for ClassSubstitutor implementations!
- * (forces a class to be never replaced)
+ * Forces the (operand-) class never to be replaced.
+ *
+ * @implNote not required for ClassSubstitutor implementations!
+ * (for framework internal use when aggregating)
*/
- public static Substitution dontReplaceClass() {
- return NOP;
+ public static Substitution neverReplaceClass() {
+ return NEVER_REPLACE_CLASS;
}
- public static Substitution ignoreClass() {
- return IGNORE;
+ public static Substitution neverIntrospect() {
+ return NEVER_INTROSPECT_CLASS;
}
- public static Substitution replaceClass(@lombok.NonNull @org.springframework.lang.NonNull Class<?> cls) {
+ public static Substitution replaceWith(@lombok.NonNull @org.springframework.lang.NonNull Class<?> cls) {
return of(Type.REPLACE_WITH_OTHER_CLASS, cls);
}
+ // -- PREDICATES
+
/**
- * @return whether the replacement is an identity operation (do nothing)
+ * @return whether to act as a pass-through (indifferent)
*/
- public boolean isDoNotReplace() {
- return type == Type.DO_NOT_REPLACE;
+ public boolean isPassThrough() {
+ return type == Type.PASSTHROUGH;
+ }
+
+ /**
+ * @return whether to not replace the class (do nothing)
+ */
+ public boolean isNeverReplace() {
+ return type == Type.NEVER_REPLACE_CLASS;
}
/**
* @return whether to ignore the class (never introspect)
*/
- public boolean isIgnore() {
- return type == Type.IGNORE_CLASS;
+ public boolean isNeverIntrospect() {
+ return type == Type.NEVER_INTROSPECT_CLASS;
}
/**
@@ -92,8 +116,11 @@ public interface ClassSubstitutor {
return type == Type.REPLACE_WITH_OTHER_CLASS;
}
- public Class<?> replace(Class<?> cls) {
- if(isIgnore()) {
+ // -- OPERATOR
+
+ @Override
+ public Class<?> apply(Class<?> cls) {
+ if(isNeverIntrospect()) {
return null;
}
return isReplace() ? getReplacement() : cls;
@@ -105,12 +132,9 @@ public interface ClassSubstitutor {
/**
* @param cls
- * @return Substitution for given {@code cls} if any
- * or Substitution.ignore(), when {@code cls} shall be ignored
- * @implNote most likely do not return Substitution.dontReplaceClass(), return {@code null} instead
+ * @return (non-null) Substitution for given {@code cls}
* @since 2.0
*/
- @Nullable
Substitution getSubstitution(@lombok.NonNull @org.springframework.lang.NonNull Class<?> cls);
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 bea06ad..445a094 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
@@ -33,18 +33,18 @@ import lombok.val;
public abstract class ClassSubstitutorAbstract implements ClassSubstitutor {
@Override
- public Substitution getSubstitution(@NonNull Class<?> cls) {
+ public final Substitution getSubstitution(@NonNull Class<?> cls) {
val replacement = getReplacement(cls);
if(replacement==null) {
- return Substitution.ignoreClass();
+ return Substitution.neverIntrospect();
}
if(cls.equals(replacement)) {
- return null; // NOP
+ return Substitution.passThrough(); // indifferent
}
- return Substitution.replaceClass(replacement) ;
+ return Substitution.replaceWith(replacement) ;
}
- private Class<?> getReplacement(final Class<?> cls) {
+ protected Class<?> getReplacement(final Class<?> cls) {
if(cls == null) {
return null;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
index 920e61d..1fe6adf 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorForCollections.java
@@ -42,20 +42,20 @@ public class ClassSubstitutorForCollections implements ClassSubstitutor {
@Override
public Substitution getSubstitution(@NonNull Class<?> cls) {
if(Vector.class.isAssignableFrom(cls)) {
- return Substitution.replaceClass(Vector.class);
+ return Substitution.replaceWith(Vector.class);
}
if(List.class.isAssignableFrom(cls)) {
- return Substitution.replaceClass(List.class);
+ return Substitution.replaceWith(List.class);
}
if(SortedSet.class.isAssignableFrom(cls)) {
- return Substitution.replaceClass(SortedSet.class);
+ return Substitution.replaceWith(SortedSet.class);
}
if(Set.class.isAssignableFrom(cls)) {
- return Substitution.replaceClass(Set.class);
+ return Substitution.replaceWith(Set.class);
}
if(Collection.class.isAssignableFrom(cls)) {
- return Substitution.replaceClass(Collection.class);
+ return Substitution.replaceWith(Collection.class);
}
- return null; // NOP
+ return Substitution.passThrough(); // indifferent
}
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java
index c20ba96..1ad7249 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java
@@ -30,16 +30,20 @@ import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.apache.isis.applib.annotation.OrderPrecedence;
-import org.apache.isis.core.commons.internal.base._NullSafe;
import org.apache.isis.core.commons.internal.collections._Maps;
+import org.apache.isis.core.commons.internal.functions._Predicates;
import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutor.Substitution;
+import lombok.val;
+import lombok.extern.log4j.Log4j2;
+
/**
* Aggregates all {@link ClassSubstitutor}s.
*/
@Component
@Named("isisMetaModel.ClassSubstitutorRegistry")
@Order(OrderPrecedence.MIDPOINT)
+@Log4j2
public class ClassSubstitutorRegistry {
private final List<ClassSubstitutor> classSubstitutors;
@@ -51,9 +55,13 @@ public class ClassSubstitutorRegistry {
private final Map<Class<?>, Substitution> cache = _Maps.newConcurrentHashMap();
+ /**
+ * @param originalClass
+ * @return (non-null) the aggregated Substitution that applies to given originalClass
+ */
public Substitution getSubstitution(@Nullable final Class<?> originalClass) {
if(originalClass == null) {
- return Substitution.dontReplaceClass();
+ return Substitution.neverReplaceClass();
}
return cache.computeIfAbsent(originalClass, this::findSubstitutionFor);
}
@@ -63,11 +71,24 @@ public class ClassSubstitutorRegistry {
private Substitution findSubstitutionFor(final Class<?> originalClass) {
return classSubstitutors.stream()
- .map(classSubstitutor->classSubstitutor.getSubstitution(originalClass))
- .filter(_NullSafe::isPresent)
+ .map(classSubstitutor->getSubstitutionElseWarn(classSubstitutor, originalClass))
+ .filter(_Predicates.not(Substitution::isPassThrough))
.findFirst()
- .orElse(Substitution.dontReplaceClass());
+ .orElse(Substitution.neverReplaceClass());
}
+ private Substitution getSubstitutionElseWarn(ClassSubstitutor substitutor, Class<?> originalClass) {
+ val substitution = substitutor.getSubstitution(originalClass);
+ if(substitution == null) {
+ log.warn("ClassSubstitutor.getSubstitution(Class) must never return null! "
+ + "However, substitutor {} just did for class argument {}. "
+ + "Pass-through was applied instead.",
+ substitutor.getClass().getName(),
+ originalClass.getClass().getName());
+ return Substitution.passThrough();
+ }
+ return substitution;
+ }
+
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java
index b166bab..a87e03b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java
@@ -354,7 +354,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
// ensure that all types are loadable
if (Arrays.stream(domainTypes)
.map(classSubstitutorRegistry::getSubstitution)
- .anyMatch(Substitution::isIgnore)) {
+ .anyMatch(Substitution::isNeverIntrospect)) {
return false;
}
Arrays.stream(domainTypes).forEach(this::loadSpecification);
@@ -373,11 +373,11 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
requires(upTo, "upTo");
val substitute = classSubstitutorRegistry.getSubstitution(type);
- if (substitute.isIgnore()) {
+ if (substitute.isNeverIntrospect()) {
return null; // never inspect
}
- val substitutedType = substitute.replace(type);
+ val substitutedType = substitute.apply(type);
val typeName = substitutedType.getName();
@@ -519,12 +519,12 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
private void invalidateCache(final Class<?> cls) {
val substitute = classSubstitutorRegistry.getSubstitution(cls);
- if(substitute.isIgnore()) {
+ if(substitute.isNeverIntrospect()) {
return;
}
ObjectSpecification spec =
- loadSpecification(substitute.replace(cls), IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
+ loadSpecification(substitute.apply(cls), IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
while(spec != null) {
val type = spec.getCorrespondingClass();
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 8ede154..2ca54c0 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
@@ -315,7 +315,7 @@ public class FacetedMethodsBuilder {
facetedMethod.setType(elementType);
// skip if class substitutor says so.
- if (classSubstitutorRegistry.getSubstitution(elementType).isIgnore()) {
+ if (classSubstitutorRegistry.getSubstitution(elementType).isNeverIntrospect()) {
continue;
}
@@ -333,7 +333,7 @@ public class FacetedMethodsBuilder {
final Class<?> returnType = accessorMethod.getReturnType();
// skip if class strategy says so.
- if (classSubstitutorRegistry.getSubstitution(returnType).isIgnore()) {
+ if (classSubstitutorRegistry.getSubstitution(returnType).isNeverIntrospect()) {
continue;
}
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/classsubstitutor/ClassSubstitutorTest_getClass.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/classsubstitutor/ClassSubstitutorTest_getClass.java
index 39d7418..8103490 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/classsubstitutor/ClassSubstitutorTest_getClass.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/classsubstitutor/ClassSubstitutorTest_getClass.java
@@ -57,21 +57,21 @@ public class ClassSubstitutorTest_getClass {
@Test
public void regularDomainObject() throws Exception {
val input = SomeDomainObject.class;
- val replacement = classSubstitutorReg.getSubstitution(input).replace(input);
+ val replacement = classSubstitutorReg.getSubstitution(input).apply(input);
assertEquals(input, replacement);
}
@Test
public void someEnum() throws Exception {
val input = SomeDomainObject.SomeEnum.class;
- val replacement = classSubstitutorReg.getSubstitution(input).replace(input);
+ val replacement = classSubstitutorReg.getSubstitution(input).apply(input);
assertEquals(input, replacement);
}
@Test
public void someAnonymousSubtypeOfEnum() throws Exception {
val input = SomeDomainObject.SomeEnum.Foo.getClass();
- val replacement = classSubstitutorReg.getSubstitution(input).replace(input);
+ val replacement = classSubstitutorReg.getSubstitution(input).apply(input);
assertEquals(SomeDomainObject.SomeEnum.class, replacement);
}
diff --git a/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metamodel/facets/object/discriminator/JdoDiscriminatorAnnotationFacetFactory.java b/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metamodel/facets/object/discriminator/JdoDiscriminatorAnnotationFacetFactory.java
index b869dca..13fa490 100644
--- a/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metamodel/facets/object/discriminator/JdoDiscriminatorAnnotationFacetFactory.java
+++ b/persistence/jdo/datanucleus-5/src/main/java/org/apache/isis/persistence/jdo/datanucleus5/metamodel/facets/object/discriminator/JdoDiscriminatorAnnotationFacetFactory.java
@@ -69,11 +69,11 @@ implements ObjectSpecIdFacetFactory {
annotationValue, facetHolder);
} else {
val substitute = classSubstitutorRegistry.getSubstitution(cls);
- if(substitute.isIgnore()) {
+ if(substitute.isNeverIntrospect()) {
return;
}
- val substituted = substitute.replace(cls);
+ val substituted = substitute.apply(cls);
facet = new ObjectSpecIdFacetDerivedFromClassName(
substituted.getCanonicalName(),
facetHolder);