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/03/05 10:47:53 UTC

[isis] branch master updated: ISIS-2553: ApplicationFeature: polish formal 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 660c713  ISIS-2553: ApplicationFeature: polish formal API
660c713 is described below

commit 660c713d1889862ec34e4b3e4ad2aa4621cfcc73
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Mar 5 11:47:41 2021 +0100

    ISIS-2553: ApplicationFeature: polish formal API
---
 .../services/appfeat/ApplicationFeature.java       |  67 ++++++++---
 .../appfeat/ApplicationFeatureDefault.java         | 132 +++++++--------------
 .../ApplicationFeatureRepositoryDefault.java       |  26 ++--
 .../metamodel/services/appfeat/_Predicates.java    |   2 +-
 .../services/appfeat/ApplicationFeatureIdTest.java |   4 +-
 .../model/dom/feature/ApplicationTypeAction.java   |   9 +-
 .../dom/feature/ApplicationTypeCollection.java     |   6 +-
 .../model/dom/feature/ApplicationTypeProperty.java |  24 +++-
 8 files changed, 140 insertions(+), 130 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeature.java b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeature.java
index 4e7988b..7c8f864 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeature.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/appfeat/ApplicationFeature.java
@@ -18,7 +18,9 @@
  */
 package org.apache.isis.applib.services.appfeat;
 
+import java.util.Collections;
 import java.util.Optional;
+import java.util.OptionalInt;
 import java.util.SortedSet;
 
 import org.apache.isis.applib.annotation.SemanticsOf;
@@ -36,11 +38,60 @@ public interface ApplicationFeature {
     }
 
     /**
-     * Optionally the member sort, based on whether this feature is a member.
+     * Returns optionally the member sort, based on whether this feature is of sort 
+     * {@link ApplicationFeatureSort#MEMBER}.
      */
     Optional<ApplicationMemberSort> getMemberSort();
     
-    SortedSet<ApplicationFeatureId> membersOfSort(ApplicationMemberSort memberSort);
+    default SortedSet<ApplicationFeatureId> getMembersOfSort(final ApplicationMemberSort memberSort) {
+        switch (memberSort) {
+        case PROPERTY:
+            return getProperties();
+        case COLLECTION:
+            return getCollections();
+        case ACTION:
+            return getActions();
+        default:
+            return Collections.emptySortedSet();
+        }
+    }
+    
+    /**
+     * Returns optionally the action's return type, based on
+     * whether this feature is of sorts
+     * {@link ApplicationFeatureSort#MEMBER member} and 
+     * {@link ApplicationMemberSort#ACTION action}.
+     */
+    Optional<Class<?>> getActionReturnType();
+    
+    /**
+     * Returns optionally the action's semantics, based on
+     * whether this feature is of sorts
+     * {@link ApplicationFeatureSort#MEMBER member} and 
+     * {@link ApplicationMemberSort#ACTION action}.
+     */
+    Optional<SemanticsOf> getActionSemantics();
+
+    /** 
+     * @return {@code false} when not a property or collection 
+     */
+    boolean isPropertyOrCollectionDerived();
+
+    /**
+     * Returns optionally the property's semantics, based on
+     * whether this feature is of sorts
+     * {@link ApplicationFeatureSort#MEMBER member} and 
+     * {@link ApplicationMemberSort#PROPERTY property}.
+     */
+    OptionalInt getPropertyTypicalLength();
+
+    /**
+     * Returns optionally the property's max-length constraint, based on
+     * whether this feature is of sorts
+     * {@link ApplicationFeatureSort#MEMBER member} and 
+     * {@link ApplicationMemberSort#PROPERTY property}.
+     */
+    OptionalInt getPropertyMaxLength();
     
     SortedSet<ApplicationFeatureId> getContents();
 
@@ -49,17 +100,5 @@ public interface ApplicationFeature {
     SortedSet<ApplicationFeatureId> getCollections();
 
     SortedSet<ApplicationFeatureId> getActions();
-
-    // -- TODO probably non formal API, only used by secman ...
-
-    String getReturnTypeName();
-
-    SemanticsOf getActionSemantics();
-
-    Boolean getDerived();
-
-    Integer getPropertyTypicalLength();
-
-    Integer getPropertyMaxLength();
     
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureDefault.java
index c3edc6d..d21b3bb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureDefault.java
@@ -18,9 +18,9 @@
  */
 package org.apache.isis.core.metamodel.services.appfeat;
 
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.Optional;
+import java.util.OptionalInt;
 import java.util.SortedSet;
 
 import org.apache.isis.applib.annotation.SemanticsOf;
@@ -35,6 +35,7 @@ import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.ToString;
 import org.apache.isis.commons.internal.collections._Sets;
 
+import lombok.AccessLevel;
 import lombok.Getter;
 import lombok.NonNull;
 import lombok.Setter;
@@ -51,120 +52,69 @@ import lombok.Setter;
 @Value
 public class ApplicationFeatureDefault 
 implements 
-    ApplicationFeature,
-    Comparable<ApplicationFeature> {
+ApplicationFeature,
+Comparable<ApplicationFeature> {
 
     // -- CONSTRUCTORS
-    
-    public ApplicationFeatureDefault(final ApplicationFeatureId featureId) {
+
+    public ApplicationFeatureDefault(final @NonNull ApplicationFeatureId featureId) {
         this.featureId = featureId;
     }
-    
+
     // -- FIELDS
 
     @Getter(onMethod_ = {@Override})
-    private final ApplicationFeatureId featureId;
+    private final @NonNull ApplicationFeatureId featureId;
 
     @Getter(onMethod_ = {@Override})
-    private Optional<ApplicationMemberSort> memberSort = Optional.empty();
-    
-    void setMemberSort(final @NonNull ApplicationMemberSort memberSort) {
-        this.memberSort = Optional.of(memberSort);
-    }
+    @Setter(AccessLevel.PACKAGE)
+    private @NonNull Optional<ApplicationMemberSort> memberSort = Optional.empty();
 
-    /**
-     * Only for {@link ApplicationMemberSort#ACTION action}s.
-     */
-    @Getter @Setter
-    private String returnTypeName;
-
-    /**
-     * Only for {@link ApplicationMemberSort#PROPERTY} and {@link ApplicationMemberSort#COLLECTION}
-     */
-    @Getter @Setter
-    private Boolean derived;
-
-    /**
-     * Only for {@link ApplicationMemberSort#ACTION action}s.
-     */
-    @Getter @Setter
-    private Integer propertyMaxLength;
-    
-    /**
-     * Only for {@link ApplicationMemberSort#ACTION action}s.
-     */
-    @Getter @Setter
-    private Integer propertyTypicalLength;
-
-    /**
-     * Only for {@link ApplicationMemberSort#ACTION action}s.
-     */
-    @Getter @Setter
-    private SemanticsOf actionSemantics;
-
-    // -- NAMESPACE
-    
-    private final SortedSet<ApplicationFeatureId> contents = _Sets.newTreeSet();
+    @Getter(onMethod_ = {@Override})
+    @Setter(AccessLevel.PACKAGE)
+    private @NonNull Optional<Class<?>> actionReturnType = Optional.empty();
 
-    @Override
-    public SortedSet<ApplicationFeatureId> getContents() {
-        return contents;
-    }
+    @Getter(onMethod_ = {@Override})
+    @Setter(AccessLevel.PACKAGE)
+    private @NonNull Optional<SemanticsOf> actionSemantics = Optional.empty();
 
-    void addToContents(final ApplicationFeatureId contentId) {
-        _Asserts.ensureNamespace(this.getFeatureId());
-        _Asserts.ensureNamespaceOrType(contentId);
-        this.contents.add(contentId);
-    }
+    @Getter(onMethod_ = {@Override})
+    @Setter(AccessLevel.PACKAGE)
+    private boolean propertyOrCollectionDerived = false;
 
-    // -- PROPERTIES
-    
-    private final SortedSet<ApplicationFeatureId> properties = _Sets.newTreeSet();
+    @Getter(onMethod_ = {@Override})
+    @Setter(AccessLevel.PACKAGE)
+    private @NonNull OptionalInt propertyMaxLength = OptionalInt.empty();
 
-    @Override
-    public SortedSet<ApplicationFeatureId> getProperties() {
-        return properties;
-    }
+    @Getter(onMethod_ = {@Override}) 
+    @Setter(AccessLevel.PACKAGE)
+    private @NonNull OptionalInt propertyTypicalLength = OptionalInt.empty();
 
-    // -- COLLECTIONS
-    
+    @Getter(onMethod_ = {@Override})
+    private final SortedSet<ApplicationFeatureId> contents = _Sets.newTreeSet();
+
+    @Getter(onMethod_ = {@Override})
+    private final SortedSet<ApplicationFeatureId> properties = _Sets.newTreeSet();
+
+    @Getter(onMethod_ = {@Override})
     private final SortedSet<ApplicationFeatureId> collections = _Sets.newTreeSet();
-    
-    @Override
-    public SortedSet<ApplicationFeatureId> getCollections() {
-        return collections;
-    }
 
-    // -- ACTIONS
-    
+    @Getter(onMethod_ = {@Override})
     private final SortedSet<ApplicationFeatureId> actions = _Sets.newTreeSet();
+
+    // -- PACKAGE PRIVATE ACCESS
     
-    @Override
-    public SortedSet<ApplicationFeatureId> getActions() {
-        return actions;
+    void addToContents(final ApplicationFeatureId contentId) {
+        _Asserts.ensureNamespace(this.getFeatureId());
+        _Asserts.ensureNamespaceOrType(contentId);
+        this.contents.add(contentId);
     }
     
     void addToMembers(final ApplicationFeatureId memberId, final ApplicationMemberSort memberSort) {
         _Asserts.ensureType(this.getFeatureId());
         _Asserts.ensureMember(memberId);
 
-        membersOfSort(memberSort).add(memberId);
-    }
-    
-    // -- MEMBERS OF SORT
-    
-    @Override
-    public SortedSet<ApplicationFeatureId> membersOfSort(final ApplicationMemberSort memberSort) {
-        switch (memberSort) {
-        case PROPERTY:
-            return properties;
-        case COLLECTION:
-            return collections;
-        case ACTION:
-            return actions;
-        default:
-            return Collections.emptySortedSet();
-        }
+        getMembersOfSort(memberSort).add(memberId);
     }
 
     // -- OBJECT CONTRACT
@@ -200,8 +150,6 @@ implements
     public String toString() {
         return toString.toString(this);
     }
-    
-
 
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
index 8b9810f..9e0ea72 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
@@ -23,12 +23,15 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalInt;
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.SortedSet;
 import java.util.function.BiConsumer;
 import java.util.stream.Collectors;
 
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 import javax.inject.Named;
 
@@ -63,6 +66,7 @@ import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 
 import static org.apache.isis.commons.internal.base._NullSafe.stream;
 
+import lombok.NonNull;
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
@@ -294,21 +298,21 @@ implements ApplicationFeatureRepository {
     private void newMember(
             final ApplicationFeatureId classFeatureId,
             final String memberId,
-            final ApplicationMemberSort memberSort,
-            final Class<?> returnType,
+            final @NonNull ApplicationMemberSort memberSort,
+            final @Nullable Class<?> returnType,
             final Boolean derived,
-            final Integer maxLength, final Integer typicalLength,
-            final SemanticsOf actionSemantics) {
+            final @Nullable Integer maxLength, final @Nullable Integer typicalLength,
+            final @Nullable SemanticsOf actionSemantics) {
         final ApplicationFeatureId featureId = ApplicationFeatureId.newMember(classFeatureId.getFullyQualifiedName(), memberId);
 
         final ApplicationFeatureDefault memberFeature = (ApplicationFeatureDefault)newFeature(featureId);
-        memberFeature.setMemberSort(memberSort);
+        memberFeature.setMemberSort(Optional.of(memberSort));
 
-        memberFeature.setReturnTypeName(returnType != null ? returnType.getSimpleName() : null);
-        memberFeature.setDerived(derived);
-        memberFeature.setPropertyMaxLength(maxLength);
-        memberFeature.setPropertyTypicalLength(typicalLength);
-        memberFeature.setActionSemantics(actionSemantics);
+        memberFeature.setActionReturnType(Optional.ofNullable(returnType));
+        memberFeature.setActionSemantics(Optional.ofNullable(actionSemantics));
+        memberFeature.setPropertyOrCollectionDerived(Boolean.TRUE.equals(derived));
+        memberFeature.setPropertyMaxLength(maxLength!=null ? OptionalInt.of(maxLength) : OptionalInt.empty());
+        memberFeature.setPropertyTypicalLength(typicalLength!=null ? OptionalInt.of(typicalLength) : OptionalInt.empty());
 
         memberFeatures.put(featureId, memberFeature);
 
@@ -516,7 +520,7 @@ implements ApplicationFeatureRepository {
         if (cls == null) {
             return Collections.emptySortedSet();
         }
-        final SortedSet<ApplicationFeatureId> featureIds = cls.membersOfSort(memberSort);
+        final SortedSet<ApplicationFeatureId> featureIds = cls.getMembersOfSort(memberSort);
         return featureIds.stream()
                 .map(ApplicationFeatureId::getMemberName)
                 .collect(_Sets.toUnmodifiableSorted());
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Predicates.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Predicates.java
index 8d5ff1b..76eaa9c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Predicates.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/_Predicates.java
@@ -41,7 +41,7 @@ final class _Predicates {
                     return false;
                 }
                 return memberSort == null 
-                        || !feature.membersOfSort(memberSort).isEmpty();
+                        || !feature.getMembersOfSort(memberSort).isEmpty();
         };
     }
 
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureIdTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureIdTest.java
index 13767cd..bb8ccb4 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureIdTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureIdTest.java
@@ -642,7 +642,7 @@ public class ApplicationFeatureIdTest {
                     oneOf(mockApplicationFeatureRepository).findFeature(classFeature);
                     will(returnValue(mockApplicationFeature));
 
-                    allowing(mockApplicationFeature).membersOfSort(ApplicationMemberSort.ACTION);
+                    allowing(mockApplicationFeature).getMembersOfSort(ApplicationMemberSort.ACTION);
                     will(returnValue(new TreeSet<>()));
                 }});
 
@@ -659,7 +659,7 @@ public class ApplicationFeatureIdTest {
                     oneOf(mockApplicationFeatureRepository).findFeature(classFeature);
                     will(returnValue(mockApplicationFeature));
 
-                    allowing(mockApplicationFeature).membersOfSort(ApplicationMemberSort.ACTION);
+                    allowing(mockApplicationFeature).getMembersOfSort(ApplicationMemberSort.ACTION);
                     will(returnValue(new TreeSet<ApplicationFeatureId>() {{
                         add(ApplicationFeatureId.newMember("com.mycompany.Bar#foo"));
                     }}));
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeAction.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeAction.java
index a9d1f8b..499ca92 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeAction.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeAction.java
@@ -37,8 +37,6 @@ public class ApplicationTypeAction extends ApplicationTypeMember {
 
     public static abstract class ActionDomainEvent extends ApplicationTypeMember.ActionDomainEvent<ApplicationTypeAction> {}
 
-
-
     // -- constructors
 
     public ApplicationTypeAction() {
@@ -58,7 +56,9 @@ public class ApplicationTypeAction extends ApplicationTypeMember {
             )
     @MemberOrder(name="Data Type", sequence = "2.6")
     public String getReturnType() {
-        return getFeature().getReturnTypeName();
+        return getFeature().getActionReturnType()
+                .map(Class::getSimpleName)
+                .orElse("<none>");
     }
 
     // -- actionSemantics (property)
@@ -69,7 +69,8 @@ public class ApplicationTypeAction extends ApplicationTypeMember {
             )
     @MemberOrder(name="Detail", sequence = "2.8")
     public SemanticsOf getActionSemantics() {
-        return getFeature().getActionSemantics();
+        return getFeature().getActionSemantics()
+                .orElse(null);
     }
 
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeCollection.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeCollection.java
index cccb3d2..bdbc63a 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeCollection.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeCollection.java
@@ -58,7 +58,9 @@ public class ApplicationTypeCollection extends ApplicationTypeMember {
             )
     @MemberOrder(name="Data Type", sequence = "2.6")
     public String getElementType() {
-        return getFeature().getReturnTypeName();
+        return getFeature().getActionReturnType()
+                .map(Class::getSimpleName)
+                .orElse("<none>");
     }
 
 
@@ -71,7 +73,7 @@ public class ApplicationTypeCollection extends ApplicationTypeMember {
             )
     @MemberOrder(name="Detail", sequence = "2.7")
     public boolean isDerived() {
-        return Boolean.TRUE.equals(getFeature().getDerived());
+        return getFeature().isPropertyOrCollectionDerived();
     }
 
 
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeProperty.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeProperty.java
index 156194d..3409651 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeProperty.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/dom/feature/ApplicationTypeProperty.java
@@ -25,6 +25,8 @@ import org.apache.isis.applib.annotation.Optionality;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
 
+import lombok.val;
+
 @DomainObject(
         objectType = "isis.ext.secman.ApplicationClassProperty"
         )
@@ -57,7 +59,9 @@ public class ApplicationTypeProperty extends ApplicationTypeMember {
             )
     @MemberOrder(name="Data Type", sequence = "2.6")
     public String getReturnType() {
-        return getFeature().getReturnTypeName();
+        return getFeature().getActionReturnType()
+                .map(Class::getSimpleName)
+                .orElse("<none>");
     }
 
 
@@ -70,7 +74,7 @@ public class ApplicationTypeProperty extends ApplicationTypeMember {
             )
     @MemberOrder(name="Detail", sequence = "2.7")
     public boolean isDerived() {
-        return Boolean.TRUE.equals(getFeature().getDerived());
+        return getFeature().isPropertyOrCollectionDerived();
     }
 
 
@@ -84,10 +88,16 @@ public class ApplicationTypeProperty extends ApplicationTypeMember {
             )
     @MemberOrder(name="Detail", sequence = "2.8")
     public Integer getMaxLength() {
-        return getFeature().getPropertyMaxLength();
+        val maxLen = getFeature().getPropertyMaxLength();
+        return maxLen.isPresent() 
+                ? maxLen.getAsInt()
+                : null; // unexpected code path, as this case should be hidden 
     }
 
     public boolean hideMaxLength() {
+        if(!getFeature().getPropertyMaxLength().isPresent()) {
+            return true;
+        }
         return !String.class.getSimpleName().equals(getReturnType());
     }
 
@@ -103,10 +113,16 @@ public class ApplicationTypeProperty extends ApplicationTypeMember {
             )
     @MemberOrder(name="Detail", sequence = "2.9")
     public Integer getTypicalLength() {
-        return getFeature().getPropertyTypicalLength();
+        val maxLen = getFeature().getPropertyTypicalLength();
+        return maxLen.isPresent() 
+                ? maxLen.getAsInt()
+                : null; // unexpected code path, as this case should be hidden 
     }
 
     public boolean hideTypicalLength() {
+        if(!getFeature().getPropertyTypicalLength().isPresent()) {
+            return true;
+        }
         return !String.class.getSimpleName().equals(getReturnType());
     }