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

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

commit 9a54f2fe7d6c3112e7637baefc9e4fe3eda88c55
Merge: 62ea3ce739 6d03ff13d5
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Thu Jan 19 12:01:48 2023 +0100

    Merge remote-tracking branch 'origin/master' into spring6

 api/applib/src/main/java/module-info.java          |    1 +
 .../applib/annotation/CollectionLayout.java        |    6 +-
 .../applib/annotation/DomainObjectLayout.java      |    7 +-
 .../applib/annotation/TableDecoration.java         |   60 -
 .../causeway/applib/annotation/TableDecorator.java |   89 ++
 .../layout/component/CollectionLayoutData.java     |   19 +-
 .../layout/component/DomainObjectLayoutData.java   |   13 +-
 .../applib/layout/component/TableDecoration.java   |   31 -
 .../documentation/DocumentationService.java        |   16 +-
 .../documentation/DocumentationServiceMenu.java    |   78 ++
 .../commons/internal/reflection/_ClassCache.java   |   15 +-
 .../commons/internal/reflection/_Reflect.java      |   24 +
 .../core/config/CausewayConfiguration.java         |   51 +-
 .../facets/CollectionLayoutConfigOptions.java      |   39 -
 .../facets/DomainObjectLayoutConfigOptions.java    |   53 -
 core/metamodel/src/main/java/module-info.java      |    1 +
 .../layout/CollectionLayoutFacetFactory.java       |    4 +-
 .../PagedFacetForCollectionLayoutAnnotation.java   |    7 +-
 ...va => CollectionLayoutTableDecoratorFacet.java} |   33 +-
 ...llectionLayoutTableDecoratorFacetAbstract.java} |   18 +-
 ...coratorFacetForCollectionLayoutAnnotation.java} |   10 +-
 ...ForCollectionLayoutAnnotationAsConfigured.java} |   10 +-
 ...TableDecoratorFacetForCollectionLayoutXml.java} |   34 +-
 ...ayoutTableDecoratorFacetFromConfiguration.java} |   10 +-
 .../DomainObjectLayoutFacetFactory.java            |    4 +-
 .../PagedFacetForDomainObjectLayoutAnnotation.java |    7 +-
 ... => DomainObjectLayoutTableDecoratorFacet.java} |   35 +-
 ...inObjectLayoutTableDecoratorFacetAbstract.java} |   18 +-
 ...ratorFacetForDomainObjectLayoutAnnotation.java} |   10 +-
 ...rDomainObjectLayoutAnnotationAsConfigured.java} |   10 +-
 ...bleDecoratorFacetForDomainObjectLayoutXml.java} |   33 +-
 ...ayoutTableDecoratorFacetFromConfiguration.java} |   10 +-
 .../services/grid/GridSystemServiceAbstract.java   |    8 +-
 .../core/metamodel/spec/feature/ObjectMember.java  |    3 +-
 .../causeway/core/metamodel/util/Facets.java       |   26 +-
 .../runtimeservices/src/main/java/module-info.java |    1 +
 .../documentation/DocumentationServiceDefault.java |  270 ++++
 .../DomainObjectLayout/DomainObjectLayoutMenu.java |    8 +
 .../plural/DomainObjectLayoutPluralVm.java         |    2 -
 ...inObjectLayoutTableDecoratorVm-description.adoc |    4 +
 .../DomainObjectLayoutTableDecoratorVm.java}       |   35 +-
 .../DomainObjectLayoutTableDecoratorVm.layout.xml  |   49 +
 .../src/main/java/demoapp/dom/menubars.layout.xml  |    1 +
 .../MetaModelRegressionTest.verify.approved.xml    | 1374 ++++++++++----------
 .../entity/collection/EntityCollectionPanel.java   |   31 +-
 .../StandaloneCollectionPanel.java                 |   31 +-
 .../viewer/wicket/ui/pages/PageAbstract.java       |   11 -
 .../DatatablesJavaScriptResourceReferenceInit.java |   77 --
 .../viewer/wicket/ui/panels/PanelAbstract.java     |   15 +
 .../apache/causeway/viewer/wicket/ui/util/Wkt.java |    6 +
 .../viewer/CausewayModuleViewerWicketViewer.java   |    2 +
 .../wicketapp/config/DatatablesNetInitWkt.java     |   50 +
 52 files changed, 1547 insertions(+), 1213 deletions(-)

diff --cc 
api/applib/src/main/java/org/apache/causeway/applib/layout/component/CollectionLayoutData.java
index 90cbbfa7a1,f291719f4d..a6c11998ed
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/layout/component/CollectionLayoutData.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/layout/component/CollectionLayoutData.java
@@@ -22,15 -22,16 +22,16 @@@ import java.io.Serializable
  import java.util.ArrayList;
  import java.util.List;
  
- import org.apache.causeway.applib.annotation.Where;
- import org.apache.causeway.applib.layout.links.Link;
- 
 -import javax.xml.bind.annotation.XmlAttribute;
 -import javax.xml.bind.annotation.XmlElement;
 -import javax.xml.bind.annotation.XmlRootElement;
 -import javax.xml.bind.annotation.XmlTransient;
 -import javax.xml.bind.annotation.XmlType;
 +import jakarta.xml.bind.annotation.XmlAttribute;
 +import jakarta.xml.bind.annotation.XmlElement;
 +import jakarta.xml.bind.annotation.XmlRootElement;
 +import jakarta.xml.bind.annotation.XmlTransient;
 +import jakarta.xml.bind.annotation.XmlType;
  
+ import org.apache.causeway.applib.annotation.TableDecorator;
+ import org.apache.causeway.applib.annotation.Where;
+ import org.apache.causeway.applib.layout.links.Link;
+ 
  /**
   * Describes the layout of a single collection, broadly corresponds to the
   * {@link org.apache.causeway.applib.annotation.CollectionLayout} annotation.
diff --cc 
api/applib/src/main/java/org/apache/causeway/applib/layout/component/DomainObjectLayoutData.java
index 613f691812,06b9c5dfe7..230d593ad6
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/layout/component/DomainObjectLayoutData.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/layout/component/DomainObjectLayoutData.java
@@@ -20,15 -20,16 +20,16 @@@ package org.apache.causeway.applib.layo
  
  import java.io.Serializable;
  
 -import javax.xml.bind.annotation.XmlAttribute;
 -import javax.xml.bind.annotation.XmlElement;
 -import javax.xml.bind.annotation.XmlRootElement;
 -import javax.xml.bind.annotation.XmlTransient;
 -import javax.xml.bind.annotation.XmlType;
 -
  import org.apache.causeway.applib.annotation.BookmarkPolicy;
+ import org.apache.causeway.applib.annotation.TableDecorator;
  import org.apache.causeway.applib.layout.links.Link;
  
 +import jakarta.xml.bind.annotation.XmlAttribute;
 +import jakarta.xml.bind.annotation.XmlElement;
 +import jakarta.xml.bind.annotation.XmlRootElement;
 +import jakarta.xml.bind.annotation.XmlTransient;
 +import jakarta.xml.bind.annotation.XmlType;
 +
  /**
   * Describes the layout of the title and icon of a domain object, broadly 
corresponding to {@link 
org.apache.causeway.applib.annotation.DomainObjectLayout}.
   *
diff --cc 
api/applib/src/main/java/org/apache/causeway/applib/services/documentation/DocumentationServiceMenu.java
index 0000000000,1b45aeaada..a718c4552d
mode 000000,100644..100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/services/documentation/DocumentationServiceMenu.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/documentation/DocumentationServiceMenu.java
@@@ -1,0 -1,78 +1,78 @@@
+ /*
+  *  Licensed to the Apache Software Foundation (ASF) under one
+  *  or more contributor license agreements.  See the NOTICE file
+  *  distributed with this work for additional information
+  *  regarding copyright ownership.  The ASF licenses this file
+  *  to you under the Apache License, Version 2.0 (the
+  *  "License"); you may not use this file except in compliance
+  *  with the License.  You may obtain a copy of the License at
+  *
+  *        http://www.apache.org/licenses/LICENSE-2.0
+  *
+  *  Unless required by applicable law or agreed to in writing,
+  *  software distributed under the License is distributed on an
+  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  *  KIND, either express or implied.  See the License for the
+  *  specific language governing permissions and limitations
+  *  under the License.
+  */
+ package org.apache.causeway.applib.services.documentation;
+ 
 -import javax.inject.Named;
++import jakarta.inject.Named;
+ 
+ import org.apache.causeway.applib.CausewayModuleApplib;
+ import org.apache.causeway.applib.annotation.Action;
+ import org.apache.causeway.applib.annotation.ActionLayout;
+ import org.apache.causeway.applib.annotation.DomainService;
+ import org.apache.causeway.applib.annotation.DomainServiceLayout;
+ import org.apache.causeway.applib.annotation.MemberSupport;
+ import org.apache.causeway.applib.annotation.PriorityPrecedence;
+ import org.apache.causeway.applib.annotation.RestrictTo;
+ import org.apache.causeway.applib.annotation.SemanticsOf;
+ import org.apache.causeway.applib.value.Markup;
+ 
+ /**
+  * Simply provides a UI to for the generation of a documentation (obtained 
from {@link DocumentationService}).
+  *
+  * @since 2.x {@index}
+  */
+ @Named(DocumentationServiceMenu.LOGICAL_TYPE_NAME)
+ @DomainService()
+ @DomainServiceLayout(
+         named = "Prototyping",
+         menuBar = DomainServiceLayout.MenuBar.SECONDARY
+ )
 -@javax.annotation.Priority(PriorityPrecedence.EARLY)
++@jakarta.annotation.Priority(PriorityPrecedence.EARLY)
+ public class DocumentationServiceMenu {
+ 
+     public static final String LOGICAL_TYPE_NAME = 
CausewayModuleApplib.NAMESPACE + ".DocumentationServiceMenu";
+ 
+     public static abstract class ActionDomainEvent<T> extends 
CausewayModuleApplib.ActionDomainEvent<T> {}
+ 
+     private final DocumentationService documentationService;
+ 
+     public DocumentationServiceMenu(final DocumentationService 
DocumentationService) {
+         this.documentationService = DocumentationService;
+     }
+ 
+     @Action(
+             domainEvent = downloadDocumentation.ActionDomainEvent.class,
+             semantics = SemanticsOf.NON_IDEMPOTENT, //disable client-side 
caching
+             restrictTo = RestrictTo.PROTOTYPING
+             )
+     @ActionLayout(
+             cssClassFa = "fa-download",
+             named = "The application-level help & documentation",
+             sequence="500.450.2")
+     public class downloadDocumentation{
+ 
+         public class ActionDomainEvent extends 
DocumentationServiceMenu.ActionDomainEvent<downloadDocumentation> {}
+ 
+         @MemberSupport public Markup act() {
+             final String html = documentationService.toDocumentationHtml();
+             return new Markup(html);
+         }
+ 
+     }
+ 
+ }
diff --cc 
core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/documentation/DocumentationServiceDefault.java
index 0000000000,246e45f2a7..05f5c17f4f
mode 000000,100644..100644
--- 
a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/documentation/DocumentationServiceDefault.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/documentation/DocumentationServiceDefault.java
@@@ -1,0 -1,269 +1,270 @@@
+ /*
+  *  Licensed to the Apache Software Foundation (ASF) under one
+  *  or more contributor license agreements.  See the NOTICE file
+  *  distributed with this work for additional information
+  *  regarding copyright ownership.  The ASF licenses this file
+  *  to you under the Apache License, Version 2.0 (the
+  *  "License"); you may not use this file except in compliance
+  *  with the License.  You may obtain a copy of the License at
+  *
+  *        http://www.apache.org/licenses/LICENSE-2.0
+  *
+  *  Unless required by applicable law or agreed to in writing,
+  *  software distributed under the License is distributed on an
+  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  *  KIND, either express or implied.  See the License for the
+  *  specific language governing permissions and limitations
+  *  under the License.
+  */
+ package org.apache.causeway.core.runtimeservices.documentation;
+ 
+ import java.util.HashMap;
+ import java.util.Map;
+ import java.util.Optional;
+ 
 -import javax.annotation.Priority;
 -import javax.inject.Inject;
 -import javax.inject.Named;
++import jakarta.annotation.Priority;
++import jakarta.inject.Inject;
++import jakarta.inject.Named;
++
++import org.springframework.beans.factory.annotation.Qualifier;
++import org.springframework.stereotype.Service;
+ 
+ import org.apache.causeway.applib.annotation.DomainObject;
+ import org.apache.causeway.applib.annotation.PriorityPrecedence;
+ import org.apache.causeway.applib.layout.component.ActionLayoutData;
+ import org.apache.causeway.applib.layout.component.CollectionLayoutData;
+ import org.apache.causeway.applib.layout.component.FieldSet;
+ import org.apache.causeway.applib.layout.component.PropertyLayoutData;
+ import org.apache.causeway.applib.layout.component.ServiceActionLayoutData;
+ import org.apache.causeway.applib.layout.grid.Grid;
+ import org.apache.causeway.applib.layout.menubars.MenuBars;
+ import org.apache.causeway.applib.layout.menubars.bootstrap.BSMenuBars;
+ import org.apache.causeway.applib.services.documentation.DocumentationService;
+ import org.apache.causeway.applib.services.homepage.HomePageResolverService;
+ import org.apache.causeway.applib.services.i18n.TranslationContext;
+ import org.apache.causeway.applib.services.i18n.TranslationService;
+ import org.apache.causeway.applib.services.menu.MenuBarsService;
+ import org.apache.causeway.commons.internal.base._NullSafe;
+ import org.apache.causeway.commons.internal.base._Strings;
+ import 
org.apache.causeway.core.metamodel.facets.all.described.MemberDescribedFacet;
+ import 
org.apache.causeway.core.metamodel.facets.all.i8n.staatic.HasStaticText;
+ import org.apache.causeway.core.metamodel.facets.object.grid.GridFacet;
+ import org.apache.causeway.core.metamodel.spec.ActionScope;
+ import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
+ import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
+ import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
+ import 
org.apache.causeway.core.runtimeservices.CausewayModuleCoreRuntimeServices;
 -import org.springframework.beans.factory.annotation.Qualifier;
 -import org.springframework.stereotype.Service;
+ 
+ import lombok.RequiredArgsConstructor;
+ 
+ @Service
+ @Named(CausewayModuleCoreRuntimeServices.NAMESPACE + 
".DocumentationServiceDefault")
+ @Priority(PriorityPrecedence.MIDPOINT)
+ @Qualifier("Default")
+ @RequiredArgsConstructor(onConstructor_ = {@Inject})
+ //@Log4j2
+ public class DocumentationServiceDefault implements DocumentationService {
+ 
+     private final SpecificationLoader specificationLoader;
+     private final MenuBarsService menuBarsService;
+     private final HomePageResolverService homePageResolverService;
+     private final TranslationService translationService;
+ 
+     @Override
+     public String toDocumentationHtml() {
+         final StringBuilder html = new StringBuilder();
+         Object homePage = homePageResolverService.getHomePage();
+         if (homePage != null) {
+             
specificationLoader.specForType(homePage.getClass()).ifPresent(homeSpec -> {
+                 html.append(String.format("<i>%s</i>\n", 
homeSpec.getDescription()));
+                 
html.append("</br><i>").append(translationService.translate(TranslationContext.empty(),
 "To know more about full terminology"));
+                 html.append(" <a 
href='#allObjectSpecs'>").append(translationService.translate(TranslationContext.empty(),
 "click here")).append("</a></i>\n");
+                 html.append("<hr></hr>");
+                 
html.append("<h3>").append(translationService.translate(TranslationContext.empty(),
 "Application Home Page")).append("</h3>");
+                 html.append(documentationForObjectType(homeSpec));
+                 html.append("<hr></hr>");
+             });
+         }
+         
html.append("<h3>").append(translationService.translate(TranslationContext.empty(),
 "Menu Actions")).append("</h3>");
+ 
+         Map<String, ObjectSpecification> domainObjects = new HashMap<>();
+ 
+         MenuBars menuBars = 
menuBarsService.menuBars(MenuBarsService.Type.DEFAULT);
+         html.append("<ol>");
+         menuBars.visit(BSMenuBars.VisitorAdapter.visitingMenus(menu -> {
+             String menuName = menu.getNamed();
+             if (_Strings.isNotEmpty(menuName)) {
+ 
+                 html.append(String.format("<li><h4>%s</h4></li>\n", 
menuName));
+ 
+                 html.append("<ol>");
+                 _NullSafe.stream(menu.getSections())
+                         .forEach(menuSection -> {
+                             String sectionName = menuSection.getNamed();
+                             if (_Strings.isNotEmpty(sectionName)) {
+                                 
html.append(String.format("<li><h5>%s</h5></li>\n", sectionName));
+ 
+                                 html.append("<ul>");
+                                 
_NullSafe.stream(menuSection.getServiceActions())
+                                         .map(this::lookupAction)
+                                         .flatMap(Optional::stream)
+                                         .forEach(menuAction -> {
+                                             
html.append(String.format("<li>%s: ", menuAction.getCanonicalFriendlyName()));
+                                             
menuAction.getCanonicalDescription()
+                                                     .ifPresent(describedAs -> 
{
+                                                         
html.append(String.format("<b>%s</b>.", describedAs));
+                                                     });
+                                             ObjectSpecification 
actionReturnType = menuAction.getReturnType();
+                                             ObjectSpecification 
actionElementType = menuAction.getElementType();
+ 
+                                             if 
(actionElementType.getCorrespondingClass() == void.class) {
+                                                 html.append("<i></i>"); 
//WARNING : NOTHING
+                                             } else if 
(actionReturnType.isPlural()) {
+                                                 
domainObjects.put(actionElementType.getLogicalTypeName(), actionElementType);
+                                                 html.append(String.format(" 
<i> %s: <a href='#%s'>%s</a>\n</i>"
+                                                         , 
translationService.translate(TranslationContext.empty(), "See"), 
actionElementType.getLogicalTypeName(), actionElementType.getSingularName()));
+                                             } else {
+                                                 
domainObjects.put(actionReturnType.getLogicalTypeName(), actionReturnType);
+                                                 html.append(String.format(" 
<i> %s: <a href='#%s'>%s</a>\n</i>"
+                                                         , 
translationService.translate(TranslationContext.empty(), "See"), 
actionElementType.getLogicalTypeName(), actionElementType.getSingularName()));
+                                             }
+                                             html.append("</li>");
+                                         });
+                                 html.append("</ul>");
+                             }
+                         });
+                 html.append("</ol>");
+             }
+         }));
+         html.append("</ol>");
+ 
+         html.append("<hr></hr>");
+         html.append("<h2 
id='allObjectSpecs'>").append(translationService.translate(TranslationContext.empty(),
 "Terminology")).append("</h2>");
+         html.append("<ol>");
+         for (ObjectSpecification objectSpec : domainObjects.values()) {
+             if (objectSpec != null) {
+                 html.append(String.format("<li id='%s'><h3>%s</h3></li>\n",
+                         objectSpec.getLogicalTypeName(), 
objectSpec.getSingularName()));
+                 html.append(objectSpec.getDescription());
+                 html.append(".");
+                 html.append(String.format("%s\n", 
documentationForObjectType(objectSpec)));
+             }
+         }
+         html.append("</ol>");
+         return html.toString();
+     }
+ 
+     // -- HELPER
+ 
 -    private StringBuffer documentationForObjectType(ObjectSpecification 
objectSpec) {
++    private StringBuffer documentationForObjectType(final ObjectSpecification 
objectSpec) {
+         StringBuffer html = new StringBuffer();
+ 
+         Grid grid = toGrid(objectSpec.getCorrespondingClass());
+         html.append("<ul>");
+         {
+             html.append("<ul>");
+             {
+                 for (ActionLayoutData layout : 
grid.getAllActionsById().values()) {
+                     objectSpec.getAction(layout.getId(), 
ActionScope.PRODUCTION_ONLY)
+                             .ifPresent(member -> {
+                                 if (!"clearHints".equals(member.getId()) && 
!member.isAlwaysHidden()) {
+                                     String describedAs = 
member.getCanonicalDescription()
+                                             .map(desc -> String.format("%s", 
desc))
+                                             .orElse("");
+                                     html.append(String.format("<li><i 
class='%s'></i><b>%s</b>: %s.</li>\n",
+                                             
_Strings.isNotEmpty(layout.getCssClassFa()) ? layout.getCssClassFa() : "fa 
fa-faw fa-location-arrow",
+                                             member.getCanonicalFriendlyName(),
+                                             describedAs));
+                                 }
+                             });
+                 }
+             }
+             html.append("</ul>");
+             html.append("<ul>");
+             {
+                 for (CollectionLayoutData layout : 
grid.getAllCollectionsById().values()) {
+                     objectSpec.getCollection(layout.getId())
+                             .ifPresent(member -> {
+                                 if (!member.isAlwaysHidden()) {
+                                     String description = null;
+                                     if 
(member.containsFacet(MemberDescribedFacet.class)) {
+                                         description = 
member.getFacet(MemberDescribedFacet.class).getSpecialization()
+                                                 
.left().map(HasStaticText::text).orElse(null);
+                                     }
+                                     if (_Strings.isNotEmpty(description)) {
+                                         description = layout.getDescribedAs();
+                                     }
+                                     html.append(String.format("<li><i 
class='%s'></i><b>%s</b>: %s.</li>\n",
+                                             "fa fa-fw fa-list",
+                                             member.getCanonicalFriendlyName(),
+                                             description != null ? description 
: ""));
+                                     // FIXME[ISIS-2883] also visit associated 
actions
+                                     // ... 
collection.streamAssociatedActions()
+                                     html.append("<ul>");
+                                     
member.streamAssociatedActions().forEach(action -> {
+                                         html.append(String.format("<li><i 
class='%s'></i> <b>%s</b>: %s.</li>\n",
+                                                 "fa fa-faw fa-location-arrow",
+                                                 
action.getCanonicalFriendlyName(),
+                                                 
action.getCanonicalDescription().orElse("")));
+                                     });
+                                     html.append("</ul>");
+                                 }
+                             });
+                 }
+             }
+             html.append("</ul>");
+             html.append("<ul>");
+             {
+                 grid.visit(new Grid.VisitorAdapter() {
+                     @Override
+                     public void visit(final FieldSet fieldSet) {
+                         if (_NullSafe.isEmpty(fieldSet.getProperties())) {
+                             return;
+                         } else {
+                             html.append(String.format("<li>%s</li>\n", 
fieldSet.getName()));
+                             html.append("<ul>");
+                             for (PropertyLayoutData layout : 
fieldSet.getProperties()) {
+                                 objectSpec.getProperty(layout.getId())
+                                         .ifPresent(member -> {
+                                             if (!member.isAlwaysHidden()) {
+                                                 String describedAs = 
member.getCanonicalDescription()
+                                                         .map(desc -> 
String.format("%s", desc))
+                                                         .orElse("");
+                                                 
html.append(String.format("<li><b>%s</b>: %s.",
+                                                         
member.getCanonicalFriendlyName(),
+                                                         describedAs));
+                                                 if 
(member.getElementType().getLogicalType().getCorrespondingClass().isAnnotationPresent(DomainObject.class))
 {
+                                                     
html.append(String.format(" <i> See: <a href='#%s'>%s</a></i>",
+                                                             
member.getElementType().getLogicalTypeName(),
+                                                             
member.getElementType().getSingularName()));
+                                                 } else {
+                                                     //none
+                                                 }
+                                                 html.append("</li>\n");
+                                             }
+                                         });
+                             }
+                             html.append("</ul>");
+                         }
+                     }
+                 });
+             }
+             html.append("</ul>");
+         }
+         html.append("</ul>");
+         return html;
+     }
+ 
+     private Optional<ObjectAction> lookupAction(final ServiceActionLayoutData 
actionLayout) {
+         return specificationLoader
+                 .specForLogicalTypeName(actionLayout.getLogicalTypeName())
+                 .map(typeSpec -> typeSpec.getAction(actionLayout.getId(), 
ActionScope.PRODUCTION_ONLY).orElse(null));
+     }
+ 
+     private Grid toGrid(final Class<?> domainClass) {
+         return specificationLoader.specForType(domainClass)
+                 .flatMap(spec -> spec.lookupFacet(GridFacet.class))
+                 .map(gridFacet -> gridFacet.getGrid(null))
+                 .orElse(null);
+     }
+ }
diff --cc 
examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObjectLayout/tabledec/DomainObjectLayoutTableDecoratorVm.java
index 27e741442b,9070366277..7a7bc53fdf
--- 
a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObjectLayout/tabledec/DomainObjectLayoutTableDecoratorVm.java
+++ 
b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/DomainObjectLayout/tabledec/DomainObjectLayoutTableDecoratorVm.java
@@@ -21,14 -21,16 +21,16 @@@ package demoapp.dom.domain.objects.Doma
  import java.util.List;
  import java.util.UUID;
  
 -import javax.inject.Named;
 -import javax.xml.bind.annotation.XmlAccessType;
 -import javax.xml.bind.annotation.XmlAccessorType;
 -import javax.xml.bind.annotation.XmlElement;
 -import javax.xml.bind.annotation.XmlRootElement;
 -import javax.xml.bind.annotation.XmlType;
 +import jakarta.inject.Named;
 +import jakarta.xml.bind.annotation.XmlAccessType;
 +import jakarta.xml.bind.annotation.XmlAccessorType;
 +import jakarta.xml.bind.annotation.XmlElement;
 +import jakarta.xml.bind.annotation.XmlRootElement;
 +import jakarta.xml.bind.annotation.XmlType;
  
  import org.apache.causeway.applib.annotation.Action;
+ import org.apache.causeway.applib.annotation.Collection;
+ import org.apache.causeway.applib.annotation.CollectionLayout;
  import org.apache.causeway.applib.annotation.DomainObject;
  import org.apache.causeway.applib.annotation.DomainObjectLayout;
  import org.apache.causeway.applib.annotation.Nature;

Reply via email to