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/04/14 10:11:54 UTC

[isis] branch master updated: ISIS-2493: implement ActionOverloadingValidator

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 de599c0  ISIS-2493: implement ActionOverloadingValidator
de599c0 is described below

commit de599c003df7612bfdf5dac56ed22d6a144c0817
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Apr 14 12:11:33 2021 +0200

    ISIS-2493: implement ActionOverloadingValidator
---
 .../org/apache/isis/commons/collections/Can.java   | 12 +++++-
 .../apache/isis/commons/collections/Can_Empty.java | 11 +++++
 .../isis/commons/collections/Can_Multiple.java     | 21 ++++++++++
 .../isis/commons/collections/Can_Singleton.java    | 11 +++++
 ...eteTypeToBeIncludedWithMetamodelValidator.java} |  2 +-
 ...amodel.java => ActionOverloadingValidator.java} | 47 ++++++++++++++--------
 .../dflt/ProgrammingModelFacetsJava8.java          |  7 ++--
 7 files changed, 89 insertions(+), 22 deletions(-)

diff --git a/commons/src/main/java/org/apache/isis/commons/collections/Can.java b/commons/src/main/java/org/apache/isis/commons/collections/Can.java
index 973b43b..1790538 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can.java
@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
@@ -665,9 +666,18 @@ extends Iterable<T>, Comparable<Can<T>>, Serializable {
      * @return a serializable and immutable List, containing the elements of this Can
      */
     List<T> toList();
+    
+    /**
+     * @return a serializable and immutable Set, containing the elements of this Can
+     */
+    Set<T> toSet();
+    
+    /**
+     * @return a serializable and immutable Set, containing the elements of this Can
+     */
+    Set<T> toSet(@NonNull Consumer<T> onDuplicated);
 
 //XXX to implement when needed    
-//    Set<T> toSet();
 //    Set<T> toSortedSet();
 //    Set<T> toSortedSet(Comparator<T> comparator);
 
diff --git a/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java b/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
index d175f7e..304e839 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
@@ -24,6 +24,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
@@ -204,6 +205,16 @@ final class Can_Empty<T> implements Can<T> {
     }
     
     @Override
+    public Set<T> toSet() {
+        return Collections.emptySet(); // serializable and immutable
+    }
+    
+    @Override
+    public Set<T> toSet(@NonNull Consumer<T> onDuplicated) {
+        return Collections.emptySet(); // serializable and immutable
+    }
+    
+    @Override
     public <C extends Collection<T>> C toCollection(@NonNull Supplier<C> collectionFactory) {
         return collectionFactory.get();
     }
diff --git a/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java b/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
index f053696..bb5f158 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
@@ -25,6 +25,7 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
@@ -37,6 +38,7 @@ import javax.annotation.Nullable;
 
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._Objects;
+import org.apache.isis.commons.internal.collections._Sets;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 
 import lombok.NonNull;
@@ -296,6 +298,25 @@ final class Can_Multiple<T> implements Can<T> {
     }
     
     @Override
+    public Set<T> toSet() {
+        val set = _Sets.<T>newHashSet(); // serializable
+        elements.forEach(set::add);
+        return Collections.unmodifiableSet(set); // serializable and immutable
+    }
+    
+    @Override
+    public Set<T> toSet(@NonNull Consumer<T> onDuplicated) {
+        val set = _Sets.<T>newHashSet(); // serializable
+        elements
+        .forEach(s->{
+            if(!set.add(s)) {
+                onDuplicated.accept(s);
+            }
+        });
+        return Collections.unmodifiableSet(set); // serializable and immutable
+    }
+    
+    @Override
     public <C extends Collection<T>> C toCollection(@NonNull Supplier<C> collectionFactory) {
         val collection = collectionFactory.get();
         collection.addAll(elements);
diff --git a/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java b/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
index e332b59..b8be9b8 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
@@ -241,6 +242,16 @@ final class Can_Singleton<T> implements Can<T> {
     }
     
     @Override
+    public Set<T> toSet() {
+        return Collections.singleton(element); // serializable and immutable
+    }
+    
+    @Override
+    public Set<T> toSet(@NonNull Consumer<T> onDuplicated) {
+        return Collections.singleton(element); // serializable and immutable
+    }
+    
+    @Override
     public <C extends Collection<T>> C toCollection(@NonNull Supplier<C> collectionFactory) {
         val collection = collectionFactory.get();
         collection.add(element);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java
similarity index 96%
copy from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel.java
copy to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java
index a69544c..62fbbfd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java
@@ -31,7 +31,7 @@ import org.apache.isis.core.metamodel.specloader.validator.ValidationFailure;
 import lombok.NonNull;
 import lombok.val;
 
-public class ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel 
+public class ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator 
 extends MetaModelVisitingValidatorAbstract {
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionOverloadingValidator.java
similarity index 56%
rename from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel.java
rename to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionOverloadingValidator.java
index a69544c..b802775 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionOverloadingValidator.java
@@ -18,10 +18,10 @@
  */
 package org.apache.isis.core.metamodel.facets.actions.action;
 
-import java.util.stream.Collectors;
-
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.metamodel.BeanSort;
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.collections._Sets;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.MixedIn;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
@@ -31,30 +31,43 @@ import org.apache.isis.core.metamodel.specloader.validator.ValidationFailure;
 import lombok.NonNull;
 import lombok.val;
 
-public class ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel 
+/**
+ * Rationale: 
+ * having two actions in the UI with the exact same name wouldn't make sense to the end user,
+ * hence fail validation on 'overloading'
+ * 
+ * @since 2.0
+ * @see <a href="https://issues.apache.org/jira/browse/ISIS-2493">ISIS-2493</a>
+ */
+public class ActionOverloadingValidator 
 extends MetaModelVisitingValidatorAbstract {
 
     @Override
     public void validate(@NonNull ObjectSpecification spec) {
+        
         if(spec.getBeanSort()==BeanSort.UNKNOWN 
                 && !spec.isAbstract()) {
         
-            val actions = spec.streamActions(MixedIn.INCLUDED).collect(Collectors.toList());
+            val actionMemberNames = spec.streamActions(MixedIn.INCLUDED)
+                    .map(ObjectAction::getIdentifier)
+                    .map(Identifier::getMemberName)
+                    .collect(Can.toCan());
             
-            final int numActions = actions.size();
-            if (numActions > 0) {
-
-                val actionIds = actions.stream()
-                .map(ObjectAction::getIdentifier)
-                .map(Identifier::toString)
-                .collect(Collectors.joining(", "));
+            if (actionMemberNames.isCardinalityMultiple()) {
+                
+                val overloadedNames = _Sets.<String>newHashSet();
+                
+                actionMemberNames.toSet(overloadedNames::add);
 
-                ValidationFailure.raiseFormatted(
-                        spec,
-                        "%s: is a (concrete) but UNKNOWN sort, yet has %d actions: {%s}",
-                        spec.getCorrespondingClass().getName(),
-                        numActions,
-                        actionIds);
+                if(!overloadedNames.isEmpty()) {
+                
+                    ValidationFailure.raiseFormatted(
+                            spec,
+                            "Action method overloading is not allowed, "
+                            + "yet %s has action(s) that have a the same member name: %s",
+                            spec.getCorrespondingClass().getName(),
+                            overloadedNames);
+                }
             }
             
         }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
index 66d9d50..4c8029c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/progmodels/dflt/ProgrammingModelFacetsJava8.java
@@ -20,8 +20,9 @@ package org.apache.isis.core.metamodel.progmodels.dflt;
 import org.apache.isis.applib.services.inject.ServiceInjector;
 import org.apache.isis.core.metamodel.authorization.standard.AuthorizationFacetFactory;
 import org.apache.isis.core.metamodel.facets.actions.action.ActionAnnotationFacetFactory;
-import org.apache.isis.core.metamodel.facets.actions.action.ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel;
+import org.apache.isis.core.metamodel.facets.actions.action.ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator;
 import org.apache.isis.core.metamodel.facets.actions.action.ActionChoicesForCollectionParameterFacetFactory;
+import org.apache.isis.core.metamodel.facets.actions.action.ActionOverloadingValidator;
 import org.apache.isis.core.metamodel.facets.actions.contributing.derived.ContributingFacetDerivedFromMixinFacetFactory;
 import org.apache.isis.core.metamodel.facets.actions.defaults.method.ActionDefaultsFacetViaMethodFactory;
 import org.apache.isis.core.metamodel.facets.actions.homepage.annotation.HomePageFacetAnnotationFactory;
@@ -346,8 +347,8 @@ public final class ProgrammingModelFacetsJava8 extends ProgrammingModelAbstract
         
         addValidator(new OrphanedSupportingMethodValidator());
         addValidator(new TitlesAndTranslationsValidator());
-        addValidator(new ActionAnnotationShouldEnforceTypeToBeIncludedWithMetamodel());
-        
+        addValidator(new ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator());
+        addValidator(new ActionOverloadingValidator());
 
     }