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/11/09 10:59:51 UTC

[isis] branch master updated: ISIS-2883: site-map: fill in menu action result details

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 c42d9cd  ISIS-2883: site-map: fill in menu action result details
c42d9cd is described below

commit c42d9cd4a6f83162439dd1b7bd55cb206d2f3410
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Nov 9 11:59:43 2021 +0100

    ISIS-2883: site-map: fill in menu action result details
---
 .../metamodel/specloader/SpecificationLoader.java  | 21 ++++--
 .../specloader/SpecificationLoaderDefault.java     | 16 ++---
 .../sitemap/SitemapServiceDefault.java             | 80 ++++++++++++++++++++++
 .../wicket/model/util/PageParameterUtils.java      |  2 +-
 4 files changed, 101 insertions(+), 18 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
index cfcc695..a423811 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
@@ -127,7 +127,17 @@ public interface SpecificationLoader {
      */
     boolean loadSpecifications(Class<?>... domainTypes);
 
-    LogicalType lookupLogicalType(@Nullable String logicalTypeName);
+    Optional<LogicalType> lookupLogicalType(@Nullable String logicalTypeName);
+
+    default LogicalType lookupLogicalTypeElseFail(@NonNull final String logicalTypeName) {
+        return lookupLogicalType(logicalTypeName)
+        .orElseThrow(()->_Exceptions.unrecoverableFormatted(
+                "Lookup of logical-type-name '%s' failed, also found no matching fully qualified "
+                        + "class name to use instead. This indicates, that the class we are not finding here"
+                        + " is not discovered by Spring during bootstrapping of this application.",
+                        logicalTypeName)
+        );
+    }
 
     /**
      * queue {@code objectSpec} for later validation
@@ -145,11 +155,10 @@ public interface SpecificationLoader {
         if(_Strings.isNullOrEmpty(logicalTypeName)) {
             return null;
         }
-        val logicalType = lookupLogicalType(logicalTypeName);
-        if(logicalType==null) {
-            return null;
-        }
-        return loadSpecification(logicalType.getCorrespondingClass(), introspectionState);
+        return lookupLogicalType(logicalTypeName)
+            .map(logicalType->
+                    loadSpecification(logicalType.getCorrespondingClass(), introspectionState))
+            .orElse(null);
     }
 
     // -- SHORTCUTS - 1
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 c31470c..3d91977 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
@@ -451,10 +451,9 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
     }
 
     @Override
-    public LogicalType lookupLogicalType(final @NonNull String logicalTypeName) {
-        val logicalType = logicalTypeResolver.lookup(logicalTypeName)
-                .orElse(null);
-        if(logicalType!=null) {
+    public Optional<LogicalType> lookupLogicalType(final @NonNull String logicalTypeName) {
+        val logicalType = logicalTypeResolver.lookup(logicalTypeName);
+        if(logicalType.isPresent()) {
             return logicalType;
         }
 
@@ -472,15 +471,10 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
 //                    + "discovered by Spring during bootstrapping of this application.",
 //                    logicalType.getName(),
 //                    cls.getName());
-            return LogicalType.fqcn(cls);
+            return Optional.of(LogicalType.fqcn(cls));
         }
 
-        // immediately fail to not cause any NPEs further down the path
-        throw _Exceptions.unrecoverableFormatted(
-                "Lookup of logical-type-name '%s' failed, also found no matching fully qualified "
-                + "class name to use instead. This indicates, that the class we are not finding here"
-                + " is not discovered by Spring during bootstrapping of this application.",
-                logicalTypeName);
+        return Optional.empty();
     }
 
     // -- VALIDATION STUFF
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/sitemap/SitemapServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/sitemap/SitemapServiceDefault.java
index 8d4584c..a4d9007 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/sitemap/SitemapServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/sitemap/SitemapServiceDefault.java
@@ -18,6 +18,9 @@
  */
 package org.apache.isis.core.runtimeservices.sitemap;
 
+import java.util.Optional;
+import java.util.Stack;
+
 import javax.annotation.Priority;
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -26,6 +29,11 @@ import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.PriorityPrecedence;
+import org.apache.isis.applib.layout.component.ActionLayoutData;
+import org.apache.isis.applib.layout.component.CollectionLayoutData;
+import org.apache.isis.applib.layout.component.FieldSet;
+import org.apache.isis.applib.layout.component.PropertyLayoutData;
+import org.apache.isis.applib.layout.component.ServiceActionLayoutData;
 import org.apache.isis.applib.layout.grid.Grid;
 import org.apache.isis.applib.layout.menubars.bootstrap3.BS3MenuBars;
 import org.apache.isis.applib.services.grid.GridService;
@@ -35,6 +43,8 @@ import org.apache.isis.applib.services.sitemap.SitemapService;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 
 import lombok.RequiredArgsConstructor;
@@ -74,6 +84,70 @@ public class SitemapServiceDefault implements SitemapService {
                         ? menuSection.getNamed()
                         : "Unnamed Section";
                 adoc.append(String.format("=== %s\n\n", sectionName));
+
+                _NullSafe.stream(menuSection.getServiceActions())
+                .map(this::lookupAction)
+                .flatMap(Optional::stream)
+                .forEach(menuAction->{
+                    adoc.append(String.format("==== %s\n\n", menuAction.getCanonicalFriendlyName()));
+                    menuAction.getCanonicalDescription()
+                    .ifPresent(describedAs->{
+                        adoc.append(String.format("_%s_\n\n", describedAs));
+                    });
+
+                    val actionReturnType = menuAction.getReturnType();
+                    val actionElementType = menuAction.getElementType();
+
+                    if(actionElementType.getCorrespondingClass()==void.class) {
+                        adoc.append("WARNING: ");
+                    }
+                    if(actionReturnType.isParentedOrFreeCollection()) {
+                        adoc.append(String.format("Returns collection of: `%s`\n\n", actionElementType.getLogicalTypeName()));
+                    } else {
+                        adoc.append(String.format("Returns scalar of: `%s`\n\n", actionElementType.getLogicalTypeName()));
+                    }
+
+                    val groupStack = new Stack<String>();
+                    groupStack.push("Top-Bar");
+
+                    val grid = toGrid(actionElementType.getCorrespondingClass(), Style.CURRENT);
+                    grid.visit(new Grid.VisitorAdapter() {
+                        @Override public void visit(final ActionLayoutData actionLayoutData) {
+                            actionElementType.getAction(actionLayoutData.getId())
+                            .ifPresent(action->{
+                                if(!groupStack.isEmpty()){
+                                    adoc.append(String.format("===== %s\n\n", groupStack.pop()));
+                                }
+                                adoc.append(String.format("* [ ] Action `%s`\n\n", action.getCanonicalFriendlyName()));
+                            });
+                        }
+                        @Override public void visit(final PropertyLayoutData propertyLayoutData) {
+                            actionElementType.getProperty(propertyLayoutData.getId())
+                            .ifPresent(property->{
+                                if(!groupStack.isEmpty()){
+                                    adoc.append(String.format("===== %s\n\n", groupStack.pop()));
+                                }
+                                adoc.append(String.format("* [ ] Property `%s`\n\n", property.getCanonicalFriendlyName()));
+                            });
+                        }
+                        @Override public void visit(final CollectionLayoutData collectionLayoutData) {
+                            actionElementType.getProperty(collectionLayoutData.getId())
+                            .ifPresent(collection->{
+                                groupStack.clear();
+                                adoc.append(String.format("Collection %s\n\n", collection.getCanonicalFriendlyName()));
+                            });
+                        }
+                        @Override public void visit(final FieldSet fieldSet) {
+                            if(_NullSafe.isEmpty(fieldSet.getActions())) {
+                                return;
+                            }
+                            groupStack.clear();
+                            adoc.append(String.format("===== FieldSet %s\n\n", fieldSet.getName()));
+                        }
+                    });
+
+                });
+
             });
 
         }));
@@ -83,6 +157,12 @@ public class SitemapServiceDefault implements SitemapService {
 
     // -- HELPER
 
+    private Optional<ObjectAction> lookupAction(final ServiceActionLayoutData actionLayout) {
+        return specificationLoader
+        .specForLogicalTypeName(actionLayout.getLogicalTypeName())
+        .map(typeSpec->typeSpec.getAction(actionLayout.getId(), ActionType.USER).orElse(null));
+    }
+
     private Grid toGrid(final Class<?> domainClass, final Style style) {
 
         if (style == Style.CURRENT) {
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/PageParameterUtils.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/PageParameterUtils.java
index c21eeae..cf2186d 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/PageParameterUtils.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/util/PageParameterUtils.java
@@ -219,7 +219,7 @@ public class PageParameterUtils {
 
         val specLoader = commonContext.getSpecificationLoader();
         val owningLogicalTypeName = PageParameterNames.ACTION_OWNING_SPEC.getStringFrom(pageParameters);
-        val owningLogicalType = specLoader.lookupLogicalType(owningLogicalTypeName);
+        val owningLogicalType = specLoader.lookupLogicalTypeElseFail(owningLogicalTypeName);
 
         final ActionType actionType = PageParameterNames.ACTION_TYPE.getEnumFrom(pageParameters, ActionType.class);
         final String actionNameParms = PageParameterNames.ACTION_ID.getStringFrom(pageParameters);