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;