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 2019/10/01 19:27:48 UTC

[isis] 02/02: ISIS-2158: refine MethodRemover interface

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 2546922500a72c6cdd9264ab6afce93ec567085d
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Oct 1 21:27:36 2019 +0200

    ISIS-2158: refine MethodRemover interface
    
    - less List instances required during spec-loading
    - also makes the FacetHolderImpl thread-safe, which is required for
    concurrent spec-loading
---
 .../apache/isis/metamodel/commons/MethodUtil.java  | 14 ++++----
 .../isis/metamodel/facetapi/FacetHolderImpl.java   | 18 ++++++----
 .../isis/metamodel/facetapi/MethodRemover.java     | 24 +++++++++++--
 .../apache/isis/metamodel/facets/FacetFactory.java |  9 ++---
 .../metamodel/facets/MethodRemoverConstants.java   |  6 ++--
 .../CollectionAccessorFacetViaAccessorFactory.java | 12 ++++---
 .../PropertyAccessorFacetViaAccessorFactory.java   |  2 +-
 .../specloader/specimpl/FacetedMethodsBuilder.java | 39 +++++++++++++---------
 .../specimpl/ObjectSpecificationAbstract.java      |  3 +-
 .../specimpl/OneToOneAssociationMixedIn.java       |  2 ++
 .../metamodel/facets/MethodRemoverForTesting.java  |  4 +--
 .../domainmodel/SpecloaderPerformanceTest.java     |  2 +-
 12 files changed, 85 insertions(+), 50 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/commons/MethodUtil.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/commons/MethodUtil.java
index f6f2771..b04c719 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/commons/MethodUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/commons/MethodUtil.java
@@ -21,9 +21,9 @@ package org.apache.isis.metamodel.commons;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.function.Consumer;
 
 import org.apache.isis.metamodel.methodutils.MethodScope;
 
@@ -147,20 +147,20 @@ public class MethodUtil {
      * @param forClass
      * @param name
      * @param returnType
+     * @param onRemoval 
      * @param paramTypes
      *            the set of parameters the method should have, if null then is
      *            ignored
      * @return Method
      */
-    public static List<Method> removeMethods(
+    public static void removeMethods(
             final List<Method> methods,
             final MethodScope forClass,
             final String prefix,
             final Class<?> returnType,
             final boolean canBeVoid,
-            final int paramCount) {
-
-        final List<Method> validMethods = new ArrayList<Method>();
+            final int paramCount, 
+            Consumer<Method> onMatch) {
 
         for (int i = 0; i < methods.size(); i++) {
             final Method method = methods.get(i);
@@ -179,11 +179,11 @@ public class MethodUtil {
             final boolean goodReturn = ClassExtensions.isCompatibleAsReturnType(returnType, canBeVoid, type);
 
             if (goodPrefix && goodCount && goodReturn) {
-                validMethods.add(method);
+                onMatch.accept(method);
                 methods.set(i, null);
             }
         }
-        return validMethods;
+        
     }
 
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facetapi/FacetHolderImpl.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facetapi/FacetHolderImpl.java
index 0740fca..ab962e0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facetapi/FacetHolderImpl.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facetapi/FacetHolderImpl.java
@@ -19,10 +19,10 @@
 
 package org.apache.isis.metamodel.facetapi;
 
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Stream;
 
 import org.apache.isis.commons.internal.base._Casts;
@@ -35,7 +35,7 @@ import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
  */
 public class FacetHolderImpl implements FacetHolder {
 
-    private final Map<Class<? extends Facet>, Facet> facetsByClass = new HashMap<>();
+    private final Map<Class<? extends Facet>, Facet> facetsByClass = new ConcurrentHashMap<>();
     private final Set<Class<? extends Facet>> implementedFacetInterfaces = new HashSet<>();
 
     @Override
@@ -45,7 +45,9 @@ public class FacetHolderImpl implements FacetHolder {
 
     @Override
     public boolean containsFacetWithInterface(final Class<? extends Facet> facetType) {
-        return implementedFacetInterfaces.contains(facetType);
+        synchronized(implementedFacetInterfaces) {
+            return implementedFacetInterfaces.contains(facetType);
+        }
     }
 
     @Override
@@ -119,10 +121,12 @@ public class FacetHolderImpl implements FacetHolder {
     private void put(final Class<? extends Facet> facetType, final Facet facet) {
         facetsByClass.put(facetType, facet);
 
-        _NullSafe.stream(facetType.getInterfaces())
-        .filter(intfc->Facet.class.isAssignableFrom(intfc))
-        .map(intfc-> _Casts.<Class<? extends Facet>>uncheckedCast(intfc))
-        .forEach(implementedFacetInterfaces::add);
+        synchronized(implementedFacetInterfaces) {
+            _NullSafe.stream(facetType.getInterfaces())
+            .filter(intfc->Facet.class.isAssignableFrom(intfc))
+            .map(intfc-> _Casts.<Class<? extends Facet>>uncheckedCast(intfc))
+            .forEach(implementedFacetInterfaces::add);
+        }
 
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facetapi/MethodRemover.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facetapi/MethodRemover.java
index 25e224f..609671c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facetapi/MethodRemover.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facetapi/MethodRemover.java
@@ -20,7 +20,7 @@
 package org.apache.isis.metamodel.facetapi;
 
 import java.lang.reflect.Method;
-import java.util.List;
+import java.util.function.Consumer;
 
 import org.apache.isis.metamodel.methodutils.MethodScope;
 
@@ -37,10 +37,28 @@ public interface MethodRemover {
      * @param methodScope
      *            - whether looking for <tt>static</tt> (class) or
      *            instance-level methods.
-     * @return any methods that were removed.
+     * @param onRemoval receives any methods that were removed
      */
-    List<Method> removeMethods(MethodScope methodScope, String prefix, Class<?> returnType, boolean canBeVoid, int paramCount);
+    void removeMethods(
+            MethodScope methodScope, 
+            String prefix, 
+            Class<?> returnType, 
+            boolean canBeVoid, 
+            int paramCount,
+            Consumer<Method> onRemoval
+            );
 
+    default void removeMethods(
+            MethodScope methodScope, 
+            String prefix, 
+            Class<?> returnType, 
+            boolean canBeVoid, 
+            int paramCount) {
+        
+        removeMethods(methodScope, prefix, returnType, canBeVoid, paramCount, whatever -> {});
+    }
+    
+    
     /**
      * Locate all methods (that the implementation should somehow know about)
      * that match the criteria and remove them from the implementation's list so
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/FacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/FacetFactory.java
index 7df5cd3..c08f5ea 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/FacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/FacetFactory.java
@@ -21,6 +21,7 @@ package org.apache.isis.metamodel.facets;
 
 import java.lang.reflect.Method;
 import java.util.List;
+import java.util.function.Consumer;
 
 import org.apache.isis.metamodel.facetapi.Facet;
 import org.apache.isis.metamodel.facetapi.FacetHolder;
@@ -88,8 +89,8 @@ public interface FacetFactory {
 
 
         @Override
-        public List<Method> removeMethods(final MethodScope methodScope, final String prefix, final Class<?> returnType, final boolean canBeVoid, final int paramCount) {
-            return methodRemover.removeMethods(methodScope, prefix, returnType, canBeVoid, paramCount);
+        public void removeMethods(final MethodScope methodScope, final String prefix, final Class<?> returnType, final boolean canBeVoid, final int paramCount, Consumer<Method> onRemoval) {
+            methodRemover.removeMethods(methodScope, prefix, returnType, canBeVoid, paramCount, onRemoval);
         }
 
         @Override
@@ -142,8 +143,8 @@ public interface FacetFactory {
         }
 
         @Override
-        public List<Method> removeMethods(final MethodScope methodScope, final String prefix, final Class<?> returnType, final boolean canBeVoid, final int paramCount) {
-            return methodRemover.removeMethods(methodScope, prefix, returnType, canBeVoid, paramCount);
+        public void removeMethods(final MethodScope methodScope, final String prefix, final Class<?> returnType, final boolean canBeVoid, final int paramCount, Consumer<Method> onRemoval) {
+            methodRemover.removeMethods(methodScope, prefix, returnType, canBeVoid, paramCount, onRemoval);
         }
 
         @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodRemoverConstants.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodRemoverConstants.java
index 918c6c4..ecac2c4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodRemoverConstants.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/MethodRemoverConstants.java
@@ -20,8 +20,7 @@
 package org.apache.isis.metamodel.facets;
 
 import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.function.Consumer;
 
 import org.apache.isis.metamodel.facetapi.MethodRemover;
 import org.apache.isis.metamodel.methodutils.MethodScope;
@@ -30,8 +29,7 @@ public class MethodRemoverConstants {
 
     public static MethodRemover NULL = new MethodRemover() {
         @Override
-        public List<Method> removeMethods(final MethodScope methodScope, final String prefix, final Class<?> returnType, final boolean canBeVoid, final int paramCount) {
-            return new ArrayList<Method>();
+        public void removeMethods(final MethodScope methodScope, final String prefix, final Class<?> returnType, final boolean canBeVoid, final int paramCount, Consumer<Method> onRemoval) {
         }
 
         @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessorFactory.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessorFactory.java
index d328d1a..3311078 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessorFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessorFactory.java
@@ -95,10 +95,14 @@ extends PropertyOrCollectionIdentifyingFacetFactoryAbstract {
             final MethodRemover methodRemover,
             final List<Method> methodListToAppendTo) {
 
-        final List<Method> list =
-                methodRemover.removeMethods(MethodScope.OBJECT, MethodLiteralConstants.GET_PREFIX,
-                        Collection.class, false, 0);
-        methodListToAppendTo.addAll(list);
+        methodRemover.removeMethods(
+                MethodScope.OBJECT, 
+                MethodLiteralConstants.GET_PREFIX,
+                Collection.class, 
+                false, 
+                0,
+                methodListToAppendTo::add
+                );
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessorFactory.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessorFactory.java
index 5036e15..6ee0210 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessorFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessorFactory.java
@@ -98,7 +98,7 @@ public class PropertyAccessorFacetViaAccessorFactory extends PropertyOrCollectio
     }
 
     private static void appendMatchingMethods(final MethodRemover methodRemover, final String prefix, final Class<?> returnType, final List<Method> methodListToAppendTo) {
-        methodListToAppendTo.addAll(methodRemover.removeMethods(MethodScope.OBJECT, prefix, returnType, false, 0));
+        methodRemover.removeMethods(MethodScope.OBJECT, prefix, returnType, false, 0, methodListToAppendTo::add);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
index 0164bea..4de54c8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
@@ -25,6 +25,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Consumer;
 
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.commons.exceptions.IsisException;
@@ -69,21 +70,24 @@ public class FacetedMethodsBuilder {
 
         @Override
         public void removeMethod(
-                final MethodScope methodScope,
-                final String methodName,
-                final Class<?> returnType,
-                final Class<?>[] parameterTypes) {
+                MethodScope methodScope,
+                String methodName,
+                Class<?> returnType,
+                Class<?>[] parameterTypes) {
+            
             MethodUtil.removeMethod(methods, methodScope, methodName, returnType, parameterTypes);
         }
 
         @Override
-        public List<Method> removeMethods(
-                final MethodScope methodScope,
-                final String prefix,
-                final Class<?> returnType,
-                final boolean canBeVoid,
-                final int paramCount) {
-            return MethodUtil.removeMethods(methods, methodScope, prefix, returnType, canBeVoid, paramCount);
+        public void removeMethods(
+                MethodScope methodScope,
+                String prefix,
+                Class<?> returnType,
+                boolean canBeVoid,
+                int paramCount,
+                Consumer<Method> onRemoval) {
+            
+            MethodUtil.removeMethods(methods, methodScope, prefix, returnType, canBeVoid, paramCount, onRemoval);
         }
 
         @Override
@@ -482,21 +486,24 @@ public class FacetedMethodsBuilder {
             final Class<?> returnType,
             final int paramCount,
             final List<Method> methodListToAppendTo) {
-        final List<Method> matchingMethods = findAndRemovePrefixedMethods(methodScope, prefix, returnType, false, paramCount);
-        methodListToAppendTo.addAll(matchingMethods);
+        
+        findAndRemovePrefixedMethods(methodScope, prefix, returnType, false, paramCount, methodListToAppendTo::add);
     }
 
     /**
      * Searches for all methods matching the prefix and returns them, also
      * removing it from the {@link #methods array of methods} if found.
+     * @param onMatch 
      */
-    private List<Method> findAndRemovePrefixedMethods(
+    private void findAndRemovePrefixedMethods(
             final MethodScope methodScope,
             final String prefix,
             final Class<?> returnType,
             final boolean canBeVoid,
-            final int paramCount) {
-        return MethodUtil.removeMethods(methods, methodScope, prefix, returnType, canBeVoid, paramCount);
+            final int paramCount, 
+            Consumer<Method> onMatch) {
+        
+        MethodUtil.removeMethods(methods, methodScope, prefix, returnType, canBeVoid, paramCount, onMatch);
     }
 
     // ////////////////////////////////////////////////////////////////////////////
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
index e5c2132..41638b7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
@@ -99,11 +99,12 @@ import org.apache.isis.security.authentication.AuthenticationSession;
 
 import static org.apache.isis.commons.internal.base._NullSafe.stream;
 
+import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
-@Log4j2 //@EqualsAndHashCode(of = "correspondingClass", callSuper = false)
+@Log4j2 @EqualsAndHashCode(of = "correspondingClass", callSuper = false)
 public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implements ObjectSpecification {
 
 //    private static class Subclasses {
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
index a359431..32d52d5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
@@ -94,7 +94,9 @@ public class OneToOneAssociationMixedIn extends OneToOneAssociationDefault imple
         // These could include everything under @Property(...) because the
         // PropertyAnnotationFacetFactory is also run against actions.
         //
+        
         FacetUtil.copyFacets(mixinAction.getFacetedMethod(), facetHolder);
+        
 
         // adjust name if necessary
         final String name = getName();
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/MethodRemoverForTesting.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/MethodRemoverForTesting.java
index 3eae982..7fe4bf5 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/MethodRemoverForTesting.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/facets/MethodRemoverForTesting.java
@@ -22,6 +22,7 @@ package org.apache.isis.metamodel.facets;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Consumer;
 
 import org.apache.isis.metamodel.facetapi.MethodRemover;
 import org.apache.isis.metamodel.methodutils.MethodScope;
@@ -83,9 +84,8 @@ public class MethodRemoverForTesting implements MethodRemover {
     private final List<RemoveMethodsArgs> removeMethodsArgs = new ArrayList<RemoveMethodsArgs>();
 
     @Override
-    public List<Method> removeMethods(final MethodScope methodScope, final String prefix, final Class<?> returnType, final boolean canBeVoid, final int paramCount) {
+    public void removeMethods(final MethodScope methodScope, final String prefix, final Class<?> returnType, final boolean canBeVoid, final int paramCount, Consumer<Method> onRemoval) {
         removeMethodsArgs.add(new RemoveMethodsArgs(methodScope, prefix, returnType, canBeVoid, paramCount));
-        return removeMethodsReturn;
     }
 
 
diff --git a/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/SpecloaderPerformanceTest.java b/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/SpecloaderPerformanceTest.java
index 4b12c84..94a0202 100644
--- a/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/SpecloaderPerformanceTest.java
+++ b/examples/smoketests/src/test/java/org/apache/isis/testdomain/domainmodel/SpecloaderPerformanceTest.java
@@ -63,7 +63,7 @@ class SpecloaderPerformanceTest {
     @Test //under constr.
     void repeatedSpecloading() {
         
-        config.getReflector().getIntrospector().setParallelize(false);
+        config.getReflector().getIntrospector().setParallelize(true);
         
         for(int i=0; i<100; ++i) {
             specificationLoader.shutdown();