You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2024/10/29 13:30:28 UTC
(causeway) branch master updated: CAUSEWAY-3815: prepare meta-model to support actions in collection view
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/causeway.git
The following commit(s) were added to refs/heads/master by this push:
new dcbec39cc4d CAUSEWAY-3815: prepare meta-model to support actions in collection view
dcbec39cc4d is described below
commit dcbec39cc4d0d8178b4050834b4628bb36fb2261
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Oct 29 14:30:23 2024 +0100
CAUSEWAY-3815: prepare meta-model to support actions in collection view
---
.../applib/annotation/CollectionLayout.java | 5 --
.../ColumnOrderTxtFileServiceDefault.java | 26 ++++---
.../core/metamodel/spec/feature/ObjectAction.java | 23 ++++++
.../spec/feature/ObjectActionContainer.java | 5 ++
.../metamodel/spec/feature/ObjectAssociation.java | 17 +----
.../spec/feature/ObjectAssociationContainer.java | 2 +-
.../specimpl/dflt/ObjectSpecificationDefault.java | 9 ++-
...ationsAsColumns.java => _MembersAsColumns.java} | 16 ++++-
.../core/metamodel/util/WhereContexts.java | 23 ++++--
.../ui/components/collection/CollectionPanel.java | 3 +-
.../CollectionContentsAsAjaxTablePanel.java | 46 ++++++++----
.../ajaxtable/columns/ActionColumn.java | 82 ++++++++++++++++++++++
.../columns/AssociationColumnAbstract.java | 4 +-
.../ajaxtable/columns/GenericColumn.java | 2 +
.../ajaxtable/columns/GenericColumnAbstract.java | 23 +++++-
.../ajaxtable/columns/PluralColumn.java | 4 +-
.../ajaxtable/columns/SingularColumn.java | 4 +-
.../ajaxtable/columns/TitleColumn.java | 4 +-
.../ajaxtable/columns/ToggleboxColumn.java | 4 +-
19 files changed, 244 insertions(+), 58 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/causeway/applib/annotation/CollectionLayout.java b/api/applib/src/main/java/org/apache/causeway/applib/annotation/CollectionLayout.java
index eee4fbdc3d9..891ec29f0ec 100644
--- a/api/applib/src/main/java/org/apache/causeway/applib/annotation/CollectionLayout.java
+++ b/api/applib/src/main/java/org/apache/causeway/applib/annotation/CollectionLayout.java
@@ -88,11 +88,6 @@ public @interface CollectionLayout {
/**
* Indicates where in the UI the collection should <i>not</i>not be visible.
- *
- * <p>
- * Only {@link Where#NOWHERE NOWHERE} or {@link Where#EVERYWHERE EVERYWHERE}/{@link Where#ANYWHERE ANYWHERE}
- * apply for collections.
- * </p>
*/
Where hidden()
default Where.NOT_SPECIFIED;
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/columnorder/ColumnOrderTxtFileServiceDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/columnorder/ColumnOrderTxtFileServiceDefault.java
index 87580d29dc2..17d614b6133 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/columnorder/ColumnOrderTxtFileServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/columnorder/ColumnOrderTxtFileServiceDefault.java
@@ -27,6 +27,7 @@ import org.springframework.stereotype.Service;
import org.apache.causeway.applib.annotation.PriorityPrecedence;
import org.apache.causeway.applib.annotation.Programmatic;
+import org.apache.causeway.applib.annotation.Where;
import org.apache.causeway.applib.services.columnorder.ColumnOrderTxtFileService;
import org.apache.causeway.commons.io.ZipUtils;
import org.apache.causeway.core.metamodel.CausewayModuleCoreMetamodel;
@@ -53,6 +54,7 @@ public class ColumnOrderTxtFileServiceDefault implements ColumnOrderTxtFileServi
final SpecificationLoader specificationLoader;
+ @Override
@Programmatic
public byte[] toZip(final Object domainObject) {
var zipBuilder = ZipUtils.zipEntryBuilder();
@@ -65,7 +67,7 @@ public class ColumnOrderTxtFileServiceDefault implements ColumnOrderTxtFileServi
// HELPERS
- private void addStandaloneEntry(Object domainObject, final ZipUtils.EntryBuilder zipBuilder) {
+ private void addStandaloneEntry(final Object domainObject, final ZipUtils.EntryBuilder zipBuilder) {
var parentSpec = specificationLoader.loadSpecification(domainObject.getClass());
var buf = new StringBuilder();
@@ -79,23 +81,25 @@ public class ColumnOrderTxtFileServiceDefault implements ColumnOrderTxtFileServi
zipBuilder.addAsUtf8(fileName, fileContents);
}
- private void addCollectionEntries(Object domainObject, final ZipUtils.EntryBuilder zipBuilder) {
+ private void addCollectionEntries(final Object domainObject, final ZipUtils.EntryBuilder zipBuilder) {
var parentSpec = specificationLoader.loadSpecification(domainObject.getClass());
parentSpec.streamCollections(MixedIn.INCLUDED)
.forEach(collection -> addCollection(collection, parentSpec, zipBuilder));
}
- private void addCollection(final OneToManyAssociation collection, final ObjectSpecification parentSpec, final ZipUtils.EntryBuilder zipBuilder) {
- var buf = new StringBuilder();
+ private void addCollection(
+ final OneToManyAssociation collection,
+ final ObjectSpecification parentSpec,
+ final ZipUtils.EntryBuilder zipBuilder) {
- var collectionIdentifier = collection.getFeatureIdentifier();
- var elementType = collection.getElementType();
+ var buf = new StringBuilder();
- elementType.streamAssociations(MixedIn.INCLUDED)
- .filter(ObjectAssociation.Predicates.visibleAccordingToHiddenFacet(collectionIdentifier))
- .filter(ObjectAssociation.Predicates.referencesParent(parentSpec).negate())
- .map(ObjectFeature::getId)
- .forEach(assocId -> buf.append(assocId).append("\n"));
+ collection.getElementType()
+ .streamAssociations(MixedIn.INCLUDED)
+ .filter(ObjectAssociation.Predicates.visibleAccordingToHiddenFacet(Where.PARENTED_TABLES))
+ .filter(ObjectAssociation.Predicates.referencesParent(parentSpec).negate())
+ .map(ObjectFeature::getId)
+ .forEach(assocId -> buf.append(assocId).append("\n"));
var fileName = String.format("%s#%s.columnOrder.txt", parentSpec.getShortIdentifier(), collection.getId());
var fileContents = buf.toString();
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAction.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAction.java
index 46c30f9548f..619b6eba3e5 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAction.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAction.java
@@ -39,8 +39,10 @@ import org.apache.causeway.core.config.CausewayConfiguration.Viewer.Wicket;
import org.apache.causeway.core.metamodel.consent.Consent;
import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.causeway.core.metamodel.consent.InteractionResultSet;
+import org.apache.causeway.core.metamodel.facets.WhereValueFacet;
import org.apache.causeway.core.metamodel.facets.actions.action.choicesfrom.ChoicesFromFacet;
import org.apache.causeway.core.metamodel.facets.actions.position.ActionPositionFacet;
+import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet;
import org.apache.causeway.core.metamodel.facets.members.iconfa.FaFacet;
import org.apache.causeway.core.metamodel.facets.members.iconfa.FaLayersProvider;
import org.apache.causeway.core.metamodel.facets.members.layout.group.LayoutGroupFacet;
@@ -492,6 +494,27 @@ public interface ObjectAction extends ObjectMember {
));
}
+ /**
+ * Returns true if no {@link HiddenFacet} is found that vetoes visibility.
+ * <p>
+ * However, whereHidden={@link Where#ALL_TABLES} is used as default
+ * when no {@link HiddenFacet} is found.
+ *
+ * @see ObjectAssociation.Predicates#visibleAccordingToHiddenFacet(Where)
+ *
+ * @apiNote an alternative would be to prime the meta-model with fallback facets,
+ * however the current approach is more heap friendly
+ */
+ public static Predicate<ObjectAction> visibleAccordingToHiddenFacet(final Where whereContext) {
+ return (final ObjectAction act) -> act.lookupFacet(HiddenFacet.class)
+ .map(WhereValueFacet.class::cast)
+ .map(WhereValueFacet::where)
+ // whereHidden=ALL_TABLES is the default when not specified otherwise
+ .or(()->Optional.of(Where.ALL_TABLES))
+ .stream()
+ .noneMatch(whereHidden -> whereHidden.includes(whereContext));
+ }
+
// -- HELPER
private static class HasChoicesFrom implements Predicate<ObjectAction> {
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectActionContainer.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectActionContainer.java
index 02ed6eb4db9..70107daa2b3 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectActionContainer.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectActionContainer.java
@@ -140,6 +140,11 @@ public interface ObjectActionContainer {
*/
Stream<ObjectAction> streamRuntimeActions(MixedIn mixedIn);
+ /**
+ * Actions visible in dedicated actions-column, honoring order and visibility.
+ */
+ Stream<ObjectAction> streamActionsForColumnRendering(Identifier memberIdentifier);
+
// -- ACTION STREAM (NO INHERITANCE)
/**
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociation.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociation.java
index 7c047520a1f..e19e4557846 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociation.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociation.java
@@ -24,7 +24,6 @@ import java.util.function.Predicate;
import org.springframework.lang.Nullable;
-import org.apache.causeway.applib.Identifier;
import org.apache.causeway.applib.annotation.Domain;
import org.apache.causeway.applib.annotation.Where;
import org.apache.causeway.commons.collections.Can;
@@ -42,9 +41,6 @@ import org.apache.causeway.core.metamodel.object.ManagedObject;
import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.util.Facets;
-import static org.apache.causeway.applib.annotation.Where.PARENTED_TABLES;
-import static org.apache.causeway.applib.annotation.Where.STANDALONE_TABLES;
-
/**
* Provides reflective access to a field on a domain object.
*/
@@ -157,25 +153,18 @@ public interface ObjectAssociation extends ObjectMember, CurrentHolder {
};
}
- static Where whereContextFor(final Identifier memberIdentifier) {
- return memberIdentifier.getType().isAction()
- ? STANDALONE_TABLES
- : PARENTED_TABLES;
- }
-
/**
* Returns true if no {@link HiddenFacet} is found that vetoes visibility.
- *
* <p>
* However, if it's a 1-to-Many, whereHidden={@link Where#ALL_TABLES} is used as default
* when no {@link HiddenFacet} is found.
*
+ * @see ObjectAction.Predicates#visibleAccordingToHiddenFacet(Where)
+ *
* @apiNote an alternative would be to prime the meta-model with fallback facets,
* however the current approach is more heap friendly
*/
- public static Predicate<ObjectAssociation> visibleAccordingToHiddenFacet(
- final Identifier memberIdentifier) {
- var whereContext = whereContextFor(memberIdentifier);
+ public static Predicate<ObjectAssociation> visibleAccordingToHiddenFacet(final Where whereContext) {
return (final ObjectAssociation assoc) -> assoc.lookupFacet(HiddenFacet.class)
.map(WhereValueFacet.class::cast)
.map(WhereValueFacet::where)
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociationContainer.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociationContainer.java
index 6096e63d9b2..73928317e06 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociationContainer.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectAssociationContainer.java
@@ -131,7 +131,7 @@ public interface ObjectAssociationContainer {
}
/**
- * Properties and Collections visible as columns honoring order and visibility.
+ * Properties and Collections visible as columns, honoring order and visibility.
*/
Stream<ObjectAssociation> streamAssociationsForColumnRendering(
Identifier memberIdentifier,
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 98cd420d80b..d6538833722 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -316,10 +316,17 @@ implements FacetHolder {
final Identifier memberIdentifier,
final ManagedObject parentObject) {
- return new _AssociationsAsColumns(getMetaModelContext())
+ return new _MembersAsColumns(getMetaModelContext())
.streamAssociationsForColumnRendering(this, memberIdentifier, parentObject);
}
+ @Override
+ public Stream<ObjectAction> streamActionsForColumnRendering(
+ final Identifier memberIdentifier) {
+ return new _MembersAsColumns(getMetaModelContext())
+ .streamActionsForColumnRendering(this, memberIdentifier);
+ }
+
// -- DETERMINE INJECTABILITY
private boolean isVetoedForInjection;
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/_AssociationsAsColumns.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/_MembersAsColumns.java
similarity index 90%
rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/_AssociationsAsColumns.java
rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/_MembersAsColumns.java
index 64cd6e05e5c..d174d16193d 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/_AssociationsAsColumns.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/dflt/_MembersAsColumns.java
@@ -38,7 +38,9 @@ import org.apache.causeway.core.metamodel.facets.object.grid.GridFacet;
import org.apache.causeway.core.metamodel.object.ManagedObject;
import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.causeway.core.metamodel.util.WhereContexts;
import static org.apache.causeway.applib.annotation.Where.PARENTED_TABLES;
import static org.apache.causeway.applib.annotation.Where.STANDALONE_TABLES;
@@ -48,11 +50,21 @@ import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
-class _AssociationsAsColumns implements HasMetaModelContext {
+class _MembersAsColumns implements HasMetaModelContext {
@Getter(onMethod_ = {@Override})
private final MetaModelContext metaModelContext;
+ public final Stream<ObjectAction> streamActionsForColumnRendering(
+ final ObjectSpecification elementType,
+ final Identifier memberIdentifier) {
+ if(elementType.isValue()) return Stream.empty();
+
+ return elementType.streamRuntimeActions(MixedIn.INCLUDED)
+ .filter(ObjectAction.Predicates.visibleAccordingToHiddenFacet(WhereContexts.collectionVariant(memberIdentifier)))
+ .sorted((a, b)->a.getCanonicalFriendlyName().compareTo(b.getCanonicalFriendlyName()));
+ }
+
public final Stream<ObjectAssociation> streamAssociationsForColumnRendering(
final ObjectSpecification elementType,
final Identifier memberIdentifier,
@@ -66,7 +78,7 @@ class _AssociationsAsColumns implements HasMetaModelContext {
var assocById = _Maps.<String, ObjectAssociation>newLinkedHashMap();
elementType.streamAssociations(MixedIn.INCLUDED)
- .filter(ObjectAssociation.Predicates.visibleAccordingToHiddenFacet(memberIdentifier))
+ .filter(ObjectAssociation.Predicates.visibleAccordingToHiddenFacet(WhereContexts.collectionVariant(memberIdentifier)))
.filter(ObjectAssociation.Predicates.referencesParent(parentSpecIfAny).negate())
.filter(assoc->filterColumnsUsingSpi(assoc, elementClass)) // optional SPI to filter columns;
.forEach(assoc->assocById.put(assoc.getId(), assoc));
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumn.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/WhereContexts.java
similarity index 53%
copy from viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumn.java
copy to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/WhereContexts.java
index 3a9bc03a4c0..2e521e21bf8 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumn.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/WhereContexts.java
@@ -16,13 +16,26 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns;
+package org.apache.causeway.core.metamodel.util;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.causeway.applib.Identifier;
+import org.apache.causeway.applib.annotation.Where;
-import org.apache.causeway.core.metamodel.tabular.DataRow;
+import lombok.experimental.UtilityClass;
-public interface GenericColumn
-extends IColumn<DataRow, String> {
+@UtilityClass
+public class WhereContexts {
+
+ /**
+ * Utility, that detects the collection variant (standalone or parented),
+ * based on the feature {@link Identifier} of the originating feature,
+ * that is, the feature is either a plural member or a plural action result.
+ */
+ public Where collectionVariant(final Identifier featureId) {
+ var whereContext = featureId.getType().isAction()
+ ? Where.STANDALONE_TABLES
+ : Where.PARENTED_TABLES;
+ return whereContext;
+ }
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/CollectionPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/CollectionPanel.java
index bd61bd31b49..9aa2e605649 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/CollectionPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/CollectionPanel.java
@@ -36,6 +36,7 @@ import org.apache.causeway.viewer.wicket.ui.panels.PanelAbstract;
import lombok.Getter;
import lombok.Setter;
+
import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel;
/**
@@ -94,7 +95,7 @@ implements
var collModel = getModel();
var collMetaModel = collModel.getMetaModel();
toggleboxColumn = collMetaModel.hasAssociatedActionsWithChoicesFromThisCollection()
- ? Optional.of(new ToggleboxColumn(collModel.delegate()))
+ ? Optional.of(new ToggleboxColumn(collModel.getElementType(), collModel.delegate()))
: Optional.empty();
}
return toggleboxColumn.orElse(null);
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
index d2fff1a3d44..30797c8fe91 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
@@ -31,6 +31,7 @@ import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.causeway.commons.internal.collections._Lists;
import org.apache.causeway.core.config.CausewayConfiguration.Viewer.Wicket;
import org.apache.causeway.core.metamodel.object.ManagedObject;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation;
import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
@@ -39,6 +40,7 @@ import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel;
import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel.Variant;
import org.apache.causeway.viewer.wicket.ui.components.collection.bulk.MultiselectToggleProvider;
import org.apache.causeway.viewer.wicket.ui.components.collection.count.CollectionCountProvider;
+import org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ActionColumn;
import org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ColumnAbbreviationOptions;
import org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.GenericColumn;
import org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.PluralColumn;
@@ -107,20 +109,26 @@ implements CollectionCountProvider {
final List<GenericColumn> columns = _Lists.newArrayList();
var collectionModel = entityCollectionModel();
+ var elementType = collectionModel.getElementType();
// first create property columns, so we know how many columns there are
addPropertyColumnsIfRequired(columns);
// prepend title column, which may have distinct rendering hints,
// based on whether there are any property columns or not
prependTitleColumn(
- columns,
+ elementType,
collectionModel.getVariant(),
- getWicketViewerSettings());
+ getWicketViewerSettings(),
+ columns);
- // prepend togglebox column (left most), if enabled
+ // prepend toggle-box column (left most), if enabled
getToggleboxColumn()
.ifPresent(toggleboxColumn->columns.add(0, toggleboxColumn));
+ // last append action column
+ //TODO[CAUSEWAY-3815] disabled until action column rendering is fleshed out
+ //addActionsColumnIfRequired(elementType, columns);
+
var dataProvider = new CollectionContentsSortableDataProvider(collectionModel);
var dataTable = new CausewayAjaxDataTable(
ID_TABLE, columns, dataProvider, collectionModel.getPageSize());
@@ -157,9 +165,10 @@ implements CollectionCountProvider {
}
private void prependTitleColumn(
- final List<GenericColumn> columns,
+ final ObjectSpecification elementType,
final Variant variant,
- final Wicket wktConfig) {
+ final Wicket wktConfig,
+ final List<GenericColumn> columns) {
var contextBookmark = entityCollectionModel().getParentObject().getBookmark()
.orElse(null);
@@ -174,14 +183,15 @@ implements CollectionCountProvider {
: -1 /* don't override */)
.build();
- columns.add(0, new TitleColumn(variant, contextBookmark, maxColumnTitleLength, opts));
+ columns.add(0, new TitleColumn(elementType, variant, contextBookmark, maxColumnTitleLength, opts));
}
- private void addPropertyColumnsIfRequired(final List<GenericColumn> columns) {
+ private void addPropertyColumnsIfRequired(
+ final List<GenericColumn> columns) {
var collectionModel = getModel();
- var elementTypeSpec = collectionModel.getElementType();
- if(elementTypeSpec == null) {
+ var elementType = collectionModel.getElementType();
+ if(elementType == null) {
return;
}
@@ -189,7 +199,7 @@ implements CollectionCountProvider {
var memberIdentifier = collectionModel.getIdentifier();
// add all ordered columns to the table
- elementTypeSpec.streamAssociationsForColumnRendering(memberIdentifier, parentObject)
+ elementType.streamAssociationsForColumnRendering(memberIdentifier, parentObject)
.map(ObjectAssociation::getSpecialization)
.map(spez->spez.fold(
this::createSingularColumn,
@@ -197,7 +207,8 @@ implements CollectionCountProvider {
.forEach(columns::add);
}
- private SingularColumn createSingularColumn(final OneToOneAssociation property) {
+ private SingularColumn createSingularColumn(
+ final OneToOneAssociation property) {
var collectionModel = getModel();
final String parentTypeName = property.getDeclaringType().getLogicalTypeName();
final Optional<String> sortability = property.getElementType().isComparableOrOrdered()
@@ -205,6 +216,7 @@ implements CollectionCountProvider {
: Optional.empty();
return new SingularColumn(
+ collectionModel.getElementType(),
collectionModel.getVariant(),
Model.of(property.getCanonicalFriendlyName()),
sortability,
@@ -213,11 +225,13 @@ implements CollectionCountProvider {
property.getCanonicalDescription());
}
- private PluralColumn createPluralColumn(final OneToManyAssociation collection) {
+ private PluralColumn createPluralColumn(
+ final OneToManyAssociation collection) {
var collectionModel = getModel();
final String parentTypeName = collection.getDeclaringType().getLogicalTypeName();
return new PluralColumn(
+ collectionModel.getElementType(),
collectionModel.getVariant(),
Model.of(collection.getCanonicalFriendlyName()),
collection.getId(),
@@ -227,4 +241,12 @@ implements CollectionCountProvider {
RenderOptions.builder().build());
}
+ private void addActionsColumnIfRequired(
+ final ObjectSpecification elementType,
+ final List<GenericColumn> columns) {
+ var collectionModel = getModel();
+ var memberIdentifier = collectionModel.getIdentifier();
+ ActionColumn.create(memberIdentifier, elementType).ifPresent(columns::add);
+ }
+
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ActionColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ActionColumn.java
new file mode 100644
index 00000000000..2d7c6bc5499
--- /dev/null
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ActionColumn.java
@@ -0,0 +1,82 @@
+/*
+ * 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.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns;
+
+import java.util.Optional;
+
+import org.apache.wicket.Component;
+
+import org.apache.causeway.applib.Identifier;
+import org.apache.causeway.commons.collections.Can;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
+import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
+import org.apache.causeway.viewer.wicket.model.models.interaction.coll.DataRowWkt;
+import org.apache.causeway.viewer.wicket.ui.util.Wkt;
+
+import lombok.NonNull;
+
+public final class ActionColumn
+extends GenericColumnAbstract {
+
+ private static final long serialVersionUID = 1L;
+
+ public static Optional<ActionColumn> create(
+ @NonNull final Identifier featureId,
+ @NonNull final ObjectSpecification elementType) {
+ var actions = elementType.streamActionsForColumnRendering(featureId)
+ .collect(Can.toCan());
+ if(actions.isEmpty()) return Optional.empty();
+ return Optional.of(new ActionColumn(elementType, actions));
+ }
+
+ private final Can<String> actionIds;
+ private transient Can<ObjectAction> actions;
+
+ private ActionColumn(
+ final ObjectSpecification elementType,
+ final Can<ObjectAction> actionsForColumnRendering) {
+ super(elementType, "Actions");
+ this.actions = actionsForColumnRendering;
+ this.actionIds = actions.map(ObjectAction::getId);
+ }
+
+ @Override
+ protected Component createCellComponent(
+ final String componentId, final DataRowWkt dataRowWkt) {
+ var dataRow = dataRowWkt.getObject();
+ var rowElement = dataRow.getRowElement();
+
+ return Wkt.label(componentId, actions()
+ .map(action->action.getFriendlyName(()->rowElement))
+ .join("|"));
+ }
+
+ // -- HELPER
+
+ private Can<ObjectAction> actions() {
+ synchronized(this) {
+ if(actions==null) {
+ var elementTypeSpec = elementType();
+ this.actions = actionIds.map(elementTypeSpec::getActionElseFail);
+ }
+ }
+ return actions;
+ }
+
+}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/AssociationColumnAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/AssociationColumnAbstract.java
index 6a4f1310b2d..ef2248442de 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/AssociationColumnAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/AssociationColumnAbstract.java
@@ -26,6 +26,7 @@ import org.apache.wicket.model.IModel;
import org.apache.causeway.commons.internal.base._Strings;
import org.apache.causeway.core.metamodel.object.ManagedObject;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel;
import org.apache.causeway.viewer.wicket.ui.ComponentFactory;
import org.apache.causeway.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
@@ -53,6 +54,7 @@ extends GenericColumnAbstract {
protected final String describedAs;
public AssociationColumnAbstract(
+ final ObjectSpecification elementType,
final EntityCollectionModel.Variant collectionVariant,
final IModel<String> columnNameModel,
/**
@@ -66,7 +68,7 @@ extends GenericColumnAbstract {
final String parentTypeName,
final Optional<String> describedAs) {
- super(columnNameModel, sortProperty.orElse(null));
+ super(elementType, columnNameModel, sortProperty.orElse(null));
this.collectionVariant = collectionVariant;
this.memberId = memberId;
this.parentTypeName = parentTypeName;
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumn.java
index 3a9bc03a4c0..d9f648aefbc 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumn.java
@@ -20,9 +20,11 @@ package org.apache.causeway.viewer.wicket.ui.components.collectioncontents.ajaxt
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.tabular.DataRow;
public interface GenericColumn
extends IColumn<DataRow, String> {
+ ObjectSpecification elementType();
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumnAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumnAbstract.java
index 439cdfafd2d..ee2ef0c92e4 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumnAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/GenericColumnAbstract.java
@@ -30,6 +30,8 @@ import org.apache.wicket.model.Model;
import org.apache.causeway.applib.services.i18n.TranslationContext;
import org.apache.causeway.core.metamodel.context.HasMetaModelContext;
+import org.apache.causeway.core.metamodel.context.MetaModelContext;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.tabular.DataRow;
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
import org.apache.causeway.viewer.wicket.model.models.interaction.coll.DataRowWkt;
@@ -52,16 +54,22 @@ implements GenericColumn, HasMetaModelContext {
private static final long serialVersionUID = 1L;
private transient ComponentFactoryRegistry componentRegistry;
+ private final Class<?> elementClass;
+ private transient ObjectSpecification elementType;
protected GenericColumnAbstract(
+ final ObjectSpecification elementType,
final String columnName) {
- this(Model.of(columnName), null);
+ this(elementType, Model.of(columnName), null);
}
protected GenericColumnAbstract(
+ final ObjectSpecification elementType,
final IModel<String> columnNameModel,
final String sortColumn) {
super(columnNameModel, sortColumn);
+ this.elementType = elementType;
+ this.elementClass = elementType.getCorrespondingClass();
}
@Override
@@ -70,6 +78,9 @@ implements GenericColumn, HasMetaModelContext {
final String componentId,
final IModel<DataRow> rowModel) {
cellItem.add(createCellComponent(componentId, (DataRowWkt)rowModel));
+ if(this instanceof ActionColumn) {
+ Wkt.cssAppend(cellItem, "action-column");
+ }
if(this instanceof TitleColumn) {
Wkt.cssAppend(cellItem, "title-column");
if(((TitleColumn)this).isTitleSuppressed()) {
@@ -85,6 +96,16 @@ implements GenericColumn, HasMetaModelContext {
protected abstract Component createCellComponent(final String componentId, final DataRowWkt dataRowWkt);
+ @Override
+ public final ObjectSpecification elementType() {
+ synchronized(this) {
+ if(elementType==null) {
+ this.elementType = MetaModelContext.instanceElseFail().specForTypeElseFail(elementClass);
+ }
+ }
+ return elementType;
+ }
+
protected ComponentFactory findComponentFactory(final UiComponentType uiComponentType, final IModel<?> model) {
return getComponentRegistry().findComponentFactory(uiComponentType, model);
}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/PluralColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/PluralColumn.java
index 4dd45788896..a77863f4fdf 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/PluralColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/PluralColumn.java
@@ -31,6 +31,7 @@ import org.apache.causeway.applib.services.linking.DeepLinkService;
import org.apache.causeway.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
import org.apache.causeway.core.metamodel.object.ManagedObject;
import org.apache.causeway.core.metamodel.object.ManagedObjects;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.tabular.DataColumn;
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel;
@@ -61,13 +62,14 @@ extends AssociationColumnAbstract {
private final RenderOptions opts;
public PluralColumn(
+ final ObjectSpecification elementType,
final EntityCollectionModel.Variant collectionVariant,
final IModel<String> columnNameModel,
final String propertyId,
final String parentTypeName,
final Optional<String> describedAs,
final RenderOptions opts) {
- super(collectionVariant, columnNameModel,
+ super(elementType, collectionVariant, columnNameModel,
Optional.empty(), // empty sortProperty (hence never sortable)
propertyId, parentTypeName, describedAs);
this.opts = opts;
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/SingularColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/SingularColumn.java
index a77e0863eba..ecd25dbce94 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/SingularColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/SingularColumn.java
@@ -24,6 +24,7 @@ import org.apache.wicket.Component;
import org.apache.wicket.model.IModel;
import org.apache.causeway.core.metamodel.commons.ViewOrEditMode;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel;
import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
@@ -35,13 +36,14 @@ extends AssociationColumnAbstract {
private static final long serialVersionUID = 1L;
public SingularColumn(
+ final ObjectSpecification elementType,
final EntityCollectionModel.Variant collectionVariant,
final IModel<String> columnNameModel,
final Optional<String> sortProperty,
final String propertyId,
final String parentTypeName,
final Optional<String> describedAs) {
- super(collectionVariant, columnNameModel, sortProperty, propertyId, parentTypeName, describedAs);
+ super(elementType, collectionVariant, columnNameModel, sortProperty, propertyId, parentTypeName, describedAs);
}
@Override
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/TitleColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/TitleColumn.java
index 8efaaa18854..dccd9a0c0ac 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/TitleColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/TitleColumn.java
@@ -24,6 +24,7 @@ import org.springframework.lang.Nullable;
import org.apache.causeway.applib.services.bookmark.Bookmark;
import org.apache.causeway.core.metamodel.object.ManagedObjects;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.viewer.commons.model.components.UiComponentType;
import org.apache.causeway.viewer.wicket.model.models.EntityCollectionModel.Variant;
import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt;
@@ -39,12 +40,13 @@ extends GenericColumnAbstract {
private final Bookmark contextBookmark;
public TitleColumn(
+ final ObjectSpecification elementType,
final Variant variant,
final Bookmark contextBookmark,
final int maxColumnTitleLength,
final ColumnAbbreviationOptions opts) {
- super(columnName(variant, maxColumnTitleLength)); // i18n
+ super(elementType, columnName(variant, maxColumnTitleLength)); // i18n
this.variant = variant;
this.contextBookmark = contextBookmark;
this.opts = opts;
diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ToggleboxColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ToggleboxColumn.java
index bad078d63cb..96af6228994 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ToggleboxColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ToggleboxColumn.java
@@ -25,6 +25,7 @@ import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.model.IModel;
import org.apache.causeway.commons.internal.collections._Lists;
+import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.tabular.DataTableInteractive;
import org.apache.causeway.viewer.wicket.model.models.interaction.coll.DataRowToggleWkt;
import org.apache.causeway.viewer.wicket.model.models.interaction.coll.DataRowWkt;
@@ -48,8 +49,9 @@ extends GenericColumnAbstract {
private final List<ContainedToggleboxPanel> rowToggles = _Lists.newArrayList();
public ToggleboxColumn(
+ final ObjectSpecification elementType,
final IModel<DataTableInteractive> dataTableModelHolder) {
- super("");
+ super(elementType, "");
this.dataTableModelHolder = dataTableModelHolder;
}