diff --git a/api/applib/src/main/java/org/apache/causeway/applib/services/appfeat/ApplicationFeatureFilter.java b/api/applib/src/main/java/org/apache/causeway/applib/services/appfeat/ApplicationFeatureFilter.java new file mode 100644 index 00000000000..7a055cdd650 --- /dev/null +++ b/api/applib/src/main/java/org/apache/causeway/applib/services/appfeat/ApplicationFeatureFilter.java @@ -0,0 +1,41 @@ +/* + * 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.appfeat; + +/** + * The various viewer implementations will individually honor any filters registered with Spring, + * based on a matching qualifier ('Graphql', 'Restful', etc.). + * + *

All filters that match a qualifier are consulted until any one rejects the {@link ApplicationFeature}. + * + *

If no filters match a qualifier, any {@link ApplicationFeature} is accepted. + * + *

'NoViewer' is a reserved string internally used to mean 'no filtering', hence it should not be used to qualify a filter. + * + * @since 4.0 {@index} + */ +@FunctionalInterface +public interface ApplicationFeatureFilter { + + /** + * Whether to include given {@link ApplicationFeature}. + */ + boolean filter(ApplicationFeature feature); + +} diff --git a/api/applib/src/main/java/org/apache/causeway/applib/services/wrapper/control/SyncControl.java b/api/applib/src/main/java/org/apache/causeway/applib/services/wrapper/control/SyncControl.java index cb2896057fa..bd21a063650 100644 --- a/api/applib/src/main/java/org/apache/causeway/applib/services/wrapper/control/SyncControl.java +++ b/api/applib/src/main/java/org/apache/causeway/applib/services/wrapper/control/SyncControl.java @@ -20,8 +20,9 @@ import java.util.UUID; -import org.jspecify.annotations.Nullable; +import org.springframework.util.StringUtils; +import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.iactnlayer.InteractionContext; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.schema.cmd.v2.CommandDto; @@ -31,7 +32,7 @@ /** * Controls the way that a (synchronous) wrapper works. * - * @since 2.0 revised for 3.4 {@index} + * @since 2.0 revised for 3.4 and 4.0 {@index} */ public record SyncControl( /** @@ -50,7 +51,12 @@ public record SyncControl( * *

The default behaviour is to rethrow the exception. */ - ExceptionHandler exceptionHandler) { + ExceptionHandler exceptionHandler, + /** + * Simulated viewerId, honoring feature filtering. + */ + String viewerId, + Where where) { //TODO can this be further simplified, or is there already an API we can reuse? @@ -79,22 +85,22 @@ public void onCommand( } public static SyncControl defaults() { - return new SyncControl(false, false, null, null); + return new SyncControl(false, false, null, null, null, null); } - public SyncControl( - boolean isSkipRules, - boolean isSkipExecute, - @Nullable Can commandListeners, - @Nullable ExceptionHandler exceptionHandler) { - this.isSkipRules = isSkipRules; - this.isSkipExecute = isSkipExecute; - this.commandListeners = commandListeners!=null - ? commandListeners - : Can.empty(); - this.exceptionHandler = exceptionHandler!=null - ? exceptionHandler - : exception -> { throw exception; }; + public SyncControl { + commandListeners = commandListeners!=null + ? commandListeners + : Can.empty(); + exceptionHandler = exceptionHandler!=null + ? exceptionHandler + : exception -> { throw exception; }; + viewerId = StringUtils.hasText(viewerId) + ? viewerId + : "NoViewer"; + where = where!=null + ? where + : Where.ANYWHERE; } /** @@ -102,27 +108,27 @@ public SyncControl( * executing the underlying property or action */ public SyncControl withSkipRules() { - return new SyncControl(true, isSkipExecute, commandListeners, exceptionHandler); + return new SyncControl(true, isSkipExecute, commandListeners, exceptionHandler, viewerId, where); } public SyncControl withCheckRules() { - return new SyncControl(false, isSkipExecute, commandListeners, exceptionHandler); + return new SyncControl(false, isSkipExecute, commandListeners, exceptionHandler, viewerId, where); } /** * Explicitly set the action to be executed. */ public SyncControl withExecute() { - return new SyncControl(isSkipRules, false, commandListeners, exceptionHandler); + return new SyncControl(isSkipRules, false, commandListeners, exceptionHandler, viewerId, where); } /** * Explicitly set the action to not be executed, in other words a 'dry run'. */ public SyncControl withNoExecute() { - return new SyncControl(isSkipRules, true, commandListeners, exceptionHandler); + return new SyncControl(isSkipRules, true, commandListeners, exceptionHandler, viewerId, where); } - public SyncControl listen(@NonNull CommandListener commandListener) { - return new SyncControl(isSkipRules, isSkipExecute, commandListeners.add(commandListener), exceptionHandler); + public SyncControl listen(@NonNull final CommandListener commandListener) { + return new SyncControl(isSkipRules, isSkipExecute, commandListeners.add(commandListener), exceptionHandler, viewerId, where); } /** @@ -131,13 +137,21 @@ public SyncControl listen(@NonNull CommandListener commandListener) { *

The default behaviour is to rethrow the exception. */ public SyncControl withExceptionHandler(final @NonNull ExceptionHandler exceptionHandler) { - return new SyncControl(isSkipRules, isSkipExecute, commandListeners, exceptionHandler); + return new SyncControl(isSkipRules, isSkipExecute, commandListeners, exceptionHandler, viewerId, where); + } + + public SyncControl withViewerId(final String viewerId) { + return new SyncControl(isSkipRules, isSkipExecute, commandListeners, exceptionHandler, viewerId, where); + } + + public SyncControl withWhere(final Where where) { + return new SyncControl(isSkipRules, isSkipExecute, commandListeners, exceptionHandler, viewerId, where); } /** * @return whether this and other share the same execution mode, ignoring exceptionHandling */ - public boolean isEquivalent(SyncControl other) { + public boolean isEquivalent(final SyncControl other) { return this.isSkipExecute == other.isSkipExecute && this.isSkipRules == other.isSkipRules; } diff --git a/commons/src/main/java/org/apache/causeway/commons/internal/ioc/SpringContextHolder.java b/commons/src/main/java/org/apache/causeway/commons/internal/ioc/SpringContextHolder.java index edae73de62a..d1c14fa31e3 100644 --- a/commons/src/main/java/org/apache/causeway/commons/internal/ioc/SpringContextHolder.java +++ b/commons/src/main/java/org/apache/causeway/commons/internal/ioc/SpringContextHolder.java @@ -105,7 +105,6 @@ public Optional get(final @NonNull Class requiredType) { * @see #select(Class, Annotation[]) * @see #getSingletonElseFail(Class) */ - @SuppressWarnings("javadoc") public Can select(final @NonNull Class requiredType) { var allMatchingBeans = springContext.getBeanProvider(requiredType) .orderedStream() @@ -128,7 +127,6 @@ public Can select(final @NonNull Class requiredType) { * * @see #select(Class) */ - @SuppressWarnings("javadoc") public Can select( final @NonNull Class requiredType, final @Nullable Annotation[] qualifiers) { @@ -165,7 +163,6 @@ public Can select( * @return IoC managed singleton * @throws NoSuchElementException - if the singleton is not resolvable */ - @SuppressWarnings("javadoc") public T getSingletonElseFail(final @NonNull Class type) { var candidates = select(type); if (candidates.getCardinality() == Cardinality.ZERO) { diff --git a/commons/src/main/java/org/apache/causeway/commons/io/JaxbUtils.java b/commons/src/main/java/org/apache/causeway/commons/io/JaxbUtils.java index f8726d3f1d0..ce6c8310f48 100644 --- a/commons/src/main/java/org/apache/causeway/commons/io/JaxbUtils.java +++ b/commons/src/main/java/org/apache/causeway/commons/io/JaxbUtils.java @@ -24,7 +24,6 @@ import java.io.StringReader; import java.io.StringWriter; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.Consumer; diff --git a/commons/src/test/java/org/apache/causeway/commons/net/DataUriTest.java b/commons/src/test/java/org/apache/causeway/commons/net/DataUriTest.java index 3fd6f9b17ef..4bfba4e4eec 100644 --- a/commons/src/test/java/org/apache/causeway/commons/net/DataUriTest.java +++ b/commons/src/test/java/org/apache/causeway/commons/net/DataUriTest.java @@ -27,8 +27,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.apache.causeway.commons.net.DataUri; - import lombok.RequiredArgsConstructor; class DataUriTest { diff --git a/core/interaction/src/main/java/module-info.java b/core/interaction/src/main/java/module-info.java index 0f71704d9c1..ecf9de42631 100644 --- a/core/interaction/src/main/java/module-info.java +++ b/core/interaction/src/main/java/module-info.java @@ -18,6 +18,7 @@ */ module org.apache.causeway.core.interaction { exports org.apache.causeway.core.interaction; + exports org.apache.causeway.core.interaction.core; exports org.apache.causeway.core.interaction.scope; exports org.apache.causeway.core.interaction.session; diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenTypeFacet.java b/core/interaction/src/main/java/org/apache/causeway/core/interaction/core/AccessRestriction.java similarity index 76% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenTypeFacet.java rename to core/interaction/src/main/java/org/apache/causeway/core/interaction/core/AccessRestriction.java index f05d8e798ed..43b8f3ef348 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenTypeFacet.java +++ b/core/interaction/src/main/java/org/apache/causeway/core/interaction/core/AccessRestriction.java @@ -16,8 +16,16 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.causeway.core.metamodel.facets.object.hidden; +package org.apache.causeway.core.interaction.core; -public interface HiddenTypeFacet extends HiddenInstanceFacet { +import java.util.Optional; +import org.apache.causeway.core.metamodel.consent.Consent; + +public record AccessRestriction( + boolean canView, + boolean canEdit, + Optional vetoReasonOpt + ) { } + diff --git a/core/interaction/src/main/java/org/apache/causeway/core/interaction/core/ApplicationFeatureFilters.java b/core/interaction/src/main/java/org/apache/causeway/core/interaction/core/ApplicationFeatureFilters.java new file mode 100644 index 00000000000..7bf7f815473 --- /dev/null +++ b/core/interaction/src/main/java/org/apache/causeway/core/interaction/core/ApplicationFeatureFilters.java @@ -0,0 +1,85 @@ +/* + * 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.interaction.core; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; + +import org.jspecify.annotations.Nullable; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.util.StringUtils; + +import org.apache.causeway.applib.services.appfeat.ApplicationFeatureFilter; +import org.apache.causeway.commons.collections.Can; +import org.apache.causeway.commons.internal.base._NullSafe; +import org.apache.causeway.commons.internal.collections._Multimaps; + +record ApplicationFeatureFilters( + Can unqualifiedFilters, + Map> filtersByQualifier) { + + // -- FACTORIES + + static ApplicationFeatureFilters empty() { + return new ApplicationFeatureFilters(Can.empty(), Collections.emptyMap()); + } + + static ApplicationFeatureFilters collectFrom(final @Nullable ApplicationContext springContext) { + if(springContext==null) + //JUnit Support + return ApplicationFeatureFilters.empty(); + + var unqualifiedFilters = new ArrayList(); + var filtersByQualifier = _Multimaps.newListMultimap(); + + Stream.of(springContext.getBeanNamesForType(ApplicationFeatureFilter.class)) + .forEach(beanName->{ + var filterBean = springContext.getBean(beanName, ApplicationFeatureFilter.class); + @SuppressWarnings("deprecation") + Set qualifiers = AnnotationUtils.getRepeatableAnnotations(filterBean.getClass(), Qualifier.class); + if(!_NullSafe.isEmpty(qualifiers)) { + qualifiers.forEach(qualifier->{ + if(StringUtils.hasText(qualifier.value())) { + filtersByQualifier.putElement(qualifier.value(), filterBean); + } else { + unqualifiedFilters.add(filterBean); + } + }); + } else { + unqualifiedFilters.add(filterBean); + } + }); + + // Sanitize (no duplicates, when already in unqualified Can) and make immutable + var unqualifiedFiltersCanned = Can.ofCollection(unqualifiedFilters).distinct(); + var filtersByQualifierCanned = new HashMap>(); + filtersByQualifier.forEach((k, v)->filtersByQualifierCanned.put(k, Can.ofCollection(v).distinct().filter(it->!unqualifiedFiltersCanned.contains(it)))); + return new ApplicationFeatureFilters( + unqualifiedFiltersCanned, + Collections.unmodifiableMap(filtersByQualifierCanned)); + } + +} diff --git a/core/interaction/src/main/java/org/apache/causeway/core/interaction/core/InteractionConstraint.java b/core/interaction/src/main/java/org/apache/causeway/core/interaction/core/InteractionConstraint.java new file mode 100644 index 00000000000..6d7fc44a0d7 --- /dev/null +++ b/core/interaction/src/main/java/org/apache/causeway/core/interaction/core/InteractionConstraint.java @@ -0,0 +1,44 @@ +/* + * 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.interaction.core; + +import org.apache.causeway.applib.annotation.Where; +import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; + +public record InteractionConstraint( + WhatViewer whatViewer, + InteractionInitiatedBy initiatedBy, + Where where + ) { + + public InteractionConstraint withWhere(final Where where) { + return new InteractionConstraint(whatViewer, initiatedBy, where); + } + + public InteractionConstraint withInitiatedBy(final InteractionInitiatedBy initiatedBy) { + return new InteractionConstraint(whatViewer, initiatedBy, where); + } + + public VisibilityConstraint asVisibilityConstraint() { + return new VisibilityConstraint(whatViewer, where); + } + +} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java index fbb95181e90..7eee4f7c807 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java @@ -114,15 +114,15 @@ public Optional toOptional() { /** * {@code Pi}: origin=PROGRAMMING_MODEL, nature=implicit (NO_ICON_UNLESS_PROTOTYPING)
* {@code Pe}: origin=PROGRAMMING_MODEL, nature=explicit (SHOW_BAN_ICON)
- * {@code S(e)}: origin=SECURITY, nature=explicit (SHOW_BAN_ICON)
+ * {@code Se}: origin=SECURITY, nature=explicit (SHOW_BAN_ICON)
*

* {@code Pi ৹ Pi := pick any or concat}
* {@code Pe ৹ Pe := pick any or concat}
- * {@code S(e) ৹ S(e) := pick any or concat}
+ * {@code Se ৹ Se := pick any or concat}
*
* {@code Pi ৹ Pe := Pe}
- * {@code Pi ৹ S(e) := Pi}
- * {@code Pe ৹ S(e) := Pe}
+ * {@code Pi ৹ Se := Pi}
+ * {@code Pe ৹ Se := Pe}
* In other words: winner picking is driven by origin first and nature second. */ public VetoReason reduce(final VetoReason other) { @@ -187,8 +187,8 @@ public static VetoReason delegatedTo(final @NonNull Class - * Will correspond to the {@link InteractionResult#getReason() reason} in + * + *

Will correspond to the {@link InteractionResult#getReason() reason} in * the contained {@link #getInteractionResult() InteractionResult} (if one * was specified). */ @@ -204,8 +204,7 @@ default Optional getReasonAsString() { /** * Description of the interaction that this consent represents. * - *

- * May be null. + *

May be null. */ String getDescription(); @@ -222,7 +221,6 @@ default Optional getReasonAsString() { * The {@link InteractionResult} that created this {@link Consent}. * * @return - may be null if created as a legacy {@link Consent}. - * */ public InteractionResult getInteractionResult(); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/InteractionAdvisor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/InteractionAdvisor.java index 875c2634771..f5ddfdf5826 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/InteractionAdvisor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/InteractionAdvisor.java @@ -18,13 +18,7 @@ */ package org.apache.causeway.core.metamodel.consent; -import java.util.function.BiConsumer; - import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.interactions.InteractionAdvisorFacet; - -import org.jspecify.annotations.NonNull; /** * Marker interface for implementations (specifically, {@link Facet}s) that can @@ -34,37 +28,4 @@ */ public interface InteractionAdvisor { - /** - * For testing purposes only. - */ - public static InteractionAdvisor forTesting() { - return new InteractionAdvisorFacet() { - - @Override - public boolean semanticEquals(final @NonNull Facet other) { - return this == other; - } - - @Override - public void visitAttributes(final BiConsumer visitor) { - } - - @Override - public Class facetType() { - return null; - } - - @Override - public FacetHolder facetHolder() { - return null; - } - - @Override - public Precedence precedence() { - return Facet.Precedence.FALLBACK; - } - - }; - } - } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/ActionExecutor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/ActionExecutor.java index 6c21e2243af..2aba4eea9d8 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/ActionExecutor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/ActionExecutor.java @@ -23,6 +23,8 @@ import java.util.Objects; import java.util.Optional; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.events.domain.AbstractDomainEvent; import org.apache.causeway.applib.events.domain.ActionDomainEvent; import org.apache.causeway.applib.services.bookmark.Bookmark; @@ -42,6 +44,7 @@ import org.apache.causeway.core.metamodel.facets.actions.action.invocation.ActionInvocationFacetAbstract; import org.apache.causeway.core.metamodel.facets.actions.semantics.ActionSemanticsFacet; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.ManagedObjects; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; @@ -52,9 +55,9 @@ import static org.apache.causeway.commons.internal.base._Casts.uncheckedCast; import lombok.Getter; -import org.jspecify.annotations.NonNull; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; +import lombok.experimental.Accessors; @RequiredArgsConstructor //@Slf4j @@ -68,6 +71,7 @@ public final class ActionExecutor public static ActionExecutor forAction( final @NonNull FacetHolder facetHolder, final @NonNull InteractionInitiatedBy interactionInitiatedBy, + final @NonNull WhatViewer whatViewer, final @NonNull InteractionHead head, final @NonNull Can argumentAdapters, final @NonNull ObjectAction owningAction, @@ -77,15 +81,14 @@ public static ActionExecutor forAction( "action's parameter count and provided argument count must match"); // guard against malformed argumentAdapters - argumentAdapters.forEach(arg->{if(!ManagedObjects.isSpecified(arg)) { - throw _Exceptions.illegalArgument("arguments must be specified for action %s", owningAction); - }}); + argumentAdapters.forEach(arg->{if(!ManagedObjects.isSpecified(arg)) + throw _Exceptions.illegalArgument("arguments must be specified for action %s", owningAction);}); - var method = actionInvocationFacetAbstract.getMethods().getFirstElseFail(); + var method = actionInvocationFacetAbstract.methods().getFirstElseFail(); return new ActionExecutor( owningAction.getMetaModelContext(), facetHolder, - interactionInitiatedBy, owningAction, method, head, argumentAdapters, actionInvocationFacetAbstract); + interactionInitiatedBy, whatViewer, owningAction, method, head, argumentAdapters, actionInvocationFacetAbstract); } // -- CONSTRUCTION @@ -97,6 +100,9 @@ public static ActionExecutor forAction( private final @NonNull FacetHolder facetHolder; @Getter private final @NonNull InteractionInitiatedBy interactionInitiatedBy; + @Getter @Accessors(fluent = true) + private final @NonNull WhatViewer whatViewer; + @Getter private final @NonNull ObjectAction owningAction; @Getter @@ -225,9 +231,8 @@ private Object invokeMethodElseFromCache( ()->CanonicalInvoker.invoke(method, targetPojo, executionParameters), targetPojo.getClass(), method.getName(), targetPojoPlusExecutionParameters); - } else { - return CanonicalInvoker.invoke(method, targetPojo, executionParameters); - } + } else + return CanonicalInvoker.invoke(method, targetPojo, executionParameters); } private static Can updateArguments( diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/MemberExecutorService.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/MemberExecutorService.java index 03a5534d839..1e98e91ad61 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/MemberExecutorService.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/execution/MemberExecutorService.java @@ -20,6 +20,8 @@ import java.util.Optional; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.exceptions._Exceptions; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; @@ -30,12 +32,11 @@ import org.apache.causeway.core.metamodel.facets.properties.update.clear.PropertyClearFacet; import org.apache.causeway.core.metamodel.facets.properties.update.modify.PropertySetterFacet; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; -import org.jspecify.annotations.NonNull; - /** * Used by ActionInvocationFacets and PropertySetterOrClearFacets to submit their executions. *

@@ -70,6 +71,7 @@ default InteractionInternal getInteractionElseFail() { default ManagedObject invokeAction( final @NonNull FacetHolder facetHolder, final @NonNull InteractionInitiatedBy interactionInitiatedBy, + final @NonNull WhatViewer whatViewer, final @NonNull InteractionHead head, // action specifics final @NonNull Can argumentAdapters, @@ -78,7 +80,7 @@ default ManagedObject invokeAction( var actionExecutor = ActionExecutor.forAction( facetHolder, interactionInitiatedBy, - head, + whatViewer, head, argumentAdapters, owningAction, actionInvocationFacetAbstract); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facetapi/FacetUtil.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facetapi/FacetUtil.java index fd6af2ddcef..02823c588e0 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facetapi/FacetUtil.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facetapi/FacetUtil.java @@ -34,9 +34,9 @@ import org.apache.causeway.commons.internal.base._Strings; import org.apache.causeway.commons.internal.collections._Lists; import org.apache.causeway.core.metamodel.facetapi.Facet.Precedence; -import org.apache.causeway.core.metamodel.facetapi.FacetWithAttributes.DisablingOrEnabling; -import org.apache.causeway.core.metamodel.facetapi.FacetWithAttributes.HidingOrShowing; -import org.apache.causeway.core.metamodel.facetapi.FacetWithAttributes.Validating; +import org.apache.causeway.core.metamodel.interactions.DisablingInteractionAdvisor; +import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; +import org.apache.causeway.core.metamodel.interactions.ValidatingInteractionAdvisor; import org.apache.causeway.core.metamodel.util.snapshot.XmlSchema; import lombok.experimental.UtilityClass; @@ -245,9 +245,17 @@ public static void visitAttributes(Facet facet, BiConsumer visit } private String interactionAdvisors(Facet facet, final String delimiter) { - return Stream.of(Validating.class, HidingOrShowing.class, DisablingOrEnabling.class) + return Stream.of( + ValidatingInteractionAdvisor.class, + HidingInteractionAdvisor.class, + DisablingInteractionAdvisor.class) .filter(marker->marker.isAssignableFrom(facet.getClass())) - .map(Class::getSimpleName) + .map(cls->switch(cls.getSimpleName().substring(0, 1)) { + case "V" -> "Validating"; + case "H" -> "HidingOrShowing"; + case "D" -> "DisablingOrEnabling"; + default -> "?"; + }) .collect(Collectors.joining(delimiter)); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facetapi/FacetWithAttributes.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facetapi/FacetWithAttributes.java index 8b407ca2349..de713a767f6 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facetapi/FacetWithAttributes.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facetapi/FacetWithAttributes.java @@ -31,22 +31,5 @@ public interface FacetWithAttributes { default void visitAttributes(final BiConsumer visitor) { FacetUtil.visitAttributes((Facet)this, visitor); } - - /** - * Marker interface used within {@link FacetUtil#visitAttributes()}. - */ - public static interface HidingOrShowing { - } - - /** - * Marker interface used within {@link FacetUtil#visitAttributes()}. - */ - public static interface DisablingOrEnabling { - } - /** - * Marker interface used within {@link FacetUtil#visitAttributes()}. - */ - public static interface Validating { - } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/HasImperativeAspect.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/HasImperativeAspect.java index e7c034df9a6..0862b038959 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/HasImperativeAspect.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/HasImperativeAspect.java @@ -24,16 +24,16 @@ public interface HasImperativeAspect extends ImperativeFacet { - ImperativeAspect getImperativeAspect(); + ImperativeAspect imperativeAspect(); @Override - default Can getMethods() { - return getImperativeAspect().methods(); + default Can methods() { + return imperativeAspect().methods(); } @Override - default Intent getIntent() { - return getImperativeAspect().intent(); + default Intent intent() { + return imperativeAspect().intent(); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/ImperativeFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/ImperativeFacet.java index fbcbfaef4a1..3ee47dafb4d 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/ImperativeFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/ImperativeFacet.java @@ -56,7 +56,7 @@ public interface ImperativeFacet extends Facet { /** * The {@link Method}s invoked by this {@link Facet}. */ - public Can getMethods(); + Can methods(); public static enum Intent { CHECK_IF_HIDDEN, @@ -79,17 +79,17 @@ public static enum Intent { /** * The intent of this method, so that the {@link WrapperFactory} knows whether to delegate on or to reject. */ - public Intent getIntent(); + Intent intent(); public static void visitAttributes(final ImperativeFacet imperativeFacet, final BiConsumer visitor) { - var methods = imperativeFacet.getMethods(); + var methods = imperativeFacet.methods(); visitor.accept("methods", methods.stream() .map(MethodFacade::toString) .collect(Collectors.joining(", "))); methods.forEach(method-> visitor.accept( - "intent." + method.getName(), imperativeFacet.getIntent())); + "intent." + method.getName(), imperativeFacet.intent())); } // -- UTILITIES @@ -103,11 +103,11 @@ public static Intent getIntent(final ObjectMember member, final ResolvedMethod m case 0: break; case 1: - return imperativeFacets.get(0).getIntent(); + return imperativeFacets.get(0).intent(); default: Intent intentToReturn = null; for (ImperativeFacet imperativeFacet : imperativeFacets) { - Intent intent = imperativeFacet.getIntent(); + Intent intent = imperativeFacet.intent(); if(intentToReturn == null) { intentToReturn = intent; } else if(intentToReturn != intent) { @@ -143,7 +143,7 @@ public static Can singleRegularMethod(final @NonNull ResolvedMetho // -- HELPER private boolean containsMethod(final ResolvedMethod method) { - return getMethods().stream() + return methods().stream() .map(MethodFacade::asMethodForIntrospection) .anyMatch(method::equals); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java index 14d86e5e7d9..2b43c9ae2f4 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java @@ -35,7 +35,7 @@ import org.apache.causeway.core.metamodel.facets.actions.action.invocation.ActionDomainEventFacet; import org.apache.causeway.core.metamodel.facets.actions.action.invocation.ActionInvocationFacetForAction; import org.apache.causeway.core.metamodel.facets.actions.action.invocation.ActionInvocationFacetForMixedInPropertyOrCollection; -import org.apache.causeway.core.metamodel.facets.actions.action.prototype.PrototypeFacetForActionAnnotation; +import org.apache.causeway.core.metamodel.facets.actions.action.prototype.HiddenFacetForDeploymentTypeViaActionAnnotation; import org.apache.causeway.core.metamodel.facets.actions.action.typeof.TypeOfFacetForActionAnnotation; import org.apache.causeway.core.metamodel.facets.actions.fileaccept.FileAcceptFacetForActionAnnotation; import org.apache.causeway.core.metamodel.facets.actions.semantics.ActionSemanticsFacet; @@ -145,10 +145,10 @@ void processRestrictTo(final ProcessMethodContext processMethodContext, final Op // search for @Action(restrictTo=...) addFacetIfPresent( - PrototypeFacetForActionAnnotation + HiddenFacetForDeploymentTypeViaActionAnnotation .create( actionIfAny, facetedMethod, - ()->super.getSystemEnvironment().deploymentType())); + super.getSystemEnvironment().deploymentType())); } void processSemantics(final ProcessMethodContext processMethodContext, final Optional actionIfAny) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacet.java index 9b058f37926..c56ff501108 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacet.java @@ -22,6 +22,7 @@ import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -39,7 +40,8 @@ ManagedObject invoke( ObjectAction owningAction, InteractionHead head, Can argumentAdapters, - InteractionInitiatedBy interactionInitiatedBy); + InteractionInitiatedBy interactionInitiatedBy, + WhatViewer whatViewer); ObjectSpecification getReturnType(); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetAbstract.java index ebe4a5d6930..00a5f69b9d3 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetAbstract.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.events.domain.ActionDomainEvent; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; @@ -32,7 +34,7 @@ import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public abstract class ActionInvocationFacetAbstract extends DomainEventFacetAbstract> @@ -46,7 +48,8 @@ private static final Class type() { // -- CONSTRUCTION - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; @Getter(onMethod_ = {@Override}) private final ObjectSpecification declaringType; @Getter(onMethod_ = {@Override}) private final ObjectSpecification returnType; @@ -67,7 +70,7 @@ protected ActionInvocationFacetAbstract( } @Override - public final Intent getIntent() { + public final Intent intent() { return Intent.EXECUTE; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForAction.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForAction.java index 91abed72ce2..1b07c32348d 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForAction.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForAction.java @@ -25,6 +25,7 @@ import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facets.DomainEventHolder; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -51,10 +52,11 @@ public ManagedObject invoke( final ObjectAction owningAction, final InteractionHead head, final Can argumentAdapters, - final InteractionInitiatedBy interactionInitiatedBy) { + final InteractionInitiatedBy interactionInitiatedBy, + final WhatViewer whatViewer) { return memberExecutorService.invokeAction(facetHolder(), interactionInitiatedBy, - head, argumentAdapters, owningAction, this); + whatViewer, head, argumentAdapters, owningAction, this); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForMixedInPropertyOrCollection.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForMixedInPropertyOrCollection.java index 95cdea4e04b..7799d89bfdb 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForMixedInPropertyOrCollection.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForMixedInPropertyOrCollection.java @@ -28,6 +28,7 @@ import org.apache.causeway.core.metamodel.facets.collections.collection.modify.CollectionDomainEventFacet; import org.apache.causeway.core.metamodel.facets.properties.property.modify.PropertyDomainEventFacet; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -61,9 +62,10 @@ public ManagedObject invoke( final ObjectAction owningAction, final InteractionHead head, final Can argumentAdapters, - final InteractionInitiatedBy interactionInitiatedBy) { + final InteractionInitiatedBy interactionInitiatedBy, + final WhatViewer whatViewer) { return memberExecutorService.invokeAction(facetHolder(), interactionInitiatedBy, - head, argumentAdapters, owningAction, this); + whatViewer, head, argumentAdapters, owningAction, this); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/prototype/PrototypeFacetForActionAnnotation.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/prototype/HiddenFacetForDeploymentTypeViaActionAnnotation.java similarity index 51% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/prototype/PrototypeFacetForActionAnnotation.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/prototype/HiddenFacetForDeploymentTypeViaActionAnnotation.java index ff3f1ef9dd6..45a3edca345 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/prototype/PrototypeFacetForActionAnnotation.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/action/prototype/HiddenFacetForDeploymentTypeViaActionAnnotation.java @@ -19,31 +19,46 @@ package org.apache.causeway.core.metamodel.facets.actions.action.prototype; import java.util.Optional; -import java.util.function.Supplier; +import java.util.function.BiConsumer; import org.apache.causeway.applib.annotation.Action; import org.apache.causeway.applib.annotation.RestrictTo; import org.apache.causeway.core.config.environment.DeploymentType; +import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.facets.actions.prototype.PrototypeFacetAbstract; +import org.apache.causeway.core.metamodel.facets.actions.prototype.HiddenFacetForDeploymentType; +import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; -public class PrototypeFacetForActionAnnotation -extends PrototypeFacetAbstract { +public record HiddenFacetForDeploymentTypeViaActionAnnotation( + DeploymentType deploymentType, + FacetHolder facetHolder + ) implements HiddenFacetForDeploymentType { - public static Optional create( + public static Optional create( final Optional actionsIfAny, final FacetHolder holder, - final Supplier lazyDeploymentType) { + final DeploymentType deploymentType) { return actionsIfAny - .map(Action::restrictTo) - .filter(restrictTo -> restrictTo == RestrictTo.PROTOTYPING) - .map(restrictTo -> new PrototypeFacetForActionAnnotation(holder, lazyDeploymentType.get())); - + .map(Action::restrictTo) + .filter(restrictTo -> restrictTo == RestrictTo.PROTOTYPING) + .map(restrictTo -> new HiddenFacetForDeploymentTypeViaActionAnnotation(deploymentType, holder)); } - private PrototypeFacetForActionAnnotation(final FacetHolder holder, final DeploymentType deploymentType) { - super(holder, deploymentType); - } + @Override public Class facetType() { return HiddenFacetForDeploymentType.class; } + @Override public Precedence precedence() { return Precedence.DEFAULT; } + @Override + public String hides(VisibilityContext ic) { + return deploymentType.isProduction() + ? "Prototyping action not visible in production mode" + : null; + } + + @Override + public void visitAttributes(final BiConsumer visitor) { + HiddenFacetForDeploymentType.super.visitAttributes(visitor); + visitor.accept("deploymentType", deploymentType.name()); + } + } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutAnnotation.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutAnnotation.java index 4d1a7ccd099..51b78fde56e 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutAnnotation.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutAnnotation.java @@ -23,10 +23,10 @@ import org.apache.causeway.applib.annotation.ActionLayout; import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetAbstract; +import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetForLayoutAbstract; import org.apache.causeway.core.metamodel.object.ManagedObject; -public class HiddenFacetForActionLayoutAnnotation extends HiddenFacetAbstract { +public class HiddenFacetForActionLayoutAnnotation extends HiddenFacetForLayoutAbstract { public static Optional create( final Optional actionLayoutIfAny, diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutXml.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutXml.java index 39ab3bf49e5..69746f843d6 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutXml.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/layout/HiddenFacetForActionLayoutXml.java @@ -23,14 +23,14 @@ import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.layout.component.ActionLayoutData; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; -import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetAbstract; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; +import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetForLayoutAbstract; import org.apache.causeway.core.metamodel.object.ManagedObject; public class HiddenFacetForActionLayoutXml -extends HiddenFacetAbstract { +extends HiddenFacetForLayoutAbstract { - public static Optional create( + public static Optional create( final ActionLayoutData actionLayout, final FacetHolder holder, final Precedence precedence) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/prototype/HiddenFacetForDeploymentType.java similarity index 89% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacet.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/prototype/HiddenFacetForDeploymentType.java index cab8fd3ba3a..27c0b77a281 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/prototype/HiddenFacetForDeploymentType.java @@ -18,12 +18,11 @@ */ package org.apache.causeway.core.metamodel.facets.actions.prototype; -import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; /** * Indicates that the action should only be available in prototype mode. */ -public interface PrototypeFacet extends Facet, HidingInteractionAdvisor { +public interface HiddenFacetForDeploymentType extends HidingInteractionAdvisor { } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacetAbstract.java deleted file mode 100644 index 102fd5c4b03..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacetAbstract.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.metamodel.facets.actions.prototype; - -import java.util.function.BiConsumer; - -import org.apache.causeway.core.config.environment.DeploymentType; -import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetAbstract; -import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; - -public abstract class PrototypeFacetAbstract -extends FacetAbstract -implements PrototypeFacet { - - private final DeploymentType deploymentType; - - private static final Class type() { - return PrototypeFacet.class; - } - - public PrototypeFacetAbstract(final FacetHolder holder, final DeploymentType deploymentType) { - super(type(), holder); - this.deploymentType = deploymentType; - } - - @Override - public String hides( - final VisibilityContext ic) { - return deploymentType.isProduction() - ? "Prototyping action not visible in production mode" - : null; - } - - @Override - public void visitAttributes(final BiConsumer visitor) { - super.visitAttributes(visitor); - visitor.accept("deploymentType", deploymentType.name()); - } -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/validate/method/ActionParameterValidationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/validate/method/ActionParameterValidationFacetViaMethod.java index d19a8e813e7..9f6fdc96fcd 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/validate/method/ActionParameterValidationFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/validate/method/ActionParameterValidationFacetViaMethod.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.services.i18n.TranslatableString; import org.apache.causeway.applib.services.i18n.TranslationContext; import org.apache.causeway.applib.services.i18n.TranslationService; @@ -33,13 +35,14 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class ActionParameterValidationFacetViaMethod extends ActionParameterValidationFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final TranslationService translationService; private final TranslationContext translationContext; @@ -55,7 +58,7 @@ public ActionParameterValidationFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHECK_IF_VALID; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java index d9a669f40ca..b5cf3c70b41 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.services.i18n.TranslatableString; import org.apache.causeway.applib.services.i18n.TranslationContext; import org.apache.causeway.commons.collections.Can; @@ -34,13 +36,14 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class ActionValidationFacetViaMethod extends ActionValidationFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final TranslationContext translationContext; private final Optional patConstructor; @@ -56,7 +59,7 @@ public ActionValidationFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHECK_IF_VALID; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/hide/HiddenFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/hide/HiddenFacetForLayout.java similarity index 73% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/hide/HiddenFacet.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/hide/HiddenFacetForLayout.java index ce145305973..e6afa5f0713 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/hide/HiddenFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/hide/HiddenFacetForLayout.java @@ -25,37 +25,15 @@ import org.jspecify.annotations.NonNull; /** - * Hide a property, collection or action. + * Optionally hides a property, collection or action via layout. */ -public interface HiddenFacet +public interface HiddenFacetForLayout extends WhereValueFacet, HidingInteractionAdvisor { - public enum Semantics { - - /** regular semantics */ - HIDDEN, - - /** inverted semantics */ - SHOWN; - - public boolean isHidden() { - return this == HIDDEN; - } - - public boolean isShown() { - return this == SHOWN; - } - } - - // default semantics unless inverted - default Semantics getSemantics() { - return Semantics.HIDDEN; - } - // -- PREDICATES static boolean isAlwaysHidden(final @NonNull FacetHolder facetHolder) { - return WhereValueFacet.isAlways(facetHolder, HiddenFacet.class); + return WhereValueFacet.isAlways(facetHolder, HiddenFacetForLayout.class); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/i8n/imperative/HasImperativeTextFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/i8n/imperative/HasImperativeTextFacetAbstract.java index 37c14e97f8e..d21e35d9258 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/i8n/imperative/HasImperativeTextFacetAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/all/i8n/imperative/HasImperativeTextFacetAbstract.java @@ -21,6 +21,8 @@ import java.util.Objects; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.services.i18n.TranslationContext; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.functional.Try; @@ -34,7 +36,7 @@ import org.apache.causeway.core.metamodel.object.ManagedObjects; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class HasImperativeTextFacetAbstract extends FacetAbstract @@ -44,7 +46,8 @@ public class HasImperativeTextFacetAbstract protected final TranslationContext translationContext; - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; protected HasImperativeTextFacetAbstract( final Class facetType, @@ -64,7 +67,7 @@ public final Try text(final ManagedObject object) { } @Override - public final Intent getIntent() { + public final Intent intent() { return Intent.UI_HINT; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java index d636ae92fed..4a5abe7520f 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/accessor/CollectionAccessorFacetViaAccessor.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; @@ -34,13 +36,14 @@ import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class CollectionAccessorFacetViaAccessor extends PropertyOrCollectionAccessorFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; public CollectionAccessorFacetViaAccessor( final ObjectSpecification declaringType, @@ -51,7 +54,7 @@ public CollectionAccessorFacetViaAccessor( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.ACCESSOR; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/layout/HiddenFacetForCollectionLayoutAnnotation.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/layout/HiddenFacetForCollectionLayoutAnnotation.java index 1a42c66f40e..16bb823aa6b 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/layout/HiddenFacetForCollectionLayoutAnnotation.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/layout/HiddenFacetForCollectionLayoutAnnotation.java @@ -24,11 +24,11 @@ import org.apache.causeway.applib.annotation.CollectionLayout; import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetAbstract; +import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetForLayoutAbstract; import org.apache.causeway.core.metamodel.object.ManagedObject; public class HiddenFacetForCollectionLayoutAnnotation -extends HiddenFacetAbstract { +extends HiddenFacetForLayoutAbstract { public static Optional create( final Optional collectionLayoutIfAny, diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/layout/HiddenFacetForCollectionLayoutXml.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/layout/HiddenFacetForCollectionLayoutXml.java index c7262bbbcd3..eec0cf04234 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/layout/HiddenFacetForCollectionLayoutXml.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/collections/layout/HiddenFacetForCollectionLayoutXml.java @@ -23,14 +23,14 @@ import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.layout.component.CollectionLayoutData; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; -import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetAbstract; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; +import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetForLayoutAbstract; import org.apache.causeway.core.metamodel.object.ManagedObject; public class HiddenFacetForCollectionLayoutXml -extends HiddenFacetAbstract { +extends HiddenFacetForLayoutAbstract { - public static Optional create( + public static Optional create( final CollectionLayoutData collectionLayout, final FacetHolder holder, final Precedence precedence) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/disabled/method/DisableForContextFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/disabled/method/DisableForContextFacet.java index b05a26680f2..f7b56322e12 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/disabled/method/DisableForContextFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/disabled/method/DisableForContextFacet.java @@ -18,7 +18,6 @@ */ package org.apache.causeway.core.metamodel.facets.members.disabled.method; -import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.DisablingInteractionAdvisor; import org.apache.causeway.core.metamodel.object.ManagedObject; @@ -30,6 +29,6 @@ * In the standard Apache Causeway Programming Model, corresponds to invoking the * disableXxx support method for the member. */ -public interface DisableForContextFacet extends Facet, DisablingInteractionAdvisor { +public interface DisableForContextFacet extends DisablingInteractionAdvisor { } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java index 60ad25c09fc..dfb3ffba37f 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.services.i18n.TranslatableString; import org.apache.causeway.applib.services.i18n.TranslationContext; import org.apache.causeway.commons.collections.Can; @@ -34,13 +36,14 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class DisableForContextFacetViaMethod extends DisableForContextFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final TranslationContext translationContext; public DisableForContextFacetViaMethod( @@ -52,7 +55,7 @@ public DisableForContextFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHECK_IF_DISABLED; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/HiddenFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/HiddenFacetForLayoutAbstract.java similarity index 83% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/HiddenFacetAbstract.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/HiddenFacetForLayoutAbstract.java index c3a0fc53ece..1cd770ba76f 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/HiddenFacetAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/HiddenFacetForLayoutAbstract.java @@ -24,25 +24,25 @@ import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facets.WhereValueFacetAbstract; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; import org.apache.causeway.core.metamodel.object.ManagedObject; -public abstract class HiddenFacetAbstract +public abstract class HiddenFacetForLayoutAbstract extends WhereValueFacetAbstract -implements HiddenFacet { +implements HiddenFacetForLayout { - public static final Class type() { - return HiddenFacet.class; + public static final Class type() { + return HiddenFacetForLayout.class; } - public HiddenFacetAbstract( + public HiddenFacetForLayoutAbstract( final Where where, final FacetHolder holder) { super(type(), holder, where); } - public HiddenFacetAbstract( + public HiddenFacetForLayoutAbstract( final Where where, final FacetHolder holder, final Facet.Precedence precedence) { @@ -50,12 +50,12 @@ public HiddenFacetAbstract( } // to instantiate contributed facets - private HiddenFacetAbstract(final HiddenFacetAbstract toplevelFacet) { + private HiddenFacetForLayoutAbstract(final HiddenFacetForLayoutAbstract toplevelFacet) { super(type(), toplevelFacet.facetHolder(), toplevelFacet.where()); } @Override - public String hides(final VisibilityContext ic) { + public final String hides(final VisibilityContext ic) { return hiddenReason(ic.target(), ic.where()); } @@ -68,7 +68,6 @@ public String hides(final VisibilityContext ic) { @Override public final void visitAttributes(final BiConsumer visitor) { super.visitAttributes(visitor); - visitor.accept("semantics", getSemantics()); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/HiddenFacetFromLayoutPropertiesAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/HiddenFacetFromLayoutPropertiesAbstract.java deleted file mode 100644 index 96a622b0b76..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/HiddenFacetFromLayoutPropertiesAbstract.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.metamodel.facets.members.hidden; - -import java.util.Properties; - -import org.apache.causeway.applib.annotation.Where; -import org.apache.causeway.commons.internal.base._Strings; -import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.object.ManagedObject; - -public abstract class HiddenFacetFromLayoutPropertiesAbstract extends HiddenFacetAbstract { - - protected static Where hidden(final Properties properties) { - if(properties == null) { - return null; - } - final String hidden = _Strings.emptyToNull(properties.getProperty("hidden")); - if(hidden == null) { - return null; - } - return Where.valueOf(hidden); - } - - protected HiddenFacetFromLayoutPropertiesAbstract(final Where where, final FacetHolder holder) { - super(where, holder); - } - - @Override - public String hiddenReason(final ManagedObject targetAdapter, final Where whereContext) { - if(!where().includes(whereContext)) { - return null; - } - return "Hidden on " + where().getFriendlyName(); - } -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HiddenFacetForMember.java similarity index 79% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacet.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HiddenFacetForMember.java index 84b495b703e..b147146ac52 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HiddenFacetForMember.java @@ -18,18 +18,16 @@ */ package org.apache.causeway.core.metamodel.facets.members.hidden.method; -import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; import org.apache.causeway.core.metamodel.object.ManagedObject; /** - * Hide a property, collection or action based on the state of the target + * Optionally hides a property, collection or action based on the state of the target * {@link ManagedObject object}. * - *

- * In the standard Apache Causeway Programming Model, corresponds to invoking the + *

In the standard Apache Causeway Programming Model, corresponds to invoking the * hideXxx support method for the member. */ -public interface HideForContextFacet extends Facet, HidingInteractionAdvisor { +public interface HiddenFacetForMember extends HidingInteractionAdvisor { } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HiddenFacetForMemberViaMethod.java similarity index 70% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethod.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HiddenFacetForMemberViaMethod.java index 89b26eae214..957c85ce6c0 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HiddenFacetForMemberViaMethod.java @@ -23,29 +23,27 @@ import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; +import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; +import org.apache.causeway.core.metamodel.facetapi.FacetUtil; import org.apache.causeway.core.metamodel.facets.ImperativeFacet; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.MmInvokeUtils; -import lombok.Getter; -import org.jspecify.annotations.NonNull; +public record HiddenFacetForMemberViaMethod( + Can methods, + FacetHolder facetHolder + ) implements HiddenFacetForMember, ImperativeFacet { + + @Override public Class facetType() { return HiddenFacetForMember.class; } + @Override public Precedence precedence() { return Precedence.DEFAULT; } + @Override public Intent intent() { return Intent.CHECK_IF_HIDDEN;} -public class HideForContextFacetViaMethod -extends HideForContextFacetAbstract -implements ImperativeFacet { + public Can getMethods() { return methods(); } - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; - - public HideForContextFacetViaMethod(final ResolvedMethod method, final FacetHolder holder) { - super(holder); - this.methods = ImperativeFacet.singleRegularMethod(method); - } - - @Override - public Intent getIntent() { - return Intent.CHECK_IF_HIDDEN; + public HiddenFacetForMemberViaMethod(final ResolvedMethod method, final FacetHolder holder) { + this(ImperativeFacet.singleRegularMethod(method), holder); } @Override @@ -60,8 +58,13 @@ public String hides(final VisibilityContext ic) { @Override public void visitAttributes(final BiConsumer visitor) { - super.visitAttributes(visitor); + HiddenFacetForMember.super.visitAttributes(visitor); ImperativeFacet.visitAttributes(this, visitor); } + + @Override + public String toString() { + return FacetUtil.toString(this); + } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethodFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HiddenFacetForMemberViaMethodFactory.java similarity index 91% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethodFactory.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HiddenFacetForMemberViaMethodFactory.java index d857fb2f997..dbd5e4fd0e3 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetViaMethodFactory.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HiddenFacetForMemberViaMethodFactory.java @@ -26,11 +26,11 @@ import org.apache.causeway.core.metamodel.facets.members.support.MemberSupportFacetFactoryAbstract; import org.apache.causeway.core.metamodel.methods.MethodFinder; -public class HideForContextFacetViaMethodFactory +public class HiddenFacetForMemberViaMethodFactory extends MemberSupportFacetFactoryAbstract { @Inject - public HideForContextFacetViaMethodFactory(final MetaModelContext mmc) { + public HiddenFacetForMemberViaMethodFactory(final MetaModelContext mmc) { super(mmc, FeatureType.MEMBERS, MemberSupportPrefix.HIDE); } @@ -44,7 +44,7 @@ protected void search( .peek(processMethodContext::removeMethod) .forEach(hideMethod->{ addFacet( - new HideForContextFacetViaMethod( + new HiddenFacetForMemberViaMethod( hideMethod, processMethodContext.getFacetHolder())); }); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetAbstract.java deleted file mode 100644 index 29d25e5a352..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetAbstract.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.metamodel.facets.members.hidden.method; - -import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetAbstract; -import org.apache.causeway.core.metamodel.facetapi.FacetHolder; - -public abstract class HideForContextFacetAbstract extends FacetAbstract implements HideForContextFacet { - - private static final Class type() { - return HideForContextFacet.class; - } - - public HideForContextFacetAbstract(final FacetHolder holder) { - super(type(), holder); - } - - public HideForContextFacetAbstract(final FacetHolder holder, final Facet.Precedence precedence) { - super(type(), holder, precedence); - } - -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/navigation/NavigationFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/navigation/HiddenFacetForNavigation.java similarity index 83% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/navigation/NavigationFacet.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/navigation/HiddenFacetForNavigation.java index 10fc0cc1643..9c8c6349c10 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/navigation/NavigationFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/navigation/HiddenFacetForNavigation.java @@ -18,13 +18,12 @@ */ package org.apache.causeway.core.metamodel.facets.members.navigation; -import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenTypeFacet; +import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenFacetForNoMembersAuthorized; import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; /** * Hides object members that would allow navigation to a domain type that is - * {@link HiddenTypeFacet hidden} (typically due to security permissions). + * {@link HiddenFacetForNoMembersAuthorized hidden} (typically due to security permissions). */ -public interface NavigationFacet extends Facet, HidingInteractionAdvisor { +public interface HiddenFacetForNavigation extends HidingInteractionAdvisor { } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/callbacks/CallbackFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/callbacks/CallbackFacetAbstract.java index 762cf7ebcc6..4dcb5f79dd4 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/callbacks/CallbackFacetAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/callbacks/CallbackFacetAbstract.java @@ -28,6 +28,7 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; +import lombok.experimental.Accessors; /** * Adapter superclass for {@link Facet}s for {@link CallbackFacet}. @@ -36,7 +37,7 @@ public abstract class CallbackFacetAbstract extends FacetAbstract implements CallbackFacet { - @Getter(onMethod_ = {@Override}) + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) private final Can methods; private final Can asRegularMethods; @@ -50,7 +51,7 @@ protected CallbackFacetAbstract( } @Override - public final Intent getIntent() { + public final Intent intent() { return Intent.LIFECYCLE; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/cssclass/method/CssClassFacetViaCssClassMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/cssclass/method/CssClassFacetViaCssClassMethod.java index f3ecec740a0..5648f5f4986 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/cssclass/method/CssClassFacetViaCssClassMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/cssclass/method/CssClassFacetViaCssClassMethod.java @@ -21,6 +21,7 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; @@ -32,13 +33,14 @@ import org.apache.causeway.core.metamodel.object.ManagedObject; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class CssClassFacetViaCssClassMethod extends CssClassFacetAbstract implements HasImperativeAspect { - @Getter(onMethod_ = {@Override}) private final @NonNull ImperativeAspect imperativeAspect; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull ImperativeAspect imperativeAspect; public static Optional create( final @Nullable ResolvedMethod methodIfAny, diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/disabled/DisabledObjectFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/disabled/DisabledObjectFacet.java index 395670db73e..370001f3058 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/disabled/DisabledObjectFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/disabled/DisabledObjectFacet.java @@ -18,7 +18,6 @@ */ package org.apache.causeway.core.metamodel.facets.object.disabled; -import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facets.object.immutable.ImmutableFacet; import org.apache.causeway.core.metamodel.interactions.DisablingInteractionAdvisor; @@ -39,7 +38,7 @@ * @see ImmutableFacet */ public interface DisabledObjectFacet -extends Facet, DisablingInteractionAdvisor { +extends DisablingInteractionAdvisor { /** * Clone this facet onto another {@link FacetHolder}. diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/disabled/method/DisabledObjectFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/disabled/method/DisabledObjectFacetViaMethod.java index 41af51e99c6..b21da7680e8 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/disabled/method/DisabledObjectFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/disabled/method/DisabledObjectFacetViaMethod.java @@ -35,13 +35,16 @@ import org.apache.causeway.core.metamodel.object.ManagedObject; import lombok.Getter; +import lombok.experimental.Accessors; + import org.jspecify.annotations.NonNull; public class DisabledObjectFacetViaMethod extends DisabledObjectFacetAbstract implements HasImperativeAspect { - @Getter(onMethod_ = {@Override}) private final @NonNull ImperativeAspect imperativeAspect; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull ImperativeAspect imperativeAspect; private final TranslationContext translationContext; diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForNoMembersAuthorized.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForNoMembersAuthorized.java new file mode 100644 index 00000000000..961ff1781d2 --- /dev/null +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForNoMembersAuthorized.java @@ -0,0 +1,28 @@ +/* + * 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.metamodel.facets.object.hidden; + +import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; + +/** + * Optionally hides an object, based on whether non of its properties, collections and actions is visible. + */ +public interface HiddenFacetForNoMembersAuthorized extends HidingInteractionAdvisor { + +} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenTypeFacetFromAuthorizationFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForNoMembersAuthorizedFactory.java similarity index 84% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenTypeFacetFromAuthorizationFactory.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForNoMembersAuthorizedFactory.java index e501f314430..d46d90caeba 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenTypeFacetFromAuthorizationFactory.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForNoMembersAuthorizedFactory.java @@ -28,21 +28,21 @@ import org.apache.causeway.core.metamodel.spec.ObjectSpecification; /** - * Installs the {@link HiddenTypeFacetFromAuthorization} on the + * Installs the {@link HiddenFacetForNoMembersAuthorizedImpl} on the * {@link ObjectSpecification}. */ -public class HiddenTypeFacetFromAuthorizationFactory +public class HiddenFacetForNoMembersAuthorizedFactory extends FacetFactoryAbstract { @Inject - public HiddenTypeFacetFromAuthorizationFactory(final MetaModelContext mmc) { + public HiddenFacetForNoMembersAuthorizedFactory(final MetaModelContext mmc) { super(mmc, FeatureType.OBJECTS_ONLY); } @Override public void process(final ProcessClassContext processClassContext) { final FacetHolder facetHolder = processClassContext.getFacetHolder(); - FacetUtil.addFacet(new HiddenTypeFacetFromAuthorization(facetHolder)); + FacetUtil.addFacet(new HiddenFacetForNoMembersAuthorizedImpl(facetHolder)); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenTypeFacetFromAuthorization.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForNoMembersAuthorizedImpl.java similarity index 91% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenTypeFacetFromAuthorization.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForNoMembersAuthorizedImpl.java index 3245f2a36f5..85dfea926de 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenTypeFacetFromAuthorization.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForNoMembersAuthorizedImpl.java @@ -25,19 +25,12 @@ import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; -public record HiddenTypeFacetFromAuthorization( +public record HiddenFacetForNoMembersAuthorizedImpl( FacetHolder facetHolder - ) implements HiddenTypeFacet { + ) implements HiddenFacetForNoMembersAuthorized { - @Override - public Class facetType() { - return HiddenTypeFacet.class; - } - - @Override - public Precedence precedence() { - return Precedence.HIGH; // facet has final say, don't override; - } + @Override public Class facetType() { return HiddenFacetForNoMembersAuthorized.class; } + @Override public Precedence precedence() { return Precedence.HIGH; } @Override public String hides(final VisibilityContext vc) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenObjectFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForObject.java similarity index 86% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenObjectFacet.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForObject.java index 217a021e1b7..e55b14915ee 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenObjectFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenFacetForObject.java @@ -19,10 +19,11 @@ package org.apache.causeway.core.metamodel.facets.object.hidden; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; +import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectMember; -public interface HiddenObjectFacet extends HiddenInstanceFacet { +public interface HiddenFacetForObject extends HidingInteractionAdvisor { /** * Copy this facet to another {@link FacetHolder}. @@ -31,6 +32,6 @@ public interface HiddenObjectFacet extends HiddenInstanceFacet { * {@link ObjectSpecification}, and then copied down onto each of the spec's * {@link ObjectMember}s. */ - public HiddenObjectFacet copyTo(FacetHolder holder); + public HiddenFacetForObject copyTo(FacetHolder holder); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenInstanceFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenInstanceFacet.java deleted file mode 100644 index 2243cb6948c..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenInstanceFacet.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.metamodel.facets.object.hidden; - -import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; -import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; - -/** - * Mechanism for determining whether an object should be hidden. - * - *

Even though all the properties of an object may themselves be visible, there - * could be reasons to hide the object. - * - *

In the standard Apache Causeway Programming Model, typically corresponds to the - * hidden method. - * - * @see HiddenFacet - * @see HiddenObjectFacet - * @see HiddenTypeFacet - * - * @apiNote An unification attempt on HiddenTypeFacet and HiddenObjectFacet into a single, - * failed, because both facets must co-exist, where each has veto power (not one overruling the other). - */ -public interface HiddenInstanceFacet extends Facet, HidingInteractionAdvisor { - -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenObjectFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenObjectFacetAbstract.java deleted file mode 100644 index cd83642e1a2..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/HiddenObjectFacetAbstract.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.metamodel.facets.object.hidden; - -import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetAbstract; -import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; -import org.apache.causeway.core.metamodel.object.ManagedObject; - -public abstract class HiddenObjectFacetAbstract -extends FacetAbstract -implements HiddenObjectFacet { - - private static final Class type() { - return HiddenObjectFacet.class; - } - - public HiddenObjectFacetAbstract(final FacetHolder holder) { - super(type(), holder); - } - - @Override - public String hides(final VisibilityContext ic) { - final ManagedObject toValidate = ic.target(); - return toValidate != null ? hiddenReason(toValidate) : null; - } - - protected abstract String hiddenReason(ManagedObject toHide); - -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/method/HiddenObjectFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/method/HiddenFacetForObjectViaMethod.java similarity index 58% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/method/HiddenObjectFacetViaMethod.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/method/HiddenFacetForObjectViaMethod.java index 0b3b36ebb7e..a75a2dbd070 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/method/HiddenObjectFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/hidden/method/HiddenFacetForObjectViaMethod.java @@ -24,36 +24,30 @@ import org.jspecify.annotations.Nullable; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; +import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facets.HasImperativeAspect; import org.apache.causeway.core.metamodel.facets.ImperativeAspect; -import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenObjectFacet; -import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenObjectFacetAbstract; +import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenFacetForObject; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; import org.apache.causeway.core.metamodel.object.ManagedObject; -import lombok.Getter; -import org.jspecify.annotations.NonNull; +public record HiddenFacetForObjectViaMethod( + ImperativeAspect imperativeAspect, + FacetHolder facetHolder + ) implements HiddenFacetForObject, HasImperativeAspect { -public class HiddenObjectFacetViaMethod -extends HiddenObjectFacetAbstract -implements HasImperativeAspect { - - @Getter(onMethod_ = {@Override}) private final @NonNull ImperativeAspect imperativeAspect; - - public static Optional create( - final @Nullable ResolvedMethod methodIfAny, - final FacetHolder holder) { - - return Optional.ofNullable(methodIfAny) - .map(method->ImperativeAspect.singleRegularMethod(method, Intent.CHECK_IF_HIDDEN)) - .map(imperativeAspect->new HiddenObjectFacetViaMethod(imperativeAspect, holder)); - } - - private HiddenObjectFacetViaMethod(final ImperativeAspect imperativeAspect, final FacetHolder holder) { - super(holder); - this.imperativeAspect = imperativeAspect; - } + public static Optional create( + final @Nullable ResolvedMethod methodIfAny, + final FacetHolder holder) { + + return Optional.ofNullable(methodIfAny) + .map(method->ImperativeAspect.singleRegularMethod(method, Intent.CHECK_IF_HIDDEN)) + .map(imperativeAspect->new HiddenFacetForObjectViaMethod(imperativeAspect, holder)); + } + + @Override public Class facetType() { return HiddenFacetForObject.class; } + @Override public Precedence precedence() { return Precedence.DEFAULT;} @Override public String hides(final VisibilityContext ic) { @@ -62,19 +56,21 @@ public String hides(final VisibilityContext ic) { } @Override - public String hiddenReason(final ManagedObject target) { - final boolean isHidden = imperativeAspect.eval(target, false); - return isHidden ? "Hidden" : null; - } - - @Override - public HiddenObjectFacetViaMethod copyTo(final FacetHolder holder) { - return new HiddenObjectFacetViaMethod(imperativeAspect, holder); + public HiddenFacetForObjectViaMethod copyTo(final FacetHolder holder) { + return new HiddenFacetForObjectViaMethod(imperativeAspect, holder); } @Override public void visitAttributes(final BiConsumer visitor) { - super.visitAttributes(visitor); + HiddenFacetForObject.super.visitAttributes(visitor); imperativeAspect.visitAttributes(visitor); } + + // -- HELPER + + private String hiddenReason(final ManagedObject target) { + final boolean isHidden = imperativeAspect.eval(target, false); + return isHidden ? "Hidden" : null; + } + } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconMethod.java index 3cb2fde883c..d1abdbfc5b2 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconMethod.java @@ -50,7 +50,6 @@ public static Optional create( @Override public Class facetType() { return IconFacet.class; } @Override public Precedence precedence() { return Precedence.DEFAULT; } - @Override public ImperativeAspect getImperativeAspect() { return imperativeAspect; } @Override public Optional icon(ManagedObject domainObject, IconSize iconSize) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java index 68bd46e1eba..0b00b1f5afb 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/icon/method/IconFacetViaIconNameMethod.java @@ -51,7 +51,6 @@ public static Optional create( @Override public Class facetType() { return IconFacet.class; } @Override public Precedence precedence() { return Precedence.LOW; } - @Override public ImperativeAspect getImperativeAspect() { return imperativeAspect; } @Override public Optional icon(ManagedObject domainObject, IconSize iconSize) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/layout/LayoutPrefixFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/layout/LayoutPrefixFacetViaMethod.java index b218b0fe685..6fcb0f11eb6 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/layout/LayoutPrefixFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/layout/LayoutPrefixFacetViaMethod.java @@ -68,11 +68,6 @@ public String layoutPrefix(final ManagedObject managedObject) { } } - @Override - public ImperativeAspect getImperativeAspect() { - return imperativeAspect(); - } - @Override public void visitAttributes(final BiConsumer visitor) { LayoutPrefixFacet.super.visitAttributes(visitor); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/ObjectValidPropertiesFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/ObjectValidPropertiesFacet.java index 92ce07058d6..04d8543e743 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/ObjectValidPropertiesFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/ObjectValidPropertiesFacet.java @@ -33,9 +33,8 @@ public interface ObjectValidPropertiesFacet extends Facet, ValidatingInteraction /** * The reason the object is invalid. * - *

- * . If the object is actually valid, should return null. + *

If the object is actually valid, should return null. */ - public String invalidReason(ObjectValidityContext context); + String invalidReason(ObjectValidityContext context); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/ObjectValidPropertiesFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/ObjectValidPropertiesFacetAbstract.java deleted file mode 100644 index e586b25d253..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/ObjectValidPropertiesFacetAbstract.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.metamodel.facets.object.objectvalidprops; - -import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetAbstract; -import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.interactions.val.ObjectValidityContext; -import org.apache.causeway.core.metamodel.interactions.val.ValidityContext; - -public abstract class ObjectValidPropertiesFacetAbstract extends FacetAbstract implements ObjectValidPropertiesFacet { - - private static final Class type() { - return ObjectValidPropertiesFacet.class; - } - - public ObjectValidPropertiesFacetAbstract(final FacetHolder holder) { - super(type(), holder); - } - - @Override - public String invalidates(final ValidityContext ic) { - if (!(ic instanceof ObjectValidityContext)) { - return null; - } - final ObjectValidityContext validityContext = (ObjectValidityContext) ic; - return invalidReason(validityContext); - } - -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/impl/ObjectValidPropertiesFacetImpl.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/impl/ObjectValidPropertiesFacetImpl.java index 086d41fd642..06a82a704f4 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/impl/ObjectValidPropertiesFacetImpl.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/objectvalidprops/impl/ObjectValidPropertiesFacetImpl.java @@ -19,48 +19,64 @@ package org.apache.causeway.core.metamodel.facets.object.objectvalidprops.impl; import org.apache.causeway.applib.annotation.Where; +import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.facets.object.objectvalidprops.ObjectValidPropertiesFacetAbstract; +import org.apache.causeway.core.metamodel.facetapi.FacetUtil; +import org.apache.causeway.core.metamodel.facets.object.objectvalidprops.ObjectValidPropertiesFacet; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.val.ObjectValidityContext; +import org.apache.causeway.core.metamodel.interactions.val.ValidityContext; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; -public class ObjectValidPropertiesFacetImpl -extends ObjectValidPropertiesFacetAbstract { +public record ObjectValidPropertiesFacetImpl( + FacetHolder facetHolder) +implements ObjectValidPropertiesFacet { - // REVIEW: should provide this rendering context, rather than hardcoding. - // the net effect currently is that class members annotated with - // @Hidden(where=Where.ANYWHERE) or @Disabled(where=Where.ANYWHERE) will indeed - // be hidden/disabled, but will be visible/enabled (perhaps incorrectly) - // for any other value for Where - private final Where where = Where.ANYWHERE; + @Override public Class facetType() { return ObjectValidPropertiesFacet.class; } + @Override public Precedence precedence() { return Precedence.DEFAULT; } - public ObjectValidPropertiesFacetImpl(final FacetHolder holder) { - super(holder); + @Override + public String toString() { + return FacetUtil.toString(this); } @Override - public String invalidReason( - final ObjectValidityContext context) { - final StringBuilder buf = new StringBuilder(); - final ManagedObject adapter = context.target(); + public String invalidates(final ValidityContext ic) { + return (ic instanceof final ObjectValidityContext validityContext) + ? invalidReason(validityContext) + : null; + } - adapter.objSpec().streamProperties(MixedIn.EXCLUDED) - .filter(property->property.isVisible(adapter, context.initiatedBy(), where).isVetoed()) // ignore hidden properties - .filter(property->property.isUsable(adapter, context.initiatedBy(), where).isVetoed()) // ignore disabled properties - .forEach(property->{ - final ManagedObject value = property.get(adapter, context.initiatedBy()); - if (property.isAssociationValid(adapter, value, context.initiatedBy()).isVetoed()) { - if (buf.length() > 0) { - buf.append(", "); - } - buf.append(property.getFriendlyName(context::target)); - } - }); - if (buf.length() > 0) { - return "Invalid properties: " + buf.toString(); - } - return null; + @Override + public String invalidReason(final ObjectValidityContext context) { + final ManagedObject mo = context.target(); + var sb = new StringBuilder(); + + mo.objSpec().streamProperties(MixedIn.EXCLUDED) + .filter(property->property.isVisible(mo, context.initiatedBy(), VISIBILITY_CONSTRAINT).isVetoed()) // ignore hidden properties + .filter(property->property.isUsable(mo, context.initiatedBy(), VISIBILITY_CONSTRAINT).isVetoed()) // ignore disabled properties + .forEach(property->{ + final ManagedObject value = property.get(mo, context.initiatedBy()); + if (property.isAssociationValid(mo, value, context.initiatedBy()).isVetoed()) { + if (sb.length() > 0) { + sb.append(", "); + } + sb.append(property.getFriendlyName(context::target)); + } + }); + return (sb.length() > 0) + ? "Invalid properties: " + sb.toString() + : null; } + // REVIEW: should provide the rendering context, rather than hardcoding. + // The net effect currently is that class members annotated with + // @Hidden(where=Where.ANYWHERE) or @Disabled(where=Where.ANYWHERE) will indeed + // be hidden/disabled, but will be visible/enabled (perhaps incorrectly) + // for any other value for Where. + // However, ultimately we do check, whether the object is valid prior to persisting, + // I think, this should not be constraint by WhatViewer or Where. + private final static VisibilityConstraint VISIBILITY_CONSTRAINT = VisibilityConstraint.noViewer(Where.ANYWHERE); + } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/support/ObjectSupportFacetFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/support/ObjectSupportFacetFactory.java index 30485697243..a19a1bf1adb 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/support/ObjectSupportFacetFactory.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/support/ObjectSupportFacetFactory.java @@ -37,8 +37,8 @@ import org.apache.causeway.core.metamodel.facets.object.cssclass.method.CssClassFacetViaCssClassMethod; import org.apache.causeway.core.metamodel.facets.object.disabled.DisabledObjectFacet; import org.apache.causeway.core.metamodel.facets.object.disabled.method.DisabledObjectFacetViaMethod; -import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenObjectFacet; -import org.apache.causeway.core.metamodel.facets.object.hidden.method.HiddenObjectFacetViaMethod; +import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenFacetForObject; +import org.apache.causeway.core.metamodel.facets.object.hidden.method.HiddenFacetForObjectViaMethod; import org.apache.causeway.core.metamodel.facets.object.icon.method.IconFacetViaIconMethod; import org.apache.causeway.core.metamodel.facets.object.icon.method.IconFacetViaIconNameMethod; import org.apache.causeway.core.metamodel.facets.object.layout.LayoutPrefixFacetViaMethod; @@ -51,7 +51,7 @@ /** * Installs {@link DisabledObjectFacetViaMethod} - * and {@link HiddenObjectFacetViaMethod} on the + * and {@link HiddenFacetForObjectViaMethod} on the * {@link ObjectSpecification}, and copies this facet onto each * {@link ObjectMember}. *

@@ -81,7 +81,7 @@ public final void process(final ProcessClassContext processClassContext) { // priming 'toString()' into Precedence.INFERRED rank inferTitleFromToString(processClassContext); - processObjectSupport(processClassContext, ObjectSupportMethod.HIDDEN, NO_ARG, HiddenObjectFacetViaMethod::create); + processObjectSupport(processClassContext, ObjectSupportMethod.HIDDEN, NO_ARG, HiddenFacetForObjectViaMethod::create); processObjectSupport(processClassContext, ObjectSupportMethod.DISABLED, NO_ARG, DisabledObjectFacetViaMethod::create); processObjectSupport(processClassContext, ObjectSupportMethod.TITLE, NO_ARG, TitleFacetViaTitleMethod::create); processObjectSupport(processClassContext, ObjectSupportMethod.LAYOUT, NO_ARG, LayoutPrefixFacetViaMethod::create); @@ -101,7 +101,7 @@ public void process(final ProcessMethodContext processMethodContext) { .map(disabledObjectFacet->disabledObjectFacet.clone(member)) .ifPresent(FacetUtil::addFacet); - owningSpec.lookupFacet(HiddenObjectFacet.class) + owningSpec.lookupFacet(HiddenFacetForObject.class) .map(hiddenObjectFacet->hiddenObjectFacet.copyTo(member)) .ifPresent(FacetUtil::addFacet); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/TitleFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/TitleFacetAbstract.java index 9a410be7f9b..db3689f0f2f 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/TitleFacetAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/TitleFacetAbstract.java @@ -62,8 +62,8 @@ public boolean semanticEquals(final @NonNull Facet other) { && otherFacet instanceof ImperativeFacet) { return ((ImperativeFacet)this) - .getMethods() - .equals(((ImperativeFacet)otherFacet).getMethods()); + .methods() + .equals(((ImperativeFacet)otherFacet).methods()); } return false; diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java index 39e9a0041d0..f3eb799aaba 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java @@ -25,6 +25,8 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.annotation.Title; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.base._Strings; @@ -35,8 +37,8 @@ import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; import org.apache.causeway.commons.internal.reflection._Reflect.InterfacePolicy; import org.apache.causeway.commons.internal.reflection._Reflect.TypeHierarchyPolicy; -import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants.ObjectSupportMethod; import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants.MessageTemplate; +import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants.ObjectSupportMethod; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facets.Evaluators; import org.apache.causeway.core.metamodel.facets.Evaluators.MethodEvaluator; @@ -49,8 +51,8 @@ import lombok.AccessLevel; import lombok.Getter; -import org.jspecify.annotations.NonNull; import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -85,7 +87,8 @@ public static Optional create( } @Getter private final Can components; - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; protected TitleFacetViaTitleAnnotation(final Can components, final FacetHolder holder) { super(holder); @@ -109,7 +112,7 @@ protected TitleFacetViaTitleAnnotation(final Can components, fin } @Override - public Intent getIntent() { + public Intent intent() { return Intent.UI_HINT; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/methods/TitleFacetFromToStringMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/methods/TitleFacetFromToStringMethod.java index 14a08e92da2..347a7256716 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/methods/TitleFacetFromToStringMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/methods/TitleFacetFromToStringMethod.java @@ -21,6 +21,7 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; @@ -33,13 +34,14 @@ import org.apache.causeway.core.metamodel.facets.object.title.TitleRenderRequest; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class TitleFacetFromToStringMethod extends TitleFacetAbstract implements HasImperativeAspect { - @Getter(onMethod_ = {@Override}) private final @NonNull ImperativeAspect imperativeAspect; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull ImperativeAspect imperativeAspect; public static Optional create( final @Nullable ResolvedMethod methodIfAny, diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/methods/TitleFacetViaTitleMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/methods/TitleFacetViaTitleMethod.java index 68e8a809598..706ea5731bf 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/methods/TitleFacetViaTitleMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/title/methods/TitleFacetViaTitleMethod.java @@ -36,6 +36,8 @@ import org.apache.causeway.core.metamodel.object.ManagedObjects; import lombok.Getter; +import lombok.experimental.Accessors; + import org.jspecify.annotations.NonNull; import lombok.extern.slf4j.Slf4j; @@ -44,7 +46,8 @@ public class TitleFacetViaTitleMethod extends TitleFacetAbstract implements HasImperativeAspect { - @Getter(onMethod_ = {@Override}) private final @NonNull ImperativeAspect imperativeAspect; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull ImperativeAspect imperativeAspect; private final TranslationContext translationContext; public static Optional create( diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/CompositeValueUpdater.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/CompositeValueUpdater.java index f9d30c19c3a..3a3c69c1bb4 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/CompositeValueUpdater.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/value/CompositeValueUpdater.java @@ -20,7 +20,6 @@ import org.apache.causeway.applib.annotation.PromptStyle; import org.apache.causeway.applib.annotation.SemanticsOf; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.core.metamodel.commons.CanonicalInvoker; import org.apache.causeway.core.metamodel.commons.ParameterConverters; @@ -34,6 +33,8 @@ import org.apache.causeway.core.metamodel.facets.object.value.CompositeValueUpdater.CompositeValueUpdaterForParameter; import org.apache.causeway.core.metamodel.facets.object.value.CompositeValueUpdater.CompositeValueUpdaterForProperty; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.interactions.managed.ManagedProperty; import org.apache.causeway.core.metamodel.interactions.managed.ParameterNegotiationModel; import org.apache.causeway.core.metamodel.object.ManagedObject; @@ -68,20 +69,22 @@ default CompositeValueUpdater overrideFacets() { // -- OBJECT ACTION MOCKUP - @Override default Consent isVisible(final ManagedObject a, final InteractionInitiatedBy b, final Where c) { return Allow.DEFAULT; } - @Override default Consent isUsable(final ManagedObject a, final InteractionInitiatedBy b, final Where c) { return Allow.DEFAULT; } + @Override default Consent isVisible(final ManagedObject a, final InteractionInitiatedBy b, final VisibilityConstraint c) { return Allow.DEFAULT; } + @Override default Consent isUsable(final ManagedObject a, final InteractionInitiatedBy b, final VisibilityConstraint c) { return Allow.DEFAULT; } @Override default PromptStyle getPromptStyle() { return PromptStyle.INLINE_AS_IF_EDIT; } @Override default SemanticsOf getSemantics() { return SemanticsOf.SAFE; } @Override default ManagedObject execute( final InteractionHead head, final Can parameters, - final InteractionInitiatedBy interactionInitiatedBy) { + final InteractionInitiatedBy interactionInitiatedBy, + final WhatViewer whatViewer) { return map(simpleExecute(head, parameters)); } @Override default ManagedObject executeWithRuleChecking( final InteractionHead head, final Can parameters, - final InteractionInitiatedBy interactionInitiatedBy, final Where where) throws AuthorizationException { - return execute(head, parameters, interactionInitiatedBy); + final InteractionInitiatedBy interactionInitiatedBy, + final VisibilityConstraint visibilityConstraint) throws AuthorizationException { + return execute(head, parameters, interactionInitiatedBy, visibilityConstraint.whatViewer()); } // -- IMPLEMENTATIONS diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/autocomplete/method/ActionParameterAutoCompleteFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/autocomplete/method/ActionParameterAutoCompleteFacetViaMethod.java index c322b857d3e..45e154fac3e 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/autocomplete/method/ActionParameterAutoCompleteFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/autocomplete/method/ActionParameterAutoCompleteFacetViaMethod.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedConstructor; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; @@ -38,13 +40,14 @@ import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class ActionParameterAutoCompleteFacetViaMethod extends ActionParameterAutoCompleteFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final ResolvedType paramSupportReturnType; private final int minLength; private final Optional patConstructor; @@ -63,7 +66,7 @@ public ActionParameterAutoCompleteFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHOICES_OR_AUTOCOMPLETE; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java index b66cf424592..4dcdcd7715a 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/choices/methodnum/ActionParameterChoicesFacetViaMethod.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedConstructor; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; @@ -38,13 +40,14 @@ import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class ActionParameterChoicesFacetViaMethod extends ActionParameterChoicesFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final ResolvedType paramSupportReturnType; private final Optional patConstructor; @@ -61,7 +64,7 @@ public ActionParameterChoicesFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHOICES_OR_AUTOCOMPLETE; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java index 349f16a3c1e..6ff0c4f338c 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/defaults/methodnum/ActionParameterDefaultsFacetViaMethod.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.base._NullSafe; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedConstructor; @@ -34,13 +36,14 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class ActionParameterDefaultsFacetViaMethod extends ActionParameterDefaultsFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final int paramNum; private final Optional patConstructor; @@ -63,7 +66,7 @@ public ActionParameterDefaultsFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.DEFAULTS; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/disable/ActionParameterDisabledFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/disable/ActionParameterDisabledFacet.java index 9e17a7b44ee..84d71e16308 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/disable/ActionParameterDisabledFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/disable/ActionParameterDisabledFacet.java @@ -22,7 +22,6 @@ import org.apache.causeway.commons.collections.Can; import org.apache.causeway.core.metamodel.consent.Consent.VetoReason; -import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.DisablingInteractionAdvisor; import org.apache.causeway.core.metamodel.object.ManagedObject; @@ -33,7 +32,7 @@ * In the standard Apache Causeway Programming Model, corresponds to invoking the * disableNXxx support method for an action. */ -public interface ActionParameterDisabledFacet extends Facet, DisablingInteractionAdvisor { +public interface ActionParameterDisabledFacet extends DisablingInteractionAdvisor { /** * Reason why the parameter is disabled, or Optional.empts() if okay. diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/disable/method/ActionParameterDisabledFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/disable/method/ActionParameterDisabledFacetViaMethod.java index 1557b86eeed..c2cb958daf1 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/disable/method/ActionParameterDisabledFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/disable/method/ActionParameterDisabledFacetViaMethod.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.services.i18n.TranslatableString; import org.apache.causeway.applib.services.i18n.TranslationContext; import org.apache.causeway.commons.collections.Can; @@ -35,13 +37,14 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class ActionParameterDisabledFacetViaMethod extends ActionParameterDisabledFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final TranslationContext translationContext; private final Optional patConstructor; @@ -57,7 +60,7 @@ public ActionParameterDisabledFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHECK_IF_VALID; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/ActionParameterHiddenFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/ActionParameterHiddenFacetAbstract.java deleted file mode 100644 index 3f4c1677373..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/ActionParameterHiddenFacetAbstract.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.metamodel.facets.param.hide; - -import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetAbstract; -import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.interactions.vis.ParamVisibilityContext; -import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; - -public abstract class ActionParameterHiddenFacetAbstract -extends FacetAbstract -implements ActionParameterHiddenFacet { - - private static final Class type() { - return ActionParameterHiddenFacet.class; - } - - public ActionParameterHiddenFacetAbstract(final FacetHolder holder) { - super(type(), holder); - } - - @Override - public String hides(final VisibilityContext context) { - if (!(context instanceof ParamVisibilityContext)) { - return null; - } - var actionArgVisibilityContext = (ParamVisibilityContext) context; - return isHidden( - actionArgVisibilityContext.target(), - actionArgVisibilityContext.args()) - ? "Hidden" - : null; - } -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/ActionParameterHiddenFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/HiddenFacetForActionParameter.java similarity index 91% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/ActionParameterHiddenFacet.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/HiddenFacetForActionParameter.java index 9def2099734..2481d0cf4e9 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/ActionParameterHiddenFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/HiddenFacetForActionParameter.java @@ -19,7 +19,6 @@ package org.apache.causeway.core.metamodel.facets.param.hide; import org.apache.causeway.commons.collections.Can; -import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; import org.apache.causeway.core.metamodel.object.ManagedObject; @@ -31,8 +30,8 @@ * In the standard Apache Causeway Programming Model, corresponds to invoking the * hideNXxx support method for an action. */ -public interface ActionParameterHiddenFacet -extends Facet, HidingInteractionAdvisor { +public interface HiddenFacetForActionParameter +extends HidingInteractionAdvisor { /** * Whether the parameter is hidden. diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethodFactory.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethodFactory.java index 2ea4457fba4..3dd97ac4ea7 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethodFactory.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethodFactory.java @@ -24,11 +24,11 @@ import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facets.FacetedMethodParameter; import org.apache.causeway.core.metamodel.facets.ParameterSupport.ParamSupportingMethodSearchResult; -import org.apache.causeway.core.metamodel.facets.param.hide.ActionParameterHiddenFacet; +import org.apache.causeway.core.metamodel.facets.param.hide.HiddenFacetForActionParameter; import org.apache.causeway.core.metamodel.facets.param.support.ActionParameterSupportFacetFactoryAbstract; /** - * Sets up {@link ActionParameterHiddenFacet}. + * Sets up {@link HiddenFacetForActionParameter}. */ public class ActionParameterHiddenFacetViaMethodFactory extends ActionParameterSupportFacetFactoryAbstract { @@ -45,7 +45,7 @@ protected void onSearchResult( var hideMethod = searchResult.supportingMethod(); var patConstructor = searchResult.patConstructor(); addFacet( - new ActionParameterHiddenFacetViaMethod( + new HiddenFacetForActionParameterViaMethod( hideMethod, patConstructor, paramAsHolder)); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/HiddenFacetForActionParameterViaMethod.java similarity index 63% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethod.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/HiddenFacetForActionParameterViaMethod.java index 1b042af9ba6..5a0413760d7 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/ActionParameterHiddenFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/hide/method/HiddenFacetForActionParameterViaMethod.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedConstructor; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; @@ -28,33 +30,40 @@ import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facets.ImperativeFacet; -import org.apache.causeway.core.metamodel.facets.param.hide.ActionParameterHiddenFacetAbstract; +import org.apache.causeway.core.metamodel.facets.param.hide.HiddenFacetForActionParameter; +import org.apache.causeway.core.metamodel.interactions.vis.ParamVisibilityContext; +import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.MmInvokeUtils; -import lombok.Getter; -import org.jspecify.annotations.NonNull; - -public class ActionParameterHiddenFacetViaMethod -extends ActionParameterHiddenFacetAbstract -implements ImperativeFacet { +public record HiddenFacetForActionParameterViaMethod( + Can methods, + Optional patConstructor, + FacetHolder facetHolder + ) implements HiddenFacetForActionParameter, ImperativeFacet { + + @Override public Class facetType() { return HiddenFacetForActionParameter.class; } + @Override public Precedence precedence() { return Precedence.DEFAULT; } + @Override public Intent intent() { return Intent.CHECK_IF_VALID;} - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; - private final @NonNull Optional patConstructor; - - public ActionParameterHiddenFacetViaMethod( + public HiddenFacetForActionParameterViaMethod( final ResolvedMethod method, final Optional patConstructor, final FacetHolder holder) { - - super(holder); - this.methods = ImperativeFacet.singleMethod(method, patConstructor); - this.patConstructor = patConstructor; + this(ImperativeFacet.singleMethod(method, patConstructor), patConstructor, holder); } @Override - public Intent getIntent() { - return Intent.CHECK_IF_VALID; + public String hides(final VisibilityContext context) { + if (!(context instanceof ParamVisibilityContext)) { + return null; + } + var actionArgVisibilityContext = (ParamVisibilityContext) context; + return isHidden( + actionArgVisibilityContext.target(), + actionArgVisibilityContext.args()) + ? "Hidden" + : null; } @Override @@ -74,18 +83,18 @@ public boolean isHidden( @Override public boolean semanticEquals(final @NonNull Facet otherFacet) { - if(! (otherFacet instanceof ActionParameterHiddenFacetViaMethod)) { + if(! (otherFacet instanceof HiddenFacetForActionParameterViaMethod)) { return false; } - var other = (ActionParameterHiddenFacetViaMethod)otherFacet; + var other = (HiddenFacetForActionParameterViaMethod)otherFacet; return this.patConstructor.equals(other.patConstructor) - && this.getMethods().equals(other.getMethods()); + && this.methods().equals(other.methods()); } @Override public void visitAttributes(final BiConsumer visitor) { - super.visitAttributes(visitor); + HiddenFacetForActionParameter.super.visitAttributes(visitor); ImperativeFacet.visitAttributes(this, visitor); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/validate/method/ActionParameterValidationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/validate/method/ActionParameterValidationFacetViaMethod.java index 40c70a6787a..1db3be69c8c 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/validate/method/ActionParameterValidationFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/param/validate/method/ActionParameterValidationFacetViaMethod.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.services.i18n.TranslatableString; import org.apache.causeway.applib.services.i18n.TranslationContext; import org.apache.causeway.commons.collections.Can; @@ -34,13 +36,14 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class ActionParameterValidationFacetViaMethod extends ActionParameterValidationFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final TranslationContext translationContext; private final Optional patConstructor; @@ -56,7 +59,7 @@ public ActionParameterValidationFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHECK_IF_VALID; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java index 10913b41585..54a3469e800 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/accessor/PropertyAccessorFacetViaAccessor.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; @@ -27,19 +29,21 @@ import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facets.ImperativeFacet; import org.apache.causeway.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacetAbstract; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import org.apache.causeway.core.metamodel.object.MmVisibilityUtils; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class PropertyAccessorFacetViaAccessor extends PropertyOrCollectionAccessorFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; public PropertyAccessorFacetViaAccessor( final ObjectSpecification declaringType, @@ -51,7 +55,7 @@ public PropertyAccessorFacetViaAccessor( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.ACCESSOR; } @@ -66,7 +70,7 @@ public Object getAssociationValueAsPojo( if(isConfiguredToFilterForVisibility()) { final ManagedObject referencedAdapter = getObjectManager().adapt(referencedObject); final boolean visible = MmVisibilityUtils - .isVisible(referencedAdapter, interactionInitiatedBy); + .isVisible(referencedAdapter, interactionInitiatedBy, WhatViewer.invalid()); if (!visible) return null; } return referencedObject; diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/autocomplete/method/PropertyAutoCompleteFacetMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/autocomplete/method/PropertyAutoCompleteFacetMethod.java index b5f98633ffe..52b0392efe0 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/autocomplete/method/PropertyAutoCompleteFacetMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/autocomplete/method/PropertyAutoCompleteFacetMethod.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; @@ -33,13 +35,14 @@ import org.apache.causeway.core.metamodel.object.MmVisibilityUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class PropertyAutoCompleteFacetMethod extends PropertyAutoCompleteFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final Class choicesClass; private final int minLength; @@ -54,7 +57,7 @@ public PropertyAutoCompleteFacetMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHOICES_OR_AUTOCOMPLETE; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java index 830d1d907f2..e5855bef4b2 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/choices/method/PropertyChoicesFacetViaMethod.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; @@ -33,13 +35,14 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class PropertyChoicesFacetViaMethod extends PropertyChoicesFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final Class choicesClass; public PropertyChoicesFacetViaMethod( @@ -52,7 +55,7 @@ public PropertyChoicesFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHOICES_OR_AUTOCOMPLETE; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java index f1eb5b3c6aa..3e6a21e2664 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/defaults/method/PropertyDefaultFacetViaMethod.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.exceptions.unrecoverable.UnknownTypeException; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; @@ -31,13 +33,14 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class PropertyDefaultFacetViaMethod extends PropertyDefaultFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; public PropertyDefaultFacetViaMethod( final ResolvedMethod method, @@ -47,7 +50,7 @@ public PropertyDefaultFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.DEFAULTS; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyLayoutAnnotation.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyLayoutAnnotation.java index fa313b9c518..8e40de8f247 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyLayoutAnnotation.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyLayoutAnnotation.java @@ -23,11 +23,11 @@ import org.apache.causeway.applib.annotation.PropertyLayout; import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetAbstract; +import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetForLayoutAbstract; import org.apache.causeway.core.metamodel.object.ManagedObject; public class HiddenFacetForPropertyLayoutAnnotation -extends HiddenFacetAbstract { +extends HiddenFacetForLayoutAbstract { public static Optional create( final Optional propertyLayoutIfAny, diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyLayoutXml.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyLayoutXml.java index 2e3ded06dd0..d2fba54f62b 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyLayoutXml.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/HiddenFacetForPropertyLayoutXml.java @@ -23,14 +23,14 @@ import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.layout.component.PropertyLayoutData; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; -import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetAbstract; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; +import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetForLayoutAbstract; import org.apache.causeway.core.metamodel.object.ManagedObject; public class HiddenFacetForPropertyLayoutXml -extends HiddenFacetAbstract { +extends HiddenFacetForLayoutAbstract { - public static Optional create( + public static Optional create( final PropertyLayoutData propertyLayout, final FacetHolder holder, final Precedence precedence) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaClearMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaClearMethod.java index e8395fe1f2a..bb2b49ff5c4 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaClearMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaClearMethod.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; @@ -31,13 +33,14 @@ import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class PropertyClearFacetViaClearMethod extends PropertyClearFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; public PropertyClearFacetViaClearMethod(final ResolvedMethod method, final FacetHolder holder) { super(holder); @@ -45,7 +48,7 @@ public PropertyClearFacetViaClearMethod(final ResolvedMethod method, final Facet } @Override - public Intent getIntent() { + public Intent intent() { return Intent.MODIFY_PROPERTY_SUPPORTING; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaSetterMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaSetterMethod.java index 68897a2e357..d4ed62aa867 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaSetterMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/clear/PropertyClearFacetViaSetterMethod.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; @@ -31,13 +33,14 @@ import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class PropertyClearFacetViaSetterMethod extends PropertyClearFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; public PropertyClearFacetViaSetterMethod(final ResolvedMethod method, final FacetHolder holder) { super(holder); @@ -45,7 +48,7 @@ public PropertyClearFacetViaSetterMethod(final ResolvedMethod method, final Face } @Override - public Intent getIntent() { + public Intent intent() { return Intent.MODIFY_PROPERTY; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/init/PropertyInitializationFacetViaSetterMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/init/PropertyInitializationFacetViaSetterMethod.java index 42a06b25c9a..67d5bf40663 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/init/PropertyInitializationFacetViaSetterMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/init/PropertyInitializationFacetViaSetterMethod.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; @@ -29,13 +31,14 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class PropertyInitializationFacetViaSetterMethod extends PropertyInitializationFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; public PropertyInitializationFacetViaSetterMethod(final ResolvedMethod method, final FacetHolder holder) { super(holder); @@ -43,7 +46,7 @@ public PropertyInitializationFacetViaSetterMethod(final ResolvedMethod method, f } @Override - public Intent getIntent() { + public Intent intent() { // LIMITATION: we cannot distinguish between setXxx being called for a modify or for an initialization // so we just assume its a setter. return Intent.MODIFY_PROPERTY; diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaSetterMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaSetterMethod.java index 73642bdd23b..d718108cdd5 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaSetterMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/update/modify/PropertySetterFacetViaSetterMethod.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedMethod; import org.apache.causeway.commons.internal.reflection._MethodFacades.MethodFacade; @@ -31,13 +33,14 @@ import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class PropertySetterFacetViaSetterMethod extends PropertySetterFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; public PropertySetterFacetViaSetterMethod(final ResolvedMethod method, final FacetHolder holder) { super(holder); @@ -45,7 +48,7 @@ public PropertySetterFacetViaSetterMethod(final ResolvedMethod method, final Fac } @Override - public Intent getIntent() { + public Intent intent() { return Intent.MODIFY_PROPERTY; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/validating/method/PropertyValidateFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/validating/method/PropertyValidateFacetViaMethod.java index 6d45cd1d404..e0f7c6d55fa 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/validating/method/PropertyValidateFacetViaMethod.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/properties/validating/method/PropertyValidateFacetViaMethod.java @@ -20,6 +20,8 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.services.i18n.TranslatableString; import org.apache.causeway.applib.services.i18n.TranslationContext; import org.apache.causeway.commons.collections.Can; @@ -32,11 +34,12 @@ import org.apache.causeway.core.metamodel.object.MmInvokeUtils; import lombok.Getter; -import org.jspecify.annotations.NonNull; +import lombok.experimental.Accessors; public class PropertyValidateFacetViaMethod extends PropertyValidateFacetAbstract implements ImperativeFacet { - @Getter(onMethod_ = {@Override}) private final @NonNull Can methods; + @Getter(onMethod_ = {@Override}) @Accessors(fluent = true) + private final @NonNull Can methods; private final TranslationContext translationContext; public PropertyValidateFacetViaMethod( @@ -48,7 +51,7 @@ public PropertyValidateFacetViaMethod( } @Override - public Intent getIntent() { + public Intent intent() { return Intent.CHECK_IF_VALID; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/DisablingInteractionAdvisor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/DisablingInteractionAdvisor.java index c7f2440c20c..2620328e176 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/DisablingInteractionAdvisor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/DisablingInteractionAdvisor.java @@ -21,7 +21,8 @@ import java.util.Optional; import org.apache.causeway.core.metamodel.consent.Consent.VetoReason; -import org.apache.causeway.core.metamodel.facetapi.FacetWithAttributes.DisablingOrEnabling; +import org.apache.causeway.core.metamodel.consent.InteractionAdvisor; +import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; /** @@ -32,7 +33,7 @@ * @see HidingInteractionAdvisor */ public interface DisablingInteractionAdvisor -extends InteractionAdvisorFacet, DisablingOrEnabling { +extends InteractionAdvisor, Facet { /** * Whether the rule represented by this facet disables the member to which diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/HidingInteractionAdvisor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/HidingInteractionAdvisor.java index 37ec3e6e4ed..1d676d2b80d 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/HidingInteractionAdvisor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/HidingInteractionAdvisor.java @@ -18,18 +18,33 @@ */ package org.apache.causeway.core.metamodel.interactions; -import org.apache.causeway.core.metamodel.facetapi.FacetWithAttributes.HidingOrShowing; +import org.apache.causeway.core.metamodel.consent.InteractionAdvisor; +import org.apache.causeway.core.metamodel.facetapi.Facet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; +import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenFacetForObject; +import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenFacetForNoMembersAuthorized; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; /** - * Mix-in interface for facets that can advise as to whether a member should be - * hidden. + * Mechanism for determining whether an object or member should be hidden. * + *

Even though all the properties of an object may themselves be visible, there + * could be reasons to hide the object. + * + *

In the standard Apache Causeway Programming Model, typically corresponds to the + * hidden method. + * + * @see HiddenFacetForLayout + * @see HiddenFacetForObject + * @see HiddenFacetForNoMembersAuthorized * @see DisablingInteractionAdvisor * @see ValidatingInteractionAdvisor + * + * @apiNote An unification attempt on HiddenTypeFacet and HiddenObjectFacet into a single, + * failed, because both facets must co-exist, where each has veto power (not one overruling the other). */ public interface HidingInteractionAdvisor -extends InteractionAdvisorFacet, HidingOrShowing { +extends InteractionAdvisor, Facet { /** * Whether the rule represented by this facet hides the member to which it diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionAdvisorFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionAdvisorFacet.java deleted file mode 100644 index 8d51bc3d318..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionAdvisorFacet.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.metamodel.interactions; - -import org.apache.causeway.core.metamodel.consent.Allow; -import org.apache.causeway.core.metamodel.consent.Consent; -import org.apache.causeway.core.metamodel.consent.InteractionAdvisor; -import org.apache.causeway.core.metamodel.consent.Veto; -import org.apache.causeway.core.metamodel.facetapi.Facet; - -/** - * Used by {@link Consent} (specifically the main implementations {@link Allow} - * and {@link Veto}), with the idea being that the only things that can create - * {@link Consent} objects are {@link Facet}s. - * - *

- * TODO: note, this is a work-in-progress, because the DnD viewer in particular - * creates its own {@link Allow}s and {@link Veto}s. The constructors that it - * uses have been deprecated to flag that the DnD logic should move into - * {@link Facet}s that implement this interface. - * - * @author Dan Haywood - * - */ -public interface InteractionAdvisorFacet extends InteractionAdvisor, Facet { - -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionContext.java index c7c15861a05..1570aaa4a11 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionContext.java @@ -19,7 +19,6 @@ package org.apache.causeway.core.metamodel.interactions; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.InteractionEvent; import org.apache.causeway.core.metamodel.consent.InteractionContextType; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; @@ -93,11 +92,6 @@ public interface InteractionContext { */ InteractionHead head(); - /** - * Where the element is to be rendered. - */ - Where where(); - /** * The target object that this interaction is associated with. */ diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionUtils.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionUtils.java index d88b2f462a9..960fc6bbc0d 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionUtils.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/InteractionUtils.java @@ -19,14 +19,13 @@ package org.apache.causeway.core.metamodel.interactions; import java.util.Optional; +import java.util.function.Supplier; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.apache.causeway.applib.Identifier; import org.apache.causeway.commons.internal.base._Strings; -import org.apache.causeway.core.config.CausewayConfiguration; -import org.apache.causeway.core.config.environment.DeploymentType; import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants; import org.apache.causeway.core.metamodel.consent.Consent; import org.apache.causeway.core.metamodel.consent.InteractionAdvisor; @@ -39,7 +38,6 @@ import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; import org.apache.causeway.core.metamodel.interactions.val.ValidityContext; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; -import org.apache.causeway.core.metamodel.object.ManagedObject; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; @@ -73,7 +71,8 @@ public InteractionResult isVisibleResult(final FacetHolder facetHolder, final Vi return builder.build(); } - public InteractionResult isUsableResult(final FacetHolder facetHolder, final UsabilityContext context) { + public InteractionResult isUsableResult(final FacetHolder facetHolder, final UsabilityContext context, + final Supplier visibilityContextSupplierForDebugging) { var builder = InteractionResult.builder(context.createInteractionEvent()); @@ -84,11 +83,10 @@ public InteractionResult isUsableResult(final FacetHolder facetHolder, final Usa break; case SHOW_AS_DISABLED: case SHOW_AS_DISABLED_WITH_DIAGNOSTICS: - var visibilityContext = context.asVisibilityContext(); - facetHolder.streamFacets(HidingInteractionAdvisor.class) + facetHolder.streamFacets(HidingInteractionAdvisor.class) .filter(advisor->compatible(advisor, context)) .forEach(advisor->{ - _Strings.nonEmpty(advisor.hides(visibilityContext)) + _Strings.nonEmpty(advisor.hides(visibilityContextSupplierForDebugging.get())) .map(Consent.VetoReason::explicit) .ifPresent(hidingReason->{ if(ifHiddenPolicy.isShowAsDisabledWithDiagnostics()) { @@ -139,12 +137,6 @@ public InteractionResultSet isValidResultSet( return resultSet.add(isValidResult(facetHolder, context)); } - public RenderPolicy renderPolicy(final ManagedObject ownerAdapter) { - return new RenderPolicy( - determineIfHiddenPolicyFrom(ownerAdapter), - determineIfDisabledPolicyFrom(ownerAdapter)); - } - // -- HELPER /** @@ -167,13 +159,11 @@ private Optional guardAgainstEmptyReasonString( private static boolean compatible(final InteractionAdvisor advisor, final InteractionContext ic) { if(ic.initiatedBy().isPassThrough() - && isDomainEventAdvisor(advisor)) { - //[CAUSEWAY-3810] when pass-through, then don't trigger any domain events + && isDomainEventAdvisor(advisor)) + //[CAUSEWAY-3810] when pass-through, then don't trigger any domain events return false; - } - if(advisor instanceof ActionDomainEventFacet) { - return ic instanceof ActionInteractionContext; - } + if(advisor instanceof ActionDomainEventFacet) + return ic instanceof ActionInteractionContext; return true; } @@ -181,25 +171,4 @@ private static boolean isDomainEventAdvisor(final InteractionAdvisor advisor) { return advisor instanceof DomainEventFacetAbstract; } - private CausewayConfiguration.Prototyping.IfHiddenPolicy determineIfHiddenPolicyFrom(final ManagedObject ownerAdapter) { - DeploymentType deploymentType = ownerAdapter.getSystemEnvironment().deploymentType(); - switch (deploymentType) { - case PROTOTYPING: - return ownerAdapter.getConfiguration().prototyping().ifHiddenPolicy(); - case PRODUCTION: - default: - return CausewayConfiguration.Prototyping.IfHiddenPolicy.HIDE; - } - } - - private CausewayConfiguration.Prototyping.IfDisabledPolicy determineIfDisabledPolicyFrom(final ManagedObject ownerAdapter) { - DeploymentType deploymentType = ownerAdapter.getSystemEnvironment().deploymentType(); - switch (deploymentType) { - case PROTOTYPING: - return ownerAdapter.getConfiguration().prototyping().ifDisabledPolicy(); - case PRODUCTION: - default: - return CausewayConfiguration.Prototyping.IfDisabledPolicy.DISABLE; - } - } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/RenderPolicy.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/RenderPolicy.java index ad171b9d1a2..f86ead9c360 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/RenderPolicy.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/RenderPolicy.java @@ -23,6 +23,7 @@ import org.jspecify.annotations.NonNull; import org.apache.causeway.core.config.CausewayConfiguration; +import org.apache.causeway.core.metamodel.context.MetaModelContext; /** *

Troubleshooting Visibility and Usability

@@ -66,7 +67,22 @@ public record RenderPolicy( */ CausewayConfiguration.Prototyping.@NonNull IfDisabledPolicy ifDisabledPolicy ) implements Serializable { - + + /** + * Counterpart to {@link #forActionParameters()}, that is objects and members, but not parameters. + */ + public static RenderPolicy forNonActionParam(MetaModelContext mmc) { + return new RenderPolicy( + switch (mmc.getSystemEnvironment().deploymentType()) { + case PROTOTYPING->mmc.getConfiguration().prototyping().ifHiddenPolicy(); + case PRODUCTION->CausewayConfiguration.Prototyping.IfHiddenPolicy.HIDE; + }, + switch (mmc.getSystemEnvironment().deploymentType()) { + case PROTOTYPING -> mmc.getConfiguration().prototyping().ifDisabledPolicy(); + case PRODUCTION -> CausewayConfiguration.Prototyping.IfDisabledPolicy.DISABLE; + }); + } + /** * Always HIDE and DISABLE. */ diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/ValidatingInteractionAdvisor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/ValidatingInteractionAdvisor.java index 469505eeab3..33c569418c3 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/ValidatingInteractionAdvisor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/ValidatingInteractionAdvisor.java @@ -18,8 +18,8 @@ */ package org.apache.causeway.core.metamodel.interactions; +import org.apache.causeway.core.metamodel.consent.InteractionAdvisor; import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetWithAttributes.Validating; import org.apache.causeway.core.metamodel.interactions.val.ValidityContext; /** @@ -33,7 +33,8 @@ * @see DisablingInteractionAdvisor * @see HidingInteractionAdvisor */ -public interface ValidatingInteractionAdvisor extends InteractionAdvisorFacet, Validating { +public interface ValidatingInteractionAdvisor +extends InteractionAdvisor, Facet { /** * Whether the validation represented by this facet passes or fails. diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetNone.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/VisibilityConstraint.java similarity index 60% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetNone.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/VisibilityConstraint.java index b151fe944c6..ebda1a73edc 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/members/hidden/method/HideForContextFacetNone.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/VisibilityConstraint.java @@ -16,24 +16,20 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.causeway.core.metamodel.facets.members.hidden.method; +package org.apache.causeway.core.metamodel.interactions; -import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; +import org.apache.causeway.applib.annotation.Where; -public class HideForContextFacetNone -extends HideForContextFacetAbstract { +public record VisibilityConstraint( + WhatViewer whatViewer, + Where where) { - public HideForContextFacetNone(final FacetHolder holder) { - super(holder, Precedence.FALLBACK); - } + public static VisibilityConstraint noViewer(final Where where) { + return new VisibilityConstraint(WhatViewer.noViewer(), where); + } - /** - * Always returns null. - */ - @Override - public String hides(final VisibilityContext ic) { - return null; - } + public VisibilityConstraint withWhere(final Where where) { + return new VisibilityConstraint(whatViewer, where); + } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/WhatViewer.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/WhatViewer.java new file mode 100644 index 00000000000..73e8c94dcca --- /dev/null +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/WhatViewer.java @@ -0,0 +1,44 @@ +/* + * 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.metamodel.interactions; + +import org.apache.causeway.applib.services.command.CommandExecutorService; +import org.apache.causeway.applib.services.wrapper.WrapperFactory; + +/** + * Viewer identifier, used for viewer specific feature filtering. + */ +public record WhatViewer( + String viewerId) { + + /** + * Used by {@link WrapperFactory}, {@link CommandExecutorService} and Object title interaction. + */ + public static WhatViewer noViewer() { + return new WhatViewer("NoViewer"); + } + + /** + * @deprecated for refactoring only + */ + @Deprecated + public static WhatViewer invalid() { + return new WhatViewer("invalid"); + } +} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ActionInteraction.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ActionInteraction.java index 86e3fb2962e..d1ff4704ee7 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ActionInteraction.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ActionInteraction.java @@ -24,11 +24,11 @@ import org.jspecify.annotations.NonNull; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.functional.Railway; import org.apache.causeway.commons.internal.exceptions._Exceptions; import org.apache.causeway.core.metamodel.facets.object.value.ValueFacet; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.ManagedObjects; import org.apache.causeway.core.metamodel.spec.feature.MixedIn; @@ -66,17 +66,17 @@ public static interface ParameterInvalidCallback { public static ActionInteraction start( final @NonNull ManagedObject owner, final @NonNull String memberId, - final @NonNull Where where) { - return startWithMultiselect(owner, memberId, where, Can::empty); + final @NonNull VisibilityConstraint visibilityConstraint) { + return startWithMultiselect(owner, memberId, visibilityConstraint, Can::empty); } public static ActionInteraction startWithMultiselect( final @NonNull ManagedObject owner, final @NonNull String actionId, - final @NonNull Where where, + final @NonNull VisibilityConstraint visibilityConstraint, final @NonNull MultiselectChoices multiselectChoices) { - var managedAction = ManagedAction.lookupActionWithMultiselect(owner, actionId, where, multiselectChoices); + var managedAction = ManagedAction.lookupActionWithMultiselect(owner, actionId, visibilityConstraint, multiselectChoices); final InteractionRailway railway = managedAction.isPresent() ? InteractionRailway.success(managedAction.get()) @@ -84,7 +84,7 @@ public static ActionInteraction startWithMultiselect( return new ActionInteraction( actionId, - managedAction.map(x->x.getAction()), + managedAction.map(ManagedAction::getAction), railway); } @@ -92,7 +92,7 @@ public static ActionInteraction startWithMultiselect( public static ActionInteraction startAsBoundToProperty( final ManagedProperty associatedWithProperty, final String memberId, - final Where where) { + final VisibilityConstraint visibilityConstraint) { var propertyOwner = associatedWithProperty.getOwner(); var prop = associatedWithProperty.getMetaModel(); var elementType = prop.getElementType(); @@ -117,12 +117,12 @@ public static ActionInteraction startAsBoundToProperty( var mixinAction = valueFacet.selectCompositeValueMixinForProperty(associatedWithProperty); if(mixinAction.isPresent()) { - var managedAction = ManagedAction.of(compositeValue, mixinAction.get(), where); + var managedAction = ManagedAction.of(compositeValue, mixinAction.get(), visibilityConstraint); return ActionInteraction.wrap(managedAction); } } // fallback if not a composite value - return ActionInteraction.start(propertyOwner, memberId, where); + return ActionInteraction.start(propertyOwner, memberId, visibilityConstraint); } /** Supports composite-value-types via mixin (in case detected). */ @@ -130,7 +130,7 @@ public static ActionInteraction startAsBoundToParameter( final ParameterNegotiationModel parameterNegotiationModel, final int paramIndex, final String memberId, - final Where where) { + final VisibilityConstraint visibilityConstraint) { var actionOwner = parameterNegotiationModel.getActionTarget(); var param = parameterNegotiationModel.getParamModels().getElseFail(paramIndex); @@ -155,13 +155,13 @@ public static ActionInteraction startAsBoundToParameter( var mixinAction = valueFacet.selectCompositeValueMixinForParameter(parameterNegotiationModel, paramIndex); if(mixinAction.isPresent()) { - var managedAction = ManagedAction.of(compositeValue, mixinAction.get(), where); + var managedAction = ManagedAction.of(compositeValue, mixinAction.get(), visibilityConstraint); return ActionInteraction.wrap(managedAction); } } // else if not a composite value - return ActionInteraction.start(actionOwner, memberId, where); + return ActionInteraction.start(actionOwner, memberId, visibilityConstraint); } public static ActionInteraction wrap(final @NonNull ManagedAction managedAction) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/CollectionInteraction.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/CollectionInteraction.java index d8879f43140..fc733248605 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/CollectionInteraction.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/CollectionInteraction.java @@ -24,7 +24,7 @@ import org.jspecify.annotations.NonNull; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; public record CollectionInteraction( @@ -34,9 +34,9 @@ public record CollectionInteraction( public static final CollectionInteraction start( final @NonNull ManagedObject owner, final @NonNull String memberId, - final @NonNull Where where) { + final @NonNull VisibilityConstraint visibilityConstraint) { - var managedCollection = ManagedCollection.lookupCollection(owner, memberId, where); + var managedCollection = ManagedCollection.lookupCollection(owner, memberId, visibilityConstraint); final InteractionRailway railway = managedCollection.isPresent() ? InteractionRailway.success(managedCollection.get()) diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedAction.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedAction.java index 5b21c9409c2..1931fb43080 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedAction.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedAction.java @@ -25,7 +25,6 @@ import org.jspecify.annotations.Nullable; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.registry.ServiceRegistry; import org.apache.causeway.applib.services.routing.RoutingService; import org.apache.causeway.commons.collections.Can; @@ -36,6 +35,7 @@ import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.ManagedObjects; import org.apache.causeway.core.metamodel.objectmanager.ObjectManager; @@ -55,27 +55,27 @@ public final class ManagedAction extends ManagedMember { public static final ManagedAction of( final @NonNull ManagedObject owner, final @NonNull ObjectAction action, - final @NonNull Where where) { - return new ManagedAction(owner, action, where, Can::empty); + final @NonNull VisibilityConstraint visibilityConstraint) { + return new ManagedAction(owner, action, visibilityConstraint, Can::empty); } public static final Optional lookupAction( final @NonNull ManagedObject owner, final @NonNull String memberId, - final @NonNull Where where) { + final @NonNull VisibilityConstraint visibilityConstraint) { return ManagedMember.lookup(owner.objSpec(), Identifier.Type.ACTION, memberId) - .map(objectAction -> of(owner, objectAction, where)); + .map(objectAction -> of(owner, objectAction, visibilityConstraint)); } public static final Optional lookupActionWithMultiselect( final @NonNull ManagedObject owner, final @NonNull String memberId, - final @NonNull Where where, + final @NonNull VisibilityConstraint visibilityConstraint, final @NonNull MultiselectChoices multiselectChoices) { return ManagedMember.lookup(owner.objSpec(), Identifier.Type.ACTION, memberId) - .map(objectAction -> new ManagedAction(owner, objectAction, where, multiselectChoices)); + .map(objectAction -> new ManagedAction(owner, objectAction, visibilityConstraint, multiselectChoices)); } // -- IMPLEMENTATION @@ -86,10 +86,10 @@ public static final Optional lookupActionWithMultiselect( private ManagedAction( final @NonNull ManagedObject owner, final @NonNull ObjectAction action, - final @NonNull Where where, + final @NonNull VisibilityConstraint visibilityConstraint, final @NonNull MultiselectChoices multiselectChoices) { - super(owner, where); + super(owner, visibilityConstraint); /* entities might become removed, but even though removed, an entity delete mixin say, may still want to provide an action result, that does not need the mixee instance to be produced; eg. delete ApplicationUser mixin that returns a collection of all remaining users @@ -140,7 +140,7 @@ public Railway invoke( final ManagedObject actionResult = getAction() // under the hood intercepts cases, where the owner is a value-type; // executions on value-types have no rule checking and trigger no domain events - .execute(interactionHead(), actionParameters, interactionInitiatedBy); + .execute(interactionHead(), actionParameters, interactionInitiatedBy, visibilityConstraint().whatViewer()); return Railway.success(route(actionResult)); } @@ -158,7 +158,7 @@ public final ManagedObject invokeWithRuleChecking( // under the hood intercepts cases, where the owner is a value-type; // executions on value-types have no rule checking and trigger no domain events .executeWithRuleChecking( - interactionHead(), actionParameters, InteractionInitiatedBy.USER, getWhere()); + interactionHead(), actionParameters, InteractionInitiatedBy.USER, visibilityConstraint()); return route(actionResult); } @@ -167,9 +167,8 @@ public final ManagedObject invokeWithRuleChecking( private ManagedObject route(final @Nullable ManagedObject actionResult) { - if(ManagedObjects.isNullOrUnspecifiedOrEmpty(actionResult)) { - return ManagedObject.empty(action.getReturnType()); - } + if(ManagedObjects.isNullOrUnspecifiedOrEmpty(actionResult)) + return ManagedObject.empty(action.getReturnType()); var resultPojo = actionResult.getPojo(); var objManager = mmc().getObjectManager(); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedCollection.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedCollection.java index 6cf1b7e8b9e..aefd00b0902 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedCollection.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedCollection.java @@ -21,18 +21,19 @@ import java.util.Optional; import java.util.stream.Stream; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.facets.collections.CollectionFacet; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.causeway.core.metamodel.tabular.DataTableInteractive; import lombok.Getter; -import org.jspecify.annotations.NonNull; public final class ManagedCollection extends ManagedMember { @@ -41,17 +42,17 @@ public final class ManagedCollection extends ManagedMember { public static final ManagedCollection of( final @NonNull ManagedObject owner, final @NonNull OneToManyAssociation collection, - final @NonNull Where where) { - return new ManagedCollection(owner, collection, where); + final @NonNull VisibilityConstraint visibilityConstraint) { + return new ManagedCollection(owner, collection, visibilityConstraint); } public static final Optional lookupCollection( final @NonNull ManagedObject owner, final @NonNull String memberId, - final @NonNull Where where) { + final @NonNull VisibilityConstraint visibilityConstraint) { return ManagedMember.lookup(owner.objSpec(), Identifier.Type.COLLECTION, memberId) - .map(objectAction -> of(owner, objectAction, where)); + .map(objectAction -> of(owner, objectAction, visibilityConstraint)); } // -- IMPLEMENTATION @@ -61,9 +62,9 @@ public static final Optional lookupCollection( private ManagedCollection( final @NonNull ManagedObject owner, final @NonNull OneToManyAssociation collection, - final @NonNull Where where) { + final @NonNull VisibilityConstraint visibilityConstraint) { - super(owner, where); + super(owner, visibilityConstraint); this.collection = collection; } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedMember.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedMember.java index 036d664117b..65745bf850a 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedMember.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedMember.java @@ -23,10 +23,10 @@ import org.jspecify.annotations.NonNull; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.internal.base._Casts; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.consent.Veto; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectMember; @@ -34,6 +34,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; +import lombok.experimental.Accessors; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -59,7 +60,7 @@ public enum RepresentationMode { @Getter @NonNull private ManagedObject owner; - @Getter @NonNull private final Where where; + @Getter @Accessors(fluent = true) @NonNull private final VisibilityConstraint visibilityConstraint; /** * Allows a managed property of a view model to replace its owner with a clone. @@ -110,11 +111,10 @@ public Optional getDescription() { * @return non-empty if hidden */ public Optional checkVisibility() { - try { var visibilityConsent = getMetaModel() - .isVisible(getOwner(), InteractionInitiatedBy.USER, where); + .isVisible(getOwner(), InteractionInitiatedBy.USER, visibilityConstraint); return visibilityConsent.isVetoed() ? Optional.of(InteractionVeto.hidden(visibilityConsent)) @@ -133,12 +133,10 @@ public Optional checkVisibility() { * @return non-empty if not usable/editable (meaning if read-only) */ public Optional checkUsability() { - try { - var usabilityConsent = getMetaModel() - .isUsable(getOwner(), InteractionInitiatedBy.USER, where); + .isUsable(getOwner(), InteractionInitiatedBy.USER, visibilityConstraint); return usabilityConsent.isVetoed() ? Optional.of(InteractionVeto.readonly(usabilityConsent)) diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedProperty.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedProperty.java index 9dd7f766f72..2f0b96c8062 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedProperty.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/ManagedProperty.java @@ -20,22 +20,22 @@ import java.util.Optional; +import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.binding.Observable; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.binding._Observables; import org.apache.causeway.commons.internal.binding._Observables.LazyObservable; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.consent.Veto; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; import lombok.Getter; -import org.jspecify.annotations.NonNull; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -47,17 +47,17 @@ public final class ManagedProperty public static final ManagedProperty of( final @NonNull ManagedObject owner, final @NonNull OneToOneAssociation property, - final @NonNull Where where) { - return new ManagedProperty(owner, property, where); + final @NonNull VisibilityConstraint visibilityConstraint) { + return new ManagedProperty(owner, property, visibilityConstraint); } public static final Optional lookupProperty( final @NonNull ManagedObject owner, final @NonNull String memberId, - final @NonNull Where where) { + final @NonNull VisibilityConstraint visibilityConstraint) { return ManagedMember.lookup(owner.objSpec(), Identifier.Type.PROPERTY, memberId) - .map(objectAction -> of(owner, objectAction, where)); + .map(objectAction -> of(owner, objectAction, visibilityConstraint)); } // -- IMPLEMENTATION @@ -72,8 +72,8 @@ public static final Optional lookupProperty( private ManagedProperty( final @NonNull ManagedObject owner, final @NonNull OneToOneAssociation property, - final @NonNull Where where) { - super(owner, where); + final @NonNull VisibilityConstraint visibilityConstraint) { + super(owner, visibilityConstraint); this.property = property; observablePropValue = _Observables.lazy(this::reassessPropertyValue); } @@ -132,9 +132,8 @@ public Optional modifyProperty(final @Nullable ManagedObject ne private ManagedObject reassessPropertyValue() { var property = getProperty(); var owner = getOwner(); - - return property.isVisible(owner, InteractionInitiatedBy.FRAMEWORK, getWhere()).isAllowed() - && property.isVisible(owner, InteractionInitiatedBy.USER, getWhere()).isAllowed() + return property.isVisible(owner, InteractionInitiatedBy.FRAMEWORK, visibilityConstraint()).isAllowed() + && property.isVisible(owner, InteractionInitiatedBy.USER, visibilityConstraint()).isAllowed() ? property.get(owner, InteractionInitiatedBy.USER) : ManagedObject.empty(property.getElementType()); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/PropertyInteraction.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/PropertyInteraction.java index 097593bb387..fd7ce7114d8 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/PropertyInteraction.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/managed/PropertyInteraction.java @@ -24,7 +24,7 @@ import org.jspecify.annotations.NonNull; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; public record PropertyInteraction( @@ -34,9 +34,9 @@ public record PropertyInteraction( public static final PropertyInteraction start( final @NonNull ManagedObject owner, final @NonNull String memberId, - final @NonNull Where where) { + final @NonNull VisibilityConstraint visibilityConstraint) { - var managedProperty = ManagedProperty.lookupProperty(owner, memberId, where); + var managedProperty = ManagedProperty.lookupProperty(owner, memberId, visibilityConstraint); final InteractionRailway railway = managedProperty.isPresent() ? InteractionRailway.success(managedProperty.get()) diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/ActionUsabilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/ActionUsabilityContext.java index 6780cbff485..6b2c4be3e1f 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/ActionUsabilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/ActionUsabilityContext.java @@ -19,7 +19,6 @@ package org.apache.causeway.core.metamodel.interactions.use; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.ActionUsabilityEvent; import org.apache.causeway.core.metamodel.consent.InteractionContextType; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; @@ -27,7 +26,6 @@ import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; -import org.apache.causeway.core.metamodel.interactions.vis.ActionVisibilityContext; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -40,7 +38,6 @@ public record ActionUsabilityContext( InteractionHead head, Identifier identifier, InteractionInitiatedBy initiatedBy, - Where where, RenderPolicy renderPolicy, ObjectAction objectAction ) @@ -51,10 +48,9 @@ public ActionUsabilityContext( final ObjectAction objectAction, final Identifier id, final InteractionInitiatedBy initiatedBy, - final Where where, final RenderPolicy renderPolicy) { this(InteractionContextType.ACTION_USABLE, - head, id, initiatedBy, where, renderPolicy, + head, id, initiatedBy, renderPolicy, objectAction); } @@ -63,9 +59,4 @@ public ActionUsabilityEvent createInteractionEvent() { return new ActionUsabilityEvent(MmUnwrapUtils.single(target()), identifier()); } - @Override - public ActionVisibilityContext asVisibilityContext() { - return new ActionVisibilityContext(head(), objectAction(), identifier(), - initiatedBy(), where(), renderPolicy()); - } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/CollectionUsabilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/CollectionUsabilityContext.java index d494fefb1de..56c9552a304 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/CollectionUsabilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/CollectionUsabilityContext.java @@ -19,14 +19,12 @@ package org.apache.causeway.core.metamodel.interactions.use; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.CollectionUsabilityEvent; import org.apache.causeway.core.metamodel.consent.InteractionContextType; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; -import org.apache.causeway.core.metamodel.interactions.vis.CollectionVisibilityContext; /** * See {@link InteractionContext} for overview; analogous to @@ -37,7 +35,6 @@ public record CollectionUsabilityContext( InteractionHead head, Identifier identifier, InteractionInitiatedBy initiatedBy, - Where where, RenderPolicy renderPolicy) implements UsabilityContext { @@ -45,20 +42,13 @@ public CollectionUsabilityContext( final InteractionHead head, final Identifier identifier, final InteractionInitiatedBy initiatedBy, - final Where where, final RenderPolicy renderPolicy) { this(InteractionContextType.COLLECTION_USABLE, - head, identifier, initiatedBy, where, renderPolicy); + head, identifier, initiatedBy, renderPolicy); } @Override public CollectionUsabilityEvent createInteractionEvent() { return new CollectionUsabilityEvent(target().getPojo(), identifier()); } - - @Override - public CollectionVisibilityContext asVisibilityContext() { - return new CollectionVisibilityContext(head(), identifier(), - initiatedBy(), where(), renderPolicy()); - } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/ParamUsabilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/ParamUsabilityContext.java index a28348cbb85..2f141e711a2 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/ParamUsabilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/ParamUsabilityContext.java @@ -19,7 +19,6 @@ package org.apache.causeway.core.metamodel.interactions.use; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.events.ActionArgumentUsabilityEvent; import org.apache.causeway.applib.services.wrapper.events.ActionArgumentEvent; import org.apache.causeway.commons.collections.Can; @@ -29,7 +28,6 @@ import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; -import org.apache.causeway.core.metamodel.interactions.vis.ParamVisibilityContext; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -43,7 +41,6 @@ public record ParamUsabilityContext( InteractionHead head, Identifier identifier, InteractionInitiatedBy initiatedBy, - Where where, RenderPolicy renderPolicy, ObjectAction objectAction, Can args, @@ -60,7 +57,7 @@ public ParamUsabilityContext( final RenderPolicy renderPolicy) { this(InteractionContextType.ACTION_PARAMETER_USABLE, - head, id, initiatedBy, Where.OBJECT_FORMS, renderPolicy, + head, id, initiatedBy, renderPolicy, objectAction, args, position); } @@ -73,10 +70,4 @@ public ActionArgumentUsabilityEvent createInteractionEvent() { position()); } - @Override - public ParamVisibilityContext asVisibilityContext() { - return new ParamVisibilityContext(head(), objectAction(), identifier(), - args, position, initiatedBy(), renderPolicy()); - } - } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/PropertyUsabilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/PropertyUsabilityContext.java index 8ab024f0e05..71be348a788 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/PropertyUsabilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/PropertyUsabilityContext.java @@ -19,14 +19,12 @@ package org.apache.causeway.core.metamodel.interactions.use; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.PropertyUsabilityEvent; import org.apache.causeway.core.metamodel.consent.InteractionContextType; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; -import org.apache.causeway.core.metamodel.interactions.vis.PropertyVisibilityContext; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; /** @@ -38,7 +36,6 @@ public record PropertyUsabilityContext( InteractionHead head, Identifier identifier, InteractionInitiatedBy initiatedBy, - Where where, RenderPolicy renderPolicy) implements UsabilityContext { @@ -46,10 +43,9 @@ public PropertyUsabilityContext( final InteractionHead head, final Identifier identifier, final InteractionInitiatedBy initiatedBy, - final Where where, final RenderPolicy renderPolicy) { this(InteractionContextType.PROPERTY_USABLE, - head, identifier, initiatedBy, where, renderPolicy); + head, identifier, initiatedBy, renderPolicy); } @Override @@ -57,9 +53,4 @@ public PropertyUsabilityEvent createInteractionEvent() { return new PropertyUsabilityEvent(MmUnwrapUtils.single(target()), identifier()); } - @Override - public PropertyVisibilityContext asVisibilityContext() { - return new PropertyVisibilityContext(head(), identifier(), - initiatedBy(), where(), renderPolicy()); - } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/UsabilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/UsabilityContext.java index 9edbce3254c..3aafe9c9fee 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/UsabilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/use/UsabilityContext.java @@ -22,13 +22,14 @@ import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionEventSupplier; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; -import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; public sealed interface UsabilityContext extends InteractionContext, InteractionEventSupplier permits ActionUsabilityContext, CollectionUsabilityContext, ParamUsabilityContext, PropertyUsabilityContext { + /** + * for debugging usability when prototyping + */ RenderPolicy renderPolicy(); - VisibilityContext asVisibilityContext(); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/val/ValidityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/val/ValidityContext.java index 04c1610c9df..af8dac64ebf 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/val/ValidityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/val/ValidityContext.java @@ -20,7 +20,6 @@ import java.util.function.Supplier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.ValidityEvent; import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionEventSupplier; @@ -35,9 +34,4 @@ default String friendlyName() { return friendlyNameProvider().get(); } - @Override - default Where where() { - return Where.NOT_SPECIFIED; - } - } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ActionVisibilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ActionVisibilityContext.java index f9415271a89..54489c173ff 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ActionVisibilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ActionVisibilityContext.java @@ -19,7 +19,6 @@ package org.apache.causeway.core.metamodel.interactions.vis; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.ActionVisibilityEvent; import org.apache.causeway.core.metamodel.consent.InteractionContextType; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; @@ -27,6 +26,7 @@ import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -35,13 +35,13 @@ * {@link ActionVisibilityEvent}. */ public record ActionVisibilityContext( - InteractionContextType interactionType, - InteractionHead head, - Identifier identifier, - InteractionInitiatedBy initiatedBy, - Where where, - RenderPolicy renderPolicy, - ObjectAction objectAction) + InteractionContextType interactionType, + InteractionHead head, + Identifier identifier, + InteractionInitiatedBy initiatedBy, + VisibilityConstraint visibilityConstraint, + RenderPolicy renderPolicy, + ObjectAction objectAction) implements VisibilityContext, ActionInteractionContext { public ActionVisibilityContext( @@ -49,10 +49,10 @@ public ActionVisibilityContext( final ObjectAction objectAction, final Identifier identifier, final InteractionInitiatedBy initiatedBy, - final Where where, + final VisibilityConstraint visibilityConstraint, final RenderPolicy renderPolicy) { this(InteractionContextType.ACTION_VISIBLE, - head, identifier, initiatedBy, where, renderPolicy, + head, identifier, initiatedBy, visibilityConstraint, renderPolicy, objectAction); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/CollectionVisibilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/CollectionVisibilityContext.java index 4ee46ff2bec..cfb2c1c1a5c 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/CollectionVisibilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/CollectionVisibilityContext.java @@ -19,13 +19,13 @@ package org.apache.causeway.core.metamodel.interactions.vis; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.CollectionVisibilityEvent; import org.apache.causeway.core.metamodel.consent.InteractionContextType; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; /** @@ -33,22 +33,22 @@ * {@link CollectionVisibilityEvent}. */ public record CollectionVisibilityContext( - InteractionContextType interactionType, - InteractionHead head, - Identifier identifier, - InteractionInitiatedBy initiatedBy, - Where where, - RenderPolicy renderPolicy) + InteractionContextType interactionType, + InteractionHead head, + Identifier identifier, + InteractionInitiatedBy initiatedBy, + VisibilityConstraint visibilityConstraint, + RenderPolicy renderPolicy) implements VisibilityContext { public CollectionVisibilityContext( final InteractionHead head, final Identifier identifierAdapter, final InteractionInitiatedBy initiatedBy, - final Where where, + final VisibilityConstraint visibilityConstraint, final RenderPolicy renderPolicy) { this(InteractionContextType.COLLECTION_VISIBLE, - head, identifierAdapter, initiatedBy, where, renderPolicy); + head, identifierAdapter, initiatedBy, visibilityConstraint, renderPolicy); } @Override diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ObjectVisibilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ObjectVisibilityContext.java index 4f542b7b043..460c2b8df1d 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ObjectVisibilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ObjectVisibilityContext.java @@ -19,15 +19,14 @@ package org.apache.causeway.core.metamodel.interactions.vis; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.ObjectVisibilityEvent; import org.apache.causeway.core.metamodel.consent.InteractionContextType; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; -import org.apache.causeway.core.metamodel.interactions.InteractionUtils; import org.apache.causeway.core.metamodel.interactions.ProposedHolder; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; @@ -36,12 +35,12 @@ * {@link ObjectVisibilityEvent}. */ public record ObjectVisibilityContext( - InteractionContextType interactionType, - InteractionHead head, - Identifier identifier, - InteractionInitiatedBy initiatedBy, - Where where, - RenderPolicy renderPolicy) + InteractionContextType interactionType, + InteractionHead head, + Identifier identifier, + InteractionInitiatedBy initiatedBy, + VisibilityConstraint visibilityConstraint, + RenderPolicy renderPolicy) implements VisibilityContext, ProposedHolder { // -- FACTORIES @@ -52,13 +51,13 @@ public record ObjectVisibilityContext( public static ObjectVisibilityContext createForRegular( final ManagedObject domainObject, final InteractionInitiatedBy initiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { return new ObjectVisibilityContext( InteractionHead.regular(domainObject), domainObject.objSpec().getFeatureIdentifier(), initiatedBy, - where, - InteractionUtils.renderPolicy(domainObject)); + visibilityConstraint, + RenderPolicy.forNonActionParam(domainObject)); } // -- CONSTRUCTION @@ -67,10 +66,10 @@ public ObjectVisibilityContext( final InteractionHead head, final Identifier identifier, final InteractionInitiatedBy initiatedBy, - final Where where, + final VisibilityConstraint visibilityConstraint, final RenderPolicy renderPolicy) { this(InteractionContextType.OBJECT_VISIBILITY, - head, identifier, initiatedBy, where, renderPolicy); + head, identifier, initiatedBy, visibilityConstraint, renderPolicy); } @Override diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ParamVisibilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ParamVisibilityContext.java index b09699b922b..f2da555eea0 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ParamVisibilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/ParamVisibilityContext.java @@ -29,6 +29,7 @@ import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -38,15 +39,15 @@ * {@link ActionArgumentEvent}. */ public record ParamVisibilityContext( - InteractionContextType interactionType, - InteractionHead head, - Identifier identifier, - InteractionInitiatedBy initiatedBy, - Where where, - RenderPolicy renderPolicy, - ObjectAction objectAction, - Can args, - int position) + InteractionContextType interactionType, + InteractionHead head, + Identifier identifier, + InteractionInitiatedBy initiatedBy, + VisibilityConstraint visibilityConstraint, + RenderPolicy renderPolicy, + ObjectAction objectAction, + Can args, + int position) implements VisibilityContext, ActionInteractionContext { public ParamVisibilityContext( @@ -58,8 +59,12 @@ public ParamVisibilityContext( final InteractionInitiatedBy initiatedBy, final RenderPolicy renderPolicy) { + // assumption: param visibility is never directly constraint by WhatViewer or Where; + // instead those constraints apply only to their 'owning' action + // in other words, if an action is visible honoring WhatViewer or Where, then no further + // visibility vetos for params are considered based on WhatViewer or Where. this(InteractionContextType.ACTION_PARAMETER_VISIBLE, - head, id, initiatedBy, Where.OBJECT_FORMS, renderPolicy, + head, id, initiatedBy, VisibilityConstraint.noViewer(Where.ANYWHERE), renderPolicy, objectAction, args, position); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/PropertyVisibilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/PropertyVisibilityContext.java index 0fad557d06e..e1aeb044ddd 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/PropertyVisibilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/PropertyVisibilityContext.java @@ -19,13 +19,13 @@ package org.apache.causeway.core.metamodel.interactions.vis; import org.apache.causeway.applib.Identifier; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.PropertyVisibilityEvent; import org.apache.causeway.core.metamodel.consent.InteractionContextType; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; /** @@ -33,23 +33,23 @@ * {@link PropertyVisibilityEvent}. */ public record PropertyVisibilityContext( - InteractionContextType interactionType, - InteractionHead head, - Identifier identifier, - InteractionInitiatedBy initiatedBy, - Where where, - RenderPolicy renderPolicy + InteractionContextType interactionType, + InteractionHead head, + Identifier identifier, + InteractionInitiatedBy initiatedBy, + VisibilityConstraint visibilityConstraint, + RenderPolicy renderPolicy ) implements VisibilityContext { public PropertyVisibilityContext( final InteractionHead head, final Identifier identifier, final InteractionInitiatedBy initiatedBy, - final Where where, + final VisibilityConstraint visibilityConstraint, final RenderPolicy renderPolicy) { this(InteractionContextType.PROPERTY_VISIBLE, - head, identifier, initiatedBy, where, renderPolicy); + head, identifier, initiatedBy, visibilityConstraint, renderPolicy); } @Override diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/VisibilityContext.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/VisibilityContext.java index 418df088599..70afbaf8cb9 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/VisibilityContext.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/interactions/vis/VisibilityContext.java @@ -18,10 +18,12 @@ */ package org.apache.causeway.core.metamodel.interactions.vis; +import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.wrapper.events.VisibilityEvent; import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionEventSupplier; import org.apache.causeway.core.metamodel.interactions.RenderPolicy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; /** * See {@link InteractionContext} for overview; analogous to @@ -32,6 +34,21 @@ public sealed interface VisibilityContext permits ParamVisibilityContext, ActionVisibilityContext, CollectionVisibilityContext, ObjectVisibilityContext, PropertyVisibilityContext { + /** + * for debugging visibility when prototyping + */ RenderPolicy renderPolicy(); + /** + * Where and by what viewer the element is to be rendered. + */ + VisibilityConstraint visibilityConstraint(); + + /** + * Where the element is to be rendered. + */ + default Where where() { + return visibilityConstraint().where(); + } + } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/layout/LayoutFacetUtil.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/layout/LayoutFacetUtil.java index 42d581c4f87..41c6cec24a2 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/layout/LayoutFacetUtil.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/layout/LayoutFacetUtil.java @@ -44,7 +44,7 @@ import org.apache.causeway.core.metamodel.facets.actions.position.ActionPositionFacet; import org.apache.causeway.core.metamodel.facets.all.described.MemberDescribedFacet; import org.apache.causeway.core.metamodel.facets.all.described.ObjectDescribedFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.all.named.MemberNamedFacet; import org.apache.causeway.core.metamodel.facets.all.named.ObjectNamedFacet; import org.apache.causeway.core.metamodel.facets.collections.collection.defaultview.DefaultViewFacet; @@ -299,7 +299,7 @@ private void setHiddenIfAny( final HasHidden hasHidden, final FacetHolder facetHolder) { - var hiddenFacet = facetHolder.getFacet(HiddenFacet.class); + var hiddenFacet = facetHolder.getFacet(HiddenFacetForLayout.class); if (isNonFallback(hiddenFacet)) { final Where where = hiddenFacet.where(); if(where != null) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmVisibilityUtils.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmVisibilityUtils.java index 4a27cffc8c7..7d63f1135d8 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmVisibilityUtils.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmVisibilityUtils.java @@ -26,8 +26,9 @@ import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.facets.collections.CollectionFacet; import org.apache.causeway.core.metamodel.interactions.InteractionUtils; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.interactions.vis.ObjectVisibilityContext; -import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; import lombok.experimental.UtilityClass; @@ -35,7 +36,7 @@ public final class MmVisibilityUtils { public static Predicate filterOn(final InteractionInitiatedBy interactionInitiatedBy) { - return $->MmVisibilityUtils.isVisible($, interactionInitiatedBy); + return $->MmVisibilityUtils.isVisible($, interactionInitiatedBy, WhatViewer.invalid()); } /** @@ -82,43 +83,33 @@ public static Object visiblePojosAutofit( } /** - * @param adapter - wrapper of domain object whose visibility is being checked, + * @param mo - wrapper of domain object whose visibility is being checked, * must not be a mixin * @param interactionInitiatedBy */ public static boolean isVisible( - final ManagedObject adapter, - final InteractionInitiatedBy interactionInitiatedBy) { + final ManagedObject mo, + final InteractionInitiatedBy interactionInitiatedBy, + final WhatViewer whatViewer) { - if(ManagedObjects.isNullOrUnspecifiedOrEmpty(adapter)) { - // a choices list could include a null (eg example in ToDoItems#choices1Categorized()); want to show as "visible" - return true; - } - var spec = adapter.objSpec(); - if(spec.isEntity()) { - if(MmEntityUtils.getEntityState(adapter).isTransientOrRemoved()) { - return false; - } - } - if(!interactionInitiatedBy.isUser()) { + if(ManagedObjects.isNullOrUnspecifiedOrEmpty(mo)) + // a choices list could include a null (eg example in ToDoItems#choices1Categorized()); want to show as "visible" return true; - } - var visibilityContext = createVisibleInteractionContext( - adapter, + var spec = mo.objSpec(); + if(spec.isEntity() + && MmEntityUtils.getEntityState(mo).isTransientOrRemoved()) + return false; + + if(!interactionInitiatedBy.isUser()) + return true; + + var visibilityContext = ObjectVisibilityContext.createForRegular( + mo, InteractionInitiatedBy.USER, - Where.OBJECT_FORMS); + new VisibilityConstraint(whatViewer, Where.OBJECT_FORMS)); return InteractionUtils.isVisibleResult(spec, visibilityContext) .isAllowing(); } - private static VisibilityContext createVisibleInteractionContext( - final ManagedObject objectAdapter, - final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { - - return ObjectVisibilityContext - .createForRegular(objectAdapter, interactionInitiatedBy, where); - } - } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacet.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacet.java index b847f3f8671..05dc74d6a49 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacet.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacet.java @@ -18,12 +18,12 @@ */ package org.apache.causeway.core.metamodel.postprocessors.allbutparam.authorization; +import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.apache.causeway.applib.Identifier; import org.apache.causeway.core.config.progmodel.ProgrammingModelConstants; import org.apache.causeway.core.metamodel.context.MetaModelContext; -import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.DisablingInteractionAdvisor; import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; import org.apache.causeway.core.metamodel.interactions.vis.ActionVisibilityContext; @@ -34,14 +34,12 @@ import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; -import org.jspecify.annotations.NonNull; - /** - * Optionally hide or disable an object, property, collection or action + * Optionally hides or disables an object, property, collection or action * depending on the authorization. */ public interface AuthorizationFacet -extends Facet, HidingInteractionAdvisor, DisablingInteractionAdvisor { +extends HidingInteractionAdvisor, DisablingInteractionAdvisor { public static boolean hidesProperty( final @NonNull OneToOneAssociation property, @@ -53,7 +51,7 @@ public static boolean hidesProperty( vc.head(), property.getFeatureIdentifier(), vc.initiatedBy(), - vc.where(), + vc.visibilityConstraint(), vc.renderPolicy())) != null) .orElse(false); } @@ -68,7 +66,7 @@ public static boolean hidesCollection( vc.head(), collection.getFeatureIdentifier(), vc.initiatedBy(), - vc.where(), + vc.visibilityConstraint(), vc.renderPolicy())) != null) .orElse(false); } @@ -84,7 +82,7 @@ public static boolean hidesAction( action, action.getFeatureIdentifier(), vc.initiatedBy(), - vc.where(), + vc.visibilityConstraint(), vc.renderPolicy())) != null) .orElse(false); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetAbstract.java deleted file mode 100644 index 3754ad7cf3c..00000000000 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetAbstract.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.metamodel.postprocessors.allbutparam.authorization; - -import java.util.Optional; - -import org.apache.causeway.core.metamodel.consent.Consent.VetoReason; -import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetAbstract; -import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; -import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; -import org.apache.causeway.core.security.authorization.manager.AuthorizationManager; - -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public abstract class AuthorizationFacetAbstract -extends FacetAbstract -implements AuthorizationFacet { - - private static final Class type() { - return AuthorizationFacet.class; - } - - private final AuthorizationManager authorizationManager; - - public AuthorizationFacetAbstract( - final FacetHolder holder) { - super(type(), holder); - this.authorizationManager = getAuthorizationManager(); - } - - @Override - public String hides(final VisibilityContext ic) { - - if(ic.head().owner().objSpec().isValue()) { - return null; // never hide value-types - } - - var hides = authorizationManager - .isVisible( - getInteractionService().currentInteractionContextElseFail(), - ic.identifier()) - ? null - : "Not authorized to view"; - - if(hides!=null && log.isDebugEnabled()) { - log.debug("hides[{}] -> {}", ic.identifier(), hides); - } - - return hides; - } - - @Override - public Optional disables(final UsabilityContext ic) { - - if(ic.head().owner().objSpec().isValue()) { - return Optional.empty(); // never disable value-types - } - - var disables = authorizationManager - .isUsable( - getInteractionService().currentInteractionContextElseFail(), - ic.identifier()) - ? null - : AuthorizationFacet.formatNotAuthorizedToEdit(ic.identifier(), getMetaModelContext()); - - if(disables!=null && log.isDebugEnabled()) { - log.debug("disables[{}] -> {}", ic.identifier(), disables); - } - - return Optional.ofNullable(disables).map(VetoReason::unauthorized); - } - -} diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetImpl.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetImpl.java index fc82c0c9ba6..a79efd196b6 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetImpl.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetImpl.java @@ -18,12 +18,66 @@ */ package org.apache.causeway.core.metamodel.postprocessors.allbutparam.authorization; +import java.util.Optional; + +import org.apache.causeway.core.metamodel.consent.Consent.VetoReason; +import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; +import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; +import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; +import org.apache.causeway.core.security.authorization.manager.AuthorizationManager; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public record AuthorizationFacetImpl( + AuthorizationManager authorizationManager, + FacetHolder facetHolder + ) implements AuthorizationFacet { + + @Override public Class facetType() { return AuthorizationFacet.class; } + @Override public Precedence precedence() { return Precedence.DEFAULT; } + + @Override + public String hides(final VisibilityContext ic) { + + if(ic.head().owner().objSpec().isValue()) { + return null; // never hide value-types + } + + var hides = authorizationManager + .isVisible( + facetHolder.getInteractionService().currentInteractionContextElseFail(), + ic.identifier()) + ? null + : "Not authorized to view"; + + if(hides!=null && log.isDebugEnabled()) { + log.debug("hides[{}] -> {}", ic.identifier(), hides); + } + + return hides; + } + + @Override + public Optional disables(final UsabilityContext ic) { + + if(ic.head().owner().objSpec().isValue()) { + return Optional.empty(); // never disable value-types + } + + var disables = authorizationManager + .isUsable( + facetHolder.getInteractionService().currentInteractionContextElseFail(), + ic.identifier()) + ? null + : AuthorizationFacet.formatNotAuthorizedToEdit(ic.identifier(), facetHolder.getMetaModelContext()); -public class AuthorizationFacetImpl extends AuthorizationFacetAbstract { + if(disables!=null && log.isDebugEnabled()) { + log.debug("disables[{}] -> {}", ic.identifier(), disables); + } - public AuthorizationFacetImpl(final FacetHolder holder) { - super(holder); + return Optional.ofNullable(disables).map(VetoReason::unauthorized); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationPostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationPostProcessor.java index 389dcb4495b..355b1904c8d 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationPostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationPostProcessor.java @@ -57,7 +57,7 @@ public void postProcessCollection(final ObjectSpecification objectSpecification, } private static void addFacet(final FacetHolder facetHolder) { - facetHolder.addFacet(new AuthorizationFacetImpl(facetHolder)); + facetHolder.addFacet(new AuthorizationFacetImpl(facetHolder.getAuthorizationManager(), facetHolder)); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenType.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/HiddenFacetForNavigationFromHiddenType.java similarity index 64% rename from core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenType.java rename to core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/HiddenFacetForNavigationFromHiddenType.java index cd6874af027..b93e8b04e5f 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenType.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/HiddenFacetForNavigationFromHiddenType.java @@ -24,60 +24,53 @@ import org.apache.causeway.applib.Identifier; import org.apache.causeway.commons.internal.assertions._Assert; import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetAbstract; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; -import org.apache.causeway.core.metamodel.facets.members.navigation.NavigationFacet; -import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenTypeFacet; +import org.apache.causeway.core.metamodel.facets.members.navigation.HiddenFacetForNavigation; +import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenFacetForNoMembersAuthorized; import org.apache.causeway.core.metamodel.interactions.vis.ObjectVisibilityContext; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; -public class NavigationFacetFromHiddenType -extends FacetAbstract -implements - NavigationFacet { +public record HiddenFacetForNavigationFromHiddenType( + ObjectSpecification navigatedType, + FacetHolder facetHolder + ) implements HiddenFacetForNavigation { - private final ObjectSpecification navigatedType; + public static Optional create(final ObjectSpecification navigatedType, final FacetHolder holder) { + return navigatedType.isValue() + ? Optional.empty() // don't create for value types (optimization, not strictly required) + : Optional.of(new HiddenFacetForNavigationFromHiddenType(navigatedType, holder)); + } - private static final Class type() { - return NavigationFacet.class; - } - - public static Optional create(final ObjectSpecification navigatedType, final FacetHolder holder) { - return navigatedType.isValue() - ? Optional.empty() // don't create for value types (optimization, not strictly required) - : Optional.of(new NavigationFacetFromHiddenType(navigatedType, holder)); - } + @Override public Class facetType() { return HiddenFacetForNavigation.class; } + @Override public Precedence precedence() { return Precedence.DEFAULT; } - private NavigationFacetFromHiddenType(final ObjectSpecification navigatedType, final FacetHolder holder) { - super(type(), holder); - this.navigatedType = navigatedType; + public HiddenFacetForNavigationFromHiddenType { _Assert.assertTrue(navigatedType.isSingular(), ()->String.format( "framework bug: elementType must not match any supported plural (collection) types, " + "nevertheless got %s", navigatedType)); } @Override - public String hides(final VisibilityContext ic) { - var facet = navigatedType.getFacet(HiddenTypeFacet.class); - if(facet == null) { - // not expected to happen; this facet should only be installed for object members + public String hides(final VisibilityContext vc) { + var facet = navigatedType.getFacet(HiddenFacetForNoMembersAuthorized.class); + if(facet == null) + // not expected to happen; this facet should only be installed for object members // that navigate to a class that has the HiddenTypeFacet return null; - } var objVisibilityContext = new ObjectVisibilityContext( - ic.head(), + vc.head(), Identifier.classIdentifier(navigatedType.logicalType()), - ic.initiatedBy(), - ic.where(), - ic.renderPolicy()); + vc.initiatedBy(), + vc.visibilityConstraint(), + vc.renderPolicy()); final String hides = facet.hides(objVisibilityContext); return hides; } @Override public void visitAttributes(final BiConsumer visitor) { - super.visitAttributes(visitor); + HiddenFacetForNavigation.super.visitAttributes(visitor); visitor.accept("navigatedType", navigatedType.logicalTypeName()); visitor.accept("navigatedTypeFqcn", navigatedType.getCorrespondingClass().getName()); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenTypePostProcessor.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenTypePostProcessor.java index 66bcc7ed094..e961f316e88 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenTypePostProcessor.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/members/navigation/NavigationFacetFromHiddenTypePostProcessor.java @@ -23,7 +23,7 @@ import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facetapi.FacetUtil; -import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenTypeFacet; +import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenFacetForNoMembersAuthorized; import org.apache.causeway.core.metamodel.postprocessors.MetaModelPostProcessorAbstract; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; @@ -32,7 +32,7 @@ import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; /** - * Installs the {@link NavigationFacetFromHiddenType} on all of the + * Installs the {@link HiddenFacetForNavigationFromHiddenType} on all of the * {@link ObjectMember}s of the {@link ObjectSpecification}. */ public class NavigationFacetFromHiddenTypePostProcessor extends MetaModelPostProcessorAbstract { @@ -60,8 +60,8 @@ public void postProcessCollection(final ObjectSpecification objectSpecification, // -- HELPER private static void addFacetIfRequired(final FacetHolder facetHolder, final ObjectSpecification navigatedType) { - if(navigatedType.containsNonFallbackFacet(HiddenTypeFacet.class)) { - FacetUtil.addFacetIfPresent(NavigationFacetFromHiddenType.create(navigatedType, facetHolder)); + if(navigatedType.containsNonFallbackFacet(HiddenFacetForNoMembersAuthorized.class)) { + FacetUtil.addFacetIfPresent(HiddenFacetForNavigationFromHiddenType.create(navigatedType, facetHolder)); } } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java index d286c6f943a..06423d74062 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java @@ -51,7 +51,7 @@ import org.apache.causeway.core.metamodel.CausewayModuleCoreMetamodel; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facets.SingleIntValueFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet; import org.apache.causeway.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet; import org.apache.causeway.core.metamodel.facets.properties.update.modify.PropertySetterFacet; @@ -359,7 +359,7 @@ protected boolean exclude(final ObjectSpecification spec) { } protected boolean isHidden(final ObjectSpecification spec) { - return HiddenFacet.isAlwaysHidden(spec); + return HiddenFacetForLayout.isAlwaysHidden(spec); } protected boolean isBuiltIn(final ObjectSpecification spec) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/metamodel/DomainMemberDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/metamodel/DomainMemberDefault.java index 1042dfc5284..e69ab7abc55 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/metamodel/DomainMemberDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/services/metamodel/DomainMemberDefault.java @@ -37,7 +37,7 @@ import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facets.ImperativeFacet; import org.apache.causeway.core.metamodel.facets.actions.validate.ActionValidationFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.members.disabled.DisabledFacet; import org.apache.causeway.core.metamodel.facets.param.autocomplete.ActionParameterAutoCompleteFacet; import org.apache.causeway.core.metamodel.facets.param.choices.ActionParameterChoicesFacet; @@ -164,7 +164,7 @@ public String getMixin() { @XmlElement @Override public String getHidden() { - return interpret(HiddenFacet.class); + return interpret(HiddenFacetForLayout.class); } @XmlElement @Override @@ -271,7 +271,7 @@ private static String interpretFacet(final Facet facet) { } if (facet instanceof ImperativeFacet) { ImperativeFacet imperativeFacet = (ImperativeFacet) facet; - return imperativeFacet.getMethods().getFirstElseFail().getName(); + return imperativeFacet.methods().getFirstElseFail().getName(); } final String name = facet.getClass().getSimpleName(); if (ignore(name)) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java index d2ecdd8ca1a..9eaa0d7df9a 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/ObjectSpecification.java @@ -26,6 +26,7 @@ import java.util.Optional; import java.util.stream.Stream; +import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.apache.causeway.applib.annotation.DomainObject; @@ -50,7 +51,7 @@ import org.apache.causeway.core.metamodel.facetapi.HasFacetHolder; import org.apache.causeway.core.metamodel.facets.all.described.ObjectDescribedFacet; import org.apache.causeway.core.metamodel.facets.all.help.HelpFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.all.i8n.noun.HasNoun; import org.apache.causeway.core.metamodel.facets.all.i8n.staatic.HasStaticText; import org.apache.causeway.core.metamodel.facets.all.named.ObjectNamedFacet; @@ -78,7 +79,6 @@ import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociationContainer; import org.apache.causeway.core.metamodel.spec.feature.ObjectMember; -import org.jspecify.annotations.NonNull; import lombok.experimental.UtilityClass; /** @@ -301,24 +301,24 @@ ObjectTitleContext createTitleInteractionContext( // internal API ObjectValidityContext createValidityInteractionContext( - final ManagedObject targetAdapter, - final InteractionInitiatedBy interactionInitiatedBy); + ManagedObject targetAdapter, + InteractionInitiatedBy interactionInitiatedBy); /** * Determines whether the specified object is in a valid state (for example, * so can be persisted); represented as a {@link Consent}. */ Consent isValid( - final ManagedObject targetAdapter, - final InteractionInitiatedBy interactionInitiatedBy); + ManagedObject targetAdapter, + InteractionInitiatedBy interactionInitiatedBy); /** * Determines whether the specified object is in a valid state (for example, * so can be persisted); represented as a {@link InteractionResult}. */ InteractionResult isValidResult( - final ManagedObject targetAdapter, - final InteractionInitiatedBy interactionInitiatedBy); + ManagedObject targetAdapter, + InteractionInitiatedBy interactionInitiatedBy); // -- FACETS @@ -391,7 +391,7 @@ default boolean isValueOrIsParented() { boolean isImmutable(); /** - * Whether has the {@link HiddenFacet} + * Whether has the {@link HiddenFacetForLayout} */ boolean isHidden(); @@ -515,14 +515,12 @@ default boolean isEntityOrViewModelOrAbstract() { */ default Object instantiatePojo() { final Class correspondingClass = getCorrespondingClass(); - if (correspondingClass.isArray()) { - return Array.newInstance(correspondingClass.getComponentType(), 0); - } + if (correspondingClass.isArray()) + return Array.newInstance(correspondingClass.getComponentType(), 0); final Class cls = correspondingClass; - if (Modifier.isAbstract(cls.getModifiers())) { - throw new UnrecoverableException("Cannot create an instance of an abstract class: " + cls); - } + if (Modifier.isAbstract(cls.getModifiers())) + throw new UnrecoverableException("Cannot create an instance of an abstract class: " + cls); final Object newInstance; try { @@ -590,9 +588,8 @@ default public void assertPojoCompatible(final @Nullable Object pojo) { default public boolean isAssignableFrom(final Class actualType) { var expectedType = getCorrespondingClass(); if(expectedType.isAssignableFrom(actualType) - || ClassExtensions.equalsWhenBoxing(expectedType, actualType)) { - return true; - } + || ClassExtensions.equalsWhenBoxing(expectedType, actualType)) + return true; return false; } @@ -603,9 +600,8 @@ default public boolean isPojoCompatible(final Object pojo) { var actualType = pojo.getClass(); if(expectedType.isAssignableFrom(actualType) - || ClassExtensions.equalsWhenBoxing(expectedType, actualType)) { - return true; - } + || ClassExtensions.equalsWhenBoxing(expectedType, actualType)) + return true; var elementSpec = getElementSpecification() .orElse(this); @@ -646,12 +642,10 @@ public static ObjectSpecification commonSuperType( var cls_a = a.getCorrespondingClass(); var cls_b = b.getCorrespondingClass(); - if(cls_a.isAssignableFrom(cls_b)) { - return a; - } - if(cls_b.isAssignableFrom(cls_a)) { - return b; - } + if(cls_a.isAssignableFrom(cls_b)) + return a; + if(cls_b.isAssignableFrom(cls_a)) + return b; // assuming the algorithm is correct: if non of the above is true, // we must be able to walk up the tree on both branches _Assert.assertNotNull(a.superclass()); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/HasObjectAction.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/HasObjectAction.java index 2729dd71e34..d301ce18af7 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/HasObjectAction.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/HasObjectAction.java @@ -25,7 +25,6 @@ import org.jspecify.annotations.NonNull; import org.apache.causeway.applib.annotation.SemanticsOf; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.collections.CanVector; import org.apache.causeway.core.metamodel.consent.Consent; @@ -34,6 +33,8 @@ import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facetapi.FeatureType; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.ActionScope; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; @@ -55,11 +56,11 @@ public interface HasObjectAction extends ObjectAction { @Override default boolean isAlwaysHidden() { return getObjectAction().isAlwaysHidden(); } - @Override default Consent isVisible(final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, final Where where) { - return getObjectAction().isVisible(target, interactionInitiatedBy, where); + @Override default Consent isVisible(final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, final VisibilityConstraint visConstraint) { + return getObjectAction().isVisible(target, interactionInitiatedBy, visConstraint); } - @Override default Consent isUsable(final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, final Where where) { - return getObjectAction().isUsable(target, interactionInitiatedBy, where); + @Override default Consent isUsable(final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, final VisibilityConstraint visConstraint) { + return getObjectAction().isUsable(target, interactionInitiatedBy, visConstraint); } @Override default boolean isPropertyOrCollection() { return getObjectAction().isPropertyOrCollection(); @@ -129,12 +130,12 @@ default FacetHolder getFacetHolder() { return getObjectAction().hasReturn(); } @Override default ManagedObject executeWithRuleChecking(final InteractionHead head, final Can parameters, - final InteractionInitiatedBy interactionInitiatedBy, final Where where) throws AuthorizationException { - return getObjectAction().executeWithRuleChecking(head, parameters, interactionInitiatedBy, where); + final InteractionInitiatedBy interactionInitiatedBy, final VisibilityConstraint visibilityConstraint) throws AuthorizationException { + return getObjectAction().executeWithRuleChecking(head, parameters, interactionInitiatedBy, visibilityConstraint); } @Override default ManagedObject execute(final InteractionHead head, final Can parameters, - final InteractionInitiatedBy interactionInitiatedBy) { - return getObjectAction().execute(head, parameters, interactionInitiatedBy); + final InteractionInitiatedBy interactionInitiatedBy, final WhatViewer whatViewer) { + return getObjectAction().execute(head, parameters, interactionInitiatedBy, whatViewer); } @Override default Consent isArgumentSetValid(final InteractionHead head, final Can proposedArguments, final InteractionInitiatedBy interactionInitiatedBy) { 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 993c9537233..cb52e9d0b8c 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 @@ -43,12 +43,14 @@ 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.all.hide.HiddenFacetForLayout; 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; import org.apache.causeway.core.metamodel.facets.object.promptStyle.PromptStyleFacet; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteractionHead; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.ManagedObjects; @@ -104,7 +106,7 @@ ManagedObject executeWithRuleChecking( InteractionHead head, Can parameters, InteractionInitiatedBy interactionInitiatedBy, - Where where) throws AuthorizationException; + VisibilityConstraint visibilityConstraint) throws AuthorizationException; /** * Invokes the action's method on the target object given the specified set @@ -117,7 +119,8 @@ ManagedObject executeWithRuleChecking( ManagedObject execute( InteractionHead head, Can parameters, - InteractionInitiatedBy interactionInitiatedBy); + InteractionInitiatedBy interactionInitiatedBy, + WhatViewer whatViewer); // -- isArgumentSetValid, isArgumentSetValidForParameters, isArgumentSetValidForAction @@ -271,10 +274,9 @@ default PromptStyle getPromptStyle() { // whereas for INLINE it would render a form with no fields || getParameterCount() == 0) { if (promptStyle.isPresent()) { - if (promptStyle.get().isDialogAny()) { - // preserve dialog specialization + if (promptStyle.get().isDialogAny()) + // preserve dialog specialization return promptStyle.get(); - } } // fallback to generic dialog return PromptStyle.DIALOG; @@ -283,16 +285,13 @@ default PromptStyle getPromptStyle() { var needsFallback = promptStyle.isEmpty() || promptStyle.get() == PromptStyle.AS_CONFIGURED; - if(needsFallback) { - // modal vs side-bar - switch (getWicketViewerSettings().dialogMode()) { - case SIDEBAR: - return PromptStyle.DIALOG_SIDEBAR; - case MODAL: - default: - return PromptStyle.DIALOG_MODAL; - } - } + if(needsFallback) + // modal vs side-bar + return switch (getWicketViewerSettings().dialogMode()) { + case SIDEBAR -> PromptStyle.DIALOG_SIDEBAR; + case MODAL -> PromptStyle.DIALOG_MODAL; + default -> PromptStyle.DIALOG_MODAL; + }; return promptStyle.get(); } @@ -309,9 +308,8 @@ public static boolean returnsBlobOrClob(final ObjectAction objectAction) { if (returnType != null) { Class cls = returnType.getCorrespondingClass(); if (Blob.class.isAssignableFrom(cls) - || Clob.class.isAssignableFrom(cls)) { - return true; - } + || Clob.class.isAssignableFrom(cls)) + return true; } return false; } @@ -320,18 +318,15 @@ public static boolean isDirectlyAssociatedWithAnyProperty( final ObjectAction action) { var layoutGroupFacet = action.getFacet(LayoutGroupFacet.class); - if (layoutGroupFacet == null) { - return false; - } + if (layoutGroupFacet == null) + return false; var layoutGroupId = layoutGroupFacet.getGroupId(); - if (_Strings.isNullOrEmpty(layoutGroupId)) { - return false; - } + if (_Strings.isNullOrEmpty(layoutGroupId)) + return false; var prop = action.getDeclaringType().getProperty(layoutGroupId, MixedIn.INCLUDED) .orElse(null); - if (prop == null) { - return false; - } + if (prop == null) + return false; return true; } @@ -363,9 +358,10 @@ public static Optional cssClassFaFactoryFor( /** * Returns a Stream of those to be rendered with the entity header panel. + * @param whatViewer */ public static Stream streamTopBarActions( - final ManagedObject adapter) { + final ManagedObject adapter, final WhatViewer whatViewer) { var spec = adapter.objSpec(); @@ -374,7 +370,7 @@ public static Stream streamTopBarActions( .isSharingAnyLayoutGroupOf(spec.streamAssociations(MixedIn.INCLUDED)) .negate()) .filter(Predicates - .dynamicallyVisible(adapter, InteractionInitiatedBy.USER, Where.ANYWHERE)); + .dynamicallyVisible(adapter, InteractionInitiatedBy.USER, new VisibilityConstraint(whatViewer, Where.ANYWHERE))); } public static Stream findForAssociation( @@ -388,15 +384,13 @@ public static Stream findForAssociation( public static PromptStyle promptStyleFor(final ObjectAction objectAction) { PromptStyleFacet facet = objectAction.getFacet(PromptStyleFacet.class); - if(facet == null) { - // don't think this can occur, see PromptStyleFallback + if(facet == null) + // don't think this can occur, see PromptStyleFallback return PromptStyle.INLINE; - } final PromptStyle promptStyle = facet.value(); - if(promptStyle == PromptStyle.AS_CONFIGURED) { - // don't think this can occur, see PromptStyleConfiguration + if(promptStyle == PromptStyle.AS_CONFIGURED) + // don't think this can occur, see PromptStyleConfiguration return PromptStyle.INLINE; - } return promptStyle; } @@ -436,13 +430,11 @@ public static Predicate isSameLayoutGroupAs( return (final ObjectAction objectAction) -> { var layoutGroupFacet = objectAction.getFacet(LayoutGroupFacet.class); - if (layoutGroupFacet == null) { - return false; - } + if (layoutGroupFacet == null) + return false; var layoutGroupId = layoutGroupFacet.getGroupId(); - if (_Strings.isNullOrEmpty(layoutGroupId)) { - return false; - } + if (_Strings.isNullOrEmpty(layoutGroupId)) + return false; return layoutGroupId.equals(memberId); }; } @@ -457,13 +449,11 @@ private static Predicate isSharingAnyLayoutGroupOf( return (final ObjectAction objectAction) -> { var layoutGroupFacet = objectAction.getFacet(LayoutGroupFacet.class); - if (layoutGroupFacet == null) { - return false; - } + if (layoutGroupFacet == null) + return false; var layoutGroupId = layoutGroupFacet.getGroupId(); - if (_Strings.isNullOrEmpty(layoutGroupId)) { - return false; - } + if (_Strings.isNullOrEmpty(layoutGroupId)) + return false; return associationIds.contains(layoutGroupId); }; } @@ -480,10 +470,10 @@ public static Predicate choicesFromAndHavingCollectionParameterFor } /** - * Returns true if no {@link HiddenFacet} is found that vetoes visibility. + * Returns true if no {@link HiddenFacetForLayout} is found that vetoes visibility. *

* However, whereHidden={@link Where#ALL_TABLES} is used as default - * when no {@link HiddenFacet} is found. + * when no {@link HiddenFacetForLayout} is found. * * @see ObjectAssociation.Predicates#visibleAccordingToHiddenFacet(Where) * @@ -491,7 +481,7 @@ public static Predicate choicesFromAndHavingCollectionParameterFor * however the current approach is more heap friendly */ public static Predicate visibleAccordingToHiddenFacet(final Where whereContext) { - return (final ObjectAction act) -> act.lookupFacet(HiddenFacet.class) + return (final ObjectAction act) -> act.lookupFacet(HiddenFacetForLayout.class) .map(WhereValueFacet.class::cast) .map(WhereValueFacet::where) // whereHidden=ALL_TABLES is the default when not specified otherwise @@ -512,13 +502,11 @@ public HasChoicesFrom(final @NonNull ObjectAssociation objectAssociation) { @Override public boolean test(final ObjectAction objectAction) { var choicesFromFacet = objectAction.getFacet(ChoicesFromFacet.class); - if(choicesFromFacet == null) { - return false; - } + if(choicesFromFacet == null) + return false; var choicesFromMemberName = choicesFromFacet.value(); - if (choicesFromMemberName == null) { - return false; - } + if (choicesFromMemberName == null) + return false; var memberNameLowerCase = choicesFromMemberName.toLowerCase(); return Objects.equals(memberId, memberNameLowerCase); } @@ -541,12 +529,9 @@ public boolean test(final ObjectAction objectAction) { private static Predicate dynamicallyVisible( final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { - return (final ObjectAction objectAction) -> { - final Consent visible = objectAction.isVisible(target, interactionInitiatedBy, where); - return visible.isAllowed(); - }; + return (final ObjectAction objectAction) -> objectAction.isVisible(target, interactionInitiatedBy, visibilityConstraint).isAllowed(); } } 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 55204ee56d3..e6562079b7c 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 @@ -29,7 +29,7 @@ import org.apache.causeway.commons.internal.functions._Predicates; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.facets.WhereValueFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.util.Facets; @@ -139,7 +139,7 @@ private Predicates(){} public static Predicate staticallyVisible(final Where where) { return assoc -> { var b = assoc.streamFacets() - .filter(facet -> facet instanceof HiddenFacet) + .filter(facet -> facet instanceof HiddenFacetForLayout) .map(facet -> (WhereValueFacet) facet) .anyMatch(wawF -> wawF.where().includes(where)); return !b; @@ -147,10 +147,10 @@ public static Predicate staticallyVisible(final Where where) } /** - * Returns true if no {@link HiddenFacet} is found that vetoes visibility. + * Returns true if no {@link HiddenFacetForLayout} is found that vetoes visibility. *

* However, if it's a 1-to-Many, whereHidden={@link Where#ALL_TABLES} is used as default - * when no {@link HiddenFacet} is found. + * when no {@link HiddenFacetForLayout} is found. * * @see ObjectAction.Predicates#visibleAccordingToHiddenFacet(Where) * @@ -158,7 +158,7 @@ public static Predicate staticallyVisible(final Where where) * however the current approach is more heap friendly */ public static Predicate visibleAccordingToHiddenFacet(final Where whereContext) { - return (final ObjectAssociation assoc) -> assoc.lookupFacet(HiddenFacet.class) + return (final ObjectAssociation assoc) -> assoc.lookupFacet(HiddenFacetForLayout.class) .map(WhereValueFacet.class::cast) .map(WhereValueFacet::where) // in case it's a 1-to-Many, whereHidden=ALL_TABLES is the default when not specified otherwise diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectMember.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectMember.java index d463c5c656d..2dec105f634 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectMember.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/ObjectMember.java @@ -35,10 +35,11 @@ import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facetapi.FacetUtil; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.collections.sortedby.SortedByFacet; import org.apache.causeway.core.metamodel.facets.object.paged.PagedFacet; import org.apache.causeway.core.metamodel.facets.object.tabledec.TableDecoratorFacet; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.MmSortUtils; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; @@ -60,10 +61,6 @@ public interface ObjectMember extends ObjectFeature { */ ObjectSpecification getDeclaringType(); - // ///////////////////////////////////////////////////////////// - // Name, Description, Help (convenience for facets) - // ///////////////////////////////////////////////////////////// - /** * Return the help text for this member - the field or action - to * complement the description. @@ -72,16 +69,12 @@ public interface ObjectMember extends ObjectFeature { */ String getHelp(); - // ///////////////////////////////////////////////////////////// - // Hidden (or visible) - // ///////////////////////////////////////////////////////////// - /** * When the member is always hidden. * *

- * Determined as per the {@link HiddenFacet} being present and - * {@link HiddenFacet#where()} returning {@link Where#ANYWHERE}. + * Determined as per the {@link HiddenFacetForLayout} being present and + * {@link HiddenFacetForLayout#where()} returning {@link Where#ANYWHERE}. */ boolean isAlwaysHidden(); @@ -93,13 +86,9 @@ public interface ObjectMember extends ObjectFeature { * @param where */ Consent isVisible( - final ManagedObject target, - final InteractionInitiatedBy interactionInitiatedBy, - final Where where); - - // ///////////////////////////////////////////////////////////// - // Disabled (or enabled) - // ///////////////////////////////////////////////////////////// + ManagedObject target, + InteractionInitiatedBy interactionInitiatedBy, + VisibilityConstraint visibilityConstraint); /** * Determines whether this member is usable (not disabled), represented as a @@ -107,16 +96,12 @@ Consent isVisible( * @param target * may be null if just checking for authorization. * @param interactionInitiatedBy - * @param where + * @param visibilityConstraint only ever used for debugging while prototyping */ Consent isUsable( - final ManagedObject target, - final InteractionInitiatedBy interactionInitiatedBy, - final Where where); - - // ///////////////////////////////////////////////////////////// - // isAssociation, isAction - // ///////////////////////////////////////////////////////////// + ManagedObject target, + InteractionInitiatedBy interactionInitiatedBy, + VisibilityConstraint visibilityConstraint); /** * Whether this member represents a {@link ObjectAssociation}. @@ -166,9 +151,7 @@ default boolean isMixedIn() { */ boolean isExplicitlyAnnotated(); - // ///////////////////////////////////////////////////////////// - // Debugging - // ///////////////////////////////////////////////////////////// + // -- DEBUGGING /** * Thrown if the user is not authorized to access an action or any property/collection of an entity. @@ -276,9 +259,8 @@ default Optional> getElementComparator(){ .map(SortedByFacet::value) .orElse(null); - if(sortedBy == null) { - return Optional.empty(); - } + if(sortedBy == null) + return Optional.empty(); var pojoComparator = _Casts.>uncheckedCast( _InstanceUtil.createInstance(sortedBy)); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionDefault.java index e8bc2ace6cb..df4278d9a92 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionDefault.java @@ -30,7 +30,6 @@ import org.apache.causeway.applib.annotation.Action; import org.apache.causeway.applib.annotation.ActionLayout; import org.apache.causeway.applib.annotation.SemanticsOf; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.exceptions.RecoverableException; import org.apache.causeway.applib.services.bookmark.Bookmark; import org.apache.causeway.applib.services.command.Command; @@ -48,11 +47,14 @@ import org.apache.causeway.core.metamodel.facetapi.FeatureType; import org.apache.causeway.core.metamodel.facets.FacetedMethod; import org.apache.causeway.core.metamodel.facets.actions.action.invocation.ActionInvocationFacet; -import org.apache.causeway.core.metamodel.facets.actions.prototype.PrototypeFacet; +import org.apache.causeway.core.metamodel.facets.actions.prototype.HiddenFacetForDeploymentType; import org.apache.causeway.core.metamodel.facets.actions.semantics.ActionSemanticsFacet; import org.apache.causeway.core.metamodel.facets.param.choices.ActionParameterChoicesFacet; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.InteractionUtils; +import org.apache.causeway.core.metamodel.interactions.RenderPolicy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.interactions.use.ActionUsabilityContext; import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; import org.apache.causeway.core.metamodel.interactions.val.ActionValidityContext; @@ -77,9 +79,8 @@ class ObjectActionDefault public static ActionScope getType(final String typeStr) { final ActionScope type = ActionScope.valueOf(typeStr); - if (type == null) { - throw new IllegalArgumentException(); - } + if (type == null) + throw new IllegalArgumentException(); return type; } @@ -134,9 +135,8 @@ private ObjectSpecification loadDeclaringType() { .map(ActionInvocationFacet::getDeclaringType); // JUnit support if(testing - && declaringType.isEmpty()) { - return specLoaderInternal().loadSpecification(getFacetedMethod().methodFacade().getDeclaringClass()); - } + && declaringType.isEmpty()) + return specLoaderInternal().loadSpecification(getFacetedMethod().methodFacade().getDeclaringClass()); return declaringType.orElseThrow(()->_Exceptions .illegalState("missing ActionInvocationFacet on action %s", getFeatureIdentifier())); } @@ -174,9 +174,8 @@ private ObjectSpecification loadReturnType() { .map(ActionInvocationFacet::getReturnType); // JUnit support if(testing - && returType.isEmpty()) { - return specLoaderInternal().loadSpecification(getFacetedMethod().methodFacade().getReturnType()); - } + && returType.isEmpty()) + return specLoaderInternal().loadSpecification(getFacetedMethod().methodFacade().getReturnType()); return returType.orElseThrow(()->_Exceptions .illegalState("framework bug: missing ActionInvocationFacet on action %s", getFeatureIdentifier())); } @@ -187,10 +186,9 @@ private ObjectSpecification loadReturnType() { */ @Override public boolean hasReturn() { - if(getReturnType() == null) { - // this shouldn't happen; return Type always defined, even if represents void.class + if(getReturnType() == null) + // this shouldn't happen; return Type always defined, even if represents void.class return false; - } return !getReturnType().isVoidPrimitive(); } @@ -202,7 +200,7 @@ public ActionScope getScope() { } private static ActionScope getScope(final FacetHolder facetHolder) { - return facetHolder.containsFacet(PrototypeFacet.class) + return facetHolder.containsFacet(HiddenFacetForDeploymentType.class) ? ActionScope.PROTOTYPE : ActionScope.PRODUCTION; } @@ -268,10 +266,9 @@ public Can getParameters(final Predicate= parameters.size()) { - throw new IllegalArgumentException( + if (position >= parameters.size()) + throw new IllegalArgumentException( "getParameter(int): only " + parameters.size() + " parameters, position=" + position); - } return parameters.getElseFail(position); } @@ -281,14 +278,14 @@ ObjectActionParameter getParameter(final int position) { public VisibilityContext createVisibleInteractionContext( final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { return new ActionVisibilityContext( headFor(target), this, getFeatureIdentifier(), interactionInitiatedBy, - where, - InteractionUtils.renderPolicy(target)); + visibilityConstraint, + RenderPolicy.forNonActionParam(target)); } // -- USABLE @@ -296,15 +293,13 @@ public VisibilityContext createVisibleInteractionContext( @Override public UsabilityContext createUsableInteractionContext( final ManagedObject target, - final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final InteractionInitiatedBy interactionInitiatedBy) { return new ActionUsabilityContext( headFor(target), this, getFeatureIdentifier(), interactionInitiatedBy, - where, - InteractionUtils.renderPolicy(target)); + RenderPolicy.forNonActionParam(target)); } // -- VALIDATE @@ -396,33 +391,30 @@ ActionValidityContext createActionInvocationInteractionContext( // -- EXECUTE @Override - public ManagedObject executeWithRuleChecking( + public final ManagedObject executeWithRuleChecking( final InteractionHead head, final Can arguments, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { var target = head.owner(); // see it? - final Consent visibility = isVisible(target, interactionInitiatedBy, where); - if (visibility.isVetoed()) { - throw new HiddenException(); - } + final Consent visibility = isVisible(target, interactionInitiatedBy, visibilityConstraint); + if (visibility.isVetoed()) + throw new HiddenException(); // use it? - final Consent usability = isUsable(target, interactionInitiatedBy, where); - if(usability.isVetoed()) { - throw new DisabledException(usability.getReasonAsString().orElse("no reason given")); - } + final Consent usability = isUsable(target, interactionInitiatedBy, visibilityConstraint); + if(usability.isVetoed()) + throw new DisabledException(usability.getReasonAsString().orElse("no reason given")); // do it? final Consent validity = isArgumentSetValid(head, arguments, interactionInitiatedBy); - if(validity.isVetoed()) { - throw new RecoverableException(validity.getReasonAsString().orElse("no reason given")); - } + if(validity.isVetoed()) + throw new RecoverableException(validity.getReasonAsString().orElse("no reason given")); - return execute(head, arguments, interactionInitiatedBy); + return execute(head, arguments, interactionInitiatedBy, visibilityConstraint.whatViewer()); } /** @@ -433,7 +425,8 @@ public ManagedObject executeWithRuleChecking( public ManagedObject execute( final InteractionHead head, final Can argumentAdapters, - final InteractionInitiatedBy interactionInitiatedBy) { + final InteractionInitiatedBy interactionInitiatedBy, + final WhatViewer whatViewer) { _Assert.assertEquals(this.getParameterCount(), argumentAdapters.size(), "action's parameter count and provided argument count must match"); @@ -455,7 +448,7 @@ public ManagedObject execute( } } - return this.executeInternal(head, argumentAdapters, interactionInitiatedBy); + return this.executeInternal(head, argumentAdapters, interactionInitiatedBy, whatViewer); } /** @@ -464,10 +457,11 @@ public ManagedObject execute( protected ManagedObject executeInternal( final InteractionHead head, final Can argumentAdapters, - final InteractionInitiatedBy interactionInitiatedBy) { + final InteractionInitiatedBy interactionInitiatedBy, + final WhatViewer whatViewer) { var actionInvocationFacet = getFacet(ActionInvocationFacet.class); return actionInvocationFacet - .invoke(this, head, argumentAdapters, interactionInitiatedBy); + .invoke(this, head, argumentAdapters, interactionInitiatedBy, whatViewer); } protected Optional getActionInvocationFacet() { @@ -530,9 +524,8 @@ public void setupCommand( final InteractionHead head, final Can argumentAdapters) { - if(head.owner().objSpec().isValue()) { - return; // do not record value type mixin actions - } + if(head.owner().objSpec().isValue()) + return; // do not record value type mixin actions setupCommand(head, interactionId->commandDtoFor(interactionId, head, argumentAdapters)); @@ -571,9 +564,8 @@ public FacetHolder getFacetHolder() { // -- HELPER protected String argsFor(final Can parameters, final Can arguments) { - if(parameters.size() != arguments.size()) { - return "???"; // shouldn't happen - } + if(parameters.size() != arguments.size()) + return "???"; // shouldn't happen return parameters.stream().map(IndexedFunction.zeroBased((i, param) -> { var id = param.getId(); var argStr = argStr(id, arguments, i); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionMixedIn.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionMixedIn.java index d878bd98e1c..ad20a0a7d4b 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionMixedIn.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionMixedIn.java @@ -36,6 +36,7 @@ import org.apache.causeway.core.metamodel.facets.all.named.MemberNamedFacet; import org.apache.causeway.core.metamodel.facets.all.named.MemberNamedFacetForStaticMemberName; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.MixedInAction; @@ -154,7 +155,8 @@ protected ManagedObject mixinAdapterFor(final ManagedObject mixeeAdapter) { public ManagedObject execute( final InteractionHead head, final Can argumentAdapters, - final InteractionInitiatedBy interactionInitiatedBy) { + final InteractionInitiatedBy interactionInitiatedBy, + final WhatViewer whatViewer) { final ManagedObject owner = head.owner(); final ManagedObject target = mixinAdapterFor(mixinSpec, owner); @@ -178,7 +180,8 @@ public ManagedObject execute( return mixinAction.executeInternal( head, argumentAdapters, - interactionInitiatedBy); + interactionInitiatedBy, + whatViewer); } @Override diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionParameterAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionParameterAbstract.java index 744b4aad4e3..b78e797df44 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionParameterAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectActionParameterAbstract.java @@ -21,6 +21,8 @@ import java.util.Optional; import java.util.function.Supplier; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.Identifier; import org.apache.causeway.applib.exceptions.unrecoverable.DomainModelException; import org.apache.causeway.commons.collections.Can; @@ -51,7 +53,6 @@ import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter; import lombok.Getter; -import org.jspecify.annotations.NonNull; abstract class ObjectActionParameterAbstract implements @@ -188,9 +189,8 @@ public Can getAutoComplete( final InteractionInitiatedBy interactionInitiatedBy) { var autoCompleteFacet = getFacet(ActionParameterAutoCompleteFacet.class); - if (autoCompleteFacet == null) { - return Can.empty(); - } + if (autoCompleteFacet == null) + return Can.empty(); var paramSpec = getElementType(); @@ -226,9 +226,8 @@ public Can getChoices( var paramSpec = getElementType(); var choicesFacet = getFacet(ActionParameterChoicesFacet.class); - if (choicesFacet == null) { - return Can.empty(); - } + if (choicesFacet == null) + return Can.empty(); var visibleChoices = choicesFacet.getChoices(paramSpec, pendingArgs.actionInteractionHead(), @@ -296,11 +295,10 @@ static void checkChoicesOrAutoCompleteType( // in other words is assignable from // TODO: should implement this instead as a MetaModelValidator (subject to [CAUSEWAY-3172]) - if (!choiceWrappedSpec.isOfType(paramWrappedSpec)) { - throw new DomainModelException(String.format( + if (!choiceWrappedSpec.isOfType(paramWrappedSpec)) + throw new DomainModelException(String.format( "Type incompatible with parameter type; expected %s, but was %s", paramSpec.getFullIdentifier(), choiceClass.getName())); - } } } @@ -318,7 +316,7 @@ head, parentAction, getFeatureIdentifier(), pendingArgs, position, interactionIn } @Override - public Consent isVisible( + public final Consent isVisible( final InteractionHead head, final Can pendingArgs, final InteractionInitiatedBy interactionInitiatedBy) { @@ -348,7 +346,7 @@ private ParamUsabilityContext createArgumentUsabilityContext( } @Override - public Consent isUsable( + public final Consent isUsable( final InteractionHead head, final Can pendingArgs, final InteractionInitiatedBy interactionInitiatedBy) { @@ -356,8 +354,9 @@ public Consent isUsable( var usabilityContext = createArgumentUsabilityContext( head, pendingArgs, getParameterIndex(), interactionInitiatedBy); - var usableResult = InteractionUtils.isUsableResult(this, usabilityContext); - return usableResult.createConsent(); + return InteractionUtils.isUsableResult(this, usabilityContext, ()->createArgumentVisibilityContext( + head, pendingArgs, getParameterIndex(), interactionInitiatedBy)) + .createConsent(); } // -- Validation @@ -374,7 +373,7 @@ public ParamValidityContext createProposedArgumentInteractionContext( } @Override - public Consent isValid( + public final Consent isValid( final InteractionHead head, final Can pendingArgs, final InteractionInitiatedBy interactionInitiatedBy) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectMemberAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectMemberAbstract.java index cd53c40cb7c..9572d448772 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectMemberAbstract.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectMemberAbstract.java @@ -26,6 +26,8 @@ import java.util.function.Function; import java.util.function.Supplier; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.Identifier; import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.iactn.InteractionProvider; @@ -42,7 +44,7 @@ import org.apache.causeway.core.metamodel.facets.HasFacetedMethod; import org.apache.causeway.core.metamodel.facets.all.described.MemberDescribedFacet; import org.apache.causeway.core.metamodel.facets.all.help.HelpFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.all.i8n.staatic.HasStaticText; import org.apache.causeway.core.metamodel.facets.all.named.MemberNamedFacet; import org.apache.causeway.core.metamodel.interactions.DisablingInteractionAdvisor; @@ -50,6 +52,7 @@ import org.apache.causeway.core.metamodel.interactions.InteractionContext; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.InteractionUtils; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.acc.AccessContext; import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; @@ -61,7 +64,6 @@ import org.apache.causeway.schema.cmd.v2.CommandDto; import lombok.Getter; -import org.jspecify.annotations.NonNull; abstract class ObjectMemberAbstract implements @@ -84,9 +86,8 @@ protected ObjectMemberAbstract( this.featureIdentifier = featureIdentifier; this.facetedMethod = facetedMethod; this.featureType = featureType; - if (getId() == null) { - throw new IllegalArgumentException("Id must always be set"); - } + if (getId() == null) + throw new IllegalArgumentException("Id must always be set"); } // -- IDENTIFIERS @@ -113,13 +114,12 @@ public final String getFriendlyName(final Supplier domainObjectPr var namedFacet = getFacet(MemberNamedFacet.class); - if(namedFacet==null) { - throw _Exceptions.unrecoverable("no MemberNamedFacet preset on %s", getFeatureIdentifier()); - } + if(namedFacet==null) + throw _Exceptions.unrecoverable("no MemberNamedFacet preset on %s", getFeatureIdentifier()); return namedFacet .getSpecialization() - .fold( textFacet->textFacet.translated(), + .fold( HasStaticText::translated, textFacet->textFacet.textElseNull(headFor(domainObjectProvider.get()).target())); } @@ -138,7 +138,7 @@ public final Optional getDescription(final Supplier domai return lookupFacet(MemberDescribedFacet.class) .map(MemberDescribedFacet::getSpecialization) .map(specialization->specialization - .fold(textFacet->textFacet.translated(), + .fold(HasStaticText::translated, textFacet->textFacet.textElseNull(headFor(domainObjectProvider.get()).target()))); } @@ -195,13 +195,13 @@ public final Optional getCanonicalDescription() { * {@link AccessContext} accesses) have no corresponding vetoing methods. */ protected abstract VisibilityContext createVisibleInteractionContext( - final ManagedObject target, - final InteractionInitiatedBy interactionInitiatedBy, - final Where where); + ManagedObject target, + InteractionInitiatedBy interactionInitiatedBy, + VisibilityConstraint visibilityConstraint); @Override public boolean isAlwaysHidden() { - return HiddenFacet.isAlwaysHidden(getFacetHolder()); + return HiddenFacetForLayout.isAlwaysHidden(getFacetHolder()); } /** @@ -209,12 +209,12 @@ public boolean isAlwaysHidden() { * returns true only if none hide the member. */ @Override - public Consent isVisible( + public final Consent isVisible( final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { - var visibilityContext = createVisibleInteractionContext(target, interactionInitiatedBy, where); + var visibilityContext = createVisibleInteractionContext(target, interactionInitiatedBy, visibilityConstraint); return InteractionUtils.isVisibleResult(this, visibilityContext).createConsent(); } @@ -230,22 +230,22 @@ public Consent isVisible( * {@link AccessContext} accesses) have no corresponding vetoing methods. */ protected abstract UsabilityContext createUsableInteractionContext( - final ManagedObject target, - final InteractionInitiatedBy interactionInitiatedBy, - final Where where); + ManagedObject target, + InteractionInitiatedBy interactionInitiatedBy); /** * Loops over all {@link DisablingInteractionAdvisor} {@link Facet}s and * returns true only if none disables the member. */ @Override - public Consent isUsable( + public final Consent isUsable( final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { - var usabilityContext = createUsableInteractionContext(target, interactionInitiatedBy, where); - return InteractionUtils.isUsableResult(this, usabilityContext).createConsent(); + var usabilityContext = createUsableInteractionContext(target, interactionInitiatedBy); + return InteractionUtils.isUsableResult(this, usabilityContext, ()->createVisibleInteractionContext(target, interactionInitiatedBy, visibilityConstraint)) + .createConsent(); } // -- PREDICATES @@ -277,9 +277,8 @@ protected ManagedObject mixinAdapterFor( final @NonNull ManagedObject mixee) { // nullable for action parameter mixins - if(ManagedObjects.isNullOrUnspecifiedOrEmpty(mixee)) { - return ManagedObject.empty(mixinSpec); - } + if(ManagedObjects.isNullOrUnspecifiedOrEmpty(mixee)) + return ManagedObject.empty(mixinSpec); var mixinPojo = getFactoryService().mixin(mixinSpec.getCorrespondingClass(), mixee.getPojo()); return ManagedObject.mixin(mixinSpec, mixinPojo); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java index 381916f1a51..f6ecd455d5e 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ObjectSpecificationDefault.java @@ -75,7 +75,7 @@ import org.apache.causeway.core.metamodel.facets.actcoll.typeof.TypeOfFacet; import org.apache.causeway.core.metamodel.facets.all.described.ObjectDescribedFacet; import org.apache.causeway.core.metamodel.facets.all.help.HelpFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.all.named.MemberNamedFacet; import org.apache.causeway.core.metamodel.facets.all.named.MemberNamedFacetForStaticMemberName; import org.apache.causeway.core.metamodel.facets.all.named.ObjectNamedFacet; @@ -165,7 +165,7 @@ public ObjectSpecificationDefault( // naturally supports attribute inheritance from the type's hierarchy this.introspectionPolicy = this.lookupFacet(IntrospectionPolicyFacet.class) - .map(introspectionPolicyFacet->introspectionPolicyFacet.getIntrospectionPolicy()) + .map(IntrospectionPolicyFacet::getIntrospectionPolicy) .orElseGet(()->mmc.getConfiguration().core().metaModel().introspector().policy()); this.facetedMethodsBuilder = @@ -273,13 +273,12 @@ private Stream createAssociations() { } private ObjectAssociation createAssociation(final FacetedMethod facetMethod) { - if (facetMethod.featureType().isCollection()) { - return OneToManyAssociationDefault.forMethod(facetMethod); - } else if (facetMethod.featureType().isProperty()) { - return OneToOneAssociationDefault.forMethod(facetMethod); - } else { - return null; - } + if (facetMethod.featureType().isCollection()) + return OneToManyAssociationDefault.forMethod(facetMethod); + else if (facetMethod.featureType().isProperty()) + return OneToOneAssociationDefault.forMethod(facetMethod); + else + return null; } private Stream createActions() { @@ -302,9 +301,8 @@ private ObjectAction createAction(final FacetedMethod facetedMethod) { return this.isMixin() ? ObjectActionDefault.forMixinMain(facetedMethod) : ObjectActionDefault.forMethod(facetedMethod); - } else { - return null; - } + } else + return null; } // -- getObjectAction @@ -352,7 +350,7 @@ private void cataloguePropertiesAndCollections(final BiConsumer field.streamFacets(ImperativeFacet.class) - .map(ImperativeFacet::getMethods) + .map(ImperativeFacet::methods) .flatMap(Can::stream) .map(MethodFacade::asMethodElseFail) // expected regular .peek(method->_Reflect.guardAgainstSynthetic(method.method())) // expected non-synthetic @@ -363,7 +361,7 @@ private void catalogueActions(final BiConsumer onM streamDeclaredActions(MixedIn.INCLUDED) .forEach(userAction-> userAction.streamFacets(ImperativeFacet.class) - .map(ImperativeFacet::getMethods) + .map(ImperativeFacet::methods) .flatMap(Can::stream) .map(MethodFacade::asMethodForIntrospection) .peek(method->_Reflect.guardAgainstSynthetic(method.method())) // expected non-synthetic @@ -375,7 +373,7 @@ private void catalogueActions(final BiConsumer onM private final _Lazy> elementSpecification = _Lazy.threadSafe(()->lookupFacet(TypeOfFacet.class) - .map(typeOfFacet -> typeOfFacet.elementSpec())); + .map(TypeOfFacet::elementSpec)); @Override public Optional getElementSpecification() { @@ -555,7 +553,7 @@ public final String getFullIdentifier() { } @Override - public void introspect(IntrospectionRequest request) { + public void introspect(final IntrospectionRequest request) { switch (request) { case REGISTER -> introspectUpTo(IntrospectionState.NOT_INTROSPECTED, ()->"introspect(%s)".formatted(request)); @@ -592,7 +590,7 @@ enum IntrospectionState { /** * @param introspectionContextProvider keeps track of the causal chain of introspection requests */ - private void introspectUpTo(final IntrospectionState upTo, Supplier introspectionContextProvider) { + private void introspectUpTo(final IntrospectionState upTo, final Supplier introspectionContextProvider) { if(!isLessThan(upTo)) return; // optimization if(log.isDebugEnabled()) { @@ -645,9 +643,8 @@ private boolean isLessThan(final IntrospectionState upTo) { } protected void loadSpecOfSuperclass(final Class superclass) { - if (superclass == null) { - return; - } + if (superclass == null) + return; superclassSpec = specLoaderInternal().loadSpecification(superclass); if (superclassSpec != null) { if (log.isDebugEnabled()) { @@ -803,7 +800,7 @@ public Can getAliases() { // -- ICON @Override - public Optional getIcon(final ManagedObject domainObject, ObjectSupport.IconSize iconSize) { + public Optional getIcon(final ManagedObject domainObject, final ObjectSupport.IconSize iconSize) { if(ManagedObjects.isSpecified(domainObject)) { _Assert.assertEquals(domainObject.objSpec(), this); } @@ -849,7 +846,7 @@ public boolean isOfTypeResolvePrimitive(final ObjectSpecification other) { @Override public String getSingularName() { return lookupFacet(ObjectNamedFacet.class) - .flatMap(textFacet->textFacet.translated()) + .flatMap(ObjectNamedFacet::translated) // unexpected code reach, however keep for JUnit testing .orElseGet(()->String.format( "(%s has neither title- nor object-named-facet)", @@ -920,12 +917,10 @@ private static class NotANoopFacetFilter implements Predicate interfaces() { @Override public Can subclasses(final Depth depth) { - if (depth == Depth.DIRECT) { - return directSubclasses.snapshot(); - } + if (depth == Depth.DIRECT) + return directSubclasses.snapshot(); // depth == Depth.TRANSITIVE) if (transitiveSubclasses == null) { @@ -1061,9 +1055,8 @@ public Stream streamDeclaredActions( * Creates all mixed in properties and collections for this spec. */ private Stream createMixedInAssociations() { - if (isInjectable() || isValue()) { - return Stream.empty(); - } + if (isInjectable() || isValue()) + return Stream.empty(); return getCausewayBeanTypeRegistry().streamMixinTypes() .flatMap(this::createMixedInAssociation); } @@ -1072,17 +1065,14 @@ private Stream createMixedInAssociation(final Class mixinT var mixinSpec = specLoaderInternal().loadSpecification(mixinType, IntrospectionRequest.FULL); if (mixinSpec == null - || mixinSpec == this) { - return Stream.empty(); - } + || mixinSpec == this) + return Stream.empty(); var mixinFacet = mixinSpec.mixinFacet().orElse(null); - if(mixinFacet == null) { - // this shouldn't happen; to be covered by meta-model validation later + if(mixinFacet == null) + // this shouldn't happen; to be covered by meta-model validation later return Stream.empty(); - } - if(!mixinFacet.isMixinFor(getCorrespondingClass())) { - return Stream.empty(); - } + if(!mixinFacet.isMixinFor(getCorrespondingClass())) + return Stream.empty(); var mixinMethodName = mixinFacet.getMainMethodName(); return mixinSpec.streamActions(ActionScope.ANY, MixedIn.EXCLUDED) @@ -1106,22 +1096,18 @@ private Stream createMixedInAction(final Class mixinType var mixinSpec = specLoaderInternal().loadSpecification(mixinType, IntrospectionRequest.FULL); if (mixinSpec == null - || mixinSpec == this) { - return Stream.empty(); - } + || mixinSpec == this) + return Stream.empty(); var mixinFacet = mixinSpec.mixinFacet().orElse(null); - if(mixinFacet == null) { - // this shouldn't happen; to be covered by meta-model validation later - return Stream.empty(); - } - if(!mixinFacet.isMixinFor(getCorrespondingClass())) { + if(mixinFacet == null) + // this shouldn't happen; to be covered by meta-model validation later return Stream.empty(); - } + if(!mixinFacet.isMixinFor(getCorrespondingClass())) + return Stream.empty(); // don't mixin Object_ mixins to domain services if(getBeanSort().isManagedBeanContributing() - && mixinFacet.isMixinFor(java.lang.Object.class)) { - return Stream.empty(); - } + && mixinFacet.isMixinFor(java.lang.Object.class)) + return Stream.empty(); var mixinMethodName = mixinFacet.getMainMethodName(); @@ -1152,7 +1138,6 @@ private boolean whenIsValueThenIsAlsoConstructorMixin(final ObjectAction act) { public Consent isValid( final ManagedObject targetAdapter, final InteractionInitiatedBy interactionInitiatedBy) { - return isValidResult(targetAdapter, interactionInitiatedBy).createConsent(); } @@ -1160,9 +1145,7 @@ public Consent isValid( public InteractionResult isValidResult( final ManagedObject targetAdapter, final InteractionInitiatedBy interactionInitiatedBy) { - var validityContext = - createValidityInteractionContext( - targetAdapter, interactionInitiatedBy); + var validityContext = createValidityInteractionContext(targetAdapter, interactionInitiatedBy); return InteractionUtils.isValidResult(this, validityContext); } @@ -1172,7 +1155,8 @@ public InteractionResult isValidResult( */ @Override public ObjectValidityContext createValidityInteractionContext( - final ManagedObject targetAdapter, final InteractionInitiatedBy interactionInitiatedBy) { + final ManagedObject targetAdapter, + final InteractionInitiatedBy interactionInitiatedBy) { return new ObjectValidityContext(targetAdapter, getFeatureIdentifier(), interactionInitiatedBy); } @@ -1184,7 +1168,7 @@ public boolean isImmutable() { @Override public boolean isHidden() { - return containsFacet(HiddenFacet.class); + return containsFacet(HiddenFacetForLayout.class); } @Override @@ -1205,14 +1189,12 @@ private void createMixedInActionsAndResort() { || getBeanSort().isManagedBeanContributing() // in support of composite value-type constructor mixins || getBeanSort().isValue(); - if(!include) { - return; - } + if(!include) + return; var mixedInActions = createMixedInActions() .collect(Collectors.toList()); - if(mixedInActions.isEmpty()) { - return; // nothing to do (this spec has no mixed-in actions, regular actions have already been added) - } + if(mixedInActions.isEmpty()) + return; // nothing to do (this spec has no mixed-in actions, regular actions have already been added) var regularActions = _Lists.newArrayList(objectActions); // defensive copy @@ -1228,14 +1210,12 @@ private void createMixedInActionsAndResort() { * one-shot: must be no-op, if already created */ private void createMixedInAssociationsAndResort() { - if(!isEntityOrViewModelOrAbstract()) { - return; - } + if(!isEntityOrViewModelOrAbstract()) + return; var mixedInAssociations = createMixedInAssociations() .collect(Collectors.toList()); - if(mixedInAssociations.isEmpty()) { - return; // nothing to do (this spec has no mixed-in associations, regular associations have already been added) - } + if(mixedInAssociations.isEmpty()) + return; // nothing to do (this spec has no mixed-in associations, regular associations have already been added) var regularAssociations = _Lists.newArrayList(associations); // defensive copy diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToManyAssociationDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToManyAssociationDefault.java index 29f21d07c9f..b75da93e7ce 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToManyAssociationDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToManyAssociationDefault.java @@ -21,7 +21,6 @@ import org.apache.causeway.applib.Identifier; import org.apache.causeway.applib.annotation.Collection; import org.apache.causeway.applib.annotation.CollectionLayout; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.exceptions._Exceptions; import org.apache.causeway.commons.internal.reflection._GenericResolver.ResolvedType; @@ -31,7 +30,8 @@ import org.apache.causeway.core.metamodel.facets.FacetedMethod; import org.apache.causeway.core.metamodel.facets.collections.CollectionFacet; import org.apache.causeway.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet; -import org.apache.causeway.core.metamodel.interactions.InteractionUtils; +import org.apache.causeway.core.metamodel.interactions.RenderPolicy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.use.CollectionUsabilityContext; import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; import org.apache.causeway.core.metamodel.interactions.vis.CollectionVisibilityContext; @@ -79,21 +79,20 @@ private ResolvedType resolveTypeOfAnyCardinality() { public VisibilityContext createVisibleInteractionContext( final ManagedObject ownerAdapter, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { return new CollectionVisibilityContext( - headFor(ownerAdapter), getFeatureIdentifier(), interactionInitiatedBy, where, - InteractionUtils.renderPolicy(ownerAdapter)); + headFor(ownerAdapter), getFeatureIdentifier(), interactionInitiatedBy, visibilityConstraint, + RenderPolicy.forNonActionParam(ownerAdapter)); } @Override public UsabilityContext createUsableInteractionContext( final ManagedObject ownerAdapter, - final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final InteractionInitiatedBy interactionInitiatedBy) { return new CollectionUsabilityContext( - headFor(ownerAdapter), getFeatureIdentifier(), interactionInitiatedBy, where, - InteractionUtils.renderPolicy(ownerAdapter)); + headFor(ownerAdapter), getFeatureIdentifier(), interactionInitiatedBy, + RenderPolicy.forNonActionParam(ownerAdapter)); } // -- get, isEmpty, add, clear diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToManyAssociationMixedIn.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToManyAssociationMixedIn.java index 3d1a98f03be..54e0d890f71 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToManyAssociationMixedIn.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToManyAssociationMixedIn.java @@ -34,6 +34,7 @@ import org.apache.causeway.core.metamodel.facets.members.disabled.DisabledFacetForContributee; import org.apache.causeway.core.metamodel.facets.properties.update.SnapshotExcludeFacetFromImmutableMember; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.services.publishing.ExecutionPublisher; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; @@ -131,9 +132,8 @@ protected InteractionHead headFor(final ManagedObject mixedInAdapter) { private DisabledFacet disabledFacet() { final DisabledFacet originalFacet = facetHolder.getFacet(DisabledFacet.class); if( originalFacet != null && - originalFacet.where().isAlways()) { - return originalFacet; - } + originalFacet.where().isAlways()) + return originalFacet; // ensure that the contributed association is always disabled return new DisabledFacetForContributee(VetoReason.mixedinCollection(), this); } @@ -145,7 +145,7 @@ public ManagedObject get( return executionPublisher().withPublishingSuppressed( () -> mixinAction.executeInternal( - headFor(ownerAdapter), Can.empty(), interactionInitiatedBy)); + headFor(ownerAdapter), Can.empty(), interactionInitiatedBy, WhatViewer.invalid())); } @Override diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationDefault.java index ce7d544a473..37835599c72 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationDefault.java @@ -23,7 +23,6 @@ import org.apache.causeway.applib.Identifier; import org.apache.causeway.applib.annotation.Property; import org.apache.causeway.applib.annotation.PropertyLayout; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.command.Command; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.base._NullSafe; @@ -44,6 +43,8 @@ import org.apache.causeway.core.metamodel.facets.properties.update.modify.PropertySetterFacet; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.InteractionUtils; +import org.apache.causeway.core.metamodel.interactions.RenderPolicy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.use.PropertyUsabilityContext; import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; import org.apache.causeway.core.metamodel.interactions.val.PropertyModifyContext; @@ -88,20 +89,19 @@ protected OneToOneAssociationDefault( public VisibilityContext createVisibleInteractionContext( final ManagedObject ownerAdapter, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { return new PropertyVisibilityContext( - headFor(ownerAdapter), getFeatureIdentifier(), interactionInitiatedBy, where, - InteractionUtils.renderPolicy(ownerAdapter)); + headFor(ownerAdapter), getFeatureIdentifier(), interactionInitiatedBy, visibilityConstraint, + RenderPolicy.forNonActionParam(ownerAdapter)); } @Override public UsabilityContext createUsableInteractionContext( final ManagedObject ownerAdapter, - final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final InteractionInitiatedBy interactionInitiatedBy) { return new PropertyUsabilityContext( - headFor(ownerAdapter), getFeatureIdentifier(), interactionInitiatedBy, where, - InteractionUtils.renderPolicy(ownerAdapter)); + headFor(ownerAdapter), getFeatureIdentifier(), interactionInitiatedBy, + RenderPolicy.forNonActionParam(ownerAdapter)); } // -- VALIDITY @@ -157,11 +157,10 @@ public ManagedObject get( var referencedPojo = propertyOrCollectionAccessorFacet.getAssociationValueAsPojo(ownerAdapter, interactionInitiatedBy); - if (referencedPojo == null) { - // TODO: perhaps this should instead return ManagedObject.empty(getSpecification()) ? + if (referencedPojo == null) + // TODO: perhaps this should instead return ManagedObject.empty(getSpecification()) ? // however, that's a far-reaching change to make. return null; - } return getObjectManager().adapt(referencedPojo); } @@ -194,11 +193,10 @@ public final ManagedObject set( setupCommand(InteractionHead.regular(ownerAdapter), newValue); } - if (ManagedObjects.isNullOrUnspecifiedOrEmpty(newValue)) { - return clearValue(ownerAdapter, interactionInitiatedBy); - } else { - return setValue(ownerAdapter, newValue, interactionInitiatedBy); - } + if (ManagedObjects.isNullOrUnspecifiedOrEmpty(newValue)) + return clearValue(ownerAdapter, interactionInitiatedBy); + else + return setValue(ownerAdapter, newValue, interactionInitiatedBy); } private ManagedObject setValue( @@ -207,9 +205,8 @@ private ManagedObject setValue( final InteractionInitiatedBy interactionInitiatedBy) { var propertySetterFacet = getFacet(PropertySetterFacet.class); - if (propertySetterFacet == null) { - throw _Exceptions.unexpectedCodeReach(); - } + if (propertySetterFacet == null) + throw _Exceptions.unexpectedCodeReach(); MmEntityUtils.requiresWhenFirstIsBookmarkableSecondIsAlso(ownerAdapter, newReferencedAdapter); @@ -222,9 +219,8 @@ private ManagedObject clearValue( var propertyClearFacet = getFacet(PropertyClearFacet.class); - if (propertyClearFacet == null) { - throw _Exceptions.unexpectedCodeReach(); - } + if (propertyClearFacet == null) + throw _Exceptions.unexpectedCodeReach(); return propertyClearFacet.clearProperty(this, ownerAdapter, interactionInitiatedBy); } @@ -241,18 +237,16 @@ public ManagedObject getDefault(final ManagedObject ownerAdapter) { if (propertyDefaultFacet == null) { propertyDefaultFacet = this.getElementType().getFacet(PropertyDefaultFacet.class); } - if (propertyDefaultFacet == null) { - return null; - } + if (propertyDefaultFacet == null) + return null; return propertyDefaultFacet.getDefault(ownerAdapter); } @Override public void toDefault(final ManagedObject ownerAdapter) { // default only mandatory fields - if (!MandatoryFacet.isMandatory(this)) { - return; - } + if (!MandatoryFacet.isMandatory(this)) + return; final ManagedObject defaultValue = getDefault(ownerAdapter); if (defaultValue != null) { @@ -273,9 +267,8 @@ public Can getChoices( final InteractionInitiatedBy interactionInitiatedBy) { var propertyChoicesFacet = getFacet(PropertyChoicesFacet.class); - if (propertyChoicesFacet == null) { - return Can.empty(); - } + if (propertyChoicesFacet == null) + return Can.empty(); return propertyChoicesFacet.getChoices( ownerAdapter, diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationMixedIn.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationMixedIn.java index bd6a030883c..06d7e82527c 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationMixedIn.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationMixedIn.java @@ -31,6 +31,7 @@ import org.apache.causeway.core.metamodel.facets.members.disabled.DisabledFacet; import org.apache.causeway.core.metamodel.facets.members.disabled.DisabledFacetForContributee; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.services.publishing.ExecutionPublisher; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; @@ -112,9 +113,8 @@ protected InteractionHead headFor(final ManagedObject mixeeAdapter) { private DisabledFacet disabledFacet() { final DisabledFacet originalFacet = facetHolder.getFacet(DisabledFacet.class); if( originalFacet != null && - originalFacet.where().isAlways()) { - return originalFacet; - } + originalFacet.where().isAlways()) + return originalFacet; // ensure that the contributed association is always disabled return new DisabledFacetForContributee(VetoReason.mixedinProperty(), this); } @@ -127,7 +127,7 @@ public ManagedObject get( var head = headFor(mixedInAdapter); return executionPublisher().withPublishingSuppressed( - () -> mixinAction.executeInternal(head, Can.empty(), interactionInitiatedBy) + () -> mixinAction.executeInternal(head, Can.empty(), interactionInitiatedBy, WhatViewer.invalid()) ); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ProgrammingModelDefault.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ProgrammingModelDefault.java index 5ce2f3c7c2f..b5b9b83ad70 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ProgrammingModelDefault.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ProgrammingModelDefault.java @@ -36,7 +36,7 @@ import org.apache.causeway.core.metamodel.facets.members.cssclass.annotprop.CssClassFacetOnActionFromConfiguredRegexFactory; import org.apache.causeway.core.metamodel.facets.members.described.method.DescribedAsFacetForMemberViaMethodFactory; import org.apache.causeway.core.metamodel.facets.members.disabled.method.DisableForContextFacetViaMethodFactory; -import org.apache.causeway.core.metamodel.facets.members.hidden.method.HideForContextFacetViaMethodFactory; +import org.apache.causeway.core.metamodel.facets.members.hidden.method.HiddenFacetForMemberViaMethodFactory; import org.apache.causeway.core.metamodel.facets.members.named.method.NamedFacetForMemberViaMethodFactory; import org.apache.causeway.core.metamodel.facets.object.ViewModelSemanticCheckingFacetFactory; import org.apache.causeway.core.metamodel.facets.object.bookmarkpolicy.bookmarkable.BookmarkPolicyFacetFallbackFactory; @@ -47,7 +47,7 @@ import org.apache.causeway.core.metamodel.facets.object.domainservice.annotation.DomainServiceFacetAnnotationFactory; import org.apache.causeway.core.metamodel.facets.object.domainservicelayout.DomainServiceLayoutFacetFactory; import org.apache.causeway.core.metamodel.facets.object.grid.GridFacetFactory; -import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenTypeFacetFromAuthorizationFactory; +import org.apache.causeway.core.metamodel.facets.object.hidden.HiddenFacetForNoMembersAuthorizedFactory; import org.apache.causeway.core.metamodel.facets.object.ignore.annotation.RemoveAnnotatedMethodsFacetFactory; import org.apache.causeway.core.metamodel.facets.object.ignore.javalang.IteratorFilteringFacetFactory; import org.apache.causeway.core.metamodel.facets.object.ignore.javalang.RemoveMethodsFacetFactory; @@ -181,7 +181,7 @@ private void addFacetFactories() { addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new NamedFacetForMemberViaMethodFactory(mmc)); addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new DescribedAsFacetForMemberViaMethodFactory(mmc)); addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new DisableForContextFacetViaMethodFactory(mmc)); - addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new HideForContextFacetViaMethodFactory(mmc)); + addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new HiddenFacetForMemberViaMethodFactory(mmc)); addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new CallbackFacetFactory(mmc)); @@ -213,7 +213,7 @@ private void addFacetFactories() { // must come after DomainObjectAnnotationFacetFactory & MixinFacetFactory addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new ContributingFacetFromMixinFacetFactory(mmc)); - addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new HiddenTypeFacetFromAuthorizationFactory(mmc)); + addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new HiddenFacetForNoMembersAuthorizedFactory(mmc)); addFactory(FacetProcessingOrder.E1_MEMBER_MODELLING, new ValueSemanticsAnnotationFacetFactory(mmc)); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ValidatorDomainIncludeAnnotationEnforcesMetamodelContribution.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ValidatorDomainIncludeAnnotationEnforcesMetamodelContribution.java index 555f5a27a92..663322b1120 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ValidatorDomainIncludeAnnotationEnforcesMetamodelContribution.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/ValidatorDomainIncludeAnnotationEnforcesMetamodelContribution.java @@ -105,7 +105,7 @@ public void validateObjectEnter(final ObjectSpecification spec) { .flatMap(Optional::stream) .filter(ImperativeFacet.class::isInstance) .map(ImperativeFacet.class::cast) - .map(ImperativeFacet::getMethods) + .map(ImperativeFacet::methods) .flatMap(Can::stream) .map(MethodFacade::asMethodForIntrospection) .forEach(supportMethods::add); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/_SpecPredicates.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/_SpecPredicates.java index df1d5fea4d9..b6de9c0e158 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/_SpecPredicates.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/impl/_SpecPredicates.java @@ -19,7 +19,7 @@ package org.apache.causeway.core.metamodel.spec.impl; import org.apache.causeway.core.metamodel.facets.actions.contributing.ContributingFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.jspecify.annotations.NonNull; @@ -42,7 +42,7 @@ static boolean isGetterCandidate(final @NonNull ObjectAction action) { // -- HIGHER LEVEL - MIXINS static boolean isMixedInAction(final @NonNull ObjectAction mixinAction) { - if(HiddenFacet.isAlwaysHidden(mixinAction)) { + if(HiddenFacetForLayout.isAlwaysHidden(mixinAction)) { return false; } if(ContributingFacet.isActionContributionVetoed(mixinAction)) { @@ -58,7 +58,7 @@ static boolean isMixedInAssociation(final @NonNull ObjectAction mixinAction) { if(!mixinAction.getSemantics().isSafeInNature()) { return false; } - if(HiddenFacet.isAlwaysHidden(mixinAction)) { + if(HiddenFacetForLayout.isAlwaysHidden(mixinAction)) { return false; } if(ContributingFacet.isAssociationContributionVetoed(mixinAction)) { diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/DataColumn.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/DataColumn.java index 609f99b330c..42c9ac07e74 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/DataColumn.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/DataColumn.java @@ -29,8 +29,8 @@ public interface DataColumn { * Corresponds to the association's id. */ String columnId(); + ObjectAssociation associationMetaModel(); Observable columnFriendlyNameObservable(); Observable> columnDescriptionObservable(); - } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/DataTableInteractive.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/DataTableInteractive.java index 5ae6e23e323..3bde11973d9 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/DataTableInteractive.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/DataTableInteractive.java @@ -29,6 +29,7 @@ import org.apache.causeway.commons.binding.Bindable; import org.apache.causeway.commons.binding.Observable; import org.apache.causeway.commons.collections.Can; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteraction; import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.interactions.managed.ManagedCollection; @@ -89,7 +90,7 @@ public Optional> asComparator(final Can lookupColumnById(final @NonNull String columnId) { .findFirst(); } - /** - * Can be none, one or many per table cell. - */ @Override public Can getCellElementsForColumn(final @NonNull DataColumn column) { final ObjectAssociation assoc = column.associationMetaModel(); - var interactionInitiatedBy = InteractionInitiatedBy.PASS_THROUGH; return assoc.getSpecialization().fold( property-> Can.of( // similar to ManagedProperty#reassessPropertyValue - property.isVisible(rowElement(), interactionInitiatedBy, Where.ALL_TABLES).isAllowed() - ? property.get(rowElement(), interactionInitiatedBy) + property.isVisible(rowElement(), InteractionInitiatedBy.USER, VISIBILITY_CONSTRAINT).isAllowed() + ? property.get(rowElement(), InteractionInitiatedBy.USER) : ManagedObject.empty(property.getElementType())), collection-> ManagedObjects.unpack( - collection.isVisible(rowElement(), interactionInitiatedBy, Where.ALL_TABLES).isAllowed() - ? collection.get(rowElement(), interactionInitiatedBy) + collection.isVisible(rowElement(), InteractionInitiatedBy.USER, VISIBILITY_CONSTRAINT).isAllowed() + ? collection.get(rowElement(), InteractionInitiatedBy.USER) : null )); } - /** - * Can be none, one or many per table cell. (returns empty Can if column not found) - */ @Override public Can getCellElementsForColumn(final @NonNull String columnId) { return lookupColumnById(columnId) @@ -90,4 +83,7 @@ public Can getCellElementsForColumn(final @NonNull String columnI .orElseGet(Can::empty); } + // we are always checking whether a property is visible, constraint by Where.ALL_TABLES (but not by WhatViewer) + private final static VisibilityConstraint VISIBILITY_CONSTRAINT = VisibilityConstraint.noViewer(Where.ALL_TABLES); + } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/internal/DataTableInternal.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/internal/DataTableInternal.java index ac4e2564da0..d7a3ba64554 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/internal/DataTableInternal.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/internal/DataTableInternal.java @@ -42,6 +42,8 @@ import org.apache.causeway.commons.internal.binding._Observables.LazyObservable; import org.apache.causeway.commons.internal.collections._Streams; import org.apache.causeway.commons.internal.exceptions._Exceptions; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteraction; import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.interactions.managed.ManagedCollection; @@ -74,7 +76,7 @@ public static DataTableInternal empty(final ManagedMember managedMember, final W public static DataTableInternal forCollection( final ManagedCollection managedCollection) { - return new DataTableInternal(managedCollection, managedCollection.getWhere(), + return new DataTableInternal(managedCollection, managedCollection.visibilityConstraint().where(), managedCollection .streamElements() .collect(Can.toCan())); @@ -85,16 +87,15 @@ public static DataTableInternal forAction( final ManagedObject actionResult) { if(actionResult==null) { - new DataTableInternal(managedAction, managedAction.getWhere(), Can.empty()); - } - if(!(actionResult instanceof PackedManagedObject)) { - throw _Exceptions.unexpectedCodeReach(); + new DataTableInternal(managedAction, managedAction.visibilityConstraint().where(), Can.empty()); } + if(!(actionResult instanceof PackedManagedObject)) + throw _Exceptions.unexpectedCodeReach(); var elements = ((PackedManagedObject)actionResult).unpack(); elements.forEach(ManagedObject::getBookmark); - return new DataTableInternal(managedAction, managedAction.getWhere(), elements); + return new DataTableInternal(managedAction, managedAction.visibilityConstraint().where(), elements); } // -- CONSTRUCTION @@ -356,22 +357,20 @@ public Set getSelectedRowIndexes() { } @Override - public ActionInteraction startAssociatedActionInteraction(final String actionId, final Where where) { + public ActionInteraction startAssociatedActionInteraction(final String actionId, final VisibilityConstraint visibilityConstraint) { if(managedMember.getOwner().specialization().isEmpty() - || managedMember.getOwner().getEntityState().isTransientOrRemoved()) { - throw _Exceptions.illegalArgument("cannot start action interaction on missing or deleted action owner"); - } + || managedMember.getOwner().getEntityState().isTransientOrRemoved()) + throw _Exceptions.illegalArgument("cannot start action interaction on missing or deleted action owner"); var featureId = managedMember.getIdentifier(); - if(!featureId.type().isPropertyOrCollection()) { - return ActionInteraction.empty(String.format("[no such collection %s; instead got %s;" + if(!featureId.type().isPropertyOrCollection()) + return ActionInteraction.empty(String.format("[no such collection %s; instead got %s;" + "(while searching for an associated action %s)]", featureId, featureId.type(), actionId)); - } - return ActionInteraction.startWithMultiselect(managedMember.getOwner(), actionId, where, this); + return ActionInteraction.startWithMultiselect(managedMember.getOwner(), actionId, visibilityConstraint, this); } // -- EXPORT @@ -385,7 +384,7 @@ public DataTable export() { .map(DataColumn::associationMetaModel), dataRowsFilteredAndSortedObservable().getValue() .stream() - .map(dr->dr.rowElement()) + .map(DataRow::rowElement) .collect(Can.toCan())); } @@ -447,10 +446,12 @@ static Memento create( public DataTableInternal recreateDataTableModel(final ManagedObject owner) { var memberId = featureId.memberLogicalName(); + var visibilityConstraint = new VisibilityConstraint(WhatViewer.noViewer(), where); + final ManagedMember managedMember = featureId.type().isPropertyOrCollection() - ? ManagedCollection.lookupCollection(owner, memberId, where) + ? ManagedCollection.lookupCollection(owner, memberId, visibilityConstraint) .orElseThrow() - : ManagedAction.lookupAction(owner, memberId, where) + : ManagedAction.lookupAction(owner, memberId, visibilityConstraint) .orElseThrow(); var dataTableInteractive = new DataTableInternal(managedMember, where, @@ -484,7 +485,7 @@ public void setupBindings(final DataTableInteractive tableInteractive) { this.selectedRowIndexes = tableInteractive.getSelectedRowIndexes(); }); } - + @Override public String toString() { return "Memento[featureId=%s,dataTable.rowCount=%d]".formatted( diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataRow.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataRow.java index 3fad7bbdb41..59e103c5ec1 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataRow.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataRow.java @@ -18,14 +18,15 @@ */ package org.apache.causeway.core.metamodel.tabular.simple; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.ManagedObjects; -import org.jspecify.annotations.NonNull; - /** * Represents a single domain object (typically an entity instance) * and it's associated values as cell elements. @@ -37,24 +38,37 @@ public record DataRow( /** * Can be none, one or many per table cell. + * @param column for which to get the cell elements (none, one or many) + * @param accessMode use PASS_THROUGH for faster processing, when you know, + * that you don't need the full access check processing and also can skip associated event processing */ public Can getCellElements( final @NonNull DataColumn column, - final InteractionInitiatedBy interactionInitiatedBy) { + final DataTable.AccessMode accessMode) { + + var initiatedBy = switch(accessMode) { + case PASS_THROUGH -> InteractionInitiatedBy.PASS_THROUGH; + default -> InteractionInitiatedBy.USER; + }; + var assoc = column.metamodel(); return assoc.getSpecialization().fold( property-> Can.of( - // similar to ManagedProperty#reassessPropertyValue - interactionInitiatedBy.isPassThrough() - || property.isVisible(rowElement(), interactionInitiatedBy, Where.ALL_TABLES).isAllowed() - ? property.get(rowElement(), interactionInitiatedBy) - : ManagedObject.empty(property.getElementType())), + // similar to ManagedProperty#reassessPropertyValue + initiatedBy.isPassThrough() + || property.isVisible(rowElement(), InteractionInitiatedBy.USER, VISIBILITY_CONSTRAINT).isAllowed() + ? property.get(rowElement(), initiatedBy) + : ManagedObject.empty(property.getElementType())), collection-> ManagedObjects.unpack( - interactionInitiatedBy.isPassThrough() - || collection.isVisible(rowElement(), interactionInitiatedBy, Where.ALL_TABLES).isAllowed() - ? collection.get(rowElement(), interactionInitiatedBy) - : null + initiatedBy.isPassThrough() + || collection.isVisible(rowElement(), InteractionInitiatedBy.USER, VISIBILITY_CONSTRAINT).isAllowed() + ? collection.get(rowElement(), initiatedBy) + : null )); } + // we are checking whether a property is visible, constraint by Where.ALL_TABLES (but not by WhatViewer) + // when accessMode is PASS_THROUGH, we simply assume, that the Where.ALL_TABLES constraint is already honored by previous column filtering logic. + private final static VisibilityConstraint VISIBILITY_CONSTRAINT = VisibilityConstraint.noViewer(Where.ALL_TABLES); + } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataTable.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataTable.java index 6c644477a67..902b1a174c1 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataTable.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/DataTable.java @@ -25,6 +25,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; +import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.apache.causeway.applib.annotation.Where; @@ -39,7 +40,6 @@ import org.apache.causeway.commons.internal.base._Strings; import org.apache.causeway.commons.internal.functions._Predicates; import org.apache.causeway.commons.tabular.TabularModel.TabularSheet; -import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.objectmanager.ObjectManager; @@ -50,8 +50,6 @@ import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; import org.apache.causeway.core.metamodel.util.Facets; -import org.jspecify.annotations.NonNull; - /** * Represents a collection of domain objects (typically entity instances). * @@ -204,7 +202,7 @@ public DataTable withDataElementsFrom(final @Nullable DataTable otherTable) { */ public DataTable withDataElements(final @Nullable Iterable dataElements) { var newDataRows = Can.ofIterable(dataElements) - .map(domainObject->new DataRow(domainObject)); + .map(DataRow::new); return new DataTable(elementType, dataColumns, newDataRows, tableFriendlyName); } /** @@ -254,16 +252,16 @@ default void onRowLeave(final DataRow row) {} void onCell(DataColumn column, Can cellValues); } - public DataTable visit(final CellVisitor visitor) { - return visit(visitor, _Predicates.alwaysTrue()); + public DataTable visit(final CellVisitor visitor, final DataTable.AccessMode accessMode) { + return visit(visitor, accessMode, _Predicates.alwaysTrue()); } - public DataTable visit(final CellVisitor visitor, final Predicate columnFilter) { + public DataTable visit(final CellVisitor visitor, final DataTable.AccessMode accessMode, final Predicate columnFilter) { var columnsOfInterest = dataColumns().filter(columnFilter); if(columnsOfInterest.isNotEmpty()) { dataRows().forEach(row->{ visitor.onRowEnter(row); columnsOfInterest.forEach(col->{ - visitor.onCell(col, row.getCellElements(col, InteractionInitiatedBy.PASS_THROUGH)); + visitor.onCell(col, row.getCellElements(col, accessMode)); }); visitor.onRowLeave(row); }); @@ -327,7 +325,7 @@ public final static Predicate columnFilterExcludingMixins() { public final static Predicate columnFilterIncludingEnabledForSnapshot() { return (final ObjectAssociation assoc) -> _Casts.castTo(OneToOneAssociation.class, assoc) - .map(prop->prop.isIncludedWithSnapshots()) + .map(OneToOneAssociation::isIncludedWithSnapshots) .orElse(false); } diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/TabularUtil.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/TabularUtil.java index 46e832e580e..7ffc51f8a41 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/TabularUtil.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/tabular/simple/TabularUtil.java @@ -21,7 +21,6 @@ import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.functional.IndexedFunction; import org.apache.causeway.commons.tabular.TabularModel; -import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.object.ManagedObject; import lombok.experimental.UtilityClass; @@ -35,15 +34,10 @@ class TabularUtil { TabularModel.TabularSheet toTabularSheet( final DataTable dataTable, final DataTable.AccessMode accessMode) { - var interactionInitiatedBy = switch(accessMode) { - case PASS_THROUGH -> InteractionInitiatedBy.PASS_THROUGH; - default -> InteractionInitiatedBy.USER; - }; - var columns = dataTable.dataColumns() .map(IndexedFunction.zeroBased(TabularUtil::tabularColumn)); var rows = dataTable.dataRows() - .map(dr->tabularRow(dataTable.dataColumns(), dr, interactionInitiatedBy)); + .map(dr->tabularRow(dataTable.dataColumns(), dr, accessMode)); return new TabularModel.TabularSheet(dataTable.tableFriendlyName(), columns, rows); } @@ -59,9 +53,9 @@ private TabularModel.TabularColumn tabularColumn(final int index, final DataColu private TabularModel.TabularRow tabularRow( final Can dataColumns, final DataRow dataRow, - final InteractionInitiatedBy interactionInitiatedBy) { + final DataTable.AccessMode accessMode) { var cells = dataColumns.map(dataColumn->{ - var cellElements = dataRow.getCellElements(dataColumn, interactionInitiatedBy); + var cellElements = dataRow.getCellElements(dataColumn, accessMode); final int cardinality = cellElements.size(); final boolean forceUseTitle = !dataColumn.metamodel().getElementType().isValue(); diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/Facets.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/Facets.java index c779e530803..25790ca52d6 100644 --- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/Facets.java +++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/util/Facets.java @@ -50,7 +50,7 @@ import org.apache.causeway.core.metamodel.facetapi.FacetUtil; import org.apache.causeway.core.metamodel.facets.actcoll.typeof.TypeOfFacet; import org.apache.causeway.core.metamodel.facets.actions.semantics.ActionSemanticsFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.collections.CollectionFacet; import org.apache.causeway.core.metamodel.facets.collections.collection.defaultview.DefaultViewFacet; import org.apache.causeway.core.metamodel.facets.members.cssclass.CssClassFacet; @@ -212,8 +212,8 @@ public boolean hasSafeSemantics(final FacetHolder holder) { } public Optional hiddenWhere(final ObjectFeature feature) { - return feature.lookupFacet(HiddenFacet.class) - .map(HiddenFacet::where); + return feature.lookupFacet(HiddenFacetForLayout.class) + .map(HiddenFacetForLayout::where); } public Predicate hiddenWhereMatches(final Predicate matcher) { diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/consent/InteractionResultTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/consent/InteractionResultTest.java index 7c10916fd76..ba40bce73d3 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/consent/InteractionResultTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/consent/InteractionResultTest.java @@ -18,6 +18,9 @@ */ package org.apache.causeway.core.metamodel.consent; +import java.util.function.BiConsumer; + +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -28,11 +31,35 @@ import org.apache.causeway.applib.services.wrapper.events.InteractionEvent; import org.apache.causeway.core.metamodel.consent.Consent.VetoReason; +import org.apache.causeway.core.metamodel.facetapi.Facet; class InteractionResultTest { private InteractionResult.Builder builder = InteractionResult.builder(Mockito.mock(InteractionEvent.class)); + private static interface InteractionAdvisorFacet + extends InteractionAdvisor, Facet { + } + + public static InteractionAdvisor interactionAdvisor() { + return new InteractionAdvisorFacet() { + @Override public boolean semanticEquals(final @NonNull Facet other) { + return this == other; + } + @Override public void visitAttributes(final BiConsumer visitor) { + } + @Override public Class facetType() { + return null; + } + @Override public org.apache.causeway.core.metamodel.facetapi.FacetHolder facetHolder() { + return null; + } + @Override public Precedence precedence() { + return Facet.Precedence.FALLBACK; + } + }; + } + @Test void shouldHaveNullReasonWhenJustInstantiated() { var result = builder.build(); @@ -48,22 +75,22 @@ void shouldBeEmptyWhenJustInstantiated() { @Test void shouldHaveNonNullReasonWhenAdvisedWithNonNull() { - advise(vetoReason("foo"), InteractionAdvisor.forTesting()); + advise(vetoReason("foo"), interactionAdvisor()); var result = builder.build(); assertEquals("foo", extractReason(result)); } @Test void shouldConcatenateAdviseWhenAdvisedWithNonNull() { - advise(vetoReason("foo"), InteractionAdvisor.forTesting()); - advise(vetoReason("bar"), InteractionAdvisor.forTesting()); + advise(vetoReason("foo"), interactionAdvisor()); + advise(vetoReason("bar"), interactionAdvisor()); var result = builder.build(); assertEquals("foo; bar", extractReason(result)); } @Test void shouldNotBeEmptyWhenAdvisedWithNonNull() { - advise(vetoReason("foo"), InteractionAdvisor.forTesting()); + advise(vetoReason("foo"), interactionAdvisor()); var result = builder.build(); assertTrue(result.isVetoing()); assertFalse(result.isAllowing()); @@ -71,7 +98,7 @@ void shouldNotBeEmptyWhenAdvisedWithNonNull() { @Test void shouldThrowWhenAdvisedWithNull() { - assertThrowsExactly(NullPointerException.class, ()->advise(null, InteractionAdvisor.forTesting())); + assertThrowsExactly(NullPointerException.class, ()->advise(null, interactionAdvisor())); assertThrowsExactly(NullPointerException.class, ()->advise(vetoReason("foo"), null)); } diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/FacetFactoryTestAbstract.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/FacetFactoryTestAbstract.java index 6e284489ccb..c7b31cba497 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/FacetFactoryTestAbstract.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/FacetFactoryTestAbstract.java @@ -479,7 +479,7 @@ protected final void assertMethodWasRemoved(final Class type, final String me protected final void assertMethodEqualsFirstIn( final @NonNull ResolvedMethod method, final @NonNull ImperativeFacet imperativeFacet) { - _Utils.assertMethodEquals(method, imperativeFacet.getMethods().getFirstElseFail().asMethodElseFail()); + _Utils.assertMethodEquals(method, imperativeFacet.methods().getFirstElseFail().asMethodElseFail()); } } diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_RestrictTo.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_RestrictTo.java index 6233eab87e8..920a40de5de 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_RestrictTo.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_RestrictTo.java @@ -25,7 +25,7 @@ import org.apache.causeway.applib.annotation.Action; import org.apache.causeway.core.metamodel.facets.FacetFactory.ProcessMethodContext; -import org.apache.causeway.core.metamodel.facets.actions.prototype.PrototypeFacet; +import org.apache.causeway.core.metamodel.facets.actions.prototype.HiddenFacetForDeploymentType; class ActionAnnotationFacetFactoryTest_RestrictTo extends ActionAnnotationFacetFactoryTest { @@ -49,7 +49,7 @@ public void someAction() {} // when processRestrictTo(facetFactory, processMethodContext); // then - final PrototypeFacet facet = facetedMethod.getFacet(PrototypeFacet.class); + final HiddenFacetForDeploymentType facet = facetedMethod.getFacet(HiddenFacetForDeploymentType.class); assertNotNull(facet); }); } @@ -67,7 +67,7 @@ public void someAction() {} // when processRestrictTo(facetFactory, processMethodContext); // then - final PrototypeFacet facet = facetedMethod.getFacet(PrototypeFacet.class); + final HiddenFacetForDeploymentType facet = facetedMethod.getFacet(HiddenFacetForDeploymentType.class); assertNull(facet); }); } @@ -85,7 +85,7 @@ public void someAction() {} // when processRestrictTo(facetFactory, processMethodContext); // then - final PrototypeFacet facet = facetedMethod.getFacet(PrototypeFacet.class); + final HiddenFacetForDeploymentType facet = facetedMethod.getFacet(HiddenFacetForDeploymentType.class); assertNull(facet); }); } diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/action/PrototypeFacetAnnotationFactoryTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/action/PrototypeFacetAnnotationFactoryTest.java index 63213d0d216..58be1f2173c 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/action/PrototypeFacetAnnotationFactoryTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/action/PrototypeFacetAnnotationFactoryTest.java @@ -30,8 +30,7 @@ import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facets.FacetFactory.ProcessMethodContext; import org.apache.causeway.core.metamodel.facets.FacetFactoryTestAbstract; -import org.apache.causeway.core.metamodel.facets.actions.prototype.PrototypeFacet; -import org.apache.causeway.core.metamodel.facets.actions.prototype.PrototypeFacetAbstract; +import org.apache.causeway.core.metamodel.facets.actions.prototype.HiddenFacetForDeploymentType; class PrototypeFacetAnnotationFactoryTest extends FacetFactoryTestAbstract { @@ -64,9 +63,9 @@ public void someAction() {} //when processRestrictTo(facetFactory, processMethodContext); //then - final Facet facet = facetedMethod.getFacet(PrototypeFacet.class); + final Facet facet = facetedMethod.getFacet(HiddenFacetForDeploymentType.class); assertNotNull(facet); - assertTrue(facet instanceof PrototypeFacetAbstract); + assertTrue(facet instanceof HiddenFacetForDeploymentType); assertNoMethodsRemoved(); }); } diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryTest.java index e01bf5a4696..6f7417bc5a9 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryTest.java @@ -35,7 +35,7 @@ import org.apache.causeway.core.metamodel.facets.FacetFactoryTestAbstract; import org.apache.causeway.core.metamodel.facets.actions.position.ActionPositionFacet; import org.apache.causeway.core.metamodel.facets.actions.position.ActionPositionFacetFallback; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.members.iconfa.FaFacet; class ActionLayoutAnnotationFacetFactoryTest @@ -78,7 +78,7 @@ class Customer { actionScenario(Customer.class, "foz", (processMethodContext, facetHolder, facetedMethod)->{ facetFactory.process(processMethodContext); - final Facet facet = facetedMethod.getFacet(HiddenFacet.class); + final Facet facet = facetedMethod.getFacet(HiddenFacetForLayout.class); assertNotNull(facet); assertTrue(facet instanceof HiddenFacetForActionLayoutAnnotation); var actionLayoutFacetAnnotation = (HiddenFacetForActionLayoutAnnotation) facet; diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacetAbstractTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacetAbstractTest.java index 6ad5905f6f7..1320d9170b9 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacetAbstractTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/actions/prototype/PrototypeFacetAbstractTest.java @@ -25,6 +25,7 @@ import org.apache.causeway.core.config.environment.DeploymentType; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; +import org.apache.causeway.core.metamodel.facets.actions.action.prototype.HiddenFacetForDeploymentTypeViaActionAnnotation; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; class PrototypeFacetAbstractTest { @@ -40,7 +41,8 @@ public void allCombinations() throws Exception { protected void givenWhenThen(final DeploymentType deploymentType, final String expected) { // given - final PrototypeFacetAbstract facet = new PrototypeFacetAbstract(mockFacetHolder, deploymentType){}; + var facet = new HiddenFacetForDeploymentTypeViaActionAnnotation( + deploymentType, mockFacetHolder); // when final String reason = facet.hides(mockVisibilityContext); diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/collections/layout/annotation/CollectionLayoutAnnotationFactoryTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/collections/layout/annotation/CollectionLayoutAnnotationFactoryTest.java index 3cf86cc2d00..2516dc01410 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/collections/layout/annotation/CollectionLayoutAnnotationFactoryTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/collections/layout/annotation/CollectionLayoutAnnotationFactoryTest.java @@ -36,7 +36,7 @@ import org.apache.causeway.commons.internal.collections._Sets; import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facets.FacetFactoryTestAbstract; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.all.i8n.staatic.HasStaticText; import org.apache.causeway.core.metamodel.facets.all.named.MemberNamedFacet; import org.apache.causeway.core.metamodel.facets.collections.layout.CollectionLayoutFacetFactory; @@ -75,7 +75,7 @@ class Customer { // when facetFactory.process(processMethodContext); // then - final Facet facet = facetedMethod.getFacet(HiddenFacet.class); + final Facet facet = facetedMethod.getFacet(HiddenFacetForLayout.class); assertNotNull(facet); assertTrue(facet instanceof HiddenFacetForCollectionLayoutAnnotation); final HiddenFacetForCollectionLayoutAnnotation collLayoutFacetAnnotation = (HiddenFacetForCollectionLayoutAnnotation) facet; diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/callback/CallbackFacetFactoryTestAbstract.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/callback/CallbackFacetFactoryTestAbstract.java index 105265ac066..1ff2c9a48f1 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/callback/CallbackFacetFactoryTestAbstract.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/callback/CallbackFacetFactoryTestAbstract.java @@ -81,7 +81,7 @@ protected void assertPicksUp( callbackMethods.forEach(method->{ assertMethodWasRemoved(method); - assertTrue(imperativeFacet.getMethods() + assertTrue(imperativeFacet.methods() .map(MethodFacade::asMethodElseFail).contains(method)); }); }); diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/hidden/ObjectHiddenMethodFacetFactoryTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/hidden/ObjectHiddenMethodFacetFactoryTest.java index 6d81e95afd6..5079303d2d3 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/hidden/ObjectHiddenMethodFacetFactoryTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/hidden/ObjectHiddenMethodFacetFactoryTest.java @@ -34,7 +34,7 @@ public boolean hidden() { return true; } } - assertPicksUp(1, facetFactory, Customer.class, ObjectSupportMethod.HIDDEN, HiddenObjectFacet.class); + assertPicksUp(1, facetFactory, Customer.class, ObjectSupportMethod.HIDDEN, HiddenFacetForObject.class); } } diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/support/ObjectSupportFacetFactoryTestAbstract.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/support/ObjectSupportFacetFactoryTestAbstract.java index 086a9e17bf6..7706b3fb8a5 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/support/ObjectSupportFacetFactoryTestAbstract.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/object/support/ObjectSupportFacetFactoryTestAbstract.java @@ -77,7 +77,7 @@ protected void assertPicksUp( supportMethods.forEach(method->{ assertMethodWasRemoved(method); - assertTrue(imperativeFacet.getMethods() + assertTrue(imperativeFacet.methods() .map(MethodFacade::asMethodElseFail).contains(method)); }); diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/properties/PropertyMethodsFacetFactoryTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/properties/PropertyMethodsFacetFactoryTest.java index 90821cfaa9d..6c4b292a7ea 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/properties/PropertyMethodsFacetFactoryTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/properties/PropertyMethodsFacetFactoryTest.java @@ -30,9 +30,9 @@ import org.apache.causeway.core.metamodel.facets.members.disabled.method.DisableForContextFacet; import org.apache.causeway.core.metamodel.facets.members.disabled.method.DisableForContextFacetViaMethod; import org.apache.causeway.core.metamodel.facets.members.disabled.method.DisableForContextFacetViaMethodFactory; -import org.apache.causeway.core.metamodel.facets.members.hidden.method.HideForContextFacet; -import org.apache.causeway.core.metamodel.facets.members.hidden.method.HideForContextFacetViaMethod; -import org.apache.causeway.core.metamodel.facets.members.hidden.method.HideForContextFacetViaMethodFactory; +import org.apache.causeway.core.metamodel.facets.members.hidden.method.HiddenFacetForMember; +import org.apache.causeway.core.metamodel.facets.members.hidden.method.HiddenFacetForMemberViaMethod; +import org.apache.causeway.core.metamodel.facets.members.hidden.method.HiddenFacetForMemberViaMethodFactory; import org.apache.causeway.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet; import org.apache.causeway.core.metamodel.facets.propcoll.memserexcl.SnapshotExcludeFacet; import org.apache.causeway.core.metamodel.facets.properties.accessor.PropertyAccessorFacetViaAccessor; @@ -312,7 +312,7 @@ class Customer { @Test void hiddenFacetFoundAndMethodRemoved() { - var facetFactory = new HideForContextFacetViaMethodFactory(getMetaModelContext()); + var facetFactory = new HiddenFacetForMemberViaMethodFactory(getMetaModelContext()); @SuppressWarnings("unused") class Customer { public String getFirstName() { return null; } @@ -325,10 +325,10 @@ class Customer { // when facetFactory.process(processMethodContext); // then - final Facet facet = facetedMethod.getFacet(HideForContextFacet.class); + final Facet facet = facetedMethod.getFacet(HiddenFacetForMember.class); assertNotNull(facet); - assertTrue(facet instanceof HideForContextFacetViaMethod); - var hideForContextFacet = (HideForContextFacetViaMethod) facet; + assertTrue(facet instanceof HiddenFacetForMemberViaMethod); + var hideForContextFacet = (HiddenFacetForMemberViaMethod) facet; assertMethodEqualsFirstIn(propertyHideMethod, hideForContextFacet); assertMethodWasRemoved(propertyHideMethod); }); @@ -336,7 +336,7 @@ class Customer { @Test void hiddenFacetWithNoArgFoundAndMethodRemoved() { - var facetFactory = new HideForContextFacetViaMethodFactory(getMetaModelContext()); + var facetFactory = new HiddenFacetForMemberViaMethodFactory(getMetaModelContext()); @SuppressWarnings("unused") class Customer { public String getFirstName() { return null; } @@ -349,10 +349,10 @@ class Customer { // when facetFactory.process(processMethodContext); // then - final Facet facet = facetedMethod.getFacet(HideForContextFacet.class); + final Facet facet = facetedMethod.getFacet(HiddenFacetForMember.class); assertNotNull(facet); - assertTrue(facet instanceof HideForContextFacetViaMethod); - var hideForContextFacet = (HideForContextFacetViaMethod) facet; + assertTrue(facet instanceof HiddenFacetForMemberViaMethod); + var hideForContextFacet = (HiddenFacetForMemberViaMethod) facet; assertMethodEqualsFirstIn(propertyHideMethod, hideForContextFacet); assertMethodWasRemoved(propertyHideMethod); }); @@ -386,7 +386,7 @@ class CustomerEx extends Customer { @Test void propertyFoundOnSuperclassButHelperMethodFoundOnSubclass() { var facetFactory = new PropertyAccessorFacetViaAccessorFactory(getMetaModelContext()); - var facetFactoryForHide = new HideForContextFacetViaMethodFactory(getMetaModelContext()); + var facetFactoryForHide = new HiddenFacetForMemberViaMethodFactory(getMetaModelContext()); var facetFactoryForDisable = new DisableForContextFacetViaMethodFactory(getMetaModelContext()); @SuppressWarnings("unused") class Customer { @@ -409,10 +409,10 @@ class CustomerEx extends Customer { facetFactoryForHide.process(processMethodContext); facetFactoryForDisable.process(processMethodContext); - final Facet facet = facetedMethod.getFacet(HideForContextFacet.class); + final Facet facet = facetedMethod.getFacet(HiddenFacetForMember.class); assertNotNull(facet); - assertTrue(facet instanceof HideForContextFacetViaMethod); - var hideForContextFacet = (HideForContextFacetViaMethod) facet; + assertTrue(facet instanceof HiddenFacetForMemberViaMethod); + var hideForContextFacet = (HiddenFacetForMemberViaMethod) facet; assertMethodEqualsFirstIn(propertyHideMethod, hideForContextFacet); final Facet facet2 = facetedMethod.getFacet(DisableForContextFacet.class); diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/PropertyLayoutAnnotationFactoryTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/PropertyLayoutAnnotationFactoryTest.java index 4f9a48ee6a2..ff05baef77d 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/PropertyLayoutAnnotationFactoryTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/facets/properties/propertylayout/PropertyLayoutAnnotationFactoryTest.java @@ -35,7 +35,7 @@ import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facets.FacetFactoryTestAbstract; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.facets.all.i8n.staatic.HasStaticText; import org.apache.causeway.core.metamodel.facets.all.named.MemberNamedFacet; import org.apache.causeway.core.metamodel.facets.objectvalue.labelat.LabelAtFacet; @@ -79,7 +79,7 @@ class Customer { //when facetFactory.process(processMethodContext); //then - final Facet facet = facetedMethod.getFacet(HiddenFacet.class); + final Facet facet = facetedMethod.getFacet(HiddenFacetForLayout.class); assertNotNull(facet); assertTrue(facet instanceof HiddenFacetForPropertyLayoutAnnotation); var propLayoutFacetAnnotation = (HiddenFacetForPropertyLayoutAnnotation) facet; diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/feature/ObjectAssociationPredicatesTest_visibleWhere.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/feature/ObjectAssociationPredicatesTest_visibleWhere.java index e33c1f8e2f2..2dddc95558c 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/feature/ObjectAssociationPredicatesTest_visibleWhere.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/feature/ObjectAssociationPredicatesTest_visibleWhere.java @@ -35,17 +35,17 @@ import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.facets.WhereValueFacet; -import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacet; +import org.apache.causeway.core.metamodel.facets.all.hide.HiddenFacetForLayout; import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation; class ObjectAssociationPredicatesTest_visibleWhere { private ObjectAssociation mockObjectAssociation; - private HiddenFacet mockHiddenFacet; + private HiddenFacetForLayout mockHiddenFacet; @BeforeEach public void setUp() throws Exception { - mockHiddenFacet = Mockito.mock(HiddenFacet.class); + mockHiddenFacet = Mockito.mock(HiddenFacetForLayout.class); mockObjectAssociation = Mockito.mock(ObjectAssociation.class); } @@ -83,7 +83,7 @@ public void visibleWhere( final Predicate predicate = association -> { final List facets = association.streamFacets() .filter(facet -> facet instanceof WhereValueFacet - && facet instanceof HiddenFacet) + && facet instanceof HiddenFacetForLayout) .collect(Collectors.toList()); for (Facet facet : facets) { final WhereValueFacet wawF = (WhereValueFacet) facet; diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/ObjectAssociationAbstractTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/ObjectAssociationAbstractTest.java index b12bb89f02d..6059e7823c9 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/ObjectAssociationAbstractTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/ObjectAssociationAbstractTest.java @@ -28,7 +28,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.inject.ServiceInjector; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.base._Casts; @@ -40,6 +39,7 @@ import org.apache.causeway.core.metamodel.facets.FacetedMethod; import org.apache.causeway.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet; import org.apache.causeway.core.metamodel.facets.properties.choices.PropertyChoicesFacet; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; import org.apache.causeway.core.metamodel.object.ManagedObject; @@ -106,15 +106,14 @@ public void toDefault(final ManagedObject target) { @Override public UsabilityContext createUsableInteractionContext( - final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy) { return null; } @Override public VisibilityContext createVisibleInteractionContext( final ManagedObject targetObjectAdapter, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { return null; } diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/ObjectAssociationAbstractTest_alwaysHidden.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/ObjectAssociationAbstractTest_alwaysHidden.java index d30bd6ef882..652f19c485d 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/ObjectAssociationAbstractTest_alwaysHidden.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/ObjectAssociationAbstractTest_alwaysHidden.java @@ -35,10 +35,12 @@ import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facetapi.Facet; +import org.apache.causeway.core.metamodel.facetapi.Facet.Precedence; import org.apache.causeway.core.metamodel.facetapi.FacetUtil; import org.apache.causeway.core.metamodel.facetapi.FeatureType; import org.apache.causeway.core.metamodel.facets.FacetedMethod; -import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetAbstract; +import org.apache.causeway.core.metamodel.facets.members.hidden.HiddenFacetForLayoutAbstract; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; import org.apache.causeway.core.metamodel.object.ManagedObject; @@ -103,15 +105,14 @@ public void toDefault(final ManagedObject target) { @Override public UsabilityContext createUsableInteractionContext( - final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy) { return null; } @Override public VisibilityContext createVisibleInteractionContext( final ManagedObject targetObjectAdapter, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { return null; } @@ -157,7 +158,7 @@ public void whenNone() throws Exception { public void whenNoop() throws Exception { // given - addHiddenFacet(Where.EVERYWHERE, facetedMethod, true); + addHiddenFacet(Where.EVERYWHERE, facetedMethod, Precedence.FALLBACK); // when, then assertFalse(objectAssociation.isAlwaysHidden()); @@ -167,7 +168,7 @@ public void whenNoop() throws Exception { public void whenNotAlwaysEverywhere() throws Exception { // given - addHiddenFacet(Where.EVERYWHERE, facetedMethod, false); + addHiddenFacet(Where.EVERYWHERE, facetedMethod, Precedence.DEFAULT); // when, then assertThat(objectAssociation.isAlwaysHidden(), is(true)); @@ -177,7 +178,7 @@ public void whenNotAlwaysEverywhere() throws Exception { public void whenAlwaysNotEverywhere() throws Exception { // given - addHiddenFacet(Where.OBJECT_FORMS, facetedMethod, false); + addHiddenFacet(Where.OBJECT_FORMS, facetedMethod, Precedence.DEFAULT); // when, then assertFalse(objectAssociation.isAlwaysHidden()); @@ -187,7 +188,7 @@ public void whenAlwaysNotEverywhere() throws Exception { public void whenAlwaysEverywhere() throws Exception { // given - addHiddenFacet(Where.EVERYWHERE, facetedMethod, false); + addHiddenFacet(Where.EVERYWHERE, facetedMethod, Precedence.DEFAULT); // when, then assertTrue(objectAssociation.isAlwaysHidden()); @@ -197,7 +198,7 @@ public void whenAlwaysEverywhere() throws Exception { public void whenAlwaysAnywhere() throws Exception { // given - addHiddenFacet(Where.ANYWHERE, facetedMethod, false); + addHiddenFacet(Where.ANYWHERE, facetedMethod, Precedence.DEFAULT); // when, then assertTrue(objectAssociation.isAlwaysHidden()); @@ -206,14 +207,10 @@ public void whenAlwaysAnywhere() throws Exception { private static void addHiddenFacet( final Where where, final FacetedMethod holder, - final boolean noop) { - - var precedence = noop - ? Facet.Precedence.FALLBACK - : Facet.Precedence.DEFAULT; + final Precedence precedence) { FacetUtil.addFacet( - new HiddenFacetAbstract(where, holder, precedence) { + new HiddenFacetForLayoutAbstract(where, holder, precedence) { @Override protected String hiddenReason(final ManagedObject target, final Where whereContext) { return null; diff --git a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationAbstractTest.java b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationAbstractTest.java index b774a2e6283..11292a49af3 100644 --- a/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationAbstractTest.java +++ b/core/mmtest/src/test/java/org/apache/causeway/core/metamodel/spec/impl/OneToOneAssociationAbstractTest.java @@ -28,7 +28,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.inject.ServiceInjector; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.commons.internal.base._Casts; @@ -38,6 +37,7 @@ import org.apache.causeway.core.metamodel.facetapi.Facet.Precedence; import org.apache.causeway.core.metamodel.facets.FacetedMethod; import org.apache.causeway.core.metamodel.facets.propcoll.memserexcl.SnapshotExcludeFacet; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; import org.apache.causeway.core.metamodel.object.ManagedObject; @@ -73,7 +73,7 @@ public void setup() { facetedMethod.getFeatureIdentifier(), facetedMethod, objectSpecification) { private static final long serialVersionUID = 1L; - + @Override public ManagedObject get( final ManagedObject fromObject, @@ -104,15 +104,14 @@ public void toDefault(final ManagedObject target) { @Override public UsabilityContext createUsableInteractionContext( - final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final ManagedObject target, final InteractionInitiatedBy interactionInitiatedBy) { return null; } @Override public VisibilityContext createVisibleInteractionContext( final ManagedObject targetObjectAdapter, final InteractionInitiatedBy interactionInitiatedBy, - final Where where) { + final VisibilityConstraint visibilityConstraint) { return null; } diff --git a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/command/CommandExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/command/CommandExecutorServiceDefault.java index 7bb3af9c740..a21fa54a1b4 100644 --- a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/command/CommandExecutorServiceDefault.java +++ b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/command/CommandExecutorServiceDefault.java @@ -50,6 +50,7 @@ import org.apache.causeway.commons.internal.exceptions._Exceptions; import org.apache.causeway.core.metamodel.commons.UtilStr; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.ManagedObjects; import org.apache.causeway.core.metamodel.services.publishing.CommandPublisher; @@ -149,10 +150,9 @@ private Try doExecute( Try result = transactionService.callWithinCurrentTransactionElseCreateNew( () -> { - if (interactionContextPolicy == InteractionContextPolicy.NO_SWITCH) { - // short-circuit + if (interactionContextPolicy == InteractionContextPolicy.NO_SWITCH) + // short-circuit return doExecuteCommand(dto); - } return sudoService.call( context -> interactionContextPolicy.mapper.apply(context, dto), () -> doExecuteCommand(dto)); @@ -199,7 +199,7 @@ private Bookmark doExecuteCommand(final CommandDto dto) { var interactionHead = objectAction.interactionHead(targetAdapter); - var resultAdapter = objectAction.execute(interactionHead, argAdapters, InteractionInitiatedBy.FRAMEWORK); + var resultAdapter = objectAction.execute(interactionHead, argAdapters, InteractionInitiatedBy.FRAMEWORK, WhatViewer.noViewer()); // flush any PersistenceCommands pending // (else might get transient objects for the return value) @@ -213,10 +213,9 @@ private Bookmark doExecuteCommand(final CommandDto dto) { // Object unused = priorExecution.getReturned(); // - if(resultAdapter != null) { - return ManagedObjects.bookmark(resultAdapter) + if(resultAdapter != null) + return ManagedObjects.bookmark(resultAdapter) .orElse(null); - } } else { var propertyDto = (PropertyDto) memberDto; @@ -226,10 +225,9 @@ private Bookmark doExecuteCommand(final CommandDto dto) { var targetAdapter = valueMarshaller.recoverReferenceFrom(targetOidDto); - if(ManagedObjects.isNullOrUnspecifiedOrEmpty(targetAdapter)) { - throw _Exceptions.unrecoverable("cannot recreate ManagedObject from bookmark %s", + if(ManagedObjects.isNullOrUnspecifiedOrEmpty(targetAdapter)) + throw _Exceptions.unrecoverable("cannot recreate ManagedObject from bookmark %s", Bookmark.forOidDto(targetOidDto)); - } var property = findOneToOneAssociation(targetAdapter, logicalMemberIdentifier); var newValueAdapter = valueMarshaller.recoverPropertyFrom(propertyDto); @@ -249,12 +247,9 @@ private String targetBookmarkStrFor(final CommandDto dto) { private String argStrFor(final CommandDto dto) { var memberDto = dto.getMember(); - if(memberDto instanceof ActionDto) { - var actionDto = (ActionDto) memberDto; - return paramNameArgValuesFor(actionDto); - } - if(memberDto instanceof PropertyDto) { - var propertyDto = (PropertyDto) memberDto; + if(memberDto instanceof ActionDto actionDto) + return paramNameArgValuesFor(actionDto); + if(memberDto instanceof PropertyDto propertyDto) { var proposedValue = valueMarshaller.recoverPropertyFrom(propertyDto); return proposedValue.getTitle(); } @@ -274,9 +269,8 @@ private static ObjectAction findObjectAction( var localActionId = localPartOf(logicalMemberIdentifier); var objectAction = findActionElseNull(objectSpecification, localActionId); - if(objectAction == null) { - throw new RuntimeException(String.format("Unknown action '%s'", localActionId)); - } + if(objectAction == null) + throw new RuntimeException(String.format("Unknown action '%s'", localActionId)); return objectAction; } @@ -292,9 +286,8 @@ private static OneToOneAssociation findOneToOneAssociation( var objectSpecification = targetAdapter.objSpec(); var property = findOneToOneAssociationElseNull(objectSpecification, localPropertyId); - if(property == null) { - throw new RuntimeException(String.format("Unknown property '%s'", localPropertyId)); - } + if(property == null) + throw new RuntimeException(String.format("Unknown property '%s'", localPropertyId)); return property; } diff --git a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java index 616808c4ad8..4589ff3604a 100644 --- a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java +++ b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/executor/MemberExecutorServiceDefault.java @@ -18,10 +18,18 @@ */ package org.apache.causeway.core.runtimeservices.executor; -import static org.apache.causeway.core.metamodel.facets.members.publish.command.CommandPublishingFacet.isPublishingEnabled; - import java.util.Optional; +import jakarta.annotation.Priority; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Provider; + +import org.jspecify.annotations.NonNull; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + import org.apache.causeway.applib.annotation.PriorityPrecedence; import org.apache.causeway.applib.services.clock.ClockService; import org.apache.causeway.applib.services.command.Command; @@ -49,6 +57,7 @@ import org.apache.causeway.core.metamodel.facetapi.FacetHolder; import org.apache.causeway.core.metamodel.facets.members.publish.execution.ExecutionPublishingFacet; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.ManagedObjects; import org.apache.causeway.core.metamodel.object.MmEntityUtils; @@ -65,14 +74,9 @@ import org.apache.causeway.core.metamodel.spec.feature.ObjectMember; import org.apache.causeway.core.runtimeservices.CausewayModuleCoreRuntimeServices; import org.apache.causeway.schema.ixn.v2.ActionInvocationDto; -import org.jspecify.annotations.NonNull; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Service; -import jakarta.annotation.Priority; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import jakarta.inject.Provider; +import static org.apache.causeway.core.metamodel.facets.members.publish.command.CommandPublishingFacet.isPublishingEnabled; + import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; @@ -139,7 +143,7 @@ private ManagedObject invokeActionInternally( final ObjectAction owningAction = actionExecutor.getOwningAction(); final InteractionHead head = actionExecutor.getHead(); - + final Can argumentAdapters = actionExecutor.getArguments(); final InteractionInitiatedBy interactionInitiatedBy = actionExecutor.getInteractionInitiatedBy(); // final MethodFacade methodFacade, @@ -213,7 +217,7 @@ private ManagedObject invokeActionInternally( executionPublisher().publishActionInvocation(priorExecution); } - var result = resultFilteredHonoringVisibility(returnedAdapter, interactionInitiatedBy); + var result = resultFilteredHonoringVisibility(returnedAdapter, interactionInitiatedBy, actionExecutor.whatViewer()); _Xray.exitInvocation(xrayHandle); return result; } @@ -275,11 +279,10 @@ private ManagedObject setOrClearPropertyInternally( // TODO: should also sync DTO's 'threw' attribute here...? var executionExceptionIfAny = priorExecution.getThrew(); - if(executionExceptionIfAny != null) { - throw executionExceptionIfAny instanceof RuntimeException - ? ((RuntimeException)executionExceptionIfAny) + if(executionExceptionIfAny != null) + throw executionExceptionIfAny instanceof RuntimeException r + ? r : new RuntimeException(executionExceptionIfAny); - } // publish (if not a contributed association, query-only mixin) if (ExecutionPublishingFacet.isPublishingEnabled(propertyModifier.getFacetHolder())) { @@ -307,17 +310,14 @@ private Object invokeMethodPassThrough( private void setCommandResultIfEntity( final Command command, final ManagedObject resultAdapter) { - if(command.getResult() != null) { - // don't trample over any existing result, eg subsequent mixins. + if(command.getResult() != null) + // don't trample over any existing result, eg subsequent mixins. return; - } - if(ManagedObjects.isNullOrUnspecifiedOrEmpty(resultAdapter)) { - return; - } + if(ManagedObjects.isNullOrUnspecifiedOrEmpty(resultAdapter)) + return; var entityState = resultAdapter.getEntityState(); - if(!entityState.isPersistable()) { - return; - } + if(!entityState.isPersistable()) + return; if(entityState.isHollow() || entityState.isDetached()) { // ensure that any still-to-be-persisted adapters get persisted to DB. @@ -335,18 +335,17 @@ private void setCommandResultIfEntity( private ManagedObject resultFilteredHonoringVisibility( final ManagedObject resultAdapter, - final InteractionInitiatedBy interactionInitiatedBy) { + final InteractionInitiatedBy interactionInitiatedBy, + final WhatViewer whatViewer) { - if(ManagedObjects.isNullOrUnspecifiedOrEmpty(resultAdapter)) { - return resultAdapter; - } + if(ManagedObjects.isNullOrUnspecifiedOrEmpty(resultAdapter)) + return resultAdapter; if (!getConfiguration().core().metaModel().filterVisibility() - || resultAdapter instanceof PackedManagedObject) { - return resultAdapter; - } + || resultAdapter instanceof PackedManagedObject) + return resultAdapter; - return MmVisibilityUtils.isVisible(resultAdapter, interactionInitiatedBy) + return MmVisibilityUtils.isVisible(resultAdapter, interactionInitiatedBy, whatViewer) ? resultAdapter : null; } diff --git a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/handlers/DomainObjectInvocationHandler.java b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/handlers/DomainObjectInvocationHandler.java index 091d2dd3c20..d410811c297 100644 --- a/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/handlers/DomainObjectInvocationHandler.java +++ b/core/runtimeservices/src/main/java/org/apache/causeway/core/runtimeservices/wrapper/handlers/DomainObjectInvocationHandler.java @@ -26,7 +26,6 @@ import org.jspecify.annotations.Nullable; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.exceptions.recoverable.InteractionException; import org.apache.causeway.applib.id.LogicalType; import org.apache.causeway.applib.services.wrapper.DisabledException; @@ -46,12 +45,14 @@ import org.apache.causeway.commons.internal.collections._Arrays; import org.apache.causeway.commons.internal.exceptions._Exceptions; import org.apache.causeway.commons.internal.reflection._GenericResolver; +import org.apache.causeway.core.interaction.core.InteractionConstraint; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.consent.InteractionResult; import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facets.ImperativeFacet; import org.apache.causeway.core.metamodel.facets.ImperativeFacet.Intent; import org.apache.causeway.core.metamodel.interactions.InteractionHead; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.MmAssertionUtils; import org.apache.causeway.core.metamodel.object.MmEntityUtils; @@ -97,15 +98,14 @@ final class DomainObjectInvocationHandler } @Override - public Object invoke(WrapperInvocation wrapperInvocation) throws Throwable { + public Object invoke(final WrapperInvocation wrapperInvocation) throws Throwable { final Object target = wrapperInvocation.origin().pojo(); final Method method = wrapperInvocation.method(); if (classMetaData().isObjectMethod(method) - || isEnhancedEntityMethod(method)) { - return method.invoke(target, wrapperInvocation.args()); - } + || isEnhancedEntityMethod(method)) + return method.invoke(target, wrapperInvocation.args()); final ManagedObject targetAdapter = mmc().getObjectManager().adapt(target); @@ -113,77 +113,64 @@ public Object invoke(WrapperInvocation wrapperInvocation) throws Throwable { MmAssertionUtils.assertIsBookmarkSupported(targetAdapter); } - if (classMetaData.isTitleMethod(method) ) { - return handleTitleMethod(wrapperInvocation, targetAdapter); - } + if (classMetaData.isTitleMethod(method) ) + return handleTitleMethod(wrapperInvocation, targetAdapter); var resolvedMethod = _GenericResolver.resolveMethod(method, targetAdapter.objSpec().getCorrespondingClass()) .orElseThrow(); if(!wrapperInvocation.origin().isFallback()) { - if (classMetaData.isOriginMethod(method)) { - return wrapperInvocation.origin(); - } + if (classMetaData.isOriginMethod(method)) + return wrapperInvocation.origin(); // save method, through the proxy - if (classMetaData.isSaveMethod(method)) { - return handleSaveMethod(wrapperInvocation, targetAdapter, targetAdapter.objSpec()); - } + if (classMetaData.isSaveMethod(method)) + return handleSaveMethod(wrapperInvocation, targetAdapter, targetAdapter.objSpec()); } var objectMember = targetAdapter.objSpec().getMemberElseFail(resolvedMethod); var intent = ImperativeFacet.getIntent(objectMember, resolvedMethod); - if(intent == Intent.CHECK_IF_HIDDEN || intent == Intent.CHECK_IF_DISABLED) { - throw _Exceptions.unsupportedOperation("Cannot invoke supporting method '%s'", objectMember.getId()); - } + if(intent == Intent.CHECK_IF_HIDDEN || intent == Intent.CHECK_IF_DISABLED) + throw _Exceptions.unsupportedOperation("Cannot invoke supporting method '%s'", objectMember.getId()); - if (intent == Intent.DEFAULTS || intent == Intent.CHOICES_OR_AUTOCOMPLETE) { - return method.invoke(target, wrapperInvocation.args()); - } + if (intent == Intent.DEFAULTS || intent == Intent.CHOICES_OR_AUTOCOMPLETE) + return method.invoke(target, wrapperInvocation.args()); if (objectMember instanceof OneToOneAssociation prop) { - if (intent == Intent.CHECK_IF_VALID || intent == Intent.MODIFY_PROPERTY_SUPPORTING) { - throw _Exceptions.unsupportedOperation("Cannot invoke supporting method for '%s'; use only property accessor/mutator", objectMember.getId()); - } + if (intent == Intent.CHECK_IF_VALID || intent == Intent.MODIFY_PROPERTY_SUPPORTING) + throw _Exceptions.unsupportedOperation("Cannot invoke supporting method for '%s'; use only property accessor/mutator", objectMember.getId()); - if (intent == Intent.ACCESSOR) { - return handleGetterMethodOnProperty(wrapperInvocation, targetAdapter, prop); - } + if (intent == Intent.ACCESSOR) + return handleGetterMethodOnProperty(wrapperInvocation, targetAdapter, prop); - if (intent == Intent.MODIFY_PROPERTY || intent == Intent.INITIALIZATION) { - return handleSetterMethodOnProperty(wrapperInvocation, targetAdapter, prop); - } + if (intent == Intent.MODIFY_PROPERTY || intent == Intent.INITIALIZATION) + return handleSetterMethodOnProperty(wrapperInvocation, targetAdapter, prop); } if (objectMember instanceof OneToManyAssociation coll) { - if (intent == Intent.CHECK_IF_VALID) { - throw _Exceptions.unsupportedOperation("Cannot invoke supporting method '%s'; use only collection accessor/mutator", objectMember.getId()); - } + if (intent == Intent.CHECK_IF_VALID) + throw _Exceptions.unsupportedOperation("Cannot invoke supporting method '%s'; use only collection accessor/mutator", objectMember.getId()); - if (intent == Intent.ACCESSOR) { - return handleGetterMethodOnCollection(wrapperInvocation, targetAdapter, coll, objectMember.getId()); - } + if (intent == Intent.ACCESSOR) + return handleGetterMethodOnCollection(wrapperInvocation, targetAdapter, coll, objectMember.getId()); } if (objectMember instanceof ObjectAction objectAction) { - if (intent == Intent.CHECK_IF_VALID) { - throw _Exceptions.unsupportedOperation("Cannot invoke supporting method '%s'; use only the 'invoke' method", objectMember.getId()); - } + if (intent == Intent.CHECK_IF_VALID) + throw _Exceptions.unsupportedOperation("Cannot invoke supporting method '%s'; use only the 'invoke' method", objectMember.getId()); if(targetAdapter.objSpec().isMixin()) { final ManagedObject managedMixee = wrapperInvocation.origin().managedMixee(); - if (managedMixee == null) { - throw _Exceptions.illegalState("Missing the required managedMixee for action '%s'", objectAction.getId()); - } + if (managedMixee == null) + throw _Exceptions.illegalState("Missing the required managedMixee for action '%s'", objectAction.getId()); MmAssertionUtils.assertIsBookmarkSupported(managedMixee); final ObjectMember mixinMember = determineMixinMember(managedMixee, objectAction); if (mixinMember != null) { - if(mixinMember instanceof ObjectAction) { - return handleActionMethod(wrapperInvocation, managedMixee, (ObjectAction)mixinMember); - } + if(mixinMember instanceof ObjectAction) + return handleActionMethod(wrapperInvocation, managedMixee, (ObjectAction)mixinMember); if(mixinMember instanceof OneToOneAssociation) { _Assert.assertEquals(0, wrapperInvocation.args().length); return handleGetterMethodOnProperty(wrapperInvocation, managedMixee, (OneToOneAssociation)mixinMember); @@ -192,9 +179,8 @@ public Object invoke(WrapperInvocation wrapperInvocation) throws Throwable { _Assert.assertEquals(0, wrapperInvocation.args().length); return handleGetterMethodOnCollection(wrapperInvocation, managedMixee, (OneToManyAssociation)mixinMember, objectMember.getId()); } - } else { - throw _Exceptions.illegalState("Could not locate mixin member for action '%s' on spec '%s'", objectAction.getId(), targetAdapter.objSpec()); - } + } else + throw _Exceptions.illegalState("Could not locate mixin member for action '%s' on spec '%s'", objectAction.getId(), targetAdapter.objSpec()); } // this is just a regular non-mixin action. @@ -208,7 +194,8 @@ private static ObjectMember determineMixinMember( final ManagedObject domainObjectAdapter, final ObjectAction objectAction) { - if(domainObjectAdapter == null) return null; + if(domainObjectAdapter == null) + return null; var specification = domainObjectAdapter.objSpec(); var objectActions = specification.streamAnyActions(MixedIn.INCLUDED); @@ -225,12 +212,6 @@ private static ObjectMember determineMixinMember( // throw new RuntimeException("Unable to find the mixed-in action corresponding to " + objectAction.getIdentifier().toFullIdentityString()); } - private InteractionInitiatedBy getInteractionInitiatedBy(final WrapperInvocation wrapperInvocation) { - return wrapperInvocation.syncControl().isSkipRules() - ? InteractionInitiatedBy.FRAMEWORK - : InteractionInitiatedBy.USER; - } - private boolean isEnhancedEntityMethod(final Method method) { return targetSpec.entityFacet() .map(entityFacet->entityFacet.isProxyEnhancement(method)) @@ -255,19 +236,19 @@ private Object handleSaveMethod( final ObjectSpecification targetNoSpec) { runValidationTask(wrapperInvocation, ()->{ + var iConstraint = iConstraint(wrapperInvocation); var interactionResult = - targetNoSpec.isValidResult(targetAdapter, getInteractionInitiatedBy(wrapperInvocation)); + targetNoSpec.isValidResult(targetAdapter, iConstraint.initiatedBy()); notifyListenersAndVetoIfRequired(interactionResult); }); var spec = targetAdapter.objSpec(); - if(spec.isEntity()) { - return runExecutionTask(wrapperInvocation, ()->{ + if(spec.isEntity()) + return runExecutionTask(wrapperInvocation, ()->{ MmEntityUtils.persistInCurrentTransaction(targetAdapter); return null; }, ()->new ExceptionLogger("persist", targetAdapter)); - } return null; } @@ -278,14 +259,14 @@ private Object handleGetterMethodOnProperty( zeroArgsElseThrow(wrapperInvocation.args(), "get"); + var iConstraint = iConstraint(wrapperInvocation); runValidationTask(wrapperInvocation, ()->{ - checkVisibility(wrapperInvocation, targetAdapter, property); + checkVisibility(iConstraint, targetAdapter, property); }); return runExecutionTask(wrapperInvocation, ()->{ - var interactionInitiatedBy = getInteractionInitiatedBy(wrapperInvocation); - var currentReferencedAdapter = property.get(targetAdapter, interactionInitiatedBy); + var currentReferencedAdapter = property.get(targetAdapter, iConstraint.initiatedBy()); var currentReferencedObj = MmUnwrapUtils.single(currentReferencedAdapter); @@ -304,16 +285,17 @@ private Object handleSetterMethodOnProperty( var singleArg = singleArgUnderlyingElseNull(wrapperInvocation.args(), "setter"); + var iConstraint = iConstraint(wrapperInvocation); runValidationTask(wrapperInvocation, ()->{ - checkVisibility(wrapperInvocation, targetAdapter, property); - checkUsability(wrapperInvocation, targetAdapter, property); + checkVisibility(iConstraint, targetAdapter, property); + checkUsability(iConstraint, targetAdapter, property); }); var argumentAdapter = property.getObjectManager().adapt(singleArg); runValidationTask(wrapperInvocation, ()->{ var interactionResult = property.isAssociationValid( - targetAdapter, argumentAdapter, getInteractionInitiatedBy(wrapperInvocation)) + targetAdapter, argumentAdapter, iConstraint.initiatedBy()) .getInteractionResult(); notifyListenersAndVetoIfRequired(interactionResult); }); @@ -322,7 +304,7 @@ targetAdapter, argumentAdapter, getInteractionInitiatedBy(wrapperInvocation)) .forProperty(InteractionHead.regular(targetAdapter), property, argumentAdapter)); return runExecutionTask(wrapperInvocation, ()->{ - property.set(targetAdapter, argumentAdapter, getInteractionInitiatedBy(wrapperInvocation)); + property.set(targetAdapter, argumentAdapter, iConstraint.initiatedBy()); return null; }, ()->new ExceptionLogger("setter " + property.getId(), targetAdapter)); } @@ -335,14 +317,14 @@ private Object handleGetterMethodOnCollection( zeroArgsElseThrow(wrapperInvocation.args(), "get"); + var iConstraint = iConstraint(wrapperInvocation); runValidationTask(wrapperInvocation, ()->{ - checkVisibility(wrapperInvocation, targetAdapter, collection); + checkVisibility(iConstraint, targetAdapter, collection); }); return runExecutionTask(wrapperInvocation, ()->{ - var interactionInitiatedBy = getInteractionInitiatedBy(wrapperInvocation); - var currentReferencedAdapter = collection.get(targetAdapter, interactionInitiatedBy); + var currentReferencedAdapter = collection.get(targetAdapter, iConstraint.initiatedBy()); var currentReferencedObj = MmUnwrapUtils.single(currentReferencedAdapter); @@ -369,20 +351,18 @@ private Object handleGetterMethodOnCollection( private Collection wrapCollection( final Collection collectionToLookup, final OneToManyAssociation otma) { - if(proxyGenerator == null) { - throw new IllegalStateException("Unable to create proxy for collection; " + if(proxyGenerator == null) + throw new IllegalStateException("Unable to create proxy for collection; " + "proxyContextHandler not provided"); - } return proxyGenerator.collectionProxy(collectionToLookup, otma); } private Map wrapMap( final Map mapToLookup, final OneToManyAssociation otma) { - if(proxyGenerator == null) { - throw new IllegalStateException("Unable to create proxy for collection; " + if(proxyGenerator == null) + throw new IllegalStateException("Unable to create proxy for collection; " + "proxyContextHandler not provided"); - } return proxyGenerator.mapProxy(mapToLookup, otma); } @@ -403,9 +383,10 @@ private Object handleActionMethod( : ManagedObject.empty(paramSpec); })); + var iConstraint = iConstraint(wrapperInvocation); runValidationTask(wrapperInvocation, ()->{ - checkVisibility(wrapperInvocation, targetAdapter, objectAction); - checkUsability(wrapperInvocation, targetAdapter, objectAction); + checkVisibility(iConstraint, targetAdapter, objectAction); + checkUsability(iConstraint, targetAdapter, objectAction); checkValidity(wrapperInvocation, head, objectAction, argAdapters); }); @@ -413,11 +394,7 @@ private Object handleActionMethod( .forAction(head, objectAction, argAdapters)); return runExecutionTask(wrapperInvocation, ()->{ - var interactionInitiatedBy = getInteractionInitiatedBy(wrapperInvocation); - - var returnedAdapter = objectAction.execute( - head, argAdapters, - interactionInitiatedBy); + var returnedAdapter = objectAction.execute(head, argAdapters, iConstraint.initiatedBy(), iConstraint.whatViewer()); return MmUnwrapUtils.single(returnedAdapter); }, ()->new ExceptionLogger("action " + objectAction.getId(), targetAdapter)); } @@ -428,45 +405,31 @@ private void checkValidity( final ObjectAction objectAction, final Can argAdapters) { - var interactionResult = objectAction - .isArgumentSetValid(head, argAdapters, getInteractionInitiatedBy(wrapperInvocation)) + var interactionResult = objectAction.isArgumentSetValid(head, argAdapters, iConstraint(wrapperInvocation).initiatedBy()) .getInteractionResult(); notifyListenersAndVetoIfRequired(interactionResult); } private Object underlying(final Object arg) { - if (arg instanceof WrappingObject wrappingObject) { - return wrappingObject.__causeway_origin().pojo(); - } else { - return arg; - } + return (arg instanceof WrappingObject wrappingObject) + ? wrappingObject.__causeway_origin().pojo() + : arg; } - /** - * REVIEW: ideally should provide some way to allow to caller to indicate the 'where' context. Having - * a hard-coded value like this is an approximation. - */ - private final Where where = Where.ANYWHERE; - private void checkVisibility( - final WrapperInvocation wrapperInvocation, - final ManagedObject targetObjectAdapter, + final InteractionConstraint iConstraint, + final ManagedObject targetMo, final ObjectMember objectMember) { - - var visibleConsent = objectMember.isVisible(targetObjectAdapter, getInteractionInitiatedBy(wrapperInvocation), where); - var interactionResult = visibleConsent.getInteractionResult(); + var interactionResult = objectMember.isVisible(targetMo, iConstraint.initiatedBy(), iConstraint.asVisibilityConstraint()) + .getInteractionResult(); notifyListenersAndVetoIfRequired(interactionResult); } private void checkUsability( - final WrapperInvocation wrapperInvocation, - final ManagedObject targetObjectAdapter, + final InteractionConstraint iConstraint, + final ManagedObject targetMo, final ObjectMember objectMember) { - - var interactionResult = objectMember.isUsable( - targetObjectAdapter, - getInteractionInitiatedBy(wrapperInvocation), - where) + var interactionResult = objectMember.isUsable(targetMo, iConstraint.initiatedBy(), iConstraint.asVisibilityConstraint()) .getInteractionResult(); notifyListenersAndVetoIfRequired(interactionResult); } @@ -477,9 +440,8 @@ private void notifyListenersAndVetoIfRequired(final InteractionResult interactio var interactionEvent = interactionResult.interactionEvent(); mmc().getWrapperFactory().notifyListeners(interactionEvent); - if (interactionEvent.isVeto()) { - throw toException(interactionEvent); - } + if (interactionEvent.isVeto()) + throw toException(interactionEvent); } /** @@ -488,21 +450,14 @@ private void notifyListenersAndVetoIfRequired(final InteractionResult interactio * and returns it. */ private InteractionException toException(final InteractionEvent interactionEvent) { - if (!interactionEvent.isVeto()) { - throw new IllegalArgumentException("Provided interactionEvent must be a veto"); - } - if (interactionEvent instanceof ValidityEvent) { - final ValidityEvent validityEvent = (ValidityEvent) interactionEvent; - return new InvalidException(validityEvent); - } - if (interactionEvent instanceof VisibilityEvent) { - final VisibilityEvent visibilityEvent = (VisibilityEvent) interactionEvent; - return new HiddenException(visibilityEvent); - } - if (interactionEvent instanceof UsabilityEvent) { - final UsabilityEvent usabilityEvent = (UsabilityEvent) interactionEvent; - return new DisabledException(usabilityEvent); - } + if (!interactionEvent.isVeto()) + throw new IllegalArgumentException("Provided interactionEvent must be a veto"); + if (interactionEvent instanceof final ValidityEvent validityEvent) + return new InvalidException(validityEvent); + if (interactionEvent instanceof final VisibilityEvent visibilityEvent) + return new HiddenException(visibilityEvent); + if (interactionEvent instanceof final UsabilityEvent usabilityEvent) + return new DisabledException(usabilityEvent); throw new IllegalArgumentException("Provided interactionEvent must be a VisibilityEvent, UsabilityEvent or a ValidityEvent"); } @@ -512,8 +467,18 @@ private MetaModelContext mmc() { return targetSpec.getMetaModelContext(); } + private static InteractionConstraint iConstraint(final WrapperInvocation wrapperInvocation) { + return new InteractionConstraint( + new WhatViewer(wrapperInvocation.syncControl().viewerId()), + wrapperInvocation.syncControl().isSkipRules() + ? InteractionInitiatedBy.FRAMEWORK + : InteractionInitiatedBy.USER, + wrapperInvocation.syncControl().where()); + } + private void runValidationTask(final WrapperInvocation wrapperInvocation, final Runnable task) { - if(wrapperInvocation.syncControl().isSkipRules()) return; + if(wrapperInvocation.syncControl().isSkipRules()) + return; try { task.run(); } catch(Exception ex) { @@ -531,7 +496,8 @@ private void handleCommandListeners( if(commandRecordSupplier!=null && wrapperInvocation.syncControl().commandListeners().isNotEmpty()) { var commandRecord = commandRecordSupplier.get(); - if(commandRecord==null) return; + if(commandRecord==null) + return; wrapperInvocation.syncControl().commandListeners() .forEach(listener->listener .onCommand( @@ -545,7 +511,8 @@ private X runExecutionTask( final WrapperInvocation wrapperInvocation, final Supplier task, final Supplier exceptionLoggerSupplier) { - if(wrapperInvocation.syncControl().isSkipExecute()) return null; + if(wrapperInvocation.syncControl().isSkipExecute()) + return null; try { return task.get(); } catch(Exception ex) { @@ -570,21 +537,19 @@ private Object handleException( } private Object singleArgUnderlyingElseNull(final Object[] args, final String name) { - if (args.length != 1) { - throw _Exceptions.illegalArgument("Invoking '%s' should only have a single argument", name); - } + if (args.length != 1) + throw _Exceptions.illegalArgument("Invoking '%s' should only have a single argument", name); var argumentObj = underlying(args[0]); return argumentObj; } private void zeroArgsElseThrow(final Object[] args, final String name) { - if (!_NullSafe.isEmpty(args)) { - throw _Exceptions.illegalArgument("Invoking '%s' should have no arguments", name); - } + if (!_NullSafe.isEmpty(args)) + throw _Exceptions.illegalArgument("Invoking '%s' should have no arguments", name); } record ExceptionLogger(String what, ManagedObject mo) { - String msg(Exception ex) { + String msg(final Exception ex) { LogicalType logicalType = mo.objSpec().logicalType(); String id = mo.isBookmarkMemoized() ? mo.getBookmarkElseFail().identifier() diff --git a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationFacet.java b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationFacet.java index 4a58b04e15c..9cfc85ffd2c 100644 --- a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationFacet.java +++ b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationFacet.java @@ -18,7 +18,6 @@ */ package org.apache.causeway.extensions.secman.integration.facets; -import org.apache.causeway.core.metamodel.facetapi.Facet; import org.apache.causeway.core.metamodel.interactions.DisablingInteractionAdvisor; import org.apache.causeway.core.metamodel.interactions.HidingInteractionAdvisor; @@ -27,7 +26,7 @@ * depending on the tenancy. */ public interface TenantedAuthorizationFacet -extends Facet, HidingInteractionAdvisor, DisablingInteractionAdvisor { +extends HidingInteractionAdvisor, DisablingInteractionAdvisor { @Override public default boolean isObjectTypeSpecific() { diff --git a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationFacetDefault.java b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationFacetDefault.java index d1fba456caf..f0ec0530d44 100644 --- a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationFacetDefault.java +++ b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/facets/TenantedAuthorizationFacetDefault.java @@ -27,8 +27,8 @@ import org.apache.causeway.applib.services.user.UserService; import org.apache.causeway.core.metamodel.consent.Consent.VetoReason; import org.apache.causeway.core.metamodel.facetapi.Facet; -import org.apache.causeway.core.metamodel.facetapi.FacetAbstract; import org.apache.causeway.core.metamodel.facetapi.FacetHolder; +import org.apache.causeway.core.metamodel.facetapi.FacetUtil; import org.apache.causeway.core.metamodel.interactions.InteractionHead; import org.apache.causeway.core.metamodel.interactions.use.UsabilityContext; import org.apache.causeway.core.metamodel.interactions.vis.VisibilityContext; @@ -36,32 +36,17 @@ import org.apache.causeway.extensions.secman.applib.user.dom.ApplicationUser; import org.apache.causeway.extensions.secman.applib.user.dom.ApplicationUserRepository; -public class TenantedAuthorizationFacetDefault -extends FacetAbstract -implements TenantedAuthorizationFacet { - - private static Class type() { - return TenantedAuthorizationFacet.class; - } - - private final List evaluators; - private final ApplicationUserRepository applicationUserRepository; - private final UserService userService; - private final Provider queryResultsCacheProvider; - - public TenantedAuthorizationFacetDefault( - final List evaluators, - final ApplicationUserRepository applicationUserRepository, - final Provider queryResultsCacheProvider, - final UserService userService, - final FacetHolder holder) { - super(type(), holder); - this.evaluators = evaluators; - this.applicationUserRepository = applicationUserRepository; - this.queryResultsCacheProvider = queryResultsCacheProvider; - this.userService = userService; - } - +public record TenantedAuthorizationFacetDefault( + List evaluators, + ApplicationUserRepository applicationUserRepository, + Provider queryResultsCacheProvider, + UserService userService, + FacetHolder facetHolder + ) implements TenantedAuthorizationFacet { + + @Override public Class facetType() { return TenantedAuthorizationFacet.class; } + @Override public Precedence precedence() { return Precedence.DEFAULT; } + @Override public String hides(final VisibilityContext ic) { return evaluate(ApplicationTenancyEvaluator::hides, ic.head()) @@ -119,5 +104,10 @@ protected ApplicationUser findApplicationUser(final String userName) { protected ApplicationUser findApplicationUserNoCache(final String userName) { return applicationUserRepository.findByUsername(userName).orElse(null); } + + @Override + public String toString() { + return FacetUtil.toString(this); + } } diff --git a/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_MixinDomainWithPdfJsViewer_IntegTest.dump_facets.approved.xml b/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_MixinDomainWithPdfJsViewer_IntegTest.dump_facets.approved.xml index 46d9df30b91..c78cf71aa25 100644 --- a/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_MixinDomainWithPdfJsViewer_IntegTest.dump_facets.approved.xml +++ b/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_MixinDomainWithPdfJsViewer_IntegTest.dump_facets.approved.xml @@ -59,8 +59,8 @@ - - + + @@ -257,9 +257,9 @@ - + - + @@ -414,9 +414,9 @@ - + - + @@ -675,9 +675,9 @@ - + - + @@ -839,9 +839,9 @@ - + - + @@ -950,9 +950,9 @@ - + - + @@ -1061,9 +1061,9 @@ - + - + @@ -1192,8 +1192,8 @@ - - + + diff --git a/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_MixinDomain_IntegTest.dump_facets.approved.xml b/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_MixinDomain_IntegTest.dump_facets.approved.xml index 029e8782a27..fbb05f8aee1 100644 --- a/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_MixinDomain_IntegTest.dump_facets.approved.xml +++ b/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_MixinDomain_IntegTest.dump_facets.approved.xml @@ -59,8 +59,8 @@ - - + + @@ -250,9 +250,9 @@ - + - + @@ -407,9 +407,9 @@ - + - + @@ -668,9 +668,9 @@ - + - + @@ -832,9 +832,9 @@ - + - + @@ -943,9 +943,9 @@ - + - + @@ -1054,9 +1054,9 @@ - + - + @@ -1185,8 +1185,8 @@ - - + + diff --git a/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_PropDomainWithPdfjsViewer_IntegTest.dump_facets.approved.xml b/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_PropDomainWithPdfjsViewer_IntegTest.dump_facets.approved.xml index 46279cff1f0..11f5bb64cdd 100644 --- a/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_PropDomainWithPdfjsViewer_IntegTest.dump_facets.approved.xml +++ b/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_PropDomainWithPdfjsViewer_IntegTest.dump_facets.approved.xml @@ -59,8 +59,8 @@ - - + + @@ -246,9 +246,9 @@ - + - + @@ -403,9 +403,9 @@ - + - + @@ -664,9 +664,9 @@ - + - + @@ -828,9 +828,9 @@ - + - + @@ -939,9 +939,9 @@ - + - + @@ -1050,9 +1050,9 @@ - + - + diff --git a/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_PropDomain_IntegTest.dump_facets.approved.xml b/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_PropDomain_IntegTest.dump_facets.approved.xml index 8af28dc419b..27b3c68f9c0 100644 --- a/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_PropDomain_IntegTest.dump_facets.approved.xml +++ b/extensions/vw/pdfjs/metamodel/src/test/java/org/apache/causeway/extensions/pdfjs/metamodel/PdfjsViewer_PropDomain_IntegTest.dump_facets.approved.xml @@ -59,8 +59,8 @@ - - + + @@ -239,9 +239,9 @@ - + - + @@ -396,9 +396,9 @@ - + - + @@ -657,9 +657,9 @@ - + - + @@ -821,9 +821,9 @@ - + - + @@ -932,9 +932,9 @@ - + - + @@ -1043,9 +1043,9 @@ - + - + diff --git a/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/publishing/PublishingTestFactoryJpa.java b/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/publishing/PublishingTestFactoryJpa.java index 77805fae6c1..604c7dfb67f 100644 --- a/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/publishing/PublishingTestFactoryJpa.java +++ b/regressiontests/base-jpa/src/main/java/org/apache/causeway/testdomain/jpa/publishing/PublishingTestFactoryJpa.java @@ -43,6 +43,7 @@ import org.apache.causeway.commons.internal.debug._Probe; import org.apache.causeway.commons.internal.exceptions._Exceptions; import org.apache.causeway.commons.internal.functions._Functions.CheckedConsumer; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteraction; import org.apache.causeway.core.metamodel.interactions.managed.PropertyInteraction; import org.apache.causeway.core.metamodel.object.ManagedObject; @@ -128,73 +129,55 @@ protected void programmaticExecution( // This test does not trigger command or execution publishing, however it does trigger // entity-change-publishing. - switch(context.scenario()) { - case ENTITY_CREATION: - - context.runGiven(); - //when + switch (context.scenario()) { + case ENTITY_CREATION -> { + context.runGiven(); + //when factoryService.detachedEntity(JpaBook.fromDto(BookDto.sample())); // should trigger an ObjectCreatedEvent - factoryService.detachedEntity(JpaBook.class); // should trigger a second ObjectCreatedEvent - break; - - case ENTITY_PERSISTING: - - context.runGiven(); - //when + factoryService.detachedEntity(JpaBook.class); // should trigger a second ObjectCreatedEvent + } + case ENTITY_PERSISTING -> { + context.runGiven(); + //when setupBookForJpa(); - break; - - case ENTITY_LOADING: - - context.runGiven(); - //when + } + case ENTITY_LOADING -> { + context.runGiven(); + //when withBookDo(book->{ assertNotNull(book); }); - break; - - case PROPERTY_UPDATE: - - withBookDo(book->{ - - context.runGiven(); - - // when - direct change (circumventing the framework) - context.changeProperty(()->book.setName("Book #2")); - - repository.persistAndFlush(book); - - }); + } + case PROPERTY_UPDATE -> withBookDo(book->{ - break; - case ACTION_INVOCATION: + context.runGiven(); - withBookDo(book->{ + // when - direct change (circumventing the framework) + context.changeProperty(()->book.setName("Book #2")); - context.runGiven(); + repository.persistAndFlush(book); - // when - direct action method invocation (circumventing the framework) - context.executeAction(()->book.doubleThePrice()); + }); + case ACTION_INVOCATION -> withBookDo(book->{ - repository.persistAndFlush(book); + context.runGiven(); - }); + // when - direct action method invocation (circumventing the framework) + context.executeAction(()->book.doubleThePrice()); - break; - case ENTITY_REMOVAL: + repository.persistAndFlush(book); - withBookDo(book->{ + }); + case ENTITY_REMOVAL -> withBookDo(book->{ - context.runGiven(); - //when - repository.removeAndFlush(book); - - }); + context.runGiven(); + //when + repository.removeAndFlush(book); - break; - default: - throw _Exceptions.unmatchedCase(context.scenario()); - } + }); + default -> throw _Exceptions.unmatchedCase(context.scenario()); + } + ; } @@ -206,53 +189,44 @@ protected void interactionApiExecution( context.bind(commitListener); - switch(context.scenario()) { - - case PROPERTY_UPDATE: - - withBookDo(book->{ - - context.runGiven(); - - // when - context.changeProperty(()->{ + switch (context.scenario()) { + case PROPERTY_UPDATE -> withBookDo(book->{ - var bookAdapter = objectManager.adapt(book); - var propertyInteraction = PropertyInteraction.start(bookAdapter, "name", Where.OBJECT_FORMS); - var managedProperty = propertyInteraction.getManagedPropertyElseThrow(__->_Exceptions.noSuchElement()); - var propertyModel = managedProperty.startNegotiation(); - var propertySpec = managedProperty.getElementType(); - propertyModel.getValue().setValue(ManagedObject.value(propertySpec, "Book #2")); - propertyModel.submit(); + context.runGiven(); - }); + // when + context.changeProperty(()->{ - }); + var bookAdapter = objectManager.adapt(book); + var propertyInteraction = PropertyInteraction.start(bookAdapter, "name", VisibilityConstraint.noViewer(Where.OBJECT_FORMS)); + var managedProperty = propertyInteraction.getManagedPropertyElseThrow(__->_Exceptions.noSuchElement()); + var propertyModel = managedProperty.startNegotiation(); + var propertySpec = managedProperty.getElementType(); + propertyModel.getValue().setValue(ManagedObject.value(propertySpec, "Book #2")); + propertyModel.submit(); - break; - case ACTION_INVOCATION: + }); - withBookDo(book->{ + }); + case ACTION_INVOCATION -> withBookDo(book->{ - context.runGiven(); + context.runGiven(); - // when - context.executeAction(()->{ + // when + context.executeAction(()->{ - var bookAdapter = objectManager.adapt(book); + var bookAdapter = objectManager.adapt(book); - var actionInteraction = ActionInteraction.start(bookAdapter, "doubleThePrice", Where.OBJECT_FORMS); - var managedAction = actionInteraction.getManagedActionElseThrow(__->_Exceptions.noSuchElement()); - // this test action is always disabled, so don't enforce rules here, just invoke - managedAction.invoke(Can.empty()); // no-arg action - }); + var actionInteraction = ActionInteraction.start(bookAdapter, "doubleThePrice", VisibilityConstraint.noViewer(Where.OBJECT_FORMS)); + var managedAction = actionInteraction.getManagedActionElseThrow(__->_Exceptions.noSuchElement()); + // this test action is always disabled, so don't enforce rules here, just invoke + managedAction.invoke(Can.empty()); // no-arg action + }); - }); - - break; - default: - throw _Exceptions.unmatchedCase(context.scenario()); - } + }); + default -> throw _Exceptions.unmatchedCase(context.scenario()); + } + ; } @@ -264,37 +238,28 @@ protected void wrapperSyncExecutionNoRules( context.bind(commitListener); - switch(context.scenario()) { - - case PROPERTY_UPDATE: - - withBookDo(book->{ - - context.runGiven(); + switch (context.scenario()) { + case PROPERTY_UPDATE -> withBookDo(book->{ - // when - running synchronous - var syncControl = SyncControl.defaults().withSkipRules(); // don't enforce rules - context.changeProperty(()->wrapper.wrap(book, syncControl).setName("Book #2")); + context.runGiven(); - }); - - break; - case ACTION_INVOCATION: - - withBookDo(book->{ + // when - running synchronous + var syncControl = SyncControl.defaults().withSkipRules(); // don't enforce rules + context.changeProperty(()->wrapper.wrap(book, syncControl).setName("Book #2")); - context.runGiven(); + }); + case ACTION_INVOCATION -> withBookDo(book->{ - // when - running synchronous - var syncControl = SyncControl.defaults().withSkipRules(); // don't enforce rules - context.executeAction(()->wrapper.wrap(book, syncControl).doubleThePrice()); + context.runGiven(); - }); + // when - running synchronous + var syncControl = SyncControl.defaults().withSkipRules(); // don't enforce rules + context.executeAction(()->wrapper.wrap(book, syncControl).doubleThePrice()); - break; - default: - throw _Exceptions.unmatchedCase(context.scenario()); - } + }); + default -> throw _Exceptions.unmatchedCase(context.scenario()); + } + ; } @@ -304,43 +269,34 @@ protected void wrapperSyncExecutionWithRules( context.bind(commitListener); - switch(context.scenario()) { - - case PROPERTY_UPDATE: - - withBookDo(book->{ - - context.runGiven(); + switch (context.scenario()) { + case PROPERTY_UPDATE -> withBookDo(book->{ - // when - running synchronous - var syncControl = SyncControl.defaults().withCheckRules(); // enforce rules + context.runGiven(); - //assertThrows(DisabledException.class, ()->{ - wrapper.wrap(book, syncControl).setName("Book #2"); // should throw DisabledException - //}); + // when - running synchronous + var syncControl = SyncControl.defaults().withCheckRules(); // enforce rules - }); - - break; - case ACTION_INVOCATION: + //assertThrows(DisabledException.class, ()->{ + wrapper.wrap(book, syncControl).setName("Book #2"); // should throw DisabledException + //}); - withBookDo(book->{ + }); + case ACTION_INVOCATION -> withBookDo(book->{ - context.runGiven(); + context.runGiven(); - // when - running synchronous - var syncControl = SyncControl.defaults().withCheckRules(); // enforce rules + // when - running synchronous + var syncControl = SyncControl.defaults().withCheckRules(); // enforce rules - //assertThrows(DisabledException.class, ()->{ - wrapper.wrap(book, syncControl).doubleThePrice(); // should throw DisabledException - //}); + //assertThrows(DisabledException.class, ()->{ + wrapper.wrap(book, syncControl).doubleThePrice(); // should throw DisabledException + //}); - }); - - break; - default: - throw _Exceptions.unmatchedCase(context.scenario()); - } + }); + default -> throw _Exceptions.unmatchedCase(context.scenario()); + } + ; } diff --git a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java index 4e89f0813a0..3f1f1bf5dff 100644 --- a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java +++ b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/DomainObjectTesterFactory.java @@ -62,8 +62,10 @@ import org.apache.causeway.core.metamodel.facets.object.icon.IconFacet; import org.apache.causeway.core.metamodel.facets.object.layout.LayoutPrefixFacet; import org.apache.causeway.core.metamodel.facets.object.value.ValueFacet; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteraction; import org.apache.causeway.core.metamodel.interactions.managed.CollectionInteraction; +import org.apache.causeway.core.metamodel.interactions.managed.InteractionVeto; import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.interactions.managed.ManagedCollection; import org.apache.causeway.core.metamodel.interactions.managed.ManagedMember; @@ -94,7 +96,7 @@ public class DomainObjectTesterFactory implements HasMetaModelContext { public ObjectTester objectTester( final T domainObject) { var tester = getServiceInjector().injectServicesInto( - new ObjectTester(domainObject)); + new ObjectTester<>(domainObject)); return tester; } @@ -103,7 +105,7 @@ public ActionTester actionTester( final String actionName, final Where where) { var tester = getServiceInjector().injectServicesInto( - new ActionTester(domainObject, actionName, where)); + new ActionTester<>(domainObject, actionName, where)); tester.init(); return tester; } @@ -125,7 +127,7 @@ public PropertyTester propertyTester( final String propertyName, final Where where) { var tester = getServiceInjector().injectServicesInto( - new PropertyTester(domainObject, propertyName, where)); + new PropertyTester<>(domainObject, propertyName, where)); tester.init(); return tester; } @@ -135,7 +137,7 @@ public CollectionTester collectionTester( final String collectionName, final Where where) { var tester = getServiceInjector().injectServicesInto( - new CollectionTester(domainObject, collectionName, where)); + new CollectionTester<>(domainObject, collectionName, where)); tester.init(); return tester; } @@ -290,7 +292,7 @@ private ActionTester( super(domainObject, managedAction.getId(), "actionName", - managedAction.getWhere()); + managedAction.visibilityConstraint().where()); this.actionInteraction = actionInteraction; this.parameterNegotiationStarter = ()-> actionInteraction @@ -350,7 +352,7 @@ public Optional getElementType() { protected Optional startInteractionOn(final ManagedObject viewModel) { if(parameterNegotiationStarter==null) { this.actionInteraction = ActionInteraction - .start(viewModel, getMemberName(), Where.NOT_SPECIFIED); + .start(viewModel, getMemberName(), visibilityConstraint.withWhere(Where.NOT_SPECIFIED)); } assertNotNull(actionInteraction); return getManagedAction(); @@ -743,7 +745,7 @@ protected Optional getElementType() { @Override protected Optional startInteractionOn(final ManagedObject viewModel) { return this.managedPropertyIfAny = PropertyInteraction - .start(viewModel, getMemberName(), where) + .start(viewModel, getMemberName(), visibilityConstraint) .getManagedProperty(); } @@ -954,7 +956,7 @@ protected Optional getElementType() { @Override protected Optional startInteractionOn(final ManagedObject viewModel) { return this.managedCollectionIfAny = CollectionInteraction - .start(viewModel, getMemberName(), Where.NOT_SPECIFIED) + .start(viewModel, getMemberName(), visibilityConstraint.withWhere(Where.NOT_SPECIFIED)) .getManagedCollection(); } @@ -1002,7 +1004,7 @@ private static abstract class MemberTester @Getter private final String memberName; private final String memberSort; - protected final Where where; + protected final VisibilityConstraint visibilityConstraint; private Optional managedMemberIfAny; @@ -1014,7 +1016,7 @@ protected MemberTester( super(domainObject); this.memberName = memberName; this.memberSort = memberSort; - this.where = where; + this.visibilityConstraint = VisibilityConstraint.noViewer(where); } protected final MemberTester init() { @@ -1110,7 +1112,7 @@ private final void assertVisibilityIsVetoedWith(final @Nullable String expectedV final String actualVetoResaon = managedCollection .checkVisibility() - .flatMap(veto->veto.getReasonAsString()) + .flatMap(InteractionVeto::getReasonAsString) .orElse(null); assertEquals(expectedVetoReason, actualVetoResaon); @@ -1131,7 +1133,7 @@ public final void assertUsabilityIsVetoedWithAll(final Can expectedVetoR interactionService.runAnonymous(()->{ final String actualVetoReason = managedMember .checkUsability() - .flatMap(veto->veto.getReasonAsString()) + .flatMap(InteractionVeto::getReasonAsString) .orElse(null); if(!expectedVetoReasons.isEmpty() @@ -1162,7 +1164,7 @@ public final void assertUsabilityIsVetoedWith(final @Nullable String expectedVet interactionService.runAnonymous(()->{ final String actualVetoReason = managedMember .checkUsability() - .flatMap(veto->veto.getReasonAsString()) + .flatMap(InteractionVeto::getReasonAsString) .orElse(null); assertEquals(expectedVetoReason, actualVetoReason); diff --git a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/InteractionTestAbstract.java b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/InteractionTestAbstract.java index cbf76d1baf0..20db1cfe08e 100644 --- a/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/InteractionTestAbstract.java +++ b/regressiontests/base/src/main/java/org/apache/causeway/testdomain/util/interaction/InteractionTestAbstract.java @@ -27,17 +27,18 @@ import jakarta.inject.Inject; +import org.jspecify.annotations.Nullable; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.jspecify.annotations.Nullable; - import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.iactnlayer.InteractionService; import org.apache.causeway.applib.services.wrapper.WrapperFactory; import org.apache.causeway.commons.internal.base._NullSafe; import org.apache.causeway.commons.internal.base._Strings; import org.apache.causeway.commons.internal.collections._Sets; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteraction; import org.apache.causeway.core.metamodel.interactions.managed.CollectionInteraction; import org.apache.causeway.core.metamodel.interactions.managed.PropertyInteraction; @@ -70,19 +71,19 @@ protected ManagedObject newViewmodel(final Class type) { protected ActionInteraction startActionInteractionOn(final Class type, final String actionId, final Where where) { var viewModel = factoryService.viewModel(type); var managedObject = objectManager.adapt(viewModel); - return ActionInteraction.start(managedObject, actionId, where); + return ActionInteraction.start(managedObject, actionId, VisibilityConstraint.noViewer(where)); } protected PropertyInteraction startPropertyInteractionOn(final Class type, final String propertyId, final Where where) { var viewModel = factoryService.viewModel(type); var managedObject = objectManager.adapt(viewModel); - return PropertyInteraction.start(managedObject, propertyId, where); + return PropertyInteraction.start(managedObject, propertyId, VisibilityConstraint.noViewer(where)); } protected CollectionInteraction startCollectionInteractionOn(final Class type, final String collectionId, final Where where) { var viewModel = factoryService.viewModel(type); var managedObject = objectManager.adapt(viewModel); - return CollectionInteraction.start(managedObject, collectionId, where); + return CollectionInteraction.start(managedObject, collectionId, VisibilityConstraint.noViewer(where)); } // -- SHORTCUTS diff --git a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java index 751096377d9..21119e82a1c 100644 --- a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java +++ b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java @@ -25,6 +25,7 @@ import jakarta.inject.Inject; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -79,7 +80,9 @@ import org.apache.causeway.core.metamodel.spec.feature.MixedIn; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.specloader.SpecificationLoader; +import org.apache.causeway.core.metamodel.specloader.validator.ValidationFailure; import org.apache.causeway.core.metamodel.tabular.simple.DataTable; +import org.apache.causeway.core.metamodel.tabular.simple.DataTable.AccessMode; import org.apache.causeway.schema.metamodel.v2.DomainClassDto; import org.apache.causeway.testdomain.conf.Configuration_headless; import org.apache.causeway.testdomain.model.good.Configuration_usingValidDomain; @@ -181,7 +184,7 @@ void goodDomain_shouldPassValidation() { fail(String.format("%d problems found:\n%s", validationFailures.size(), validationFailures.stream() - .map(validationFailure->validationFailure.message()) + .map(ValidationFailure::message) .collect(Collectors.joining("\n")))); } } @@ -337,9 +340,8 @@ void metamodelContributingMembers_shouldBeInheritable(final Class type) { void metamodelContributingActions_shouldBeUnique_whenOverridden(final Class type) { if(type.isInterface() - && type.getSuperclass()==null) { - return; // not implemented for interface that don't extend from others - } + && type.getSuperclass()==null) + return; // not implemented for interface that don't extend from others var holderSpec = specificationLoader.specForTypeElseFail(type); @@ -360,9 +362,8 @@ void metamodelContributingActions_shouldBeUnique_whenOverridden(final Class t void metamodelContributingProperties_shouldBeUnique_whenOverridden(final Class type) { if(type.isInterface() - && type.getSuperclass()==null) { - return; // not implemented for interface that don't extend from others - } + && type.getSuperclass()==null) + return; // not implemented for interface that don't extend from others var holderSpec = specificationLoader.specForTypeElseFail(type); @@ -865,8 +866,8 @@ void properMemberSupportDiscovery(final Class classUnderTest) { // hide1PlaceOrder(y): boolean = false act.assertParameterVisibility( false, // skip rule checking - arg0Visible->assertFalse(arg0Visible), - arg1Visible->assertTrue(arg1Visible)); + Assertions::assertFalse, + Assertions::assertTrue); // disable0PlaceOrder(x): String = "my disable reason-0" // disable1PlaceOrder(z): String = "my disable reason-1" @@ -1123,7 +1124,8 @@ private String tableToString(final DataTable dataTable) { dataTable.visit((column, cellValues) -> sb.append(String.format("%s: %s\n", column.columnFriendlyName(), - "" + cellValues.getFirstElseFail().getPojo()))); + "" + cellValues.getFirstElseFail().getPojo())), + AccessMode.PASS_THROUGH); return sb.toString(); } diff --git a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.verify.approved.xml b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.verify.approved.xml index d0fd56e899a..394650b4962 100644 --- a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.verify.approved.xml +++ b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.verify.approved.xml @@ -48,8 +48,8 @@ - - + + @@ -154,8 +154,8 @@ - - + + @@ -224,9 +224,9 @@ - + - + @@ -359,9 +359,9 @@ - + - + @@ -564,9 +564,9 @@ - + - + @@ -706,9 +706,9 @@ - + - + @@ -812,9 +812,9 @@ - + - + @@ -918,9 +918,9 @@ - + - + @@ -1051,8 +1051,8 @@ - - + + @@ -1123,9 +1123,9 @@ - + - + @@ -1258,9 +1258,9 @@ - + - + @@ -1463,9 +1463,9 @@ - + - + @@ -1605,9 +1605,9 @@ - + - + @@ -1711,9 +1711,9 @@ - + - + @@ -1817,9 +1817,9 @@ - + - + @@ -1935,8 +1935,8 @@ - - + + @@ -2072,8 +2072,8 @@ - - + + @@ -2144,9 +2144,9 @@ - + - + @@ -2279,9 +2279,9 @@ - + - + @@ -2484,9 +2484,9 @@ - + - + @@ -2638,8 +2638,8 @@ - - + + @@ -2749,9 +2749,9 @@ - + - + @@ -2855,9 +2855,9 @@ - + - + @@ -2961,9 +2961,9 @@ - + - + @@ -3079,8 +3079,8 @@ - - + + @@ -3170,8 +3170,8 @@ - - + + @@ -3238,9 +3238,9 @@ - + - + @@ -3373,9 +3373,9 @@ - + - + @@ -3578,9 +3578,9 @@ - + - + @@ -3720,9 +3720,9 @@ - + - + @@ -3826,9 +3826,9 @@ - + - + @@ -3932,9 +3932,9 @@ - + - + @@ -4065,8 +4065,8 @@ - - + + @@ -4128,8 +4128,8 @@ - - + + @@ -4197,9 +4197,9 @@ - + - + @@ -4332,9 +4332,9 @@ - + - + @@ -4537,9 +4537,9 @@ - + - + @@ -4679,9 +4679,9 @@ - + - + @@ -4785,9 +4785,9 @@ - + - + @@ -4891,9 +4891,9 @@ - + - + @@ -5129,8 +5129,8 @@ - - + + @@ -5344,8 +5344,8 @@ - - + + @@ -5469,9 +5469,9 @@ - + - + @@ -5604,9 +5604,9 @@ - + - + @@ -5809,9 +5809,9 @@ - + - + @@ -5951,9 +5951,9 @@ - + - + @@ -6057,9 +6057,9 @@ - + - + @@ -6163,9 +6163,9 @@ - + - + @@ -6407,8 +6407,8 @@ - - + + @@ -6628,8 +6628,8 @@ - - + + @@ -6879,9 +6879,9 @@ - + - + @@ -7014,9 +7014,9 @@ - + - + @@ -7219,9 +7219,9 @@ - + - + @@ -7361,9 +7361,9 @@ - + - + @@ -7467,9 +7467,9 @@ - + - + @@ -7573,9 +7573,9 @@ - + - + @@ -7706,8 +7706,8 @@ - - + + @@ -7769,8 +7769,8 @@ - - + + @@ -7828,8 +7828,8 @@ - - + + @@ -7887,8 +7887,8 @@ - - + + @@ -7946,8 +7946,8 @@ - - + + @@ -8005,8 +8005,8 @@ - - + + @@ -8064,8 +8064,8 @@ - - + + @@ -8123,8 +8123,8 @@ - - + + @@ -8182,8 +8182,8 @@ - - + + @@ -8241,8 +8241,8 @@ - - + + @@ -8300,8 +8300,8 @@ - - + + @@ -8481,9 +8481,9 @@ - + - + @@ -8616,9 +8616,9 @@ - + - + @@ -8821,9 +8821,9 @@ - + - + @@ -8963,9 +8963,9 @@ - + - + @@ -9069,9 +9069,9 @@ - + - + @@ -9175,9 +9175,9 @@ - + - + @@ -9314,8 +9314,8 @@ - - + + @@ -9575,9 +9575,9 @@ - + - + @@ -9710,9 +9710,9 @@ - + - + @@ -9915,9 +9915,9 @@ - + - + @@ -10057,9 +10057,9 @@ - + - + @@ -10163,9 +10163,9 @@ - + - + @@ -10269,9 +10269,9 @@ - + - + @@ -10490,8 +10490,8 @@ - - + + @@ -10653,9 +10653,9 @@ - + - + @@ -10788,9 +10788,9 @@ - + - + @@ -10993,9 +10993,9 @@ - + - + @@ -11135,9 +11135,9 @@ - + - + @@ -11241,9 +11241,9 @@ - + - + @@ -11347,9 +11347,9 @@ - + - + @@ -11590,8 +11590,8 @@ - - + + @@ -11753,9 +11753,9 @@ - + - + @@ -11888,9 +11888,9 @@ - + - + @@ -12093,9 +12093,9 @@ - + - + @@ -12235,9 +12235,9 @@ - + - + @@ -12341,9 +12341,9 @@ - + - + @@ -12447,9 +12447,9 @@ - + - + @@ -12690,8 +12690,8 @@ - - + + @@ -12878,9 +12878,9 @@ - + - + @@ -13013,9 +13013,9 @@ - + - + @@ -13218,9 +13218,9 @@ - + - + @@ -13360,9 +13360,9 @@ - + - + @@ -13466,9 +13466,9 @@ - + - + @@ -13572,9 +13572,9 @@ - + - + @@ -13711,8 +13711,8 @@ - - + + @@ -14075,9 +14075,9 @@ - + - + @@ -14210,9 +14210,9 @@ - + - + @@ -14415,9 +14415,9 @@ - + - + @@ -14557,9 +14557,9 @@ - + - + @@ -14663,9 +14663,9 @@ - + - + @@ -14769,9 +14769,9 @@ - + - + @@ -15078,8 +15078,8 @@ - - + + @@ -15423,9 +15423,9 @@ - + - + @@ -15558,9 +15558,9 @@ - + - + @@ -15763,9 +15763,9 @@ - + - + @@ -15905,9 +15905,9 @@ - + - + @@ -16011,9 +16011,9 @@ - + - + @@ -16117,9 +16117,9 @@ - + - + @@ -16543,8 +16543,8 @@ - - + + @@ -16691,9 +16691,9 @@ - + - + @@ -16826,9 +16826,9 @@ - + - + @@ -17031,9 +17031,9 @@ - + - + @@ -17173,9 +17173,9 @@ - + - + @@ -17279,9 +17279,9 @@ - + - + @@ -17385,9 +17385,9 @@ - + - + @@ -17518,8 +17518,8 @@ - - + + @@ -17670,9 +17670,9 @@ - + - + @@ -17805,9 +17805,9 @@ - + - + @@ -18010,9 +18010,9 @@ - + - + @@ -18152,9 +18152,9 @@ - + - + @@ -18258,9 +18258,9 @@ - + - + @@ -18364,9 +18364,9 @@ - + - + @@ -18497,8 +18497,8 @@ - - + + @@ -18649,9 +18649,9 @@ - + - + @@ -18784,9 +18784,9 @@ - + - + @@ -18989,9 +18989,9 @@ - + - + @@ -19131,9 +19131,9 @@ - + - + @@ -19237,9 +19237,9 @@ - + - + @@ -19343,9 +19343,9 @@ - + - + @@ -19476,8 +19476,8 @@ - - + + @@ -19534,8 +19534,8 @@ - - + + @@ -19825,8 +19825,8 @@ - - + + @@ -19969,8 +19969,8 @@ - - + + @@ -20246,8 +20246,8 @@ - - + + @@ -20381,8 +20381,8 @@ - - + + @@ -20585,8 +20585,8 @@ - - + + @@ -20692,8 +20692,8 @@ - - + + @@ -20709,8 +20709,8 @@ - - + + @@ -20919,8 +20919,8 @@ - - + + @@ -20937,8 +20937,8 @@ - - + + @@ -21147,8 +21147,8 @@ - - + + @@ -21165,8 +21165,8 @@ - - + + @@ -21389,8 +21389,8 @@ - - + + @@ -21407,8 +21407,8 @@ - - + + @@ -21635,8 +21635,8 @@ - - + + @@ -21729,8 +21729,8 @@ - - + + @@ -21934,9 +21934,9 @@ - + - + @@ -22069,9 +22069,9 @@ - + - + @@ -22274,9 +22274,9 @@ - + - + @@ -22491,9 +22491,9 @@ - + - + @@ -22627,8 +22627,8 @@ - - + + @@ -22726,8 +22726,8 @@ - - + + @@ -22875,8 +22875,8 @@ - - + + @@ -23050,9 +23050,9 @@ - + - + @@ -23156,9 +23156,9 @@ - + - + @@ -23289,8 +23289,8 @@ - - + + @@ -23352,8 +23352,8 @@ - - + + @@ -23507,8 +23507,8 @@ - - + + @@ -23581,9 +23581,9 @@ - + - + @@ -23716,9 +23716,9 @@ - + - + @@ -23921,9 +23921,9 @@ - + - + @@ -24063,9 +24063,9 @@ - + - + @@ -24169,9 +24169,9 @@ - + - + @@ -24300,8 +24300,8 @@ - - + + @@ -24385,8 +24385,8 @@ - - + + @@ -24448,8 +24448,8 @@ - - + + @@ -24507,9 +24507,9 @@ - + - + @@ -24640,8 +24640,8 @@ - - + + @@ -24703,8 +24703,8 @@ - - + + @@ -24858,8 +24858,8 @@ - - + + @@ -24932,9 +24932,9 @@ - + - + @@ -25067,9 +25067,9 @@ - + - + @@ -25272,9 +25272,9 @@ - + - + @@ -25414,9 +25414,9 @@ - + - + @@ -25520,9 +25520,9 @@ - + - + @@ -25655,8 +25655,8 @@ - - + + @@ -25740,8 +25740,8 @@ - - + + @@ -25803,8 +25803,8 @@ - - + + @@ -25862,9 +25862,9 @@ - + - + @@ -25995,8 +25995,8 @@ - - + + @@ -26058,8 +26058,8 @@ - - + + @@ -26213,8 +26213,8 @@ - - + + @@ -26287,9 +26287,9 @@ - + - + @@ -26422,9 +26422,9 @@ - + - + @@ -26627,9 +26627,9 @@ - + - + @@ -26769,9 +26769,9 @@ - + - + @@ -26875,9 +26875,9 @@ - + - + @@ -27010,8 +27010,8 @@ - - + + @@ -27095,8 +27095,8 @@ - - + + @@ -27158,8 +27158,8 @@ - - + + @@ -27217,9 +27217,9 @@ - + - + @@ -27338,8 +27338,8 @@ - - + + @@ -27448,8 +27448,8 @@ - - + + @@ -27465,8 +27465,8 @@ - - + + @@ -27663,8 +27663,8 @@ - - + + @@ -27766,8 +27766,8 @@ - - + + @@ -27779,8 +27779,8 @@ - - + + @@ -27977,8 +27977,8 @@ - - + + @@ -28080,8 +28080,8 @@ - - + + @@ -28093,8 +28093,8 @@ - - + + @@ -28305,8 +28305,8 @@ - - + + @@ -28408,8 +28408,8 @@ - - + + @@ -28421,8 +28421,8 @@ - - + + @@ -28633,8 +28633,8 @@ - - + + @@ -28735,8 +28735,8 @@ - - + + @@ -28820,8 +28820,8 @@ - - + + @@ -28920,8 +28920,8 @@ - - + + @@ -29140,8 +29140,8 @@ - - + + @@ -29269,8 +29269,8 @@ - - + + @@ -29362,8 +29362,8 @@ - - + + @@ -29491,8 +29491,8 @@ - - + + @@ -29584,8 +29584,8 @@ - - + + @@ -29785,8 +29785,8 @@ - - + + @@ -29892,8 +29892,8 @@ - - + + @@ -30016,8 +30016,8 @@ - - + + @@ -30123,8 +30123,8 @@ - - + + @@ -30247,8 +30247,8 @@ - - + + @@ -30455,8 +30455,8 @@ - - + + @@ -31223,9 +31223,9 @@ - + - + @@ -31358,9 +31358,9 @@ - + - + @@ -31563,9 +31563,9 @@ - + - + @@ -31705,9 +31705,9 @@ - + - + @@ -31943,9 +31943,9 @@ - + - + @@ -32049,9 +32049,9 @@ - + - + @@ -32170,8 +32170,8 @@ - - + + @@ -32348,8 +32348,8 @@ - - + + @@ -32526,8 +32526,8 @@ - - + + @@ -32704,8 +32704,8 @@ - - + + @@ -32882,8 +32882,8 @@ - - + + @@ -33060,8 +33060,8 @@ - - + + @@ -33238,8 +33238,8 @@ - - + + @@ -33416,8 +33416,8 @@ - - + + @@ -33606,8 +33606,8 @@ - - + + @@ -33765,8 +33765,8 @@ - - + + @@ -33834,8 +33834,8 @@ - - + + @@ -33903,8 +33903,8 @@ - - + + @@ -33955,9 +33955,9 @@ - + - + @@ -34090,9 +34090,9 @@ - + - + @@ -34295,9 +34295,9 @@ - + - + @@ -34437,9 +34437,9 @@ - + - + @@ -34543,9 +34543,9 @@ - + - + @@ -34649,9 +34649,9 @@ - + - + @@ -34782,8 +34782,8 @@ - - + + @@ -34854,9 +34854,9 @@ - + - + @@ -34989,9 +34989,9 @@ - + - + @@ -35194,9 +35194,9 @@ - + - + @@ -35411,9 +35411,9 @@ - + - + @@ -35517,9 +35517,9 @@ - + - + @@ -35623,9 +35623,9 @@ - + - + @@ -35756,8 +35756,8 @@ - - + + @@ -36001,9 +36001,9 @@ - + - + @@ -36136,9 +36136,9 @@ - + - + @@ -36341,9 +36341,9 @@ - + - + @@ -36483,9 +36483,9 @@ - + - + @@ -36589,9 +36589,9 @@ - + - + @@ -36695,9 +36695,9 @@ - + - + @@ -36828,8 +36828,8 @@ - - + + @@ -37241,9 +37241,9 @@ - + - + @@ -37376,9 +37376,9 @@ - + - + @@ -37581,9 +37581,9 @@ - + - + @@ -37723,9 +37723,9 @@ - + - + @@ -37829,9 +37829,9 @@ - + - + @@ -37935,9 +37935,9 @@ - + - + @@ -38056,8 +38056,8 @@ - - + + @@ -38248,18 +38248,18 @@ - - + + + + + + + - - - - - @@ -38335,8 +38335,8 @@ - - + + @@ -38454,8 +38454,8 @@ - - + + @@ -38523,9 +38523,9 @@ - + - + @@ -38658,9 +38658,9 @@ - + - + @@ -38863,9 +38863,9 @@ - + - + @@ -39005,9 +39005,9 @@ - + - + @@ -39145,8 +39145,8 @@ - - + + @@ -39207,9 +39207,9 @@ - + - + @@ -39313,9 +39313,9 @@ - + - + @@ -39446,8 +39446,8 @@ - - + + @@ -39681,9 +39681,9 @@ - + - + @@ -39816,9 +39816,9 @@ - + - + @@ -40021,9 +40021,9 @@ - + - + @@ -40163,9 +40163,9 @@ - + - + @@ -40351,9 +40351,9 @@ - + - + @@ -40457,9 +40457,9 @@ - + - + diff --git a/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/CollectionInteractionTest.java b/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/CollectionInteractionTest.java index c866fb89ef5..7c4267687ae 100644 --- a/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/CollectionInteractionTest.java +++ b/regressiontests/interact/src/test/java/org/apache/causeway/testdomain/interact/CollectionInteractionTest.java @@ -30,6 +30,7 @@ import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.config.presets.CausewayPresets; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.MmUnwrapUtils; import org.apache.causeway.testdomain.conf.Configuration_headless; import org.apache.causeway.testdomain.model.interaction.Configuration_usingInteractionDomain; @@ -113,7 +114,7 @@ void choicesFromMultiselect() { var table = tableTester.getDataTable(); var actionInteraction = table - .startAssociatedActionInteraction("doSomethingWithItems", Where.OBJECT_FORMS); + .startAssociatedActionInteraction("doSomethingWithItems", VisibilityConstraint.noViewer(Where.OBJECT_FORMS)); var actTester = testerFactory.actionTesterForSpecificInteraction(InteractionDemo.class, actionInteraction); actTester.assertVisibilityIsNotVetoed(); diff --git a/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/PropertyInteractionProbeImpl.java b/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/PropertyInteractionProbeImpl.java index 9356babc085..06f437863a8 100644 --- a/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/PropertyInteractionProbeImpl.java +++ b/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/PropertyInteractionProbeImpl.java @@ -45,6 +45,7 @@ import org.apache.causeway.commons.internal.assertions._Assert; import org.apache.causeway.commons.internal.base._Strings; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteraction; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.services.schema.SchemaValueMarshaller; @@ -103,7 +104,7 @@ public void testComposer( var spec = specLoader.specForTypeElseFail(valueMixin.getClass()); var interaction = ActionInteraction - .start(ManagedObject.mixin(spec, valueMixin), "act", Where.ANYWHERE); + .start(ManagedObject.mixin(spec, valueMixin), "act", VisibilityConstraint.noViewer(Where.ANYWHERE)); var pendingParams = interaction .startParameterNegotiation() @@ -169,9 +170,8 @@ public void testParser( }); - if(example.getParseExpectations().isNotEmpty()) { - return; // skip round-trip test - } + if(example.getParseExpectations().isNotEmpty()) + return; // skip round-trip test //TODO eventually all examples should have their ParseExpectations, so we can remove // Parser round-trip test @@ -192,11 +192,10 @@ public void testParser( //|| valueType.equals(ZonedDateTime.class) ) { - if(stringified.endsWith("Z")) { - // skip format variations on UTC time-zone + if(stringified.endsWith("Z")) + // skip format variations on UTC time-zone //System.err.printf("DEBUG: skipping stringified: %s%n", stringified); return; - } var with4digitZone = _Strings.substring(stringified, 0, -3) + "00"; var with2digitZone = _Strings.substring(stringified, 0, -3); diff --git a/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/ValueSemanticsTester.java b/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/ValueSemanticsTester.java index d147b260139..6599fa1725a 100644 --- a/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/ValueSemanticsTester.java +++ b/regressiontests/value/src/test/java/org/apache/causeway/testdomain/value/ValueSemanticsTester.java @@ -24,6 +24,8 @@ import jakarta.inject.Inject; +import org.jspecify.annotations.NonNull; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -40,6 +42,7 @@ import org.apache.causeway.commons.internal.base._Casts; import org.apache.causeway.commons.internal.exceptions._Exceptions; import org.apache.causeway.core.metamodel.facets.object.value.ValueFacet; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteraction; import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.interactions.managed.ManagedProperty; @@ -49,7 +52,6 @@ import org.apache.causeway.core.metamodel.specloader.SpecificationLoader; import org.apache.causeway.testdomain.model.valuetypes.ValueTypeExample; -import org.jspecify.annotations.NonNull; import lombok.SneakyThrows; class ValueSemanticsTester { @@ -91,7 +93,7 @@ public void actionInteraction( var command = interactionService.currentInteractionElseFail().getCommand(); var actInteraction = ActionInteraction - .wrap(ManagedAction.of(ManagedObject.adaptSingular(objSpec, domainObject), act, Where.OBJECT_FORMS)); + .wrap(ManagedAction.of(ManagedObject.adaptSingular(objSpec, domainObject), act, VisibilityConstraint.noViewer(Where.OBJECT_FORMS))); var params = actInteraction.startParameterNegotiation().orElseThrow(); var singleArgPojoToUse = actionArgumentProvider.get(); @@ -111,7 +113,7 @@ public void actionInteraction( var command = interactionService.currentInteractionElseFail().getCommand(); var actInteraction = ActionInteraction - .wrap(ManagedAction.of(ManagedObject.adaptSingular(objSpec, domainObject), act, Where.OBJECT_FORMS)); + .wrap(ManagedAction.of(ManagedObject.adaptSingular(objSpec, domainObject), act, VisibilityConstraint.noViewer(Where.OBJECT_FORMS))); var params = actInteraction.startParameterNegotiation().orElseThrow(); @@ -199,7 +201,7 @@ public void propertyInteraction( var command = interactionService.currentInteractionElseFail().getCommand(); var propInteraction = PropertyInteraction - .wrap(ManagedProperty.of(ManagedObject.adaptSingular(objSpec, domainObject), prop, Where.OBJECT_FORMS)); + .wrap(ManagedProperty.of(ManagedObject.adaptSingular(objSpec, domainObject), prop, VisibilityConstraint.noViewer(Where.OBJECT_FORMS))); propInteraction.modifyProperty(managedProp-> ManagedObject.adaptSingular(managedProp.getElementType(), newProperyValueProvider.apply(managedProp))); diff --git a/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/header/HeaderUiService.java b/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/header/HeaderUiService.java index 1bd3315c7a1..891994f5d10 100644 --- a/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/header/HeaderUiService.java +++ b/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/header/HeaderUiService.java @@ -18,11 +18,13 @@ */ package org.apache.causeway.viewer.commons.applib.services.header; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; + /** * @since 2.0 {@index}} */ public interface HeaderUiService { - HeaderUiModel getHeader(); + HeaderUiModel getHeader(WhatViewer whatViewer); } diff --git a/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/menu/MenuUiService.java b/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/menu/MenuUiService.java index 8579198cca5..b78830b8bdc 100644 --- a/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/menu/MenuUiService.java +++ b/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/menu/MenuUiService.java @@ -18,6 +18,7 @@ */ package org.apache.causeway.viewer.commons.applib.services.menu; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.viewer.commons.applib.services.menu.model.NavbarUiModel; /** @@ -25,6 +26,6 @@ */ public interface MenuUiService { - NavbarUiModel getMenu(); + NavbarUiModel getMenu(WhatViewer whatViewer); } diff --git a/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/menu/model/MenuAction.java b/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/menu/model/MenuAction.java index a98beadb512..24d93e11a9d 100644 --- a/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/menu/model/MenuAction.java +++ b/viewers/commons/applib/src/main/java/org/apache/causeway/viewer/commons/applib/services/menu/model/MenuAction.java @@ -29,6 +29,9 @@ import org.apache.causeway.core.metamodel.consent.Consent.VetoReason; import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.core.metamodel.facets.members.iconfa.FaLayersProvider; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; +import org.apache.causeway.core.metamodel.interactions.managed.InteractionVeto; import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.spec.feature.ObjectAction; import org.apache.causeway.core.metamodel.util.Facets; @@ -57,7 +60,7 @@ static DecorationModel of(final @NonNull ManagedAction managedAction) { .isPrototype(action.isPrototype()) .paramCount(action.getParameterCount()) .interactionVetoOpt(managedAction.checkUsability() - .flatMap(veto->veto.getReason())) + .flatMap(InteractionVeto::getReason)) .fontAwesomeLayersOpt(ObjectAction.Util.cssClassFaFactoryFor( managedAction.getAction(), managedAction.getOwner()) @@ -77,10 +80,10 @@ public static MenuAction of(final @NonNull ManagedAction managedAction) { DecorationModel.of(managedAction)); } - public Optional managedAction(){ + public Optional managedAction(final WhatViewer whatViewer){ var mmc = MetaModelContext.instanceElseFail(); var service = mmc.getObjectManager().debookmark(serviceBookmark); - return ManagedAction.lookupAction(service, actionId.memberLogicalName(), Where.NOT_SPECIFIED); + return ManagedAction.lookupAction(service, actionId.memberLogicalName(), new VisibilityConstraint(whatViewer, Where.NOT_SPECIFIED)); } } diff --git a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/UiActionForm.java b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/UiActionForm.java index 2ec15693118..11ff89656e7 100644 --- a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/UiActionForm.java +++ b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/UiActionForm.java @@ -26,6 +26,8 @@ import org.apache.causeway.core.metamodel.consent.Consent; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.consent.Veto; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObjects; import org.apache.causeway.core.metamodel.object.MmTitleUtils; import org.apache.causeway.viewer.commons.model.UiModel; @@ -42,32 +44,32 @@ public interface UiActionForm // -- USABILITY - default Consent getUsabilityConsent() { + default Consent getUsabilityConsent(final WhatViewer whatViewer) { + var visibilityConstraint = new VisibilityConstraint(whatViewer, Where.OBJECT_FORMS); return getAction().isUsable( getActionOwner(), InteractionInitiatedBy.USER, - Where.OBJECT_FORMS); + visibilityConstraint); } // -- VISABILITY - default Consent getVisibilityConsent() { + default Consent getVisibilityConsent(final WhatViewer whatViewer) { // guard against missing action owner var actionOwner = getActionOwner(); - if(ManagedObjects.isNullOrUnspecifiedOrEmpty(actionOwner)) { - return Veto.DEFAULT; // veto, so we don't render the action - } + if(ManagedObjects.isNullOrUnspecifiedOrEmpty(actionOwner)) + return Veto.DEFAULT; // veto, so we don't render the action // check whether action owner type is hidden - if (getActionOwner().objSpec().isHidden()) { - return Veto.DEFAULT; - } + if (getActionOwner().objSpec().isHidden()) + return Veto.DEFAULT; + var visibilityConstraint = new VisibilityConstraint(whatViewer, Where.OBJECT_FORMS); return getAction().isVisible( actionOwner, InteractionInitiatedBy.USER, - Where.OBJECT_FORMS); + visibilityConstraint); } // -- VALIDITY diff --git a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/object/UiObject.java b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/object/UiObject.java index 1533c42c609..fd091ac9f24 100644 --- a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/object/UiObject.java +++ b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/object/UiObject.java @@ -19,6 +19,7 @@ package org.apache.causeway.viewer.commons.model.object; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.MmVisibilityUtils; import org.apache.causeway.viewer.commons.model.UiModel; @@ -27,9 +28,9 @@ public interface UiObject extends UiModel { ManagedObject getManagedObject(); - default boolean isVisible() { + default boolean isVisible(final WhatViewer whatViewer) { return MmVisibilityUtils - .isVisible(getManagedObject(), InteractionInitiatedBy.USER); + .isVisible(getManagedObject(), InteractionInitiatedBy.USER, whatViewer); } } diff --git a/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/header/HeaderUiServiceDefault.java b/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/header/HeaderUiServiceDefault.java index 6b5a23a4692..25825d68e9e 100644 --- a/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/header/HeaderUiServiceDefault.java +++ b/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/header/HeaderUiServiceDefault.java @@ -26,6 +26,7 @@ import org.springframework.stereotype.Service; import org.apache.causeway.applib.annotation.PriorityPrecedence; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.viewer.commons.applib.services.branding.BrandingUiService; import org.apache.causeway.viewer.commons.applib.services.header.HeaderUiModel; import org.apache.causeway.viewer.commons.applib.services.header.HeaderUiService; @@ -48,11 +49,11 @@ public class HeaderUiServiceDefault private final MenuUiService menuUiService; @Override - public HeaderUiModel getHeader() { + public HeaderUiModel getHeader(final WhatViewer whatViewer) { return new HeaderUiModel( brandingUiService.getHeaderBranding(), userProfileUiService.userProfile(), - menuUiService.getMenu()); + menuUiService.getMenu(whatViewer)); } } diff --git a/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/menu/MenuUiServiceDefault.java b/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/menu/MenuUiServiceDefault.java index c5f60bfbfe9..15d4e439c2e 100644 --- a/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/menu/MenuUiServiceDefault.java +++ b/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/menu/MenuUiServiceDefault.java @@ -33,6 +33,7 @@ import org.apache.causeway.applib.services.menu.MenuBarsService; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.core.metamodel.context.MetaModelContext; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.viewer.commons.applib.services.menu.MenuItemDto; import org.apache.causeway.viewer.commons.applib.services.menu.MenuUiService; import org.apache.causeway.viewer.commons.applib.services.menu.model.MenuDropdownBuilder; @@ -54,23 +55,23 @@ public class MenuUiServiceDefault private final MenuBarsService menuBarsService; @Override - public NavbarUiModel getMenu() { + public NavbarUiModel getMenu(final WhatViewer whatViewer) { return new NavbarUiModel( - buildNavBarSection(MenuBar.PRIMARY), - buildNavBarSection(MenuBar.SECONDARY), - buildNavBarSection(MenuBar.TERTIARY)); + buildNavBarSection(whatViewer, MenuBar.PRIMARY), + buildNavBarSection(whatViewer, MenuBar.SECONDARY), + buildNavBarSection(whatViewer, MenuBar.TERTIARY)); } // -- HELPER - private NavbarSection buildNavBarSection(final MenuBar menuBarSelect) { + private NavbarSection buildNavBarSection(final WhatViewer whatViewer, final MenuBar menuBarSelect) { var menuBar = (BSMenuBar) menuBarsService.menuBars() .menuBarFor(menuBarSelect); var topLevelEntries = new ArrayList(); - _MenuItemBuilder.buildMenuItems(metaModelContext, menuBar, new _MenuItemBuilder.Visitor() { + _MenuItemBuilder.buildMenuItems(metaModelContext, whatViewer, menuBar, new _MenuItemBuilder.Visitor() { private MenuDropdownBuilder currentMenu; diff --git a/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/menu/_MenuItemBuilder.java b/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/menu/_MenuItemBuilder.java index c09ba54396a..9c5998dcb8b 100644 --- a/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/menu/_MenuItemBuilder.java +++ b/viewers/commons/services/src/main/java/org/apache/causeway/viewer/commons/services/menu/_MenuItemBuilder.java @@ -20,6 +20,8 @@ import java.util.concurrent.atomic.LongAdder; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.layout.component.ServiceActionLayoutData; import org.apache.causeway.applib.layout.menubars.bootstrap.BSMenu; @@ -27,11 +29,12 @@ import org.apache.causeway.applib.layout.menubars.bootstrap.BSMenuSection; import org.apache.causeway.commons.internal.base._Strings; import org.apache.causeway.core.metamodel.context.MetaModelContext; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.viewer.commons.applib.services.menu.MenuItemDto; import org.apache.causeway.viewer.commons.services.userprof.UserProfileUiServiceDefault; -import org.jspecify.annotations.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -53,6 +56,7 @@ static interface Visitor { static void buildMenuItems( final MetaModelContext mmc, + final WhatViewer whatViewer, final BSMenuBar menuBar, final Visitor menuBuilder) { @@ -78,7 +82,7 @@ static void buildMenuItems( } var managedAction = ManagedAction - .lookupAction(serviceAdapter, actionLayoutData.getId(), Where.EVERYWHERE) + .lookupAction(serviceAdapter, actionLayoutData.getId(), new VisibilityConstraint(whatViewer, Where.EVERYWHERE)) .orElse(null); if (managedAction == null) { log.warn("No such action: bean-name '{}' action-id '{}'", diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/context/Context.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/context/Context.java index 3eef3831c94..1f03ba2ac73 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/context/Context.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/context/Context.java @@ -33,6 +33,7 @@ import org.springframework.stereotype.Component; +import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.id.HasLogicalType; import org.apache.causeway.applib.services.bookmark.BookmarkService; import org.apache.causeway.applib.services.registry.ServiceRegistry; @@ -40,6 +41,8 @@ import org.apache.causeway.commons.functional.Either; import org.apache.causeway.core.config.CausewayConfiguration; import org.apache.causeway.core.config.environment.CausewaySystemEnvironment; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.objectmanager.ObjectManager; import org.apache.causeway.core.metamodel.spec.ActionScope; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; @@ -105,9 +108,8 @@ public List objectSpecifications(final Predicate< } private void computeLogicalTypeNames() { - if (logicalTypeNames != null) { - return; - } + if (logicalTypeNames != null) + return; logicalTypeNames = doComputeLogicalTypeNames(); graphQLTypeRegistry.addTypeIfNotAlreadyPresent(logicalTypeNames); } @@ -125,4 +127,15 @@ private GraphQLEnumType doComputeLogicalTypeNames() { ) .build(); } + + // -- VISIBILITY CONSTRAINTS + + private static WhatViewer WHAT_VIEWER = new WhatViewer("Graphql"); + public static VisibilityConstraint visibilityConstraint(final Where where) { + return new VisibilityConstraint(WHAT_VIEWER, where); + } + private static VisibilityConstraint VISIBILITY_CONSTRAINT_DEFAULT = visibilityConstraint(Where.ANYWHERE); + public static VisibilityConstraint visibilityConstraint() { + return VISIBILITY_CONSTRAINT_DEFAULT; + } } diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/mutation/RichMutationForAction.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/mutation/RichMutationForAction.java index 4f43941f888..5b2c2909190 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/mutation/RichMutationForAction.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/mutation/RichMutationForAction.java @@ -33,7 +33,6 @@ import org.jspecify.annotations.Nullable; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.bookmark.Bookmark; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; @@ -159,35 +158,32 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment String key = ObjectFeatureUtils.keyFor(refValue); BookmarkedPojo value = environment.getGraphQlContext().get(key); result = Optional.of(value).map(BookmarkedPojo::getTargetPojo); - } else { - throw new IllegalArgumentException("Either 'id' or 'ref' must be specified for a DomainObject input type"); - } + } else + throw new IllegalArgumentException("Either 'id' or 'ref' must be specified for a DomainObject input type"); } sourcePojo = result .orElseThrow(); // TODO: better error handling if no such object found. } ManagedObject managedObject = ManagedObject.adaptSingular(objectSpec, sourcePojo); + var visibilityConstraint = Context.visibilityConstraint(); - var visibleConsent = objectAction.isVisible(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (visibleConsent.isVetoed()) { - throw new HiddenException(objectAction.getFeatureIdentifier()); - } + var visibleConsent = objectAction.isVisible(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (visibleConsent.isVetoed()) + throw new HiddenException(objectAction.getFeatureIdentifier()); - var usableConsent = objectAction.isUsable(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (usableConsent.isVetoed()) { - throw new DisabledException(objectAction.getFeatureIdentifier()); - } + var usableConsent = objectAction.isUsable(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (usableConsent.isVetoed()) + throw new DisabledException(objectAction.getFeatureIdentifier()); var head = objectAction.interactionHead(managedObject); var argumentManagedObjects = argumentManagedObjectsFor(environment, objectAction); var validityConsent = objectAction.isArgumentSetValid(head, argumentManagedObjects, InteractionInitiatedBy.USER); - if (validityConsent.isVetoed()) { - throw new IllegalArgumentException(validityConsent.getReasonAsString().orElse("Invalid")); - } + if (validityConsent.isVetoed()) + throw new IllegalArgumentException(validityConsent.getReasonAsString().orElse("Invalid")); - var resultManagedObject = objectAction.execute(head, argumentManagedObjects, InteractionInitiatedBy.USER); + var resultManagedObject = objectAction.execute(head, argumentManagedObjects, InteractionInitiatedBy.USER, visibilityConstraint.whatViewer()); return resultManagedObject.getPojo(); } diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/mutation/RichMutationForProperty.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/mutation/RichMutationForProperty.java index 0664977b249..e69f46c89a3 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/mutation/RichMutationForProperty.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/mutation/RichMutationForProperty.java @@ -28,15 +28,14 @@ import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.bookmark.Bookmark; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; import org.apache.causeway.viewer.graphql.model.context.Context; -import org.apache.causeway.viewer.graphql.model.domain.Environment; import org.apache.causeway.viewer.graphql.model.domain.Element; +import org.apache.causeway.viewer.graphql.model.domain.Environment; import org.apache.causeway.viewer.graphql.model.domain.SchemaType; import org.apache.causeway.viewer.graphql.model.domain.TypeNames; import org.apache.causeway.viewer.graphql.model.domain.common.query.ObjectFeatureUtils; @@ -108,9 +107,8 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment var key = ObjectFeatureUtils.keyFor(refValue); BookmarkedPojo value = environment.getGraphQlContext().get(key); result = Optional.of(value).map(BookmarkedPojo::getTargetPojo); - } else { - throw new IllegalArgumentException("Either 'id' or 'ref' must be specified for a DomainObject input type"); - } + } else + throw new IllegalArgumentException("Either 'id' or 'ref' must be specified for a DomainObject input type"); } Object sourcePojo = result .orElseThrow(); // TODO: better error handling if no such object found. @@ -120,21 +118,19 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment Map arguments = dataFetchingEnvironment.getArguments(); Object argumentValue = arguments.get(oneToOneAssociation.asciiId()); ManagedObject argumentManagedObject = ManagedObject.adaptProperty(oneToOneAssociation, argumentValue); + var visibilityConstraint = Context.visibilityConstraint(); - var visibleConsent = oneToOneAssociation.isVisible(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (visibleConsent.isVetoed()) { - throw new HiddenException(oneToOneAssociation.getFeatureIdentifier()); - } + var visibleConsent = oneToOneAssociation.isVisible(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (visibleConsent.isVetoed()) + throw new HiddenException(oneToOneAssociation.getFeatureIdentifier()); - var usableConsent = oneToOneAssociation.isUsable(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (usableConsent.isVetoed()) { - throw new DisabledException(oneToOneAssociation.getFeatureIdentifier()); - } + var usableConsent = oneToOneAssociation.isUsable(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (usableConsent.isVetoed()) + throw new DisabledException(oneToOneAssociation.getFeatureIdentifier()); var validityConsent = oneToOneAssociation.isAssociationValid(managedObject, argumentManagedObject, InteractionInitiatedBy.USER); - if (validityConsent.isVetoed()) { - throw new InvalidException(validityConsent); - } + if (validityConsent.isVetoed()) + throw new InvalidException(validityConsent); oneToOneAssociation.set(managedObject, argumentManagedObject, InteractionInitiatedBy.USER); diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionInvokeResult.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionInvokeResult.java index 249f06d01b7..7dcd831e99c 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionInvokeResult.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionInvokeResult.java @@ -27,7 +27,6 @@ import org.jspecify.annotations.Nullable; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.facets.actcoll.typeof.TypeOfFacet; import org.apache.causeway.core.metamodel.object.ManagedObject; @@ -106,32 +105,29 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment var environment = new Environment.ForTunnelled(dataFetchingEnvironment); var objectSpecification = context.specificationLoader.loadSpecification(sourcePojo.getClass()); - if (objectSpecification == null) { - return null; - } + if (objectSpecification == null) + return null; var objectAction = actionInteractor.getObjectMember(); var managedObject = ManagedObject.adaptSingular(objectSpecification, sourcePojo); + var visibilityConstraint = Context.visibilityConstraint(); - var visibleConsent = objectAction.isVisible(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (visibleConsent.isVetoed()) { - throw new HiddenException(objectAction.getFeatureIdentifier()); - } + var visibleConsent = objectAction.isVisible(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (visibleConsent.isVetoed()) + throw new HiddenException(objectAction.getFeatureIdentifier()); - var usableConsent = objectAction.isUsable(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (usableConsent.isVetoed()) { - throw new DisabledException(objectAction.getFeatureIdentifier()); - } + var usableConsent = objectAction.isUsable(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (usableConsent.isVetoed()) + throw new DisabledException(objectAction.getFeatureIdentifier()); var head = objectAction.interactionHead(managedObject); var argumentManagedObjects = actionInteractor.argumentManagedObjectsFor(environment, objectAction, context.bookmarkService); var validityConsent = objectAction.isArgumentSetValid(head, argumentManagedObjects, InteractionInitiatedBy.USER); - if (validityConsent.isVetoed()) { - throw new IllegalArgumentException(validityConsent.getReasonAsString().orElse("Invalid")); - } + if (validityConsent.isVetoed()) + throw new IllegalArgumentException(validityConsent.getReasonAsString().orElse("Invalid")); - var resultManagedObject = objectAction.execute(head, argumentManagedObjects, InteractionInitiatedBy.USER); + var resultManagedObject = objectAction.execute(head, argumentManagedObjects, InteractionInitiatedBy.USER, visibilityConstraint.whatViewer()); return resultManagedObject.getPojo(); } diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamAutoComplete.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamAutoComplete.java index f5f6970df16..96e27be7ed0 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamAutoComplete.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamAutoComplete.java @@ -34,12 +34,12 @@ import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.interactions.managed.ParameterNegotiationModel; import org.apache.causeway.core.metamodel.object.ManagedObject; - import org.apache.causeway.core.metamodel.spec.feature.ObjectFeature; - import org.apache.causeway.viewer.graphql.model.context.Context; -import org.apache.causeway.viewer.graphql.model.domain.Environment; +import org.apache.causeway.core.metamodel.spec.feature.ObjectFeature; +import org.apache.causeway.viewer.graphql.model.context.Context; import org.apache.causeway.viewer.graphql.model.domain.Element; +import org.apache.causeway.viewer.graphql.model.domain.Environment; import org.apache.causeway.viewer.graphql.model.domain.common.interactors.ActionParamInteractor; - import org.apache.causeway.viewer.graphql.model.fetcher.BookmarkedPojo; +import org.apache.causeway.viewer.graphql.model.fetcher.BookmarkedPojo; import org.apache.causeway.viewer.graphql.model.types.TypeMapper; import lombok.extern.slf4j.Slf4j; @@ -79,9 +79,8 @@ protected List fetchData(final DataFetchingEnvironment dataFetchingEnvir var sourcePojo = BookmarkedPojo.sourceFrom(dataFetchingEnvironment); var objectSpecification = context.specificationLoader.loadSpecification(sourcePojo.getClass()); - if (objectSpecification == null) { - return Collections.emptyList(); - } + if (objectSpecification == null) + return Collections.emptyList(); var objectAction = actionParamInteractor.getObjectMember(); var managedObject = ManagedObject.adaptSingular(objectSpecification, sourcePojo); @@ -90,7 +89,7 @@ protected List fetchData(final DataFetchingEnvironment dataFetchingEnvir var objectActionParameter = objectAction.getParameterById(objectFeature.asciiId()); var argumentManagedObjects = actionParamInteractor.argumentManagedObjectsFor(new Environment.For(dataFetchingEnvironment), objectAction, context.bookmarkService); - var managedAction = ManagedAction.of(managedObject, objectAction, Where.ANYWHERE); + var managedAction = ManagedAction.of(managedObject, objectAction, Context.visibilityConstraint(Where.ANYWHERE)); var pendingArgs = ParameterNegotiationModel.of(managedAction, argumentManagedObjects); var searchArg = dataFetchingEnvironment.getArgument(SEARCH_PARAM_NAME); var autoCompleteManagedObjects = objectActionParameter.getAutoComplete(pendingArgs, searchArg, InteractionInitiatedBy.USER); diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamChoices.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamChoices.java index 05d843ad0ea..e101cf7b5a5 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamChoices.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamChoices.java @@ -32,12 +32,12 @@ import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.interactions.managed.ParameterNegotiationModel; import org.apache.causeway.core.metamodel.object.ManagedObject; - import org.apache.causeway.core.metamodel.spec.feature.ObjectFeature; - import org.apache.causeway.viewer.graphql.model.context.Context; -import org.apache.causeway.viewer.graphql.model.domain.Environment; +import org.apache.causeway.core.metamodel.spec.feature.ObjectFeature; +import org.apache.causeway.viewer.graphql.model.context.Context; import org.apache.causeway.viewer.graphql.model.domain.Element; +import org.apache.causeway.viewer.graphql.model.domain.Environment; import org.apache.causeway.viewer.graphql.model.domain.common.interactors.ActionParamInteractor; - import org.apache.causeway.viewer.graphql.model.fetcher.BookmarkedPojo; +import org.apache.causeway.viewer.graphql.model.fetcher.BookmarkedPojo; import org.apache.causeway.viewer.graphql.model.types.TypeMapper; import lombok.extern.slf4j.Slf4j; @@ -71,9 +71,8 @@ protected List fetchData(final DataFetchingEnvironment dataFetchingEnvir var sourcePojo = BookmarkedPojo.sourceFrom(dataFetchingEnvironment); var objectSpecification = context.specificationLoader.loadSpecification(sourcePojo.getClass()); - if (objectSpecification == null) { - return Collections.emptyList(); - } + if (objectSpecification == null) + return Collections.emptyList(); var objectAction = actionParamInteractor.getObjectMember(); var managedObject = ManagedObject.adaptSingular(objectSpecification, sourcePojo); @@ -82,7 +81,7 @@ protected List fetchData(final DataFetchingEnvironment dataFetchingEnvir var objectActionParameter = objectAction.getParameterById(objectFeature.asciiId()); var argumentManagedObjects = actionParamInteractor.argumentManagedObjectsFor(new Environment.For(dataFetchingEnvironment), objectAction, context.bookmarkService); - var managedAction = ManagedAction.of(managedObject, objectAction, Where.ANYWHERE); + var managedAction = ManagedAction.of(managedObject, objectAction, Context.visibilityConstraint(Where.ANYWHERE)); var pendingArgs = ParameterNegotiationModel.of(managedAction, argumentManagedObjects); var choices = objectActionParameter.getChoices(pendingArgs, InteractionInitiatedBy.USER); diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamDefault.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamDefault.java index c5bf94b5200..e28e85a47b2 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamDefault.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichActionParamsParamDefault.java @@ -30,8 +30,8 @@ import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.feature.ObjectFeature; import org.apache.causeway.viewer.graphql.model.context.Context; -import org.apache.causeway.viewer.graphql.model.domain.Environment; import org.apache.causeway.viewer.graphql.model.domain.Element; +import org.apache.causeway.viewer.graphql.model.domain.Environment; import org.apache.causeway.viewer.graphql.model.domain.common.interactors.ActionParamInteractor; import org.apache.causeway.viewer.graphql.model.fetcher.BookmarkedPojo; import org.apache.causeway.viewer.graphql.model.types.TypeMapper; @@ -65,15 +65,14 @@ public RichActionParamsParamDefault( protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment) { var sourcePojo = BookmarkedPojo.sourceFrom(dataFetchingEnvironment); var objectSpecification = context.specificationLoader.loadSpecification(sourcePojo.getClass()); - if (objectSpecification == null) { - return Collections.emptyList(); - } + if (objectSpecification == null) + return Collections.emptyList(); var objectAction = actionParamInteractor.getObjectMember(); var managedObject = ManagedObject.adaptSingular(objectSpecification, sourcePojo); final ObjectFeature objectFeature = actionParamInteractor.getObjectActionParameter(); var objectActionParameter = objectAction.getParameterById(objectFeature.asciiId()); var argumentManagedObjects = actionParamInteractor.argumentManagedObjectsFor(new Environment.For(dataFetchingEnvironment), objectAction, context.bookmarkService); - var managedAction = ManagedAction.of(managedObject, objectAction, Where.ANYWHERE); + var managedAction = ManagedAction.of(managedObject, objectAction, Context.visibilityConstraint(Where.ANYWHERE)); var pendingArgs = ParameterNegotiationModel.of(managedAction, argumentManagedObjects); var defaultManagedObject = objectActionParameter.getDefault(pendingArgs); return defaultManagedObject.getPojo(); diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichMemberDisabled.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichMemberDisabled.java index 12cd63b068d..d3f3f0e4198 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichMemberDisabled.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichMemberDisabled.java @@ -22,7 +22,6 @@ import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.feature.ObjectMember; @@ -58,14 +57,12 @@ protected String fetchData(final DataFetchingEnvironment dataFetchingEnvironment var sourcePojoClass = sourcePojo.getClass(); var objectSpecification = context.specificationLoader.loadSpecification(sourcePojoClass); - if (objectSpecification == null) { - return String.format("Disabled; could not determine target object's type ('%s')", sourcePojoClass.getName()); - } + if (objectSpecification == null) + return String.format("Disabled; could not determine target object's type ('%s')", sourcePojoClass.getName()); var objectMember = memberInteractor.getObjectMember(); var managedObject = ManagedObject.adaptSingular(objectSpecification, sourcePojo); - - var usable = objectMember.isUsable(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); + var usable = objectMember.isUsable(managedObject, InteractionInitiatedBy.USER, Context.visibilityConstraint()); return usable.getReasonAsString().orElse(null); } diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichMemberHidden.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichMemberHidden.java index 4bf8f1ed12f..c87b8db8e85 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichMemberHidden.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichMemberHidden.java @@ -22,7 +22,6 @@ import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.feature.ObjectMember; @@ -58,15 +57,13 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment var sourcePojoClass = sourcePojo.getClass(); var objectSpecification = context.specificationLoader.loadSpecification(sourcePojoClass); - if (objectSpecification == null) { - // not expected + if (objectSpecification == null) + // not expected return true; - } var objectMember = memberInteractor.getObjectMember(); var managedObject = ManagedObject.adaptSingular(objectSpecification, sourcePojo); - - var visibleConsent = objectMember.isVisible(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); + var visibleConsent = objectMember.isVisible(managedObject, InteractionInitiatedBy.USER, Context.visibilityConstraint()); return visibleConsent.isVetoed(); } diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichPropertySet.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichPropertySet.java index 94e601666cf..236ea24222b 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichPropertySet.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/rich/query/RichPropertySet.java @@ -24,7 +24,6 @@ import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.viewer.graphql.model.context.Context; @@ -64,9 +63,8 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment var sourcePojoClass = sourcePojo.getClass(); var objectSpecification = context.specificationLoader.loadSpecification(sourcePojoClass); - if (objectSpecification == null) { - return null; - } + if (objectSpecification == null) + return null; var otoa = propertyInteractor.getObjectMember(); var managedObject = ManagedObject.adaptSingular(objectSpecification, sourcePojo); @@ -74,21 +72,19 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment Map arguments = dataFetchingEnvironment.getArguments(); Object argumentValue = arguments.get(otoa.asciiId()); ManagedObject argumentManagedObject = ManagedObject.adaptProperty(otoa, argumentValue); + var visibilityConstraint = Context.visibilityConstraint(); - var visibleConsent = otoa.isVisible(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (visibleConsent.isVetoed()) { - throw new HiddenException(otoa.getFeatureIdentifier()); - } + var visibleConsent = otoa.isVisible(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (visibleConsent.isVetoed()) + throw new HiddenException(otoa.getFeatureIdentifier()); - var usableConsent = otoa.isUsable(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (usableConsent.isVetoed()) { - throw new DisabledException(otoa.getFeatureIdentifier()); - } + var usableConsent = otoa.isUsable(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (usableConsent.isVetoed()) + throw new DisabledException(otoa.getFeatureIdentifier()); var validityConsent = otoa.isAssociationValid(managedObject, argumentManagedObject, InteractionInitiatedBy.USER); - if (validityConsent.isVetoed()) { - throw new InvalidException(validityConsent); - } + if (validityConsent.isVetoed()) + throw new InvalidException(validityConsent); otoa.set(managedObject, argumentManagedObject, InteractionInitiatedBy.USER); diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/mutation/SimpleMutationForAction.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/mutation/SimpleMutationForAction.java index 9c4adf2bbc4..608c7997cfc 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/mutation/SimpleMutationForAction.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/mutation/SimpleMutationForAction.java @@ -33,7 +33,6 @@ import org.jspecify.annotations.Nullable; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.bookmark.Bookmark; import org.apache.causeway.commons.collections.Can; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; @@ -158,35 +157,32 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment var key = ObjectFeatureUtils.keyFor(refValue); BookmarkedPojo value = environment.getGraphQlContext().get(key); result = Optional.of(value).map(BookmarkedPojo::getTargetPojo); - } else { - throw new IllegalArgumentException("Either 'id' or 'ref' must be specified for a DomainObject input type"); - } + } else + throw new IllegalArgumentException("Either 'id' or 'ref' must be specified for a DomainObject input type"); } sourcePojo = result .orElseThrow(); // TODO: better error handling if no such object found. } ManagedObject managedObject = ManagedObject.adaptSingular(objectSpec, sourcePojo); + var visibilityConstraint = Context.visibilityConstraint(); - var visibleConsent = objectAction.isVisible(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (visibleConsent.isVetoed()) { - throw new HiddenException(objectAction.getFeatureIdentifier()); - } + var visibleConsent = objectAction.isVisible(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (visibleConsent.isVetoed()) + throw new HiddenException(objectAction.getFeatureIdentifier()); - var usableConsent = objectAction.isUsable(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (usableConsent.isVetoed()) { - throw new DisabledException(objectAction.getFeatureIdentifier()); - } + var usableConsent = objectAction.isUsable(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (usableConsent.isVetoed()) + throw new DisabledException(objectAction.getFeatureIdentifier()); var head = objectAction.interactionHead(managedObject); var argumentManagedObjects = argumentManagedObjectsFor(environment, objectAction); var validityConsent = objectAction.isArgumentSetValid(head, argumentManagedObjects, InteractionInitiatedBy.USER); - if (validityConsent.isVetoed()) { - throw new IllegalArgumentException(validityConsent.getReasonAsString().orElse("Invalid")); - } + if (validityConsent.isVetoed()) + throw new IllegalArgumentException(validityConsent.getReasonAsString().orElse("Invalid")); - var resultManagedObject = objectAction.execute(head, argumentManagedObjects, InteractionInitiatedBy.USER); + var resultManagedObject = objectAction.execute(head, argumentManagedObjects, InteractionInitiatedBy.USER, visibilityConstraint.whatViewer()); return resultManagedObject.getPojo(); } diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/mutation/SimpleMutationForProperty.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/mutation/SimpleMutationForProperty.java index cf547124bf9..97aae39d272 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/mutation/SimpleMutationForProperty.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/mutation/SimpleMutationForProperty.java @@ -28,15 +28,14 @@ import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.bookmark.Bookmark; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.spec.ObjectSpecification; import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation; import org.apache.causeway.viewer.graphql.model.context.Context; -import org.apache.causeway.viewer.graphql.model.domain.Environment; import org.apache.causeway.viewer.graphql.model.domain.Element; +import org.apache.causeway.viewer.graphql.model.domain.Environment; import org.apache.causeway.viewer.graphql.model.domain.SchemaType; import org.apache.causeway.viewer.graphql.model.domain.TypeNames; import org.apache.causeway.viewer.graphql.model.domain.common.query.ObjectFeatureUtils; @@ -110,9 +109,8 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment String key = ObjectFeatureUtils.keyFor(refValue); BookmarkedPojo value = environment.getGraphQlContext().get(key); result = Optional.of(value).map(BookmarkedPojo::getTargetPojo); - } else { - throw new IllegalArgumentException("Either 'id' or 'ref' must be specified for a DomainObject input type"); - } + } else + throw new IllegalArgumentException("Either 'id' or 'ref' must be specified for a DomainObject input type"); } Object sourcePojo = result .orElseThrow(); // TODO: better error handling if no such object found. @@ -122,21 +120,19 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment Map arguments = dataFetchingEnvironment.getArguments(); Object argumentValue = arguments.get(oneToOneAssociation.asciiId()); ManagedObject argumentManagedObject = ManagedObject.adaptProperty(oneToOneAssociation, argumentValue); + var visibilityConstraint = Context.visibilityConstraint(); - var visibleConsent = oneToOneAssociation.isVisible(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (visibleConsent.isVetoed()) { - throw new HiddenException(oneToOneAssociation.getFeatureIdentifier()); - } + var visibleConsent = oneToOneAssociation.isVisible(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (visibleConsent.isVetoed()) + throw new HiddenException(oneToOneAssociation.getFeatureIdentifier()); - var usableConsent = oneToOneAssociation.isUsable(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (usableConsent.isVetoed()) { - throw new DisabledException(oneToOneAssociation.getFeatureIdentifier()); - } + var usableConsent = oneToOneAssociation.isUsable(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (usableConsent.isVetoed()) + throw new DisabledException(oneToOneAssociation.getFeatureIdentifier()); var validityConsent = oneToOneAssociation.isAssociationValid(managedObject, argumentManagedObject, InteractionInitiatedBy.USER); - if (validityConsent.isVetoed()) { - throw new InvalidException(validityConsent); - } + if (validityConsent.isVetoed()) + throw new InvalidException(validityConsent); oneToOneAssociation.set(managedObject, argumentManagedObject, InteractionInitiatedBy.USER); diff --git a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/query/SimpleAction.java b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/query/SimpleAction.java index 981bb3ee2c7..1b49b4f318b 100644 --- a/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/query/SimpleAction.java +++ b/viewers/graphql/model/src/main/java/org/apache/causeway/viewer/graphql/model/domain/simple/query/SimpleAction.java @@ -32,7 +32,6 @@ import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.bookmark.Bookmark; import org.apache.causeway.applib.services.bookmark.BookmarkService; import org.apache.causeway.commons.collections.Can; @@ -152,10 +151,8 @@ public static Can argumentManagedObjectsFor( case ENTITY: case VIEW_MODEL: - if (argumentValue == null) { - return ManagedObject.empty(elementType); - } - // fall through + if (argumentValue == null) + return ManagedObject.empty(elementType); case ABSTRACT: // if the parameter is abstract, we still attempt to figure out the arguments. @@ -191,9 +188,8 @@ private static ManagedObject adaptValue( final Context context) { var elementType = oap.getElementType(); - if (argumentValue == null) { - return ManagedObject.empty(elementType); - } + if (argumentValue == null) + return ManagedObject.empty(elementType); var argPojo = context.typeMapper.unmarshal(argumentValue, elementType); return ManagedObject.adaptParameter(oap, argPojo); @@ -211,22 +207,19 @@ public static Optional asPojo( if (refValue != null) { String key = ObjectFeatureUtils.keyFor(refValue); BookmarkedPojo bookmarkedPojo = environment.getGraphQlContext().get(key); - if (bookmarkedPojo == null) { - throw new IllegalArgumentException(String.format( + if (bookmarkedPojo == null) + throw new IllegalArgumentException(String.format( "Could not find object referenced '%s' in the execution context; was it saved previously using \"saveAs\" ?", refValue)); - } var targetPojoClass = bookmarkedPojo.getTargetPojo().getClass(); var targetPojoSpec = context.specificationLoader.loadSpecification(targetPojoClass); - if (targetPojoSpec == null) { - throw new IllegalArgumentException(String.format( + if (targetPojoSpec == null) + throw new IllegalArgumentException(String.format( "The object referenced '%s' is not part of the metamodel (has class '%s')", refValue, targetPojoClass.getCanonicalName())); - } - if (!elementType.isPojoCompatible(bookmarkedPojo.getTargetPojo())) { - throw new IllegalArgumentException(String.format( + if (!elementType.isPojoCompatible(bookmarkedPojo.getTargetPojo())) + throw new IllegalArgumentException(String.format( "The object referenced '%s' has a type '%s' that is not assignable to the required type '%s'", refValue, targetPojoSpec.logicalTypeName(), elementType.logicalTypeName())); - } return Optional.of(bookmarkedPojo).map(BookmarkedPojo::getTargetPojo); } @@ -236,11 +229,10 @@ public static Optional asPojo( Optional bookmarkIfAny; if(elementType.isAbstract()) { var objectSpecArg = (ObjectSpecification)argumentValue.get("logicalTypeName"); - if (objectSpecArg == null) { - throw new IllegalArgumentException(String.format( + if (objectSpecArg == null) + throw new IllegalArgumentException(String.format( "The 'logicalTypeName' is required along with the 'id', because the input type '%s' is abstract", elementType.logicalTypeName())); - } bookmarkIfAny = Optional.of(Bookmark.forLogicalTypeNameAndIdentifier(objectSpecArg.logicalTypeName(), idValue)); } else { bookmarkIfAny = context.bookmarkService.bookmarkFor(paramClass, idValue); @@ -301,32 +293,29 @@ protected Object fetchData(final DataFetchingEnvironment dataFetchingEnvironment var environment = new Environment.For(dataFetchingEnvironment); var objectSpecification = context.specificationLoader.loadSpecification(sourcePojo.getClass()); - if (objectSpecification == null) { - return null; - } + if (objectSpecification == null) + return null; var objectAction = getObjectMember(); var managedObject = ManagedObject.adaptSingular(objectSpecification, sourcePojo); + var visibilityConstraint = Context.visibilityConstraint(); - var visibleConsent = objectAction.isVisible(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (visibleConsent.isVetoed()) { - throw new HiddenException(objectAction.getFeatureIdentifier()); - } + var visibleConsent = objectAction.isVisible(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (visibleConsent.isVetoed()) + throw new HiddenException(objectAction.getFeatureIdentifier()); - var usableConsent = objectAction.isUsable(managedObject, InteractionInitiatedBy.USER, Where.ANYWHERE); - if (usableConsent.isVetoed()) { - throw new DisabledException(objectAction.getFeatureIdentifier()); - } + var usableConsent = objectAction.isUsable(managedObject, InteractionInitiatedBy.USER, visibilityConstraint); + if (usableConsent.isVetoed()) + throw new DisabledException(objectAction.getFeatureIdentifier()); var head = objectAction.interactionHead(managedObject); var argumentManagedObjects = argumentManagedObjectsFor(environment, objectAction, context.bookmarkService); var validityConsent = objectAction.isArgumentSetValid(head, argumentManagedObjects, InteractionInitiatedBy.USER); - if (validityConsent.isVetoed()) { - throw new IllegalArgumentException(validityConsent.getReasonAsString().orElse("Invalid")); - } + if (validityConsent.isVetoed()) + throw new IllegalArgumentException(validityConsent.getReasonAsString().orElse("Invalid")); - var resultManagedObject = objectAction.execute(head, argumentManagedObjects, InteractionInitiatedBy.USER); + var resultManagedObject = objectAction.execute(head, argumentManagedObjects, InteractionInitiatedBy.USER, visibilityConstraint.whatViewer()); return resultManagedObject.getPojo(); } diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/IResourceContext.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/IResourceContext.java index 778a1fa3e61..99e56529cc7 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/IResourceContext.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/IResourceContext.java @@ -24,11 +24,11 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.services.bookmark.Bookmark; import org.apache.causeway.core.config.CausewayConfiguration.Viewer.Restfulobjects; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.context.HasMetaModelContext; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.viewer.restfulobjects.rendering.domainobjects.DomainObjectReprRenderer; import org.apache.causeway.viewer.restfulobjects.rendering.domainobjects.ObjectAdapterLinkTo; @@ -68,7 +68,7 @@ public interface IResourceContext extends HasMetaModelContext { */ InteractionInitiatedBy interactionInitiatedBy(); - Where where(); + VisibilityConstraint visibilityConstraint(); ObjectAdapterLinkTo objectAdapterLinkTo(); List> followLinks(); diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext.java index 71e3a8bc0be..aa7289570f2 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/context/ResourceContext.java @@ -43,6 +43,8 @@ import org.apache.causeway.commons.io.UrlUtils; import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy; import org.apache.causeway.core.metamodel.context.MetaModelContext; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.ManagedObjects; import org.apache.causeway.viewer.restfulobjects.applib.JsonRepresentation; @@ -70,6 +72,7 @@ public record ResourceContext( boolean isValidateOnly, InteractionInitiatedBy interactionInitiatedBy, + VisibilityConstraint visibilityConstraint, JsonRepresentation queryStringAsJsonRepr, ObjectAdapterLinkTo objectAdapterLinkTo, @@ -116,6 +119,7 @@ private ResourceContext( Collections.unmodifiableList(arg(requestArgsAsMap, RequestParameter.FOLLOW_LINKS)), arg(requestArgsAsMap, RequestParameter.VALIDATE_ONLY), interactionInitiatedBy, + ResourceContext.visibilityConstraint(resourceDescriptor.where()), requestArgsAsMap, switch(resourceDescriptor.resourceLink()) { case NONE -> null; @@ -127,10 +131,6 @@ private ResourceContext( ensureDomainModelQueryParamSupported(); } - @Override public Where where() { - return resourceDescriptor().where(); - } - /** * Only applies to rendering of objects */ @@ -140,13 +140,12 @@ private ResourceContext( private void ensureDomainModelQueryParamSupported() { final DomainModel domainModel = arg(queryStringAsJsonRepr(), RequestParameter.DOMAIN_MODEL); - if(domainModel != DomainModel.FORMAL) { - throw RestfulObjectsApplicationException.createWithMessage(HttpStatus.BAD_REQUEST, + if(domainModel != DomainModel.FORMAL) + throw RestfulObjectsApplicationException.createWithMessage(HttpStatus.BAD_REQUEST, "x-ro-domain-model of '%s' is not supported".formatted(domainModel)); - } } - private static JsonRepresentation requestArgsAsMap(final Map params, RequestParams urlUnencodedQueryString) { + private static JsonRepresentation requestArgsAsMap(final Map params, final RequestParams urlUnencodedQueryString) { if(simpleQueryArgs(params)) { // try to process regular params and build up JSON repr final JsonRepresentation map = JsonRepresentation.newMap(); @@ -164,31 +163,26 @@ private static JsonRepresentation requestArgsAsMap(final Map p } } return map; - } else { - return Optional.ofNullable(urlUnencodedQueryString) + } else + return Optional.ofNullable(urlUnencodedQueryString) .orElseGet(RequestParams::ofEmptyQueryString) .asMap(); - } } static String stripQuotes(final String str) { - if(_Strings.isNullOrEmpty(str)) { - return str; - } - if(str.startsWith("\"") && str.endsWith("\"")) { - return str.substring(1, str.lastIndexOf("\"")); - } + if(_Strings.isNullOrEmpty(str)) + return str; + if(str.startsWith("\"") && str.endsWith("\"")) + return str.substring(1, str.lastIndexOf("\"")); return str; } private static boolean simpleQueryArgs(final Map params) { - if(params==null || params.isEmpty()) { - return false; - } + if(params==null || params.isEmpty()) + return false; for(String paramId: params.keySet()) { - if("x-causeway-querystring".equals(paramId) || paramId.startsWith("{")) { - return false; - } + if("x-causeway-querystring".equals(paramId) || paramId.startsWith("{")) + return false; } return true; } @@ -237,16 +231,22 @@ public ManagedObject lookupServiceAdapterElseFail( .map(this::lookupServiceAdapterById) .orElse(null); - if(serviceAdapter==null) { - throw RestfulObjectsApplicationException.createWithMessage(HttpStatus.NOT_FOUND, + if(serviceAdapter==null) + throw RestfulObjectsApplicationException.createWithMessage(HttpStatus.NOT_FOUND, "Could not locate service '%s'".formatted(serviceIdOrAlias)); - } return serviceAdapter; } + // -- VISIBILITY CONSTRAINTS + + public static WhatViewer WHAT_VIEWER = new WhatViewer("Restful"); + public static VisibilityConstraint visibilityConstraint(final Where where) { + return new VisibilityConstraint(WHAT_VIEWER, where); + } + // -- JUNIT - public static ResourceContext forTesting(String queryString, HttpServletRequest servletRequest) { + public static ResourceContext forTesting(final String queryString, final HttpServletRequest servletRequest) { return new ResourceContext(MetaModelContext.instanceNullable(), ResourceDescriptor.empty(), null, null, RequestParams.ofQueryString(UrlUtils.urlDecodeUtf8(queryString)), @@ -255,9 +255,9 @@ public static ResourceContext forTesting(String queryString, HttpServletRequest } public static ResourceContext forTesting( - ResourceDescriptor resourceDescriptor, - HttpServletRequest servletRequest, - HttpHeaders httpHeaders) { + final ResourceDescriptor resourceDescriptor, + final HttpServletRequest servletRequest, + final HttpHeaders httpHeaders) { return new ResourceContext(MetaModelContext.instanceNullable(), resourceDescriptor, null, null, null, //RequestParams diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java index 6af3b08e0c2..f684374e2af 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/AbstractObjectMemberReprRenderer.java @@ -18,14 +18,13 @@ */ package org.apache.causeway.viewer.restfulobjects.rendering.domainobjects; -import tools.jackson.databind.node.NullNode; - import org.jspecify.annotations.NonNull; import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.internal.base._Casts; import org.apache.causeway.core.metamodel.consent.Consent; import org.apache.causeway.core.metamodel.facetapi.Facet; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.managed.ManagedMember; import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.core.metamodel.object.ManagedObjects; @@ -37,6 +36,9 @@ import org.apache.causeway.viewer.restfulobjects.rendering.IResourceContext; import org.apache.causeway.viewer.restfulobjects.rendering.LinkFollowSpecs; import org.apache.causeway.viewer.restfulobjects.rendering.ReprRendererAbstract; +import org.apache.causeway.viewer.restfulobjects.rendering.context.ResourceContext; + +import tools.jackson.databind.node.NullNode; public abstract class AbstractObjectMemberReprRenderer extends ReprRendererAbstract { @@ -86,7 +88,7 @@ public boolean isEventSerialization() { * Used to determine whether to follow links; only populated for {@link Mode#INLINE inline} Mode. */ private String memberId; - protected final Where where; + protected final VisibilityConstraint visibilityConstraint; public AbstractObjectMemberReprRenderer( final IResourceContext resourceContext, @@ -97,7 +99,7 @@ public AbstractObjectMemberReprRenderer( final Where where) { super(resourceContext, linkFollower, representationType, representation); this.memberId = memberId; - this.where = where; + this.visibilityConstraint = ResourceContext.visibilityConstraint(where); } protected String getMemberId() { @@ -221,9 +223,8 @@ private void addLinkToUp() { * mutators}. */ protected void addLinkFor(final @NonNull MutatorSpec mutatorSpec) { - if (!mutatorSpec.appliesTo(objectMember)) { - return; - } + if (!mutatorSpec.appliesTo(objectMember)) + return; final JsonRepresentation arguments = mutatorArgs(mutatorSpec); final RepresentationType representationType = objectMemberType.getRepresentationType(); final JsonRepresentation mutatorLink = linkToForMutatorInvoke().memberBuilder(mutatorSpec.rel, objectMemberType, objectMember, representationType, mutatorSpec.suffix).withHttpMethod(mutatorSpec.httpMethod).withArguments(arguments).build(); @@ -243,9 +244,8 @@ protected ObjectAdapterLinkTo linkToForMutatorInvoke() { * overridden (ie by actions) if required. */ protected JsonRepresentation mutatorArgs(final MutatorSpec mutatorSpec) { - if (mutatorSpec.arguments.isNone()) { - return null; - } + if (mutatorSpec.arguments.isNone()) + return null; if (mutatorSpec.arguments.isOne()) { final JsonRepresentation repr = JsonRepresentation.newMap(); repr.mapPutJsonNode("value", NullNode.getInstance()); // force a null into @@ -257,9 +257,8 @@ protected JsonRepresentation mutatorArgs(final MutatorSpec mutatorSpec) { } private void addDetailsLinkIfPersistent() { - if (!ManagedObjects.isIdentifiable(objectAdapter)) { - return; - } + if (!ManagedObjects.isIdentifiable(objectAdapter)) + return; final JsonRepresentation link = linkTo.memberBuilder(Rel.DETAILS, objectMemberType, objectMember).build(); getLinks().arrayAdd(link); @@ -278,9 +277,8 @@ private void addDetailsLinkIfPersistent() { protected abstract void followDetailsLink(JsonRepresentation detailsLink); protected final void putDisabledReasonIfDisabled() { - if(resourceContext.config().suppressMemberDisabledReason()) { - return; - } + if(resourceContext.config().suppressMemberDisabledReason()) + return; final String disabledReasonRep = usability().getReasonAsString().orElse(null); representation.mapPutString("disabledReason", disabledReasonRep); } @@ -304,11 +302,11 @@ protected F getMemberSpecFacet(final Class facetType) { } protected Consent usability() { - return objectMember.isUsable(objectAdapter, getInteractionInitiatedBy(), where); + return objectMember.isUsable(objectAdapter, getInteractionInitiatedBy(), visibilityConstraint); } protected Consent visibility() { - return objectMember.isVisible(objectAdapter, getInteractionInitiatedBy(), where); + return objectMember.isVisible(objectAdapter, getInteractionInitiatedBy(), visibilityConstraint); } } diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java index fe1146a79eb..0a188b6750a 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java @@ -161,9 +161,8 @@ public DomainObjectReprRenderer with(final ManagedObject objectAdapter) { @Override public JsonRepresentation render() { - if(representation == null) { - return null; - } + if(representation == null) + return null; final boolean isService = objectAdapter.objSpec().isInjectable(); @@ -310,21 +309,20 @@ private void addProperties(final ManagedObject objectAdapter, final JsonRepresen for (final ObjectAssociation assoc : associations) { if (mode.checkVisibility()) { - final Consent visibility = assoc.isVisible(objectAdapter, getInteractionInitiatedBy(), resourceContext.where()); + final Consent visibility = assoc.isVisible(objectAdapter, getInteractionInitiatedBy(), resourceContext.visibilityConstraint()); if (!visibility.isAllowed()) { continue; } } - if (!(assoc instanceof OneToOneAssociation)) { + if (!(assoc instanceof final OneToOneAssociation property)) { continue; } - final OneToOneAssociation property = (OneToOneAssociation) assoc; final LinkFollowSpecs linkFollowerForProp = getLinkFollowSpecs().follow("members[" + property.getId() + "]"); final JsonRepresentation propertyRepresentation = JsonRepresentation.newMap(); final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(getResourceContext(), linkFollowerForProp, property.getId(), propertyRepresentation); - renderer.with(ManagedProperty.of(objectAdapter, property, resourceContext.where())).usingLinkTo(linkToBuilder); + renderer.with(ManagedProperty.of(objectAdapter, property, resourceContext.visibilityConstraint())).usingLinkTo(linkToBuilder); if (mode.isArgs()) { renderer.asArguments(); @@ -345,27 +343,23 @@ private void addCollections(final ManagedObject objectAdapter, final JsonReprese for (final ObjectAssociation assoc : associations) { if (mode.checkVisibility()) { - final Consent visibility = assoc.isVisible(objectAdapter, getInteractionInitiatedBy(), resourceContext.where()); + final Consent visibility = assoc.isVisible(objectAdapter, getInteractionInitiatedBy(), resourceContext.visibilityConstraint()); if (!visibility.isAllowed()) { continue; } } - if (!(assoc instanceof OneToManyAssociation)) { + if (!(assoc instanceof final OneToManyAssociation collection)) { continue; } - final OneToManyAssociation collection = (OneToManyAssociation) assoc; - final LinkFollowSpecs linkFollowerForColl = getLinkFollowSpecs().follow( "members[" + collection.getId() + "]"); final JsonRepresentation collectionRepresentation = JsonRepresentation.newMap(); final ObjectCollectionReprRenderer renderer = new ObjectCollectionReprRenderer(getResourceContext(), linkFollowerForColl, collection.getId(), collectionRepresentation); - var where = resourceContext.where(); - - renderer.with(ManagedCollection.of(objectAdapter, collection, where)).usingLinkTo(linkToBuilder); + renderer.with(ManagedCollection.of(objectAdapter, collection, resourceContext.visibilityConstraint())).usingLinkTo(linkToBuilder); if(mode.isEventSerialization()) { renderer.asEventSerialization(); } @@ -381,7 +375,7 @@ private void addActions( actions .filter(action->{ - final Consent visibility = action.isVisible(objectAdapter, getInteractionInitiatedBy(), resourceContext.where()); + final Consent visibility = action.isVisible(objectAdapter, getInteractionInitiatedBy(), resourceContext.visibilityConstraint()); return visibility.isAllowed(); }) .forEach(action->{ @@ -390,18 +384,15 @@ private void addActions( new ObjectActionReprRenderer(getResourceContext(), linkFollowSpecs, action.getId(), JsonRepresentation.newMap()); - var where = resourceContext.where(); - - renderer.with(ManagedAction.of(objectAdapter, action, where)).usingLinkTo(linkToBuilder); + renderer.with(ManagedAction.of(objectAdapter, action, resourceContext.visibilityConstraint())).usingLinkTo(linkToBuilder); members.mapPutJsonRepresentation(action.getId(), renderer.render()); }); } private void addPersistLinkIfTransientAndPersistable() { - if (ManagedObjects.isIdentifiable(objectAdapter)) { - return; - } + if (ManagedObjects.isIdentifiable(objectAdapter)) + return; final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getResourceContext(), null, JsonRepresentation.newMap()); final JsonRepresentation domainObjectRepr = renderer.with(objectAdapter).asPersistLinkArguments().render(); @@ -428,16 +419,13 @@ public DomainObjectReprRenderer asEventSerialization() { } private void addUpdatePropertiesLinkIfRequired() { - if(mode.isEventSerialization()) { - return; - } - if (!ManagedObjects.isIdentifiable(objectAdapter)) { - return; - } + if(mode.isEventSerialization()) + return; + if (!ManagedObjects.isIdentifiable(objectAdapter)) + return; final boolean isService = objectAdapter.objSpec().isInjectable(); - if(isService) { - return; - } + if(isService) + return; final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getResourceContext(), null, JsonRepresentation.newMap()); diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java index a289319f086..c07c2a06956 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java @@ -21,8 +21,6 @@ import java.util.List; import java.util.Map; -import tools.jackson.databind.node.NullNode; - import org.apache.causeway.applib.annotation.SemanticsOf; import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.internal.collections._Lists; @@ -37,8 +35,11 @@ import org.apache.causeway.viewer.restfulobjects.applib.RepresentationType; import org.apache.causeway.viewer.restfulobjects.rendering.IResourceContext; import org.apache.causeway.viewer.restfulobjects.rendering.LinkFollowSpecs; +import org.apache.causeway.viewer.restfulobjects.rendering.context.ResourceContext; import org.apache.causeway.viewer.restfulobjects.rendering.domaintypes.ActionDescriptionReprRenderer; +import tools.jackson.databind.node.NullNode; + public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer { @@ -75,9 +76,8 @@ public JsonRepresentation render() { */ @Override protected void followDetailsLink(final JsonRepresentation detailsLink) { - var where = resourceContext.where(); final ObjectActionReprRenderer renderer = new ObjectActionReprRenderer(getResourceContext(), getLinkFollowSpecs(), null, JsonRepresentation.newMap()); - renderer.with(ManagedAction.of(objectAdapter, objectMember, where)).usingLinkTo(linkTo).asFollowed(); + renderer.with(ManagedAction.of(objectAdapter, objectMember, resourceContext.visibilityConstraint())).usingLinkTo(linkTo).asFollowed(); detailsLink.mapPutJsonRepresentation("value", renderer.render()); } @@ -85,9 +85,8 @@ protected void followDetailsLink(final JsonRepresentation detailsLink) { @Override protected void addMutatorLinksIfEnabled() { - if (usability().isVetoed()) { - return; - } + if (usability().isVetoed()) + return; final Map mutators = objectMemberType.getMutators(); final SemanticsOf actionSemantics = objectMember.getSemantics(); @@ -122,7 +121,7 @@ private Object argValueFor(final int i) { private ObjectActionReprRenderer addParameterDetails() { final Map parameters = _Maps.newLinkedHashMap(); if(objectMember.getParameterCount()>0) { - var act = ManagedAction.of(objectAdapter, objectMember, Where.ANYWHERE); + var act = ManagedAction.of(objectAdapter, objectMember, ResourceContext.visibilityConstraint(Where.ANYWHERE)); var paramNeg = act.startParameterNegotiation(); for(var paramMod : paramNeg.getParamModels()) { var paramMeta = paramMod.getMetaModel(); @@ -157,9 +156,8 @@ private Object choicesFor( final ParameterNegotiationModel paramNeg) { var paramMeta = paramMod.getMetaModel(); var choiceAdapters = paramMeta.getChoices(paramNeg, getInteractionInitiatedBy()); - if (choiceAdapters == null || choiceAdapters.isEmpty()) { - return null; - } + if (choiceAdapters == null || choiceAdapters.isEmpty()) + return null; final List list = _Lists.newArrayList(); for (var choiceAdapter : choiceAdapters) { // REVIEW: previously was using the spec of the parameter, but think instead it should be the spec of the adapter itself @@ -171,9 +169,8 @@ private Object choicesFor( private Object defaultFor(final ManagedParameter paramMod) { var defaultAdapter = paramMod.getValue().getValue(); - if (ManagedObjects.isNullOrUnspecifiedOrEmpty(defaultAdapter)) { - return null; - } + if (ManagedObjects.isNullOrUnspecifiedOrEmpty(defaultAdapter)) + return null; // REVIEW: previously was using the spec of the parameter, but think instead it should be the spec of the adapter itself // final ObjectSpecification defaultSpec = param.getSpecification(); var paramMeta = paramMod.getMetaModel(); @@ -184,9 +181,8 @@ private Object defaultFor(final ManagedParameter paramMod) { @Override protected void addLinksToFormalDomainModel() { - if(resourceContext.config().suppressDescribedByLinks()) { - return; - } + if(resourceContext.config().suppressDescribedByLinks()) + return; final JsonRepresentation link = ActionDescriptionReprRenderer.newLinkToBuilder(resourceContext, Rel.DESCRIBEDBY, objectAdapter.objSpec(), objectMember).build(); getLinks().arrayAdd(link); } diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java index b4848ee03cb..d6deaccf31d 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java @@ -55,9 +55,8 @@ public ObjectCollectionReprRenderer( @Override public JsonRepresentation render() { - if(representation == null) { - return null; - } + if(representation == null) + return null; renderMemberContent(); @@ -88,9 +87,8 @@ public JsonRepresentation render() { private void addValue(final LinkFollowSpecs linkFollower) { var valueAdapter = objectMember.get(objectAdapter, getInteractionInitiatedBy()); - if (valueAdapter == null) { - return; - } + if (valueAdapter == null) + return; final LinkFollowSpecs followHref = linkFollower.follow("href"); final boolean eagerlyRender = !followHref.isTerminated() @@ -130,7 +128,7 @@ private void addValue(final LinkFollowSpecs linkFollower) { protected void followDetailsLink(final JsonRepresentation detailsLink) { var objectCollectionReprRenderer = new ObjectCollectionReprRenderer(getResourceContext(), getLinkFollowSpecs(), null, JsonRepresentation.newMap()) - .with(ManagedCollection.of(objectAdapter, objectMember, resourceContext.where())) + .with(ManagedCollection.of(objectAdapter, objectMember, resourceContext.visibilityConstraint())) .asFollowed(); detailsLink.mapPutJsonRepresentation("value", objectCollectionReprRenderer.render()); } @@ -146,9 +144,8 @@ protected void addMutatorLinksIfEnabled() { @Override protected void addLinksToFormalDomainModel() { - if(resourceContext.config().suppressDescribedByLinks()) { - return; - } + if(resourceContext.config().suppressDescribedByLinks()) + return; final JsonRepresentation link = CollectionDescriptionReprRenderer .newLinkToBuilder(resourceContext, Rel.DESCRIBEDBY, objectAdapter.objSpec(), objectMember).build(); diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java index 3dcee2cb88b..20428943edd 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java @@ -20,8 +20,6 @@ import java.util.List; -import tools.jackson.databind.node.NullNode; - import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.commons.internal.collections._Lists; import org.apache.causeway.core.metamodel.interactions.managed.ManagedProperty; @@ -38,6 +36,8 @@ import org.apache.causeway.viewer.restfulobjects.rendering.domaintypes.PropertyDescriptionReprRenderer; import org.apache.causeway.viewer.restfulobjects.rendering.service.valuerender.JsonValueConverter; +import tools.jackson.databind.node.NullNode; + public class ObjectPropertyReprRenderer extends AbstractObjectMemberReprRenderer { @@ -137,7 +137,7 @@ private void addValue(final LinkFollowSpecs linkFollower) { protected void followDetailsLink(final JsonRepresentation detailsLink) { final JsonRepresentation representation = JsonRepresentation.newMap(); final ObjectPropertyReprRenderer renderer = new ObjectPropertyReprRenderer(getResourceContext(), getLinkFollowSpecs(), null, representation); - renderer.with(ManagedProperty.of(objectAdapter, objectMember, super.where)).asFollowed(); + renderer.with(ManagedProperty.of(objectAdapter, objectMember, super.visibilityConstraint)).asFollowed(); detailsLink.mapPutJsonRepresentation("value", renderer.render()); } @@ -145,9 +145,8 @@ protected void followDetailsLink(final JsonRepresentation detailsLink) { @Override protected void addMutatorLinksIfEnabled() { - if (usability().isVetoed()) { - return; - } + if (usability().isVetoed()) + return; objectMemberType.getMutators() .values() .forEach(this::addLinkFor); @@ -167,9 +166,8 @@ private Object propertyChoices() { var choiceAdapters = objectMember .getChoices(objectAdapter, getInteractionInitiatedBy()); - if (choiceAdapters == null || choiceAdapters.isEmpty()) { - return null; - } + if (choiceAdapters == null || choiceAdapters.isEmpty()) + return null; final List list = _Lists.newArrayList(); for (var choiceAdapter : choiceAdapters) { // REVIEW: previously was using the spec of the member, but think instead it should be the spec of the adapter itself @@ -185,9 +183,8 @@ private Object propertyChoices() { @Override protected void addLinksToFormalDomainModel() { - if(resourceContext.config().suppressDescribedByLinks()) { - return; - } + if(resourceContext.config().suppressDescribedByLinks()) + return; final JsonRepresentation link = PropertyDescriptionReprRenderer.newLinkToBuilder(getResourceContext(), Rel.DESCRIBEDBY, objectAdapter.objSpec(), objectMember).build(); getLinks().arrayAdd(link); } diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceOrgApacheCausewayV2.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceOrgApacheCausewayV2.java index 4df7714e34b..f1062b3a3f1 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceOrgApacheCausewayV2.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/causeway/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceOrgApacheCausewayV2.java @@ -24,14 +24,13 @@ import java.util.stream.Stream; import jakarta.inject.Named; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import tools.jackson.databind.node.POJONode; +import org.jspecify.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -import org.jspecify.annotations.Nullable; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.apache.causeway.applib.annotation.PriorityPrecedence; @@ -58,6 +57,8 @@ import lombok.RequiredArgsConstructor; +import tools.jackson.databind.node.POJONode; + /** * @since 1.x {@index} */ @@ -198,11 +199,10 @@ public ResponseEntity buildResponse( switch (resultType) { case DOMAIN_OBJECT: - if(ManagedObjects.isNullOrUnspecifiedOrEmpty(returnedAdapter)) { - // 404 not found + if(ManagedObjects.isNullOrUnspecifiedOrEmpty(returnedAdapter)) + // 404 not found return ResponseFactory.notFound(); - - } else { + else { rootRepresentation = JsonRepresentation.newMap(); appendObjectTo(resourceContext, returnedAdapter, rootRepresentation, suppression); } @@ -213,12 +213,10 @@ public ResponseEntity buildResponse( case LIST: - if(!objectAndActionInvocation.hasElements()) { - // 404 not found + if(!objectAndActionInvocation.hasElements()) + // 404 not found return ResponseFactory.notFound(); - } - rootRepresentation = JsonRepresentation.newArray(); objectAndActionInvocation.streamElementAdapters() @@ -238,12 +236,10 @@ public ResponseEntity buildResponse( case SCALAR_VALUES: - if(!objectAndActionInvocation.hasElements()) { - // 404 not found + if(!objectAndActionInvocation.hasElements()) + // 404 not found return ResponseFactory.notFound(); - } - rootRepresentation = JsonRepresentation.newArray(); objectAndActionInvocation.streamElementAdapters() @@ -260,10 +256,9 @@ public ResponseEntity buildResponse( case SCALAR_VALUE: var dto = dtoForValue(returnedAdapter).orElse(null); - if(dto==null) { - // 404 not found + if(dto==null) + // 404 not found return ResponseFactory.notFound(); - } var jsonNode = new POJONode(dto); rootRepresentation = new JsonRepresentation(jsonNode); @@ -286,9 +281,8 @@ public ResponseEntity buildResponse( private Optional dtoForValue(final @Nullable ManagedObject valueObject) { if(ManagedObjects.isNullOrUnspecifiedOrEmpty(valueObject) - || !valueObject.objSpec().isValue()) { - return Optional.empty(); - } + || !valueObject.objSpec().isValue()) + return Optional.empty(); var valSpec = valueObject.objSpec(); var dto = valSpec.isCompositeValue() ? ScalarValueDtoV2.forValue(valueObject.getPojo(), @@ -317,7 +311,7 @@ private void appendObjectTo( appendPropertiesTo(resourceContext, owner, rootRepresentation, suppression); - var where = resourceContext.where(); + var visibilityConstraint = resourceContext.visibilityConstraint(); owner.objSpec() .streamCollections(MixedIn.INCLUDED) @@ -327,12 +321,11 @@ private void appendObjectTo( rootRepresentation.mapPutJsonRepresentation(collection.getId(), collectionRepresentation); var interactionInitiatedBy = resourceContext.interactionInitiatedBy(); - var visibilityConsent = collection.isVisible(owner, interactionInitiatedBy, where); - if (!visibilityConsent.isAllowed()) { - return; - } + var visibilityConsent = collection.isVisible(owner, interactionInitiatedBy, visibilityConstraint); + if (!visibilityConsent.isAllowed()) + return; - var managedCollection = ManagedCollection.of(owner, collection, where); + var managedCollection = ManagedCollection.of(owner, collection, visibilityConstraint); appendCollectionTo(resourceContext, managedCollection, collectionRepresentation, suppression); }); @@ -346,21 +339,21 @@ private void appendPropertiesTo( final EnumSet suppression) { var interactionInitiatedBy = resourceContext.interactionInitiatedBy(); - var where = resourceContext.where(); + var visibilityConstraint = resourceContext.visibilityConstraint(); + final Stream properties = objectAdapter.objSpec() .streamProperties(MixedIn.INCLUDED); properties.forEach(property->{ - final Consent visibility = property.isVisible(objectAdapter, interactionInitiatedBy, where); - if (!visibility.isAllowed()) { - return; - } + final Consent visibility = property.isVisible(objectAdapter, interactionInitiatedBy, visibilityConstraint); + if (!visibility.isAllowed()) + return; final JsonRepresentation propertyRepresentation = JsonRepresentation.newMap(); var renderer = new ObjectPropertyReprRenderer(resourceContext, null, property.getId(), propertyRepresentation) .asStandalone() - .with(ManagedProperty.of(objectAdapter, property, where)); + .with(ManagedProperty.of(objectAdapter, property, visibilityConstraint)); final JsonRepresentation propertyValueRepresentation = renderer.render(); diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java index 042c6b73980..f3b6b4fe5f6 100644 --- a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java +++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/DomainObjectResourceServerside.java @@ -81,45 +81,40 @@ public ResponseEntity persist( RepresentationService.Intent.JUST_CREATED, ResourceLink.OBJECT)); final JsonRepresentation objectRepr = RequestParams.ofRequestBody(object).asMap(); - if (!objectRepr.isMap()) { - throw _EndpointLogging.error(log, "POST /objects/{}", domainType, + if (!objectRepr.isMap()) + throw _EndpointLogging.error(log, "POST /objects/{}", domainType, RestfulObjectsApplicationException .createWithMessage(HttpStatus.BAD_REQUEST, "Body is not a map; got %s".formatted(objectRepr))); - } var domainTypeSpec = getSpecificationLoader().specForLogicalTypeName(domainType) .orElse(null); - if (domainTypeSpec == null) { - throw _EndpointLogging.error(log, "POST /objects/{}", domainType, + if (domainTypeSpec == null) + throw _EndpointLogging.error(log, "POST /objects/{}", domainType, RestfulObjectsApplicationException .createWithMessage(HttpStatus.BAD_REQUEST, "Could not determine type of domain object to persist (no class with domainType Id of '%s')".formatted(domainType))); - } final ManagedObject adapter = domainTypeSpec.createObject(); final ObjectAdapterUpdateHelper updateHelper = new ObjectAdapterUpdateHelper(resourceContext, adapter); final JsonRepresentation membersMap = objectRepr.getMap("members"); - if (membersMap == null) { - throw _EndpointLogging.error(log, "POST /objects/{}", domainType, + if (membersMap == null) + throw _EndpointLogging.error(log, "POST /objects/{}", domainType, RestfulObjectsApplicationException .createWithMessage(HttpStatus.BAD_REQUEST, "Could not find members map; got %s".formatted(objectRepr))); - } - if (!updateHelper.copyOverProperties(membersMap, ObjectAdapterUpdateHelper.Intent.PERSISTING_NEW)) { - throw _EndpointLogging.error(log, "POST /objects/{}", domainType, + if (!updateHelper.copyOverProperties(membersMap, ObjectAdapterUpdateHelper.Intent.PERSISTING_NEW)) + throw _EndpointLogging.error(log, "POST /objects/{}", domainType, RestfulObjectsApplicationException .createWithBody(HttpStatus.BAD_REQUEST, objectRepr, "Illegal property value")); - } final Consent validity = adapter.objSpec().isValid(adapter, InteractionInitiatedBy.USER); - if (validity.isVetoed()) { - throw _EndpointLogging.error(log, "POST /objects/{}", domainType, + if (validity.isVetoed()) + throw _EndpointLogging.error(log, "POST /objects/{}", domainType, RestfulObjectsApplicationException .createWithBody(HttpStatus.BAD_REQUEST, objectRepr, validity.getReasonAsString().orElse(null))); - } MmEntityUtils.persistInCurrentTransaction(adapter); @@ -159,31 +154,28 @@ public ResponseEntity object( RepresentationService.Intent.ALREADY_PERSISTENT, ResourceLink.OBJECT)); final JsonRepresentation argRepr = RequestParams.ofRequestBody(object).asMap(); - if (!argRepr.isMap()) { - throw _EndpointLogging.error(log, "PUT /objects/{}/{}", domainType, instanceId, + if (!argRepr.isMap()) + throw _EndpointLogging.error(log, "PUT /objects/{}/{}", domainType, instanceId, RestfulObjectsApplicationException .createWithMessage( HttpStatus.BAD_REQUEST, "Body is not a map; got %s".formatted(argRepr))); - } var objectAdapter = getObjectAdapterElseThrowNotFound(domainType, instanceId, roEx->_EndpointLogging.error(log, "PUT /objects/{}/{}", domainType, instanceId, roEx)); final ObjectAdapterUpdateHelper updateHelper = new ObjectAdapterUpdateHelper(resourceContext, objectAdapter); - if (!updateHelper.copyOverProperties(argRepr, ObjectAdapterUpdateHelper.Intent.UPDATE_EXISTING)) { - throw _EndpointLogging.error(log, "PUT /objects/{}/{}", domainType, instanceId, + if (!updateHelper.copyOverProperties(argRepr, ObjectAdapterUpdateHelper.Intent.UPDATE_EXISTING)) + throw _EndpointLogging.error(log, "PUT /objects/{}/{}", domainType, instanceId, RestfulObjectsApplicationException .createWithBody( HttpStatus.BAD_REQUEST, argRepr, "Illegal property value")); - } final Consent validity = objectAdapter.objSpec().isValid(objectAdapter, InteractionInitiatedBy.USER); - if (validity.isVetoed()) { - throw _EndpointLogging.error(log, "PUT /objects/{}/{}", domainType, instanceId, + if (validity.isVetoed()) + throw _EndpointLogging.error(log, "PUT /objects/{}/{}", domainType, instanceId, RestfulObjectsApplicationException .createWithBody( HttpStatus.BAD_REQUEST, argRepr, validity.getReasonAsString().orElse(null))); - } var domainResourceHelper = _DomainResourceHelper.ofObjectResource(resourceContext, objectAdapter); @@ -353,7 +345,7 @@ public ResponseEntity modifyProperty( roEx->_EndpointLogging.error(log, "PUT /objects/{}/{}/properties/{}", domainType, instanceId, propertyId, roEx)); PropertyInteraction - .start(objectAdapter, propertyId, resourceContext.where()) + .start(objectAdapter, propertyId, resourceContext.visibilityConstraint()) .checkVisibility() .checkUsability(AccessIntent.MUTATE) .modifyProperty(property->{ @@ -384,7 +376,7 @@ public ResponseEntity clearProperty( var objectAdapter = getObjectAdapterElseThrowNotFound(domainType, instanceId, roEx->_EndpointLogging.error(log, "DELETE /objects/{}/{}/properties/{}", domainType, instanceId, propertyId, roEx)); - PropertyInteraction.start(objectAdapter, propertyId, resourceContext.where()) + PropertyInteraction.start(objectAdapter, propertyId, resourceContext.visibilityConstraint()) .checkVisibility() .checkUsability(AccessIntent.MUTATE) .modifyProperty(property->null) diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java index b46ecf98629..53ee6863864 100644 --- a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java +++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ObjectAdapterAccessHelper.java @@ -18,7 +18,9 @@ */ package org.apache.causeway.viewer.restfulobjects.viewer.resources; -import org.apache.causeway.applib.annotation.Where; +import org.jspecify.annotations.NonNull; + +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteraction; import org.apache.causeway.core.metamodel.interactions.managed.ActionInteraction.SemanticConstraint; import org.apache.causeway.core.metamodel.interactions.managed.CollectionInteraction; @@ -30,7 +32,6 @@ import org.apache.causeway.core.metamodel.object.ManagedObject; import org.apache.causeway.viewer.restfulobjects.rendering.IResourceContext; -import org.jspecify.annotations.NonNull; import lombok.RequiredArgsConstructor; /** @@ -45,11 +46,11 @@ public static ObjectAdapterAccessHelper of( final ManagedObject managedObject) { return new ObjectAdapterAccessHelper( managedObject, - resourceContext.where()); + resourceContext.visibilityConstraint()); } private final ManagedObject managedObject; - private final Where where; + private final VisibilityConstraint visibilityConstraint; public ManagedAction getObjectActionThatIsVisibleForIntentAndSemanticConstraint( final @NonNull String actionId, @@ -57,7 +58,7 @@ public ManagedAction getObjectActionThatIsVisibleForIntentAndSemanticConstraint( final @NonNull SemanticConstraint semanticConstraint) { return ActionInteraction - .start(managedObject, actionId, where) + .start(managedObject, actionId, visibilityConstraint) .checkVisibility() .checkUsability(AccessIntent.MUTATE) .checkSemanticConstraint(semanticConstraint) @@ -69,7 +70,7 @@ public ManagedProperty getPropertyThatIsVisibleForIntent( final @NonNull AccessIntent intent) { return PropertyInteraction - .start(managedObject, propertyId, where) + .start(managedObject, propertyId, visibilityConstraint) .checkVisibility() .checkUsability(intent) .getManagedPropertyElseThrow(InteractionFailureHandler::onFailure); @@ -81,7 +82,7 @@ public ManagedCollection getCollectionThatIsVisibleForIntent( final @NonNull AccessIntent intent) { return CollectionInteraction - .start(managedObject, collectionId, where) + .start(managedObject, collectionId, visibilityConstraint) .checkVisibility() .checkUsability(intent) .getManagedCollectionElseThrow(InteractionFailureHandler::onFailure); diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ObjectAdapterUpdateHelper.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ObjectAdapterUpdateHelper.java index 1810b222dd7..062601841eb 100644 --- a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ObjectAdapterUpdateHelper.java +++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/ObjectAdapterUpdateHelper.java @@ -88,12 +88,11 @@ private boolean copyOverProperty( final Consent visibility = property.isVisible( objectAdapter, resourceContext.interactionInitiatedBy(), - resourceContext.where()); + resourceContext.visibilityConstraint()); final Consent usability = property.isUsable( objectAdapter, resourceContext.interactionInitiatedBy(), - resourceContext.where() - ); + resourceContext.visibilityConstraint()); final boolean invisible = visibility.isVetoed(); final boolean disabled = usability.isVetoed(); @@ -103,15 +102,13 @@ private boolean copyOverProperty( // no value provided if(intent.shouldValidate()) { - if(invisible || disabled) { - // that's ok, indeed expected + if(invisible || disabled) + // that's ok, indeed expected return allOk; - } } - if (!property.isMandatory()) { - // optional, so also not a problem + if (!property.isMandatory()) + // optional, so also not a problem return allOk; - } // otherwise, is an error. final String invalidReason = propertiesMap.getString("x-ro-invalidReason"); @@ -127,11 +124,10 @@ private boolean copyOverProperty( if(intent.shouldValidate()) { // value has been provided - if (invisible) { - // silently ignore; don't want to acknowledge the + if (invisible) + // silently ignore; don't want to acknowledge the // existence of this property to the caller return allOk; - } if (disabled) { // not allowed to update propertyRepr.mapPutString("invalidReason", usability.getReasonAsString().orElse(null)); diff --git a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/_DomainResourceHelper.java b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/_DomainResourceHelper.java index a5b2a9bfe35..2b64c317a51 100644 --- a/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/_DomainResourceHelper.java +++ b/viewers/restfulobjects/viewer/src/main/java/org/apache/causeway/viewer/restfulobjects/viewer/resources/_DomainResourceHelper.java @@ -200,22 +200,19 @@ private ResponseEntity invokeAction( final @NonNull JsonRepresentation arguments, final ActionResultReprRenderer.@NonNull SelfLink selfLink) { - var where = resourceContext.where(); - // lombok issue, needs explicit cast here - var actionInteraction = ActionInteraction.start(objectAdapter, actionId, where) + var actionInteraction = ActionInteraction.start(objectAdapter, actionId, resourceContext.visibilityConstraint()) .checkVisibility() .checkUsability(intent) .checkSemanticConstraint(semanticConstraint); var pendingArgs = actionInteraction.startParameterNegotiation().orElse(null); - if(pendingArgs==null) { - // no such action or not visible or not usable + if(pendingArgs==null) + // no such action or not visible or not usable throw InteractionFailureHandler.onFailure(actionInteraction .getInteractionVeto() .orElseGet(()->InteractionVeto.notFound(Identifier.Type.ACTION, actionId))); // unexpected code reach - } var hasParams = pendingArgs.getParamCount()>0; @@ -238,10 +235,9 @@ private ResponseEntity invokeAction( }); - if(vetoCount.intValue()>0) { - throw InteractionFailureHandler.onParameterListInvalid( + if(vetoCount.intValue()>0) + throw InteractionFailureHandler.onParameterListInvalid( InteractionVeto.actionParamInvalid("error parsing arguments"), arguments); - } var argAdapters = paramsOrVetos.map(Railway::getSuccessElseFail); pendingArgs.setParamValues(argAdapters); @@ -258,25 +254,22 @@ private ResponseEntity invokeAction( } }); - if(vetoCount.intValue()>0) { - throw InteractionFailureHandler.onParameterListInvalid( + if(vetoCount.intValue()>0) + throw InteractionFailureHandler.onParameterListInvalid( InteractionVeto.actionParamInvalid( String.format("%d argument(s) failed validation", vetoCount.intValue())), arguments); - } } var actionConsent = pendingArgs.validateParameterSetForAction(); - if(actionConsent.isVetoed()) { - throw InteractionFailureHandler.onParameterListInvalid( + if(actionConsent.isVetoed()) + throw InteractionFailureHandler.onParameterListInvalid( InteractionVeto.invalid(actionConsent), arguments); - } - if(resourceContext.isValidateOnly()) { - return ResponseEntity.noContent().build(); // do not progress any further - } + if(resourceContext.isValidateOnly()) + return ResponseEntity.noContent().build(); // do not progress any further var resultOrVeto = actionInteraction.invokeWith(pendingArgs); diff --git a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ActionModel.java b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ActionModel.java index ac8f51d2fa2..31be6707405 100644 --- a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ActionModel.java +++ b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/ActionModel.java @@ -40,6 +40,7 @@ import org.apache.causeway.viewer.commons.model.action.UiActionForm; import org.apache.causeway.viewer.wicket.model.models.coll.CollectionModel; import org.apache.causeway.viewer.wicket.model.models.coll.CollectionModelParented; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; import org.apache.causeway.viewer.wicket.model.models.interaction.act.ActionInteractionWkt; import org.apache.causeway.viewer.wicket.model.models.interaction.act.UiParameterWkt; import org.apache.causeway.viewer.wicket.model.util.PageParameterUtils; @@ -153,8 +154,8 @@ public static ActionModel forCollection( public static ActionModel forPropertyOrParameter( final ObjectAction action, final UiAttributeWkt attributeModel) { - return attributeModel instanceof PropertyModel - ? forProperty(action, (PropertyModel)attributeModel) + return attributeModel instanceof PropertyModel p + ? forProperty(action, p) : forParameter(action, (ParameterModel)attributeModel); } @@ -175,14 +176,13 @@ public static ActionModel forParameter( //XXX[CAUSEWAY-3080] only supported, when parameter type is a singular composite value-type var param = parameterModel.getMetaModel(); if(param.isSingular() - && param.getElementType().isCompositeValue()) { - return ActionModel.forEntity( + && param.getElementType().isCompositeValue()) + return ActionModel.forEntity( parameterModel.getParentUiModel(), action.getFeatureIdentifier(), Where.OBJECT_FORMS, ColumnActionModifier.NONE, null, parameterModel, null); - } return null; } @@ -262,11 +262,11 @@ public Optional getAssociatedParameter() { } public boolean isVisible() { - return getVisibilityConsent().isAllowed(); + return getVisibilityConsent(WktVisibility.WHAT_VIEWER).isAllowed(); } public boolean isEnabled() { - return getUsabilityConsent().isAllowed(); + return getUsabilityConsent(WktVisibility.WHAT_VIEWER).isAllowed(); } @Override @@ -309,11 +309,10 @@ public String toString() { private static void guardAgainstNotBookmarkable(final ManagedObject objectAdapter) { var isIdentifiable = ManagedObjects.isIdentifiable(objectAdapter); - if (!isIdentifiable) { - throw new IllegalArgumentException(String.format( + if (!isIdentifiable) + throw new IllegalArgumentException(String.format( "Object '%s' is not identifiable (has no identifier).", objectAdapter.getTitle())); - } } } diff --git a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/coll/CollectionModelParented.java b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/coll/CollectionModelParented.java index 7dfc746e896..5e19a7c07b1 100644 --- a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/coll/CollectionModelParented.java +++ b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/coll/CollectionModelParented.java @@ -19,6 +19,7 @@ package org.apache.causeway.viewer.wicket.model.models.coll; import org.apache.wicket.Component; +import org.jspecify.annotations.NonNull; import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.applib.layout.component.CollectionLayoutData; @@ -29,9 +30,9 @@ import org.apache.causeway.viewer.wicket.model.hints.UiHintContainer; import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt; import org.apache.causeway.viewer.wicket.model.models.interaction.BookmarkedObjectWkt; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; import lombok.Getter; -import org.jspecify.annotations.NonNull; public final class CollectionModelParented extends CollectionModelAbstract @@ -55,7 +56,7 @@ public static CollectionModelParented forParentObjectModel( .getCollectionElseFail(layoutData.getId()); // collection's member-id var bookmarkedObject = objectModel.bookmarkedObjectModel(); var tableInteractive = DataTableInteractive.forCollection( - ManagedCollection.of(bookmarkedObject.getObject(), coll, Where.NOT_SPECIFIED)); + ManagedCollection.of(bookmarkedObject.getObject(), coll, WktVisibility.visibilityConstraint(Where.NOT_SPECIFIED))); return new CollectionModelParented( bookmarkedObject, diff --git a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/coll/CollectionModelStandalone.java b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/coll/CollectionModelStandalone.java index e675c92d707..8edd013862c 100644 --- a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/coll/CollectionModelStandalone.java +++ b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/coll/CollectionModelStandalone.java @@ -18,14 +18,15 @@ */ package org.apache.causeway.viewer.wicket.model.models.coll; +import org.jspecify.annotations.NonNull; + import org.apache.causeway.applib.annotation.Where; import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction; import org.apache.causeway.core.metamodel.object.PackedManagedObject; import org.apache.causeway.core.metamodel.tabular.DataTableInteractive; import org.apache.causeway.viewer.wicket.model.models.ActionModel; import org.apache.causeway.viewer.wicket.model.models.interaction.BookmarkedObjectWkt; - -import org.jspecify.annotations.NonNull; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; public final class CollectionModelStandalone extends CollectionModelAbstract { @@ -40,7 +41,7 @@ public static CollectionModelStandalone forActionModel( var bookmarkedObject = BookmarkedObjectWkt.ofAdapter(actionModel.getParentObject()); var tableInteractive = DataTableInteractive.forAction( - ManagedAction.of(bookmarkedObject.getObject(), actionModel.getAction(), Where.NOT_SPECIFIED), + ManagedAction.of(bookmarkedObject.getObject(), actionModel.getAction(), WktVisibility.visibilityConstraint(Where.NOT_SPECIFIED)), collectionAsAdapter); return new CollectionModelStandalone(bookmarkedObject, tableInteractive); diff --git a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/WktVisibility.java b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/WktVisibility.java new file mode 100644 index 00000000000..579bd1e1efd --- /dev/null +++ b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/WktVisibility.java @@ -0,0 +1,37 @@ +/* + * 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.model.models.interaction; + +import org.apache.causeway.applib.annotation.Where; +import org.apache.causeway.core.metamodel.interactions.VisibilityConstraint; +import org.apache.causeway.core.metamodel.interactions.WhatViewer; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class WktVisibility { + + // -- VISIBILITY CONSTRAINTS + + public static WhatViewer WHAT_VIEWER = new WhatViewer("Wicket"); + public static VisibilityConstraint visibilityConstraint(final Where where) { + return new VisibilityConstraint(WHAT_VIEWER, where); + } + +} diff --git a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/act/ActionInteractionWkt.java b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/act/ActionInteractionWkt.java index 2cf1497ae99..a3abdda3707 100644 --- a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/act/ActionInteractionWkt.java +++ b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/act/ActionInteractionWkt.java @@ -23,7 +23,6 @@ import java.util.stream.Stream; import org.apache.wicket.model.ChainingModel; - import org.jspecify.annotations.Nullable; import org.apache.causeway.applib.Identifier; @@ -45,6 +44,7 @@ import org.apache.causeway.viewer.wicket.model.models.coll.CollectionModel; import org.apache.causeway.viewer.wicket.model.models.interaction.BookmarkedObjectWkt; import org.apache.causeway.viewer.wicket.model.models.interaction.HasBookmarkedOwnerAbstract; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; /** * The parent (container) model of multiple parameter models which implement @@ -146,25 +146,25 @@ private void setObjectAction(final ObjectAction objectAction) { @Override protected ActionInteraction load() { + var visibilityConstraint = WktVisibility.visibilityConstraint(where); + if(associatedWithParameterIfAny!=null) { final int paramIndex = associatedWithParameterIfAny.getParameterIndex(); // supports composite-value-types via mixin return ActionInteraction.startAsBoundToParameter( - associatedWithParameterIfAny.getParameterNegotiationModel(), paramIndex, memberId, where); + associatedWithParameterIfAny.getParameterNegotiationModel(), paramIndex, memberId, visibilityConstraint); } - if(associatedWithCollectionIfAny!=null) { - return ActionInteraction.startWithMultiselect(getBookmarkedOwner(), memberId, where, + if(associatedWithCollectionIfAny!=null) + return ActionInteraction.startWithMultiselect(getBookmarkedOwner(), memberId, visibilityConstraint, associatedWithCollectionIfAny.getDataTableModel()); - } - if(associatedWithPropertyIfAny!=null) { - // supports composite-value-types via mixin + if(associatedWithPropertyIfAny!=null) + // supports composite-value-types via mixin return ActionInteraction.startAsBoundToProperty( - associatedWithPropertyIfAny.getManagedProperty(), memberId, where); - } + associatedWithPropertyIfAny.getManagedProperty(), memberId, visibilityConstraint); - return ActionInteraction.start(getBookmarkedOwner(), memberId, where); + return ActionInteraction.start(getBookmarkedOwner(), memberId, visibilityConstraint); } public final ActionInteraction actionInteraction() { diff --git a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/prop/PropertyInteractionWkt.java b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/prop/PropertyInteractionWkt.java index 025ce157291..c315507a07e 100644 --- a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/prop/PropertyInteractionWkt.java +++ b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/interaction/prop/PropertyInteractionWkt.java @@ -34,6 +34,7 @@ import org.apache.causeway.core.metamodel.object.ManagedObjects; import org.apache.causeway.viewer.wicket.model.models.interaction.BookmarkedObjectWkt; import org.apache.causeway.viewer.wicket.model.models.interaction.HasBookmarkedOwnerAbstract; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; /** * The parent (container) model of multiple property models which implement @@ -119,7 +120,7 @@ private Optional startPropertyNegotiation() { private PropertyInteraction loadPropertyInteraction() { return PropertyInteraction.wrap( - ManagedProperty.lookupProperty(getBookmarkedOwner(), memberId, where) + ManagedProperty.lookupProperty(getBookmarkedOwner(), memberId, WktVisibility.visibilityConstraint(where)) .orElseThrow(()->_Exceptions.noSuchElement("property '%s' in %s", memberId, getBookmarkedOwner().objSpec()))); diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionlinks/serviceactions/ServiceActionUtil.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionlinks/serviceactions/ServiceActionUtil.java index d772acee3f5..eab49adbb81 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionlinks/serviceactions/ServiceActionUtil.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionlinks/serviceactions/ServiceActionUtil.java @@ -34,6 +34,7 @@ import org.apache.causeway.viewer.commons.model.decorators.ActionDecorators.ActionStyle; import org.apache.causeway.viewer.wicket.model.models.ActionModel; import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; import org.apache.causeway.viewer.wicket.ui.components.widgets.actionlink.ActionLink; import org.apache.causeway.viewer.wicket.ui.util.Wkt; import org.apache.causeway.viewer.wicket.ui.util.WktDecorators; @@ -107,8 +108,8 @@ public void onSectionSpacer() { } @Override - public void onMenuAction(MenuAction menuAction) { - var menuItem = CssMenuItem.newMenuItemWithLink(menuAction.name(), newActionLink(menuAction.managedAction().orElseThrow())); + public void onMenuAction(final MenuAction menuAction) { + var menuItem = CssMenuItem.newMenuItemWithLink(menuAction.name(), newActionLink(menuAction.managedAction(WktVisibility.WHAT_VIEWER).orElseThrow())); currentTopLevelMenu.addSubMenuItem(menuItem); } diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/temporal/DateTimeConfig.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/temporal/DateTimeConfig.java index afc7d3ede74..0ae95a9708d 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/temporal/DateTimeConfig.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/attributes/temporal/DateTimeConfig.java @@ -18,7 +18,6 @@ */ package org.apache.causeway.viewer.wicket.ui.components.attributes.temporal; -import java.io.IOException; import java.util.Locale; import java.util.Map; diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/parented/ParentedCollectionPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/parented/ParentedCollectionPanel.java index 840e9ef5a81..4c457c70414 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/parented/ParentedCollectionPanel.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/parented/ParentedCollectionPanel.java @@ -35,6 +35,7 @@ import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt; import org.apache.causeway.viewer.wicket.model.models.coll.CollectionModel; import org.apache.causeway.viewer.wicket.model.models.coll.CollectionModelParented; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; import org.apache.causeway.viewer.wicket.model.util.ComponentHintKey; import org.apache.causeway.viewer.wicket.ui.components.actionlinks.entityactions.ActionLinksPanel; import org.apache.causeway.viewer.wicket.ui.components.collection.CollectionPanel; @@ -127,7 +128,7 @@ private void buildGui() { var objectAdapter = getModel().getObject(); final Consent visibility = collectionMetaModel - .isVisible(objectAdapter, InteractionInitiatedBy.USER, Where.OBJECT_FORMS); + .isVisible(objectAdapter, InteractionInitiatedBy.USER, WktVisibility.visibilityConstraint(Where.OBJECT_FORMS)); if(visibility.isAllowed()) { diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/present/ajaxtable/columns/PluralColumn.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/present/ajaxtable/columns/PluralColumn.java index 693998ffc5e..adc963f96d0 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/present/ajaxtable/columns/PluralColumn.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/collection/present/ajaxtable/columns/PluralColumn.java @@ -57,13 +57,13 @@ public PluralColumn( final ObjectSpecification elementType, final CollectionModel.Variant collectionVariant, final IModel columnNameModel, - final String propertyId, + final String collectioId, final String parentTypeName, final Optional describedAs, final RenderOptions opts) { super(elementType, collectionVariant, columnNameModel, Optional.empty(), // empty sortProperty (hence never sortable) - propertyId, parentTypeName, describedAs); + collectioId, parentTypeName, describedAs); this.opts = opts; } @@ -74,12 +74,11 @@ protected Component createCellComponent(final String componentId, final DataRowW var cellElements = dataRow.getCellElementsForColumn(dataColumn); // if empty, render the 'empty' badge or blank based on RenderOptions - if(cellElements.isEmpty()) { - return Wkt.markup(componentId, + if(cellElements.isEmpty()) + return Wkt.markup(componentId, opts.isRenderEmptyBadge() ? getPlaceholderRenderService().asHtml(PlaceholderLiteral.NULL_REPRESENTATION) : ""); - } var container = new RepeatingView(componentId); cellElements.stream() diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/header/ObjectHeaderPanel.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/header/ObjectHeaderPanel.java index 88b94dfc32d..eb7d42c2670 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/header/ObjectHeaderPanel.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/object/header/ObjectHeaderPanel.java @@ -26,6 +26,7 @@ import org.apache.causeway.viewer.commons.model.components.UiComponentType; import org.apache.causeway.viewer.wicket.model.models.ActionModel; import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; import org.apache.causeway.viewer.wicket.ui.ComponentFactory; import org.apache.causeway.viewer.wicket.ui.components.actionlinks.entityactions.ActionLinksPanel; import org.apache.causeway.viewer.wicket.ui.panels.PanelAbstract; @@ -72,7 +73,7 @@ private void buildEntityActionsGui() { final UiObjectWkt model = getModel(); var adapter = model.getObject(); if (adapter != null) { - var topLevelActions = ObjectAction.Util.streamTopBarActions(adapter) + var topLevelActions = ObjectAction.Util.streamTopBarActions(adapter, WktVisibility.WHAT_VIEWER) .map(act->ActionModel.forEntity(act, model)) .collect(Can.toCan()); diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/actionlink/ActionLink.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/actionlink/ActionLink.java index 1d09eba3ade..e499cda6b3f 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/actionlink/ActionLink.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/actionlink/ActionLink.java @@ -41,6 +41,7 @@ import org.apache.causeway.viewer.wicket.model.models.ActionModel; import org.apache.causeway.viewer.wicket.model.models.ActionPromptProvider; import org.apache.causeway.viewer.wicket.model.models.ActionPromptWithExtraContent; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; import org.apache.causeway.viewer.wicket.model.util.PageParameterUtils; import org.apache.causeway.viewer.wicket.ui.app.registry.ComponentFactoryRegistry; import org.apache.causeway.viewer.wicket.ui.app.registry.HasComponentFactoryRegistry; @@ -134,18 +135,18 @@ protected void updateAjaxAttributes(final AjaxRequestAttributes attributes) { public String getReasonDisabledIfAny() { // no point evaluating if not visible return isVisible() - ? getActionModel().getUsabilityConsent().getReasonAsString().orElse(null) + ? getActionModel().getUsabilityConsent(WktVisibility.WHAT_VIEWER).getReasonAsString().orElse(null) : null; } @Override public boolean isVisible() { - return getActionModel().getVisibilityConsent().isAllowed(); + return getActionModel().getVisibilityConsent(WktVisibility.WHAT_VIEWER).isAllowed(); } @Override public boolean isEnabled() { - return getActionModel().getUsabilityConsent().isAllowed(); + return getActionModel().getUsabilityConsent(WktVisibility.WHAT_VIEWER).isAllowed(); } @SuppressWarnings("deprecation") diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/obj/DomainObjectPage.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/obj/DomainObjectPage.java index c64c154addf..20193db03cd 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/obj/DomainObjectPage.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/pages/obj/DomainObjectPage.java @@ -45,6 +45,7 @@ import org.apache.causeway.viewer.commons.model.components.UiComponentType; import org.apache.causeway.viewer.wicket.model.hints.UiHintContainer; import org.apache.causeway.viewer.wicket.model.models.UiObjectWkt; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; import org.apache.causeway.viewer.wicket.model.util.PageParameterUtils; import org.apache.causeway.viewer.wicket.model.util.PageUtils; import org.apache.causeway.viewer.wicket.model.whereAmI.WhereAmI; @@ -85,9 +86,8 @@ public class DomainObjectPage extends PageAbstract { */ public static DomainObjectPage forPageParameters(final PageParameters pageParameters) { var bookmark = PageParameterUtils.toBookmark(pageParameters); - if(!bookmark.isPresent()) { - throw new RestartResponseException(Application.get().getHomePage()); - } + if(!bookmark.isPresent()) + throw new RestartResponseException(Application.get().getHomePage()); return new DomainObjectPage( pageParameters, UiObjectWkt.ofPageParameters(pageParameters)); @@ -143,9 +143,8 @@ private void buildPage() { } // check that the entity overall can be viewed. - if(!model.isVisible()) { - throw new ObjectMember.AuthorizationException(); - } + if(!model.isVisible(WktVisibility.WHAT_VIEWER)) + throw new ObjectMember.AuthorizationException(); var objectSpec = model.getTypeOfSpecification(); @@ -209,7 +208,7 @@ protected void onDetach() { super.onDetach(); model.detach(); } - + // -- REFRESH ENTITIES @Override @@ -217,7 +216,7 @@ public void onNewRequestCycle() { var mo = model.getObject(); if(!PageUtils.isAjax()) { //CAUSEWAY-3944: on normal page request, make sure entities are in sync with the db before rendering - ManagedObjects.refreshEntity(mo); + ManagedObjects.refreshEntity(mo); } ManagedObjects.refreshViewmodel(mo, ()->PageParameterUtils @@ -245,9 +244,8 @@ private void onRenderingOrRendered( final Can pageRenderSubscribers, final BiFunction handler) { - if(pageRenderSubscribers.isEmpty()) { - return; - } + if(pageRenderSubscribers.isEmpty()) + return; // guard against unspecified ManagedObjects.asSpecified(model.getObject()) diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/panels/PanelBase.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/panels/PanelBase.java index bc31613afa5..9c6736cb147 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/panels/PanelBase.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/panels/PanelBase.java @@ -31,6 +31,7 @@ import org.apache.causeway.viewer.commons.applib.services.header.HeaderUiService; import org.apache.causeway.viewer.wicket.model.hints.UiHintContainer; import org.apache.causeway.viewer.wicket.model.models.IconResourceReferenceFactory; +import org.apache.causeway.viewer.wicket.model.models.interaction.WktVisibility; import org.apache.causeway.viewer.wicket.ui.app.registry.ComponentFactoryRegistry; import org.apache.causeway.viewer.wicket.ui.app.registry.HasComponentFactoryRegistry; import org.apache.causeway.viewer.wicket.ui.components.tree.themes.TreeThemeProvider; @@ -95,7 +96,7 @@ protected PageNavigationService getPageNavigationService() { private transient HeaderUiService headerUiService; protected HeaderUiModel getHeaderModel() { headerUiService = computeIfAbsent(HeaderUiService.class, headerUiService); - return headerUiService.getHeader(); + return headerUiService.getHeader(WktVisibility.WHAT_VIEWER); } // Hint support