This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 3971-layout.switching
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/3971-layout.switching by this
push:
new bc4b64f8224 CAUSEWAY-3971: LayoutService to support layout variant
exports
bc4b64f8224 is described below
commit bc4b64f8224991a08818c9c13c59a5f10af87c1a
Author: andi-huber <[email protected]>
AuthorDate: Wed Mar 4 14:00:57 2026 +0100
CAUSEWAY-3971: LayoutService to support layout variant exports
---
.../mixins/layout/Object_downloadLayout.java | 22 +++++---
.../applib/services/layout/LayoutService.java | 13 ++++-
.../services/layout/LayoutServiceDefault.java | 62 +++++++++++++++-------
3 files changed, 67 insertions(+), 30 deletions(-)
diff --git
a/api/applib/src/main/java/org/apache/causeway/applib/mixins/layout/Object_downloadLayout.java
b/api/applib/src/main/java/org/apache/causeway/applib/mixins/layout/Object_downloadLayout.java
index 4ead12fa251..4c1c72a1117 100644
---
a/api/applib/src/main/java/org/apache/causeway/applib/mixins/layout/Object_downloadLayout.java
+++
b/api/applib/src/main/java/org/apache/causeway/applib/mixins/layout/Object_downloadLayout.java
@@ -64,7 +64,9 @@ public class Object_downloadLayout {
public static class ActionDomainEvent
extends
org.apache.causeway.applib.CausewayModuleApplib.ActionDomainEvent<Object_downloadLayout>
{}
- private final Object holder;
+ @Inject LayoutService layoutService;
+
+ private final Object mixee;
@MemberSupport public Object act(
@ParameterLayout(
@@ -74,15 +76,19 @@ public static class ActionDomainEvent
final LayoutExportStyle style,
final CommonMimeType format) {
- var xmlString = layoutService.objectLayout(holder.getClass(), style,
format);
- return Clob.of(fileName, format, xmlString);
+ var layoutKey = layoutService.layoutKey(mixee).orElseThrow();
+ var xmlString = layoutService.objectLayout(layoutKey, style, format);
+ var infix= layoutKey.isVariant()
+ ? "-" + layoutKey.layoutIfAny()
+ : "";
+ return Clob.of(fileName + infix + ".layout", format, xmlString);
}
/**
* Defaults to the (simple) name of the domain object's class, with a
<code>.layout</code> suffix
*/
@MemberSupport public String default0Act() {
- return holder.getClass().getSimpleName() + ".layout";
+ return mixee.getClass().getSimpleName();
}
/**
* Default style is {@link LayoutExportStyle#MINIMAL}.
@@ -92,10 +98,10 @@ public static class ActionDomainEvent
}
@MemberSupport public CommonMimeType default2Act() {
- return layoutService.supportedObjectLayoutFormats().iterator().next();
}
+ return layoutService.supportedObjectLayoutFormats().iterator().next();
+ }
@MemberSupport public Set<CommonMimeType> choices2Act() {
- return layoutService.supportedObjectLayoutFormats(); }
-
- @Inject LayoutService layoutService;
+ return layoutService.supportedObjectLayoutFormats();
+ }
}
diff --git
a/api/applib/src/main/java/org/apache/causeway/applib/services/layout/LayoutService.java
b/api/applib/src/main/java/org/apache/causeway/applib/services/layout/LayoutService.java
index 2266a75f092..0c5581f1ddb 100644
---
a/api/applib/src/main/java/org/apache/causeway/applib/services/layout/LayoutService.java
+++
b/api/applib/src/main/java/org/apache/causeway/applib/services/layout/LayoutService.java
@@ -19,7 +19,11 @@
package org.apache.causeway.applib.services.layout;
import java.util.EnumSet;
+import java.util.Optional;
+import org.jspecify.annotations.Nullable;
+
+import org.apache.causeway.applib.services.grid.GridService.LayoutKey;
import org.apache.causeway.applib.services.menu.MenuBarsService;
import org.apache.causeway.applib.value.NamedWithMimeType.CommonMimeType;
@@ -27,12 +31,17 @@
* Provides the ability to obtain the serialized layout (eg. XML) for a single
domain object or
* for all domain objects, as well as the serialized layout for the
application's menu-bars.
*
- * @since 1.x - revised for 2.0 {@index}
+ * @since 1.x - revised for 2.0 and 4.0 {@index}
*/
public interface LayoutService {
// -- OBJECT LAYOUT
+ /**
+ * @since 4.0
+ */
+ Optional<LayoutKey> layoutKey(@Nullable Object domainObject);
+
/**
* Supported format(s) for {@link #objectLayout(Class, LayoutExportStyle,
CommonMimeType)}
* and {@link #toZip(LayoutExportStyle, CommonMimeType)}.
@@ -43,7 +52,7 @@ public interface LayoutService {
* Obtains the serialized form of the object layout (grid) for the
specified domain class.
* @throws UnsupportedOperationException when format is not supported
*/
- String objectLayout(Class<?> domainClass, LayoutExportStyle style,
CommonMimeType format);
+ String objectLayout(LayoutKey layoutKey, LayoutExportStyle style,
CommonMimeType format);
/**
* Obtains a zip file of the serialized layouts (grids) of all domain
entities and view models.
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/layout/LayoutServiceDefault.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/layout/LayoutServiceDefault.java
index 3f50fee3b38..895cd42f957 100644
---
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/layout/LayoutServiceDefault.java
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/layout/LayoutServiceDefault.java
@@ -20,6 +20,7 @@
import java.io.File;
import java.util.EnumSet;
+import java.util.Optional;
import jakarta.annotation.Priority;
import jakarta.inject.Named;
@@ -48,7 +49,11 @@
import org.apache.causeway.commons.internal.exceptions._Exceptions;
import org.apache.causeway.commons.io.ZipUtils;
import org.apache.causeway.core.metamodel.CausewayModuleCoreMetamodel;
+import org.apache.causeway.core.metamodel.context.MetaModelContext;
+import org.apache.causeway.core.metamodel.facetapi.FacetRanking;
+import
org.apache.causeway.core.metamodel.facets.object.layout.LayoutPrefixFacet;
import
org.apache.causeway.core.metamodel.layout.LayoutFacetUtil.MetamodelToGridOverridingVisitor;
+import org.apache.causeway.core.metamodel.object.ManagedObjects;
import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
@@ -85,14 +90,27 @@ public String menuBarsLayout(
// -- OBJECT LAYOUT
+ @Override
+ public Optional<LayoutKey> layoutKey(final @Nullable Object domainObject) {
+ var mo = MetaModelContext.instanceElseFail()
+ .getObjectManager()
+ .adapt(domainObject);
+ if(ManagedObjects.isNullOrUnspecifiedOrEmpty(mo))
+ return Optional.empty();
+ var layoutPrefix = mo.objSpec().lookupFacet(LayoutPrefixFacet.class)
+ .map(layoutPrefixFacet->layoutPrefixFacet.layoutPrefix(mo))
+ .orElse(null);
+ return Optional.of(new LayoutKey(domainObject.getClass(),
layoutPrefix));
+ }
+
@Override
public EnumSet<CommonMimeType> supportedObjectLayoutFormats() {
return gridService.supportedFormats();
}
@Override
- public String objectLayout(final Class<?> domainClass, final
LayoutExportStyle style, final CommonMimeType format) {
- return tryGridToFormatted(domainClass, style, format)
+ public String objectLayout(final LayoutKey layoutKey, final
LayoutExportStyle style, final CommonMimeType format) {
+ return tryGridToFormatted(layoutKey, style, format)
.ifFailureFail()
.getValue()
.orElse(null);
@@ -110,14 +128,14 @@ public byte[] toZip(final LayoutExportStyle style, final
CommonMimeType format)
for (var objectSpec : domainObjectSpecs) {
var domainClass = objectSpec.getCorrespondingClass();
- tryGridToFormatted(domainClass, style, format)
- .accept(
- failure->
- log.warn("failed to generate layout file for {}",
domainClass),
- contentIfAny->{
- contentIfAny.ifPresent(contentString->
- zipBuilder.addAsUtf8(zipEntryNameFor(objectSpec,
format), contentString));
- });
+ tryGridToFormatted(new LayoutKey(domainClass), style, format)
+ .accept(
+ failure->
+ log.warn("failed to generate layout file for {}",
domainClass),
+ contentIfAny->{
+ contentIfAny.ifPresent(contentString->
+ zipBuilder.addAsUtf8(zipEntryNameFor(objectSpec,
format), contentString));
+ });
}
return zipBuilder.toBytes();
@@ -126,20 +144,25 @@ public byte[] toZip(final LayoutExportStyle style, final
CommonMimeType format)
// -- HELPER
private BSGrid toGridForExport(
- final Class<?> domainClass,
+ final LayoutKey layoutKey,
final LayoutExportStyle style) {
// making a deep copy so, we don't modify the cached grid
- var grid = BSUtil.deepCopy(gridService.load(new
LayoutKey(domainClass)));
+ var grid = BSUtil.deepCopy(gridService.load(layoutKey));
- if (style == LayoutExportStyle.COMPLETE) return toComplete(grid,
domainClass);
- if (style == LayoutExportStyle.MINIMAL) return toMinimal(grid,
domainClass);
+ if (style == LayoutExportStyle.COMPLETE) return toComplete(grid,
layoutKey);
+ if (style == LayoutExportStyle.MINIMAL) return toMinimal(grid,
layoutKey.domainClass());
throw _Exceptions.unmatchedCase(style);
}
- private BSGrid toComplete(final BSGrid grid, final Class<?> domainClass) {
- var objectSpec = specLoader().specForTypeElseFail(domainClass);
- grid.visit(new MetamodelToGridOverridingVisitor(objectSpec));
+ private BSGrid toComplete(final BSGrid grid, final LayoutKey layoutKey) {
+ var objectSpec =
specLoader().specForTypeElseFail(layoutKey.domainClass());
+ try {
+ FacetRanking.setQualifier(layoutKey);
+ grid.visit(new MetamodelToGridOverridingVisitor(objectSpec));
+ } finally {
+ FacetRanking.removeQualifier();
+ }
return grid;
}
@@ -149,7 +172,6 @@ private BSGrid toMinimal(final BSGrid grid, final Class<?>
domainClass) {
BSUtil.remove(actionLayoutData);
}
@Override public void visit(final CollectionLayoutData
collectionLayoutData) {
-
BSUtil.remove(collectionLayoutData);
}
@Override public void visit(final PropertyLayoutData
propertyLayoutData) {
@@ -163,11 +185,11 @@ private BSGrid toMinimal(final BSGrid grid, final
Class<?> domainClass) {
}
private Try<String> tryGridToFormatted(
- final Class<?> domainClass,
+ final LayoutKey layoutKey,
final LayoutExportStyle style,
final CommonMimeType format) {
return Try.call(()->
- gridToFormatted(toGridForExport(domainClass, style), format));
+ gridToFormatted(toGridForExport(layoutKey, style), format));
}
private String gridToFormatted(final @Nullable BSGrid grid, final
CommonMimeType format) {