You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/11/24 15:41:42 UTC
[isis] branch master updated: ISIS-2877: proof of concept, that EncoderDecoder can be replaced with a ValueType Mixin
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new 048e02d ISIS-2877: proof of concept, that EncoderDecoder can be replaced with a ValueType Mixin
048e02d is described below
commit 048e02d8cc91310e55bd38a7524490d1226cf93b
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Nov 24 16:36:23 2021 +0100
ISIS-2877: proof of concept, that EncoderDecoder can be replaced with a
ValueType Mixin
- also introduces a pass-through mode for execution (action-interaction/
property-modification)
---
.../applib/services/iactn/ActionInvocation.java | 3 ++-
.../applib/value/semantics/EncoderDecoder.java | 4 +++
.../metamodel/consent/InteractionInitiatedBy.java | 28 ++++++++++++++++++-
...ctionInvocationFacetForDomainEventAbstract.java | 7 +++--
.../interactions/managed/ManagedAction.java | 11 ++++++--
.../specloader/specimpl/ObjectActionDefault.java | 4 ++-
.../valuesemantics/OidDtoValueSemantics.java | 31 ++++++++++++++++++++--
.../executor/MemberExecutorServiceDefault.java | 24 ++++++++++++++---
.../isis/testdomain/value/ValueSemanticsTest.java | 31 ++++++++++++++++++++++
9 files changed, 130 insertions(+), 13 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/iactn/ActionInvocation.java b/api/applib/src/main/java/org/apache/isis/applib/services/iactn/ActionInvocation.java
index 403eb40..47943e6 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/iactn/ActionInvocation.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/iactn/ActionInvocation.java
@@ -30,7 +30,8 @@ import lombok.Getter;
/**
* @since 1.x {@index}
*/
-public class ActionInvocation extends Execution<ActionInvocationDto, ActionDomainEvent<?>> {
+public class ActionInvocation
+extends Execution<ActionInvocationDto, ActionDomainEvent<?>> {
@Getter
private final List<Object> args;
diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/EncoderDecoder.java b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/EncoderDecoder.java
index 536647d..68a6814 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/EncoderDecoder.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/EncoderDecoder.java
@@ -66,4 +66,8 @@ public interface EncoderDecoder<T> {
*/
T fromEncodedString(String encodedString);
+ default Object getConstructorExtractor(final T value) {
+ return null;
+ }
+
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/consent/InteractionInitiatedBy.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/consent/InteractionInitiatedBy.java
index 4e9f411..f8e6ddf 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/consent/InteractionInitiatedBy.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/consent/InteractionInitiatedBy.java
@@ -26,7 +26,33 @@ import org.apache.isis.core.metamodel.interactions.InteractionContext;
*/
public enum InteractionInitiatedBy {
+ /**
+ * must be authorized, with transactions, with publishing, with domain events
+ */
USER,
- FRAMEWORK;
+
+ /**
+ * always authorized, with transactions, with publishing, with domain events
+ */
+ FRAMEWORK,
+
+ /**
+ * always authorized, no transactions, no publishing, no domain events
+ */
+ PASS_THROUGH;
+
+ /**
+ * @see #USER
+ */
+ public boolean isUser() {
+ return this==USER;
+ }
+
+ /**
+ * @see #PASS_THROUGH
+ */
+ public boolean isPassThrough() {
+ return this==PASS_THROUGH;
+ }
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
index 1c8f159..499b367 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
@@ -30,6 +30,7 @@ import org.apache.isis.applib.services.iactn.ActionInvocation;
import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
import org.apache.isis.applib.services.registry.ServiceRegistry;
import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.functional.Result;
import org.apache.isis.commons.internal.assertions._Assert;
import org.apache.isis.commons.internal.collections._Arrays;
import org.apache.isis.core.metamodel.commons.CanonicalParameterUtil;
@@ -91,8 +92,10 @@ implements ImperativeFacet {
final Can<ManagedObject> argumentAdapters,
final InteractionInitiatedBy interactionInitiatedBy) {
- val executionResult =
- getTransactionService().callWithinCurrentTransactionElseCreateNew(()->
+ val executionResult = interactionInitiatedBy.isPassThrough()
+ ? Result.of(()->
+ doInvoke(owningAction, head, argumentAdapters, interactionInitiatedBy))
+ : getTransactionService().callWithinCurrentTransactionElseCreateNew(()->
doInvoke(owningAction, head, argumentAdapters, interactionInitiatedBy));
//PersistableTypeGuard.instate(executionResult);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedAction.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedAction.java
index e57f4a7..b62018c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedAction.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ManagedAction.java
@@ -121,18 +121,25 @@ public final class ManagedAction extends ManagedMember {
// -- INTERACTION
- public _Either<ManagedObject, InteractionVeto> invoke(@NonNull final Can<ManagedObject> actionParameters) {
+ public _Either<ManagedObject, InteractionVeto> invoke(
+ final @NonNull Can<ManagedObject> actionParameters,
+ final @NonNull InteractionInitiatedBy interactionInitiatedBy) {
if(isValueTypeMixin()) {
return _Either.left(invokeValueTypeMixin(actionParameters));
}
final ManagedObject actionResult = getAction()
- .execute(interactionHead(), actionParameters, InteractionInitiatedBy.USER);
+ .execute(interactionHead(), actionParameters, interactionInitiatedBy);
return _Either.left(route(actionResult));
}
+ public _Either<ManagedObject, InteractionVeto> invoke(
+ final @NonNull Can<ManagedObject> actionParameters) {
+ return invoke(actionParameters, InteractionInitiatedBy.USER);
+ }
+
@SneakyThrows
public ManagedObject invokeWithRuleChecking(
final @NonNull Can<ManagedObject> actionParameters) throws AuthorizationException {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionDefault.java
index a51b2af..dfc1878 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionDefault.java
@@ -393,7 +393,9 @@ implements ObjectAction {
_Assert.assertEquals(this.getParameterCount(), argumentAdapters.size(),
"action's parameter count and provided argument count must match");
- setupCommand(head, argumentAdapters);
+ if(!interactionInitiatedBy.isPassThrough()) {
+ setupCommand(head, argumentAdapters);
+ }
return this.executeInternal(head, argumentAdapters, interactionInitiatedBy);
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/OidDtoValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/OidDtoValueSemantics.java
index a9c2f3b..a87c949 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/OidDtoValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/OidDtoValueSemantics.java
@@ -22,6 +22,8 @@ import javax.inject.Named;
import org.springframework.stereotype.Component;
+import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.MemberSupport;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.value.semantics.EncoderDecoder;
import org.apache.isis.applib.value.semantics.OrderRelation;
@@ -33,6 +35,7 @@ import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.schema.common.v2.OidDto;
import org.apache.isis.schema.common.v2.ValueType;
+import lombok.RequiredArgsConstructor;
import lombok.val;
@Component
@@ -80,6 +83,31 @@ implements
return compare(a, b, epsilon) == 0;
}
+ // -- CONSTRUCTOR EXTRACTOR
+
+ @Action
+ @RequiredArgsConstructor
+ public static class ConstructorExtractor {
+
+ final OidDto value;
+
+ @MemberSupport
+ public OidDto act(final String data) {
+ return Bookmark.parseElseFail(data).toOidDto();
+ }
+
+ @MemberSupport
+ public String defaultData() {
+ return Bookmark.forOidDto(value).stringify();
+ }
+
+ }
+
+ @Override
+ public ConstructorExtractor getConstructorExtractor(final OidDto object) {
+ return new ConstructorExtractor(object);
+ }
+
// -- ENCODER DECODER
@Override
@@ -89,8 +117,7 @@ implements
@Override
public OidDto fromEncodedString(final String data) {
- return Bookmark.parseElseFail(data)
- .toOidDto();
+ return Bookmark.parseElseFail(data).toOidDto();
}
// -- RENDERER
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java
index c3bc7e8..9969eba 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/executor/MemberExecutorServiceDefault.java
@@ -45,6 +45,7 @@ import org.apache.isis.commons.internal.assertions._Assert;
import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.core.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.commons.CanonicalParameterUtil;
import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.isis.core.metamodel.execution.InteractionInternal;
import org.apache.isis.core.metamodel.execution.MemberExecutorService;
@@ -68,6 +69,7 @@ import org.apache.isis.schema.ixn.v2.ActionInvocationDto;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
import lombok.val;
import lombok.extern.log4j.Log4j2;
@@ -109,6 +111,11 @@ implements MemberExecutorService {
_Assert.assertEquals(owningAction.getParameterCount(), argumentAdapters.size(),
"action's parameter count and provided argument count must match");
+ if(interactionInitiatedBy.isPassThrough()) {
+ val resultPojo = invokeMethodPassThrough(method, head, argumentAdapters);
+ return facetHolder.getObjectManager().adapt(resultPojo);
+ }
+
val interaction = getInteractionElseFail();
val command = interaction.getCommand();
@@ -133,12 +140,10 @@ implements MemberExecutorService {
new ActionInvocation(
interaction, actionId, targetPojo, argumentPojos, targetMemberName,
targetClass);
- final InteractionInternal.MemberExecutor<ActionInvocation> memberExecution =
- actionExecutorFactory.createExecutor(
- owningAction, head, argumentAdapters);
+ val memberExecutor = actionExecutorFactory.createExecutor(owningAction, head, argumentAdapters);
// sets up startedAt and completedAt on the execution, also manages the execution call graph
- interaction.execute(memberExecution, actionInvocation, clockService, metricsService.get(), command);
+ interaction.execute(memberExecutor, actionInvocation, clockService, metricsService.get(), command);
// handle any exceptions
final Execution<ActionInvocationDto, ?> priorExecution =
@@ -236,6 +241,17 @@ implements MemberExecutorService {
// -- HELPER
+ @SneakyThrows
+ private Object invokeMethodPassThrough(
+ final Method method,
+ final InteractionHead head,
+ final Can<ManagedObject> arguments) {
+
+ final Object[] executionParameters = UnwrapUtil.multipleAsArray(arguments);
+ final Object targetPojo = UnwrapUtil.single(head.getTarget());
+ return CanonicalParameterUtil.invoke(method, targetPojo, executionParameters);
+ }
+
private void setCommandResultIfEntity(
final Command command,
final ManagedObject resultAdapter) {
diff --git a/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java b/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
index 791e00e..eccf0cd 100644
--- a/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
+++ b/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
@@ -35,6 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.apache.isis.applib.annotation.Where;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.iactnlayer.InteractionContext;
import org.apache.isis.applib.services.iactnlayer.InteractionService;
@@ -43,6 +44,9 @@ import org.apache.isis.applib.util.schema.CommonDtoUtils;
import org.apache.isis.applib.value.Password;
import org.apache.isis.core.config.presets.IsisPresets;
import org.apache.isis.core.config.valuetypes.ValueSemanticsRegistry;
+import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.interactions.managed.ActionInteraction;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.schema.cmd.v2.PropertyDto;
import org.apache.isis.testdomain.conf.Configuration_headless;
@@ -84,6 +88,33 @@ class ValueSemanticsTest {
managedProp->example.getUpdateValue(),
(context, codec)->{
+ val constructorExtractor = codec.getConstructorExtractor(example.getValue());
+ if(constructorExtractor!=null) {
+
+ val spec = specLoader.specForTypeElseFail(constructorExtractor.getClass());
+ val interaction = ActionInteraction
+ .start(ManagedObject.of(spec, constructorExtractor), "act", Where.ANYWHERE);
+
+ val pendingParams = interaction
+ .startParameterNegotiation()
+ .get();
+
+ val managedAction = interaction.getManagedActionElseFail();
+ val typedTuple = pendingParams.getParamValues();
+
+ val recoveredValue = managedAction
+ .invoke(typedTuple, InteractionInitiatedBy.PASS_THROUGH)
+ .leftIfAny()
+ .getPojo();
+
+ tester.assertValueEquals(
+ example.getValue(),
+ recoveredValue,
+ "serialization roundtrip failed");
+
+ return;
+ }
+
// CoderDecoder round-trip test
val serialized = codec.toEncodedString(example.getValue());