From 9054f3068fc006e6807c0343f49c19321d04ada5 Mon Sep 17 00:00:00 2001 From: Niels Thykier Date: Thu, 3 Oct 2024 13:08:19 +0200 Subject: [PATCH] DT-271: Add scenario for receiver validation --- .../eblinterop/PintScenarioListBuilder.java | 40 ++++++++-- .../eblinterop/action/PintAction.java | 4 +- .../action/PintReceiverValidationAction.java | 77 +++++++++++++++++++ ...ationEndpointScenarioParametersAction.java | 55 +++++++++++++ .../models/DynamicScenarioParameters.java | 7 +- .../party/PintReceivingPlatform.java | 23 +++++- .../eblinterop/party/PintSendingPlatform.java | 11 ++- 7 files changed, 206 insertions(+), 11 deletions(-) create mode 100644 pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintReceiverValidationAction.java create mode 100644 pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/SupplyValidationEndpointScenarioParametersAction.java diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/PintScenarioListBuilder.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/PintScenarioListBuilder.java index 268ec230..fd267dd6 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/PintScenarioListBuilder.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/PintScenarioListBuilder.java @@ -26,6 +26,7 @@ class PintScenarioListBuilder extends ScenarioListBuilder createModuleScenarioListBuilders( String standardVersion, String sendingPlatformPartyName, String receivingPlatformPartyName) { @@ -34,9 +35,9 @@ public static LinkedHashMap createModuleScenari RECEIVING_PLATFORM_PARTY_NAME.set(receivingPlatformPartyName); return Stream.of( Map.entry( - "", + "Transfer scenarios", noAction().thenEither( - supplyScenarioParameters(0).thenEither( + supplySenderTransferScenarioParameters(0).thenEither( receiverStateSetup(ScenarioClass.NO_ISSUES) .thenEither( initiateAndCloseTransferAction(PintResponseCode.RECE).thenEither( @@ -74,7 +75,7 @@ public static LinkedHashMap createModuleScenari initiateAndCloseTransferAction(PintResponseCode.RECE))) )) ), - supplyScenarioParameters(2).thenEither( + supplySenderTransferScenarioParameters(2).thenEither( receiverStateSetup(ScenarioClass.NO_ISSUES) .then( initiateTransfer(2).thenEither( @@ -115,7 +116,11 @@ public static LinkedHashMap createModuleScenari ) ) ))) - ))) + )), + Map.entry("Receiver validation scenarios", + supplyReceiverValidationScenarioParameters() + .then(receiverValidation()) + )) .collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); @@ -127,8 +132,33 @@ private PintScenarioListBuilder( super(actionBuilder); } + private static PintScenarioListBuilder supplyReceiverValidationScenarioParameters() { + String sendingPlatform = SENDING_PLATFORM_PARTY_NAME.get(); + String receivingPlatform = RECEIVING_PLATFORM_PARTY_NAME.get(); + return new PintScenarioListBuilder( + previousAction -> + new SupplyValidationEndpointScenarioParametersAction( + sendingPlatform, + receivingPlatform, + (PintAction) previousAction + )); + } + + private static PintScenarioListBuilder receiverValidation() { + String sendingPlatform = SENDING_PLATFORM_PARTY_NAME.get(); + String receivingPlatform = RECEIVING_PLATFORM_PARTY_NAME.get(); + return new PintScenarioListBuilder( + previousAction -> + new PintReceiverValidationAction( + sendingPlatform, + receivingPlatform, + (PintAction) previousAction, + 200, + resolveMessageSchemaValidator(RECEIVER_VALIDATION_RESPONSE) + )); + } - private static PintScenarioListBuilder supplyScenarioParameters(int documentCount) { + private static PintScenarioListBuilder supplySenderTransferScenarioParameters(int documentCount) { String sendingPlatform = SENDING_PLATFORM_PARTY_NAME.get(); String receivingPlatform = RECEIVING_PLATFORM_PARTY_NAME.get(); return new PintScenarioListBuilder( diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintAction.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintAction.java index 26ab9716..1be4d575 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintAction.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintAction.java @@ -12,6 +12,8 @@ import java.util.Set; +import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER; + public abstract class PintAction extends ConformanceAction { protected final int expectedStatus; private final OverwritingReference dspReference; @@ -28,7 +30,7 @@ public PintAction( this.expectedStatus = expectedStatus; if (previousAction == null) { this.dspReference = - new OverwritingReference<>(null, new DynamicScenarioParameters(null, -1, Set.of(), null)); + new OverwritingReference<>(null, new DynamicScenarioParameters(null, -1, Set.of(), null, OBJECT_MAPPER.createObjectNode())); this.rspReference = new OverwritingReference<>(null, new ReceiverScenarioParameters("", "", "", "", "")); this.sspReference = new OverwritingReference<>(null, new SenderScenarioParameters(null, "", "", "")); } else { diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintReceiverValidationAction.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintReceiverValidationAction.java new file mode 100644 index 00000000..5863c036 --- /dev/null +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintReceiverValidationAction.java @@ -0,0 +1,77 @@ +package org.dcsa.conformance.standards.eblinterop.action; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.util.stream.Stream; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.dcsa.conformance.core.check.*; +import org.dcsa.conformance.core.traffic.HttpMessageType; +import org.dcsa.conformance.standards.eblinterop.party.PintRole; + +@Getter +@Slf4j +public class PintReceiverValidationAction extends PintAction { + private final JsonSchemaValidator responseSchemaValidator; + + public PintReceiverValidationAction( + String sourcePartyName, + String targetPartyName, + PintAction previousAction, + int responseCode, + JsonSchemaValidator responseSchemaValidator + ) { + super( + sourcePartyName, + targetPartyName, + previousAction, + "ReceiverValidation(%d)".formatted(responseCode), + responseCode + ); + this.responseSchemaValidator = responseSchemaValidator; + } + + @Override + public String getHumanReadablePrompt() { + return ("Request receiver validation for: " + getDsp().receiverValidation().toString()); + } + + @Override + public ObjectNode asJsonNode() { + var node = super.asJsonNode(); + node.set("dsp", getDsp().toJson()); + return node; + } + + @Override + public ConformanceCheck createCheck(String expectedApiVersion) { + return new ConformanceCheck(getActionTitle()) { + @Override + protected Stream createSubChecks() { + + return Stream.of( + new HttpMethodCheck(PintRole::isSendingPlatform, getMatchedExchangeUuid(), "POST"), + new UrlPathCheck( + PintRole::isSendingPlatform, getMatchedExchangeUuid(), "/receiver-validation"), + new ResponseStatusCheck( + PintRole::isReceivingPlatform, getMatchedExchangeUuid(), expectedStatus), + new ApiHeaderCheck( + PintRole::isSendingPlatform, + getMatchedExchangeUuid(), + HttpMessageType.REQUEST, + expectedApiVersion), + new ApiHeaderCheck( + PintRole::isReceivingPlatform, + getMatchedExchangeUuid(), + HttpMessageType.RESPONSE, + expectedApiVersion), + new JsonSchemaCheck( + PintRole::isReceivingPlatform, + getMatchedExchangeUuid(), + HttpMessageType.RESPONSE, + responseSchemaValidator + ) + ); + } + }; + } +} diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/SupplyValidationEndpointScenarioParametersAction.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/SupplyValidationEndpointScenarioParametersAction.java new file mode 100644 index 00000000..9e57a7eb --- /dev/null +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/SupplyValidationEndpointScenarioParametersAction.java @@ -0,0 +1,55 @@ +package org.dcsa.conformance.standards.eblinterop.action; + +import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +@Getter +@Slf4j +public class SupplyValidationEndpointScenarioParametersAction extends PintAction { + + public SupplyValidationEndpointScenarioParametersAction( + String platformPartyName, + String carrierPartyName, + PintAction previousAction) { + super( + carrierPartyName, + platformPartyName, + previousAction, + "SupplyValidationEndpointScenarioParameters", + -1); + } + + @Override + public boolean isInputRequired() { + return true; + } + + @Override + public void handlePartyInput(JsonNode partyInput) { + super.handlePartyInput(partyInput); + setDsp(getDsp().withReceiverValidation(partyInput)); + } + + public static ObjectNode getJsonForPrompt() { + var partyDef = OBJECT_MAPPER.createObjectNode(); + partyDef.put("codeListProvider", "ZZZ") + .put("partyCode", "valid-party") + .put("codeListName", "CTK"); + return partyDef; + } + + @Override + public JsonNode getJsonForHumanReadablePrompt() { + return getJsonForPrompt(); + } + + @Override + public String getHumanReadablePrompt() { + return ("Provide parameters for the receiver validation endpoint"); + } + +} diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/DynamicScenarioParameters.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/DynamicScenarioParameters.java index e44da044..b4af2e98 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/DynamicScenarioParameters.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/DynamicScenarioParameters.java @@ -15,7 +15,8 @@ public record DynamicScenarioParameters( String transportDocumentChecksum, int documentCount, Set documentChecksums, - String envelopeReference + String envelopeReference, + JsonNode receiverValidation ) { public ObjectNode toJson() { var node = OBJECT_MAPPER.createObjectNode() @@ -26,6 +27,7 @@ public ObjectNode toJson() { for (var checksum : documentChecksums) { jsonDocumentChecksums.add(checksum); } + node.set("receiverValidation", receiverValidation); return node; } @@ -36,7 +38,8 @@ public static DynamicScenarioParameters fromJson(JsonNode jsonNode) { StreamSupport.stream(jsonNode.required("documentChecksums").spliterator(), false) .map(JsonNode::asText) .collect(Collectors.toUnmodifiableSet()), - jsonNode.required("envelopeReference").asText() + jsonNode.required("envelopeReference").asText(), + jsonNode.path("receiverValidation") ); } } diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/party/PintReceivingPlatform.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/party/PintReceivingPlatform.java index 5c3d755f..08a0cb89 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/party/PintReceivingPlatform.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/party/PintReceivingPlatform.java @@ -59,7 +59,8 @@ protected void doReset() { protected Map, Consumer> getActionPromptHandlers() { return Map.ofEntries( Map.entry(ReceiverSupplyScenarioParametersAndStateSetupAction.class, this::initiateState), - Map.entry(ResetScenarioClassAction.class, this::resetScenarioClass) + Map.entry(ResetScenarioClassAction.class, this::resetScenarioClass), + Map.entry(SupplyValidationEndpointScenarioParametersAction.class, this::providedReceiverValidationScenarioParameters) ); } @@ -81,6 +82,14 @@ private void resetScenarioClass(JsonNode actionPrompt) { "Finished resetScenarioClass"); } + private void providedReceiverValidationScenarioParameters(JsonNode actionPrompt) { + log.info("EblInteropReceivingPlatform.providedReceiverValidationScenarioParameters(%s)".formatted(actionPrompt.toPrettyString())); + asyncOrchestratorPostPartyInput( + actionPrompt.required("actionId").asText(), SupplyValidationEndpointScenarioParametersAction.getJsonForPrompt()); + addOperatorLogEntry( + "Finished providedReceiverValidationScenarioParameters"); + } + private void initiateState(JsonNode actionPrompt) { log.info("EblInteropSendingPlatform.handleScenarioTypeAction(%s)".formatted(actionPrompt.toPrettyString())); var ssp = SenderScenarioParameters.fromJson(actionPrompt.get("ssp")); @@ -262,13 +271,23 @@ public ConformanceResponse handleEnvelopeRequest(ConformanceRequest request) { "Unknown endpoint"))); } + private ConformanceResponse handleReceiverValidation(ConformanceRequest request) { + return request.createResponse( + 200, + Map.of(API_VERSION, List.of(apiVersion)), + new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put("partyName", "Name of Test Party")) + ); + } + @Override public ConformanceResponse handleRequest(ConformanceRequest request) { log.info("EblInteropPlatform.handleRequest(%s)".formatted(request)); var url = request.url().replaceFirst("/++$", ""); ConformanceResponse response; - if (url.endsWith("/envelopes")) { + if (url.endsWith("/receiver-validation")) { + response = handleReceiverValidation(request); + } else if (url.endsWith("/envelopes")) { response = handleInitiateTransferRequest(request); } else if(url.contains("/envelopes/")) { response = handleEnvelopeRequest(request); diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/party/PintSendingPlatform.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/party/PintSendingPlatform.java index 8f3e6152..d25b6a85 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/party/PintSendingPlatform.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/party/PintSendingPlatform.java @@ -86,7 +86,8 @@ protected Map, Consumer> getActionP Map.entry(PintTransferAdditionalDocumentFailureAction.class, this::transferActionDocument), Map.entry(PintRetryTransferAction.class, this::retryTransfer), Map.entry(PintRetryTransferAndCloseAction.class, this::retryTransfer), - Map.entry(PintCloseTransferAction.class, this::finishTransfer) + Map.entry(PintCloseTransferAction.class, this::finishTransfer), + Map.entry(PintReceiverValidationAction.class, this::requestReceiverValidation) ); } @@ -133,6 +134,14 @@ private String generateTDR() { return tdrChars.toString(); } + private void requestReceiverValidation(JsonNode actionPrompt) { + log.info("EblInteropSendingPlatform.requestReceiverValidation(%s)".formatted(actionPrompt.toPrettyString())); + var dsp = DynamicScenarioParameters.fromJson(actionPrompt.required("dsp")); + this.syncCounterpartPost("/v" + apiVersion.charAt(0) + "/receiver-validation", dsp.receiverValidation()); + addOperatorLogEntry( + "Requested receiver validation"); + } + private void supplyScenarioParameters(JsonNode actionPrompt) { log.info("EblInteropSendingPlatform.supplyScenarioParameters(%s)".formatted(actionPrompt.toPrettyString())); var tdr = generateTDR();