From 2e59847e74efab4d8cb1c2af098b2717d859cf2f Mon Sep 17 00:00:00 2001 From: Niels Thykier <niels.thykier@dcsa.org> Date: Wed, 9 Oct 2024 10:34:04 +0200 Subject: [PATCH] DT-1832: Remove use of EPUI --- .../eblissuance/checks/IssuanceChecks.java | 8 +++ ebl-surrender/pom.xml | 5 +- .../eblsurrender/SurrenderChecks.java | 20 ++++-- .../SupplyScenarioParametersAction.java | 24 +++++-- .../party/EblSurrenderCarrier.java | 13 +++- .../party/EblSurrenderPlatform.java | 7 +- .../party/SuppliedScenarioParameters.java | 26 ++++--- .../eblsurrender-api-v3.0.0-request.json | 71 ++----------------- .../standards/ebl/checks/EBLChecks.java | 31 ++++++-- .../standards/ebl/checks/EblDatasets.java | 50 ++++++++----- .../ebl/party/TransportDocumentStatus.java | 8 +-- .../eblinterop/PintScenarioListBuilder.java | 44 ++++++------ .../eblinterop/action/PintAction.java | 4 +- .../PintInitiateAndCloseTransferAction.java | 1 + .../action/PintInitiateTransferAction.java | 4 ++ ...ntInitiateTransferUnsignedErrorAction.java | 4 ++ .../action/PintRetryTransferAction.java | 4 ++ .../PintRetryTransferAndCloseAction.java | 4 ++ ...ScenarioParametersAndStateSetupAction.java | 15 ++-- .../eblinterop/checks/PintChecks.java | 41 ++++++++--- .../models/ReceiverScenarioParameters.java | 18 ++--- .../eblinterop/models/TDReceiveState.java | 36 ++-------- .../eblinterop/models/TDSendingState.java | 61 +++------------- .../party/PintReceivingPlatform.java | 33 ++++++--- .../eblinterop/party/PintSendingPlatform.java | 25 +++---- 25 files changed, 287 insertions(+), 270 deletions(-) diff --git a/ebl-issuance/src/main/java/org/dcsa/conformance/standards/eblissuance/checks/IssuanceChecks.java b/ebl-issuance/src/main/java/org/dcsa/conformance/standards/eblissuance/checks/IssuanceChecks.java index b6974227..d36749b1 100644 --- a/ebl-issuance/src/main/java/org/dcsa/conformance/standards/eblissuance/checks/IssuanceChecks.java +++ b/ebl-issuance/src/main/java/org/dcsa/conformance/standards/eblissuance/checks/IssuanceChecks.java @@ -2,6 +2,7 @@ import static org.dcsa.conformance.core.check.JsonAttribute.*; import static org.dcsa.conformance.standards.ebl.checks.EBLChecks.genericTDContentChecks; +import static org.dcsa.conformance.standards.ebl.checks.EblDatasets.DOCUMENTATION_PARTY_CODE_LIST_PROVIDER_CODES; import java.util.Set; import java.util.UUID; @@ -19,6 +20,12 @@ public class IssuanceChecks { + private static final JsonRebaseableContentCheck ISSUE_TO_CODE_LIST_PROVIDER = JsonAttribute.allIndividualMatchesMustBeValid( + "The 'codeListProvider' is valid", + mav -> mav.submitAllMatching("issueTo.identifyingCodes.*.codeListProvider"), + JsonAttribute.matchedMustBeDatasetKeywordIfPresent(DOCUMENTATION_PARTY_CODE_LIST_PROVIDER_CODES) + ); + private static JsonRebaseableContentCheck hasEndorseeScenarioCheck(String standardsVersion, EblType eblType) { return JsonAttribute.customValidator( "[Scenario] Validate endorsee party presence is correct", @@ -53,6 +60,7 @@ public static ActionCheck tdScenarioChecks(UUID matched, String standardsVersion JsonPointer.compile("/document/isToOrder"), eblType.isToOrder() ), + ISSUE_TO_CODE_LIST_PROVIDER, hasEndorseeScenarioCheck(standardsVersion, eblType) ); } diff --git a/ebl-surrender/pom.xml b/ebl-surrender/pom.xml index bbb65e50..8ed0a88d 100644 --- a/ebl-surrender/pom.xml +++ b/ebl-surrender/pom.xml @@ -18,7 +18,10 @@ <groupId>org.dcsa.conformance</groupId> <artifactId>core</artifactId> </dependency> - + <dependency> + <groupId>org.dcsa.conformance</groupId> + <artifactId>ebl</artifactId> + </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> diff --git a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/SurrenderChecks.java b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/SurrenderChecks.java index 150cb840..10018124 100644 --- a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/SurrenderChecks.java +++ b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/SurrenderChecks.java @@ -3,19 +3,22 @@ import org.dcsa.conformance.core.check.ActionCheck; import org.dcsa.conformance.core.check.JsonAttribute; import org.dcsa.conformance.core.check.JsonContentCheck; +import org.dcsa.conformance.core.check.JsonRebaseableContentCheck; import org.dcsa.conformance.core.check.KeywordDataset; import org.dcsa.conformance.core.traffic.HttpMessageType; import org.dcsa.conformance.standards.eblsurrender.party.EblSurrenderRole; import java.util.UUID; +import static org.dcsa.conformance.standards.ebl.checks.EblDatasets.DOCUMENTATION_PARTY_CODE_LIST_PROVIDER_CODES; + public class SurrenderChecks { private static final KeywordDataset SURRENDER_ACTIONS_DATA_SET = KeywordDataset.staticDataset( "ISSUE", "ENDORSE", "SIGN", - "SURRENDER FOR DELIVERY", - "SURRENDER FOR AMENDMENT" + "SURRENDER_FOR_DELIVERY", + "SURRENDER_FOR_AMENDMENT" ); private static final JsonContentCheck SURRENDER_ACTION_VALIDATION = JsonAttribute.allIndividualMatchesMustBeValid( @@ -24,14 +27,23 @@ public class SurrenderChecks { JsonAttribute.matchedMustBeDatasetKeywordIfPresent(SURRENDER_ACTIONS_DATA_SET) ); + private static final JsonRebaseableContentCheck SURRENDER_PARTY_CODE_LIST_PROVIDER = JsonAttribute.allIndividualMatchesMustBeValid( + "Validate 'codeListProvider' is a known value", + (mav) -> { + mav.submitAllMatching("endorsementChain.*.actor.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("endorsementChain.*.recipient.identifyingCodes.*.codeListProvider"); + }, + JsonAttribute.matchedMustBeDatasetKeywordIfPresent(DOCUMENTATION_PARTY_CODE_LIST_PROVIDER_CODES) + ); + public static ActionCheck surrenderRequestChecks(UUID matched, String standardVersion) { return JsonAttribute.contentChecks( EblSurrenderRole::isPlatform, matched, HttpMessageType.REQUEST, standardVersion, - SURRENDER_ACTION_VALIDATION + SURRENDER_ACTION_VALIDATION, + SURRENDER_PARTY_CODE_LIST_PROVIDER ); - } } diff --git a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/action/SupplyScenarioParametersAction.java b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/action/SupplyScenarioParametersAction.java index a3a61453..03731c00 100644 --- a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/action/SupplyScenarioParametersAction.java +++ b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/action/SupplyScenarioParametersAction.java @@ -7,6 +7,8 @@ import org.dcsa.conformance.core.scenario.ConformanceAction; import org.dcsa.conformance.standards.eblsurrender.party.SuppliedScenarioParameters; +import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER; + @Getter public class SupplyScenarioParametersAction extends ConformanceAction { private SuppliedScenarioParameters suppliedScenarioParameters = null; @@ -47,12 +49,22 @@ public String getHumanReadablePrompt() { @Override public JsonNode getJsonForHumanReadablePrompt() { - return new SuppliedScenarioParameters( - UUID.randomUUID().toString().replace("-", "").substring(0, 20), - "XMPL", - "Example carrier party code", - "Example party code", - "Example code list") + var issueToParty = OBJECT_MAPPER.createObjectNode(); + issueToParty.put("partyName", "Issue To name") + .put("eblPlatform", "WAVE"); + var carrierParty = OBJECT_MAPPER.createObjectNode(); + carrierParty.put("partyName", "Carrier name") + .put("eblPlatform", "WAVE"); + + var surrendereeParty = OBJECT_MAPPER.createObjectNode(); + surrendereeParty.put("partyName", "Surrenderee name") + .put("eblPlatform", "BOLE"); + return new SuppliedScenarioParameters( + UUID.randomUUID().toString().replace("-", "").substring(0, 20), + issueToParty, + carrierParty, + surrendereeParty + ) .toJson(); } diff --git a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderCarrier.java b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderCarrier.java index 5eb1c45c..c7a1c461 100644 --- a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderCarrier.java +++ b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderCarrier.java @@ -86,9 +86,20 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { String tdr = UUID.randomUUID().toString().replace("-", "").substring(0, 20); eblStatesById.put(tdr, EblSurrenderState.AVAILABLE_FOR_SURRENDER); + var issueToParty = OBJECT_MAPPER.createObjectNode(); + issueToParty.put("partyName", "Issue To name") + .put("eblPlatform", "WAVE"); + var carrierParty = OBJECT_MAPPER.createObjectNode(); + carrierParty.put("partyName", "Carrier name") + .put("eblPlatform", "WAVE"); + + var surrendereeParty = OBJECT_MAPPER.createObjectNode(); + surrendereeParty.put("partyName", "Surrenderee name") + .put("eblPlatform", "BOLE"); + SuppliedScenarioParameters suppliedScenarioParameters = new SuppliedScenarioParameters( - tdr, "XMPL", "Example carrier party code", "Example party code", "Example code list"); + tdr, issueToParty, carrierParty, surrendereeParty); asyncOrchestratorPostPartyInput( actionPrompt.required("actionId").asText(), suppliedScenarioParameters.toJson()); diff --git a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderPlatform.java b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderPlatform.java index 79bef25c..50c85a74 100644 --- a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderPlatform.java +++ b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderPlatform.java @@ -91,10 +91,9 @@ private void requestSurrender(JsonNode actionPrompt) { Map.entry("SURRENDER_REQUEST_REFERENCE_PLACEHOLDER", srr), Map.entry("TRANSPORT_DOCUMENT_REFERENCE_PLACEHOLDER", tdr), Map.entry("SURRENDER_REQUEST_CODE_PLACEHOLDER", src), - Map.entry("EBL_PLATFORM_PLACEHOLDER", ssp.eblPlatform()), - Map.entry("CARRIER_PARTY_CODE_PLACEHOLDER", ssp.carrierPartyCode()), - Map.entry("PARTY_CODE_PLACEHOLDER", ssp.surrenderPartyCode()), - Map.entry("CODE_LIST_NAME_PLACEHOLDER", ssp.codeListName()), + Map.entry("ISSUE_TO_PARTY", ssp.issueToParty().toString()), + Map.entry("SURRENDEREE_PARTY", ssp.surrendereeParty().toString()), + Map.entry("CARRIER_PARTY", ssp.carrierParty().toString()), Map.entry("ACTION_DATE_TIME_PLACEHOLDER", Instant.now().toString()))); syncCounterpartPost( diff --git a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/SuppliedScenarioParameters.java b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/SuppliedScenarioParameters.java index e10ddfa5..f93c8e19 100644 --- a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/SuppliedScenarioParameters.java +++ b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/SuppliedScenarioParameters.java @@ -6,23 +6,27 @@ import com.fasterxml.jackson.databind.node.ObjectNode; public record SuppliedScenarioParameters( - String transportDocumentReference, String eblPlatform, String carrierPartyCode, String surrenderPartyCode, String codeListName) { + String transportDocumentReference, + JsonNode issueToParty, + JsonNode carrierParty, + JsonNode surrendereeParty +) { public ObjectNode toJson() { - return OBJECT_MAPPER + var r = OBJECT_MAPPER .createObjectNode() - .put("transportDocumentReference", transportDocumentReference) - .put("eblPlatform", eblPlatform) - .put("carrierPartyCode", surrenderPartyCode) - .put("surrenderPartyCode", surrenderPartyCode) - .put("codeListName", codeListName); + .put("transportDocumentReference", transportDocumentReference); + + r.set("issueToParty", issueToParty); + r.set("carrierParty", carrierParty); + r.set("surrendereeParty", surrendereeParty); + return r; } public static SuppliedScenarioParameters fromJson(JsonNode jsonNode) { return new SuppliedScenarioParameters( jsonNode.required("transportDocumentReference").asText(), - jsonNode.required("eblPlatform").asText(), - jsonNode.required("carrierPartyCode").asText(), - jsonNode.required("surrenderPartyCode").asText(), - jsonNode.required("codeListName").asText()); + jsonNode.required("issueToParty"), + jsonNode.required("carrierParty"), + jsonNode.required("surrendereeParty")); } } diff --git a/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v3.0.0-request.json b/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v3.0.0-request.json index 41d7e48e..8a515350 100644 --- a/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v3.0.0-request.json +++ b/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v3.0.0-request.json @@ -8,75 +8,14 @@ { "actionDateTime": "2024-06-11T13:54:00Z", "actionCode": "ISSUE", - "actor": { - "eblPlatform": "EBL_PLATFORM_PLACEHOLDER", - "partyName": "legal name", - "identifyingCodes": [ - { - "codeListProvider": "EPUI", - "partyCode": "CARRIER_PARTY_CODE_PLACEHOLDER", - "codeListName": "CODE_LIST_NAME_PLACEHOLDER" - } - ], - "taxLegalReferences": [ - { - "type": "PAN", - "countryCode": "IN", - "value": "AAAAA0000A" - } - ] - }, - "recipient": { - "eblPlatform": "EBL_PLATFORM_PLACEHOLDER", - "partyName": "legal name", - "identifyingCodes": [ - { - "codeListProvider": "EPUI", - "partyCode": "PARTY_CODE_PLACEHOLDER", - "codeListName": "CODE_LIST_NAME_PLACEHOLDER" - } - ] - } + "actor": ISSUE_TO_PARTY, + "recipient": SURRENDEREE_PARTY }, { "actionDateTime": "2024-06-12T14:54:00Z", - "actionCode": "SURRENDER FOR DELIVERY", - "actor": { - "eblPlatform": "EBL_PLATFORM_PLACEHOLDER", - "partyName": "legal name", - "identifyingCodes": [ - { - "codeListProvider": "EPUI", - "partyCode": "PARTY_CODE_PLACEHOLDER", - "codeListName": "CODE_LIST_NAME_PLACEHOLDER" - } - ], - "taxLegalReferences": [ - { - "type": "PAN", - "countryCode": "IN", - "value": "AAAAA0000A" - } - ] - }, - "recipient": { - "eblPlatform": "EBL_PLATFORM_PLACEHOLDER", - "partyName": "legal name", - "identifyingCodes": [ - { - "codeListProvider": "EPUI", - "partyCode": "CARRIER_PARTY_CODE_PLACEHOLDER", - "codeListName": "CODE_LIST_NAME_PLACEHOLDER" - } - ], - "taxLegalReferences": [ - { - "type": "PAN", - "countryCode": "IN", - "value": "AAAAA0000A" - } - ] - } + "actionCode": "SURRENDER_FOR_DELIVERY", + "actor": SURRENDEREE_PARTY, + "recipient": CARRIER_PARTY } ] } diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/EBLChecks.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/EBLChecks.java index 77e3fd03..684606c1 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/EBLChecks.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/EBLChecks.java @@ -1,6 +1,7 @@ package org.dcsa.conformance.standards.ebl.checks; import static org.dcsa.conformance.core.check.JsonAttribute.concatContextPath; +import static org.dcsa.conformance.standards.ebl.checks.EblDatasets.DOCUMENTATION_PARTY_CODE_LIST_PROVIDER_CODES; import static org.dcsa.conformance.standards.ebl.checks.EblDatasets.MODE_OF_TRANSPORT; import static org.dcsa.conformance.standards.ebl.checks.EblDatasets.NATIONAL_COMMODITY_CODES; @@ -212,6 +213,29 @@ public class EBLChecks { JsonAttribute.path("numberOfOriginalsWithCharges", JsonAttribute.matchedMaximum(1)) ); + private static final JsonRebaseableContentCheck DOCUMENTATION_PARTIES_CODE_LIST_PROVIDERS = JsonAttribute.allIndividualMatchesMustBeValid( + "The code in 'codeListProvider' is known", + mav -> { + mav.submitAllMatching("documentParties.shipper.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("documentParties.consignee.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("documentParties.endorsee.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("documentParties.issueTo.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("documentParties.seller.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("documentParties.buyer.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("documentParties.notifyParties.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("documentParties.other.party.identifyingCodes.*.codeListProvider"); + + + mav.submitAllMatching("houseBillOfLadings.*.documentParties.shipper.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("houseBillOfLadings.*.documentParties.consignee.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("houseBillOfLadings.*.documentParties.notifyParty.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("houseBillOfLadings.*.documentParties.seller.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("houseBillOfLadings.*.documentParties.buyer.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("houseBillOfLadings.*.documentParties.other.party.identifyingCodes.*.codeListProvider"); + }, + JsonAttribute.matchedMustBeDatasetKeywordIfPresent(DOCUMENTATION_PARTY_CODE_LIST_PROVIDER_CODES) + ); + private static final JsonRebaseableContentCheck NOTIFY_PARTIES_REQUIRED_IN_NEGOTIABLE_BLS = JsonAttribute.ifThen( "The 'documentParties.notifyParties' attribute is mandatory for negotiable B/Ls", JsonAttribute.isTrue("isToOrder"), @@ -440,6 +464,7 @@ private static Consumer<MultiAttributeValidator> allDg(Consumer<MultiAttributeVa JsonAttribute.mustBePresent(ISSUE_TO_PARTY), JsonAttribute.mustBeAbsent(ISSUE_TO_PARTY) ), + DOCUMENTATION_PARTIES_CODE_LIST_PROVIDERS, VALID_WOOD_DECLARATIONS, NATIONAL_COMMODITY_CODE_IS_VALID, VALID_REFERENCE_TYPES, @@ -490,6 +515,7 @@ private static Consumer<MultiAttributeValidator> allDg(Consumer<MultiAttributeVa JsonAttribute.isNotNull(JsonPointer.compile("/transports/onCarriageBy")), JsonAttribute.mustBeNotNull(JsonPointer.compile("/transports/placeOfDelivery"), "'onCarriageBy' is present") ), + DOCUMENTATION_PARTIES_CODE_LIST_PROVIDERS, VALID_WOOD_DECLARATIONS, NATIONAL_COMMODITY_CODE_IS_VALID, VALID_REFERENCE_TYPES, @@ -557,14 +583,9 @@ private static Consumer<MultiAttributeValidator> allDg(Consumer<MultiAttributeVa TLR_CC_T_COMBINATION_UNIQUE ); - public static final JsonContentCheck SIR_REQUIRED_IN_REF_STATUS = JsonAttribute.mustBePresent(SI_REF_SIR_PTR); public static final JsonContentCheck SIR_REQUIRED_IN_NOTIFICATION = JsonAttribute.mustBePresent(SI_NOTIFICATION_SIR_PTR); public static final JsonContentCheck TDR_REQUIRED_IN_NOTIFICATION = JsonAttribute.mustBePresent(TD_NOTIFICATION_TDR_PTR); - public static JsonContentCheck sirInRefStatusMustMatchDSP(Supplier<DynamicScenarioParameters> dspSupplier) { - return JsonAttribute.mustEqual(SI_REF_SIR_PTR, () -> dspSupplier.get().shippingInstructionsReference()); - } - public static JsonContentCheck sirInNotificationMustMatchDSP(Supplier<DynamicScenarioParameters> dspSupplier) { return JsonAttribute.mustEqual(SI_NOTIFICATION_SIR_PTR, () -> dspSupplier.get().shippingInstructionsReference()); } diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/EblDatasets.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/EblDatasets.java index dd416689..b7872ef0 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/EblDatasets.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/EblDatasets.java @@ -1,33 +1,23 @@ package org.dcsa.conformance.standards.ebl.checks; -import com.opencsv.CSVReader; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import lombok.SneakyThrows; import org.dcsa.conformance.core.check.KeywordDataset; -import org.dcsa.conformance.core.check.VersionedStaticKeywordSet; public class EblDatasets { - public static final KeywordDataset EBL_PLATFORMS_DATASET = KeywordDataset.staticVersionedDataset( - VersionedStaticKeywordSet.versionedKeywords( - _ignored -> false, - Set.of("ESSD"), - Set.of("ICED") - ), + public static final KeywordDataset EBL_PLATFORMS_DATASET = KeywordDataset.staticDataset( "WAVE", + "CARX", + "ESSD", + "IDT", "BOLE", "EDOX", "IQAX", "SECR", - "CARX", - "TRGO" + "TRGO", + "ETEU", + "TRAC", + "BRIT" ); @@ -63,4 +53,28 @@ public class EblDatasets { "CUS" ); + public static final KeywordDataset DOCUMENTATION_PARTY_CODE_LIST_PROVIDER_CODES = KeywordDataset.staticDataset( + "WAVE", + "CARX", + "ESSD", + "IDT", + "BOLE", + "EDOX", + "IQAX", + "SECR", + "TRGO", + "ETEU", + "TRAC", + "BRIT", + "GSBN", + "WISE", + "GLEIF", + "W3C", + "DNB", + "FMC", + "DCSA", + "EU", + "ZZZ" + ); + } diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/party/TransportDocumentStatus.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/party/TransportDocumentStatus.java index 985d34c7..cf781ba6 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/party/TransportDocumentStatus.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/party/TransportDocumentStatus.java @@ -14,10 +14,10 @@ public enum TransportDocumentStatus { TD_DRAFT("DRAFT"), TD_APPROVED("APPROVED"), TD_ISSUED("ISSUED"), - TD_PENDING_SURRENDER_FOR_AMENDMENT("PENDING SURRENDER FOR AMENDMENT"), - TD_SURRENDERED_FOR_AMENDMENT("SURRENDERED FOR AMENDMENT"), - TD_PENDING_SURRENDER_FOR_DELIVERY("PENDING SURRENDER FOR DELIVERY"), - TD_SURRENDERED_FOR_DELIVERY("SURRENDERED FOR DELIVERY"), + TD_PENDING_SURRENDER_FOR_AMENDMENT("PENDING_SURRENDER_FOR_AMENDMENT"), + TD_SURRENDERED_FOR_AMENDMENT("SURRENDERED_FOR_AMENDMENT"), + TD_PENDING_SURRENDER_FOR_DELIVERY("PENDING_SURRENDER_FOR_DELIVERY"), + TD_SURRENDERED_FOR_DELIVERY("SURRENDERED_FOR_DELIVERY"), TD_VOIDED("VOID"), ; 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 fd267dd6..a507223a 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 @@ -42,20 +42,20 @@ public static LinkedHashMap<String, PintScenarioListBuilder> createModuleScenari .thenEither( initiateAndCloseTransferAction(PintResponseCode.RECE).thenEither( noAction(), - retryTransfer(PintResponseCode.DUPE), + retryTransfer(PintResponseCode.DUPE, SenderTransmissionClass.VALID_TRANSFER), resignLatestEntry().then( - retryTransfer(PintResponseCode.DUPE) + retryTransfer(PintResponseCode.DUPE, SenderTransmissionClass.VALID_TRANSFER) ), manipulateLatestTransactionParameters().then( - retryTransfer(PintResponseCode.DISE) + retryTransfer(PintResponseCode.DISE, SenderTransmissionClass.VALID_TRANSFER) )), initiateAndCloseTransferAction(PintResponseCode.RECE, SenderTransmissionClass.VALID_TRANSFER).thenEither( noAction(), resignLatestEntry().then( - retryTransfer(PintResponseCode.DUPE) + retryTransfer(PintResponseCode.DUPE, SenderTransmissionClass.VALID_TRANSFER) ), manipulateLatestTransactionParameters().then( - retryTransfer(PintResponseCode.DISE) + retryTransfer(PintResponseCode.DISE, SenderTransmissionClass.VALID_TRANSFER) ) ), initiateAndCloseTransferAction(PintResponseCode.BSIG, SenderTransmissionClass.SIGNATURE_ISSUE).then( @@ -67,10 +67,10 @@ public static LinkedHashMap<String, PintScenarioListBuilder> createModuleScenari initiateAndCloseTransferAction(PintResponseCode.BENV) ), receiverStateSetup(ScenarioClass.FAIL_W_503).then( - initiateTransferUnsignedFailure(503).thenEither( + initiateTransferUnsignedFailure(503, SenderTransmissionClass.VALID_TRANSFER).thenEither( resetScenarioClass(ScenarioClass.NO_ISSUES).then( initiateAndCloseTransferAction(PintResponseCode.RECE)), - initiateTransferUnsignedFailure(503).then( + initiateTransferUnsignedFailure(503, SenderTransmissionClass.VALID_TRANSFER).then( resetScenarioClass(ScenarioClass.NO_ISSUES).then( initiateAndCloseTransferAction(PintResponseCode.RECE))) )) @@ -78,39 +78,39 @@ public static LinkedHashMap<String, PintScenarioListBuilder> createModuleScenari supplySenderTransferScenarioParameters(2).thenEither( receiverStateSetup(ScenarioClass.NO_ISSUES) .then( - initiateTransfer(2).thenEither( + initiateTransfer(2, SenderTransmissionClass.VALID_TRANSFER).thenEither( transferDocument().thenEither( transferDocument().then(closeTransferAction(PintResponseCode.RECE)), - retryTransfer(1).then( + retryTransfer(1, SenderTransmissionClass.VALID_TRANSFER).then( transferDocument().thenEither( closeTransferAction(PintResponseCode.RECE), - retryTransfer(PintResponseCode.RECE) + retryTransfer(PintResponseCode.RECE, SenderTransmissionClass.VALID_TRANSFER) ) ), resetScenarioClass(ScenarioClass.FAIL_W_503).then( transferDocumentReceiverFailure().then( resetScenarioClass(ScenarioClass.NO_ISSUES).thenEither( transferDocument().then(closeTransferAction(PintResponseCode.RECE)), - retryTransfer(1).then( + retryTransfer(1, SenderTransmissionClass.VALID_TRANSFER).then( transferDocument().thenEither( closeTransferAction(PintResponseCode.RECE), - retryTransfer(PintResponseCode.RECE) + retryTransfer(PintResponseCode.RECE, SenderTransmissionClass.VALID_TRANSFER) ) ) ) ) ), transferDocument(SenderDocumentTransmissionTypeCode.CORRUPTED_DOCUMENT).then( - retryTransfer(1).then(transferDocument().then(closeTransferAction(PintResponseCode.RECE))) + retryTransfer(1, SenderTransmissionClass.VALID_TRANSFER).then(transferDocument().then(closeTransferAction(PintResponseCode.RECE))) ), transferDocument(SenderDocumentTransmissionTypeCode.UNRELATED_DOCUMENT).then( - retryTransfer(1).then(transferDocument().then(closeTransferAction(PintResponseCode.RECE))) + retryTransfer(1, SenderTransmissionClass.VALID_TRANSFER).then(transferDocument().then(closeTransferAction(PintResponseCode.RECE))) ), closeTransferAction(PintResponseCode.MDOC).then( - retryTransfer(1).then( + retryTransfer(1, SenderTransmissionClass.VALID_TRANSFER).then( transferDocument().thenEither( closeTransferAction(PintResponseCode.RECE), - retryTransfer(PintResponseCode.RECE) + retryTransfer(PintResponseCode.RECE, SenderTransmissionClass.VALID_TRANSFER) ) ) ) @@ -253,7 +253,7 @@ private static PintScenarioListBuilder noAction() { } - private static PintScenarioListBuilder initiateTransferUnsignedFailure(int expectedStatus) { + private static PintScenarioListBuilder initiateTransferUnsignedFailure(int expectedStatus, SenderTransmissionClass senderTransmissionClass) { String sendingPlatform = SENDING_PLATFORM_PARTY_NAME.get(); String receivingPlatform = RECEIVING_PLATFORM_PARTY_NAME.get(); return new PintScenarioListBuilder( @@ -263,13 +263,14 @@ private static PintScenarioListBuilder initiateTransferUnsignedFailure(int expec sendingPlatform, (PintAction) previousAction, expectedStatus, + senderTransmissionClass, resolveMessageSchemaValidator(ENVELOPE_REQUEST_SCHEMA), resolveMessageSchemaValidator(ENVELOPE_MANIFEST_SCHEMA), resolveMessageSchemaValidator(ENVELOPE_TRANSFER_CHAIN_ENTRY_SCHEMA), resolveMessageSchemaValidator(ISSUANCE_MANIFEST_SCHEMA))); } - private static PintScenarioListBuilder initiateTransfer(int expectedMissingDocumentCount) { + private static PintScenarioListBuilder initiateTransfer(int expectedMissingDocumentCount, SenderTransmissionClass senderTransmissionClass) { String sendingPlatform = SENDING_PLATFORM_PARTY_NAME.get(); String receivingPlatform = RECEIVING_PLATFORM_PARTY_NAME.get(); return new PintScenarioListBuilder( @@ -279,6 +280,7 @@ private static PintScenarioListBuilder initiateTransfer(int expectedMissingDocum sendingPlatform, (PintAction) previousAction, expectedMissingDocumentCount, + senderTransmissionClass, resolveMessageSchemaValidator(ENVELOPE_REQUEST_SCHEMA), resolveMessageSchemaValidator(ENVELOPE_MANIFEST_SCHEMA), resolveMessageSchemaValidator(ENVELOPE_TRANSFER_CHAIN_ENTRY_SCHEMA), @@ -287,7 +289,7 @@ private static PintScenarioListBuilder initiateTransfer(int expectedMissingDocum )); } - private static PintScenarioListBuilder retryTransfer(int expectedMissingDocumentCount) { + private static PintScenarioListBuilder retryTransfer(int expectedMissingDocumentCount, SenderTransmissionClass senderTransmissionClass) { String sendingPlatform = SENDING_PLATFORM_PARTY_NAME.get(); String receivingPlatform = RECEIVING_PLATFORM_PARTY_NAME.get(); return new PintScenarioListBuilder( @@ -297,6 +299,7 @@ private static PintScenarioListBuilder retryTransfer(int expectedMissingDocument sendingPlatform, (PintAction) previousAction, expectedMissingDocumentCount, + senderTransmissionClass, resolveMessageSchemaValidator(ENVELOPE_REQUEST_SCHEMA), resolveMessageSchemaValidator(ENVELOPE_MANIFEST_SCHEMA), resolveMessageSchemaValidator(ENVELOPE_TRANSFER_CHAIN_ENTRY_SCHEMA), @@ -304,7 +307,7 @@ private static PintScenarioListBuilder retryTransfer(int expectedMissingDocument resolveMessageSchemaValidator(TRANSFER_STARTED_UNSIGNED_RESPONSE_SCHEMA))); } - private static PintScenarioListBuilder retryTransfer(PintResponseCode pintResponseCode) { + private static PintScenarioListBuilder retryTransfer(PintResponseCode pintResponseCode, SenderTransmissionClass senderTransmissionClass) { String sendingPlatform = SENDING_PLATFORM_PARTY_NAME.get(); String receivingPlatform = RECEIVING_PLATFORM_PARTY_NAME.get(); return new PintScenarioListBuilder( @@ -314,6 +317,7 @@ private static PintScenarioListBuilder retryTransfer(PintResponseCode pintRespon sendingPlatform, (PintAction) previousAction, pintResponseCode, + senderTransmissionClass, resolveMessageSchemaValidator(ENVELOPE_REQUEST_SCHEMA), resolveMessageSchemaValidator(ENVELOPE_MANIFEST_SCHEMA), resolveMessageSchemaValidator(ENVELOPE_TRANSFER_CHAIN_ENTRY_SCHEMA), 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 1be4d575..8a4caa98 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 @@ -31,7 +31,9 @@ public PintAction( if (previousAction == null) { this.dspReference = new OverwritingReference<>(null, new DynamicScenarioParameters(null, -1, Set.of(), null, OBJECT_MAPPER.createObjectNode())); - this.rspReference = new OverwritingReference<>(null, new ReceiverScenarioParameters("", "", "", "", "")); + this.rspReference = + new OverwritingReference<>( + null, new ReceiverScenarioParameters(OBJECT_MAPPER.createObjectNode(), "")); this.sspReference = new OverwritingReference<>(null, new SenderScenarioParameters(null, "", "", "")); } else { this.dspReference = new OverwritingReference<>(previousAction.dspReference, null); diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateAndCloseTransferAction.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateAndCloseTransferAction.java index 4746bbf5..c414297e 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateAndCloseTransferAction.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateAndCloseTransferAction.java @@ -151,6 +151,7 @@ protected Stream<? extends ConformanceCheck> createSubChecks() { validateInitiateTransferRequest( getMatchedExchangeUuid(), expectedApiVersion, + senderTransmissionClass, () -> getSsp(), () -> getRsp(), () -> getDsp() diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateTransferAction.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateTransferAction.java index d454264d..fdc9a5f2 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateTransferAction.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateTransferAction.java @@ -23,6 +23,7 @@ @Slf4j public class PintInitiateTransferAction extends PintAction { private final int expectedMissingDocCount; + private final SenderTransmissionClass senderTransmissionClass; private final JsonSchemaValidator requestSchemaValidator; private final JsonSchemaValidator responseSchemaValidator; private final JsonSchemaValidator envelopeEnvelopeSchemaValidator; @@ -34,6 +35,7 @@ public PintInitiateTransferAction( String sendingPlatform, PintAction previousAction, int expectedMissingDocCount, + SenderTransmissionClass senderTransmissionClass, JsonSchemaValidator requestSchemaValidator, JsonSchemaValidator envelopeEnvelopeSchemaValidator, JsonSchemaValidator envelopeTransferChainEntrySchemaValidator, @@ -48,6 +50,7 @@ public PintInitiateTransferAction( 201 ); this.expectedMissingDocCount = expectedMissingDocCount; + this.senderTransmissionClass = senderTransmissionClass; this.requestSchemaValidator = requestSchemaValidator; this.responseSchemaValidator = responseSchemaValidator; this.envelopeEnvelopeSchemaValidator = envelopeEnvelopeSchemaValidator; @@ -168,6 +171,7 @@ protected Stream<? extends ConformanceCheck> createSubChecks() { validateInitiateTransferRequest( getMatchedExchangeUuid(), expectedApiVersion, + senderTransmissionClass, () -> getSsp(), () -> getRsp(), () -> getDsp() diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateTransferUnsignedErrorAction.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateTransferUnsignedErrorAction.java index aa96ca19..17850c0e 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateTransferUnsignedErrorAction.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintInitiateTransferUnsignedErrorAction.java @@ -23,6 +23,7 @@ @Getter @Slf4j public class PintInitiateTransferUnsignedErrorAction extends PintAction { + private final SenderTransmissionClass senderTransmissionClass; private final JsonSchemaValidator requestSchemaValidator; private final JsonSchemaValidator envelopeEnvelopeSchemaValidator; private final JsonSchemaValidator envelopeTransferChainEntrySchemaValidator; @@ -33,6 +34,7 @@ public PintInitiateTransferUnsignedErrorAction( String sendingPlatform, PintAction previousAction, int expectedStatus, + SenderTransmissionClass senderTransmissionClass, JsonSchemaValidator requestSchemaValidator, JsonSchemaValidator envelopeEnvelopeSchemaValidator, JsonSchemaValidator envelopeTransferChainEntrySchemaValidator, @@ -45,6 +47,7 @@ public PintInitiateTransferUnsignedErrorAction( "StartTransfer", expectedStatus ); + this.senderTransmissionClass = senderTransmissionClass; this.requestSchemaValidator = requestSchemaValidator; this.envelopeEnvelopeSchemaValidator = envelopeEnvelopeSchemaValidator; this.envelopeTransferChainEntrySchemaValidator = envelopeTransferChainEntrySchemaValidator; @@ -146,6 +149,7 @@ protected Stream<? extends ConformanceCheck> createSubChecks() { validateInitiateTransferRequest( getMatchedExchangeUuid(), expectedApiVersion, + senderTransmissionClass, () -> getSsp(), () -> getRsp(), () -> getDsp() diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintRetryTransferAction.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintRetryTransferAction.java index 5fc5f151..e1a35fe7 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintRetryTransferAction.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintRetryTransferAction.java @@ -23,6 +23,7 @@ @Slf4j public class PintRetryTransferAction extends PintAction { private final int expectedMissingDocCount; + private final SenderTransmissionClass senderTransmissionClass; private final JsonSchemaValidator requestSchemaValidator; private final JsonSchemaValidator responseSchemaValidator; private final JsonSchemaValidator envelopeEnvelopeSchemaValidator; @@ -34,6 +35,7 @@ public PintRetryTransferAction( String sendingPlatform, PintAction previousAction, int expectedMissingDocCount, + SenderTransmissionClass senderTransmissionClass, JsonSchemaValidator requestSchemaValidator, JsonSchemaValidator envelopeEnvelopeSchemaValidator, JsonSchemaValidator envelopeTransferChainEntrySchemaValidator, @@ -48,6 +50,7 @@ public PintRetryTransferAction( 201 ); this.expectedMissingDocCount = expectedMissingDocCount; + this.senderTransmissionClass = senderTransmissionClass; this.requestSchemaValidator = requestSchemaValidator; this.responseSchemaValidator = responseSchemaValidator; this.envelopeEnvelopeSchemaValidator = envelopeEnvelopeSchemaValidator; @@ -157,6 +160,7 @@ protected Stream<? extends ConformanceCheck> createSubChecks() { validateInitiateTransferRequest( getMatchedExchangeUuid(), expectedApiVersion, + senderTransmissionClass, () -> getSsp(), () -> getRsp(), () -> getDsp() diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintRetryTransferAndCloseAction.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintRetryTransferAndCloseAction.java index 2f41e838..ecb343b5 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintRetryTransferAndCloseAction.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/PintRetryTransferAndCloseAction.java @@ -23,6 +23,7 @@ @Slf4j public class PintRetryTransferAndCloseAction extends PintAction { private final PintResponseCode responseCode; + private final SenderTransmissionClass senderTransmissionClass; private final JsonSchemaValidator requestSchemaValidator; private final JsonSchemaValidator responseSchemaValidator; private final JsonSchemaValidator envelopeEnvelopeSchemaValidator; @@ -34,6 +35,7 @@ public PintRetryTransferAndCloseAction( String sendingPlatform, PintAction previousAction, PintResponseCode responseCode, + SenderTransmissionClass senderTransmissionClass, JsonSchemaValidator requestSchemaValidator, JsonSchemaValidator envelopeEnvelopeSchemaValidator, JsonSchemaValidator envelopeTransferChainEntrySchemaValidator, @@ -48,6 +50,7 @@ public PintRetryTransferAndCloseAction( responseCode.getHttpResponseCode() ); this.responseCode = responseCode; + this.senderTransmissionClass = senderTransmissionClass; this.requestSchemaValidator = requestSchemaValidator; this.responseSchemaValidator = responseSchemaValidator; this.envelopeEnvelopeSchemaValidator = envelopeEnvelopeSchemaValidator; @@ -170,6 +173,7 @@ protected Stream<? extends ConformanceCheck> createSubChecks() { validateInitiateTransferRequest( getMatchedExchangeUuid(), expectedApiVersion, + senderTransmissionClass, () -> getSsp(), () -> getRsp(), () -> getDsp() diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/ReceiverSupplyScenarioParametersAndStateSetupAction.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/ReceiverSupplyScenarioParametersAndStateSetupAction.java index acbe969e..07611701 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/ReceiverSupplyScenarioParametersAndStateSetupAction.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/action/ReceiverSupplyScenarioParametersAndStateSetupAction.java @@ -6,6 +6,8 @@ import lombok.extern.slf4j.Slf4j; import org.dcsa.conformance.standards.eblinterop.models.ReceiverScenarioParameters; +import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER; + @Getter @Slf4j public class ReceiverSupplyScenarioParametersAndStateSetupAction extends PintAction { @@ -54,11 +56,16 @@ public String getHumanReadablePrompt() { @Override public JsonNode getJsonForHumanReadablePrompt() { + var partyCode = OBJECT_MAPPER.createObjectNode() + .put("partyCode", "some-party-code") + .put("codeListProvider", "ZZZ"); + var receiverParty = OBJECT_MAPPER.createObjectNode(); + receiverParty.put("partyName", "Jane Doe") + .put("eblPlatform", "BOLE") + .putArray("identifyingCodes") + .add(partyCode); return new ReceiverScenarioParameters( - "Platform code (WAVE, BOLE, ...)", - "John Doe", - "identifier in your system", - "Platform code or ID issuer (Wave, Bolero, ...)", + receiverParty, "-----BEGIN RSA PUBLIC KEY-----\n<YOUR PUBLIC SIGNING KEY HERE>\n-----END RSA PUBLIC KEY-----\n" ).toJson(); } diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/checks/PintChecks.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/checks/PintChecks.java index fe384a75..3cb426a8 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/checks/PintChecks.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/checks/PintChecks.java @@ -2,6 +2,7 @@ import static org.dcsa.conformance.core.check.JsonAttribute.matchedMustEqual; import static org.dcsa.conformance.standards.ebl.checks.EBLChecks.genericTDContentChecks; +import static org.dcsa.conformance.standards.ebl.checks.EblDatasets.DOCUMENTATION_PARTY_CODE_LIST_PROVIDER_CODES; import static org.dcsa.conformance.standards.ebl.checks.SignatureChecks.*; import static org.dcsa.conformance.standards.ebl.crypto.SignedNodeSupport.parseSignedNode; @@ -19,6 +20,7 @@ import org.dcsa.conformance.standards.ebl.crypto.SignedNodeSupport; import org.dcsa.conformance.standards.ebl.party.TransportDocumentStatus; import org.dcsa.conformance.standards.eblinterop.action.PintResponseCode; +import org.dcsa.conformance.standards.eblinterop.action.SenderTransmissionClass; import org.dcsa.conformance.standards.eblinterop.models.DynamicScenarioParameters; import org.dcsa.conformance.standards.eblinterop.models.ReceiverScenarioParameters; import org.dcsa.conformance.standards.eblinterop.models.SenderScenarioParameters; @@ -28,6 +30,15 @@ public class PintChecks { private static final JsonPointer TDR_PTR = JsonPointer.compile("/transportDocument/transportDocumentReference"); + private static final JsonRebaseableContentCheck TRANSACTION_PARTY_CODE_LIST_PROVIDER = JsonAttribute.allIndividualMatchesMustBeValid( + "Validate 'codeListProvider' is a known value", + (mav) -> { + mav.submitAllMatching("transactions.*.actor.identifyingCodes.*.codeListProvider"); + mav.submitAllMatching("transactions.*.recipient.identifyingCodes.*.codeListProvider"); + }, + JsonAttribute.matchedMustBeDatasetKeywordIfPresent(DOCUMENTATION_PARTY_CODE_LIST_PROVIDER_CODES) + ); + public static JsonContentMatchedValidation arraySizeMustEqual(IntSupplier expectedSizeSupplier) { return (nodeToValidate,contextPath) -> { if (!nodeToValidate.isArray()) { @@ -157,6 +168,7 @@ public static JsonContentMatchedValidation expectedTDChecksum(Supplier<DynamicSc private static void generateScenarioRelatedChecksForTransferRequest( List<JsonContentCheck> checks, + SenderTransmissionClass senderTransmissionClass, Supplier<SenderScenarioParameters> sspSupplier, Supplier<ReceiverScenarioParameters> rspSupplier, Supplier<DynamicScenarioParameters> dspSupplier) { @@ -167,17 +179,20 @@ private static void generateScenarioRelatedChecksForTransferRequest( delayedValue(sspSupplier, SenderScenarioParameters::transportDocumentReference))); checks.add( JsonAttribute.customValidator( - "[Scenario] Verify receiver EPUI is correct", + "[Scenario] Verify receiver party is present (and exactly as-is)", pathChain( signedContentValidation( pathChain( - anyArrayElementMatching( - (n) -> n.path("codeListProvider").asText("").equals("EPUI"), - JsonAttribute.path("partyCode", matchedMustEqual(delayedValue(rspSupplier, ReceiverScenarioParameters::receiverEPUI))), - true - ), - "transactions", -1, "recipient", "partyCodes") - // + (n, p) -> { + if (senderTransmissionClass == SenderTransmissionClass.WRONG_RECIPIENT_PLATFORM) { + return Set.of(); + } + if (Objects.equals(rspSupplier.get().receiverParty(), n)) { + return Set.of(); + } + return Set.of("[Scenario] Last transaction did not use the receiving party provided by the receiver (exactly as-is)"); + }, + "transactions", -1, "recipient") ), "envelopeTransferChain", -1 ) @@ -326,13 +341,14 @@ public static ActionCheck validateInnerRequestSchemas( public static ActionCheck validateInitiateTransferRequest( UUID matched, String standardsVersion, + SenderTransmissionClass senderTransmissionClass, Supplier<SenderScenarioParameters> sspSupplier, Supplier<ReceiverScenarioParameters> rspSupplier, Supplier<DynamicScenarioParameters> dspSupplier ) { var jsonContentChecks = new ArrayList<JsonContentCheck>(); - generateScenarioRelatedChecksForTransferRequest(jsonContentChecks, sspSupplier, rspSupplier, dspSupplier); + generateScenarioRelatedChecksForTransferRequest(jsonContentChecks, senderTransmissionClass, sspSupplier, rspSupplier, dspSupplier); jsonContentChecks.add( JsonAttribute.customValidator( "Validate the transportDocument checksum in the envelopeManifestSignedContent", @@ -353,6 +369,13 @@ public static ActionCheck validateInitiateTransferRequest( ) ) ); + jsonContentChecks.add( + JsonAttribute.allIndividualMatchesMustBeValid( + "Validate codeListProvider", + (mav) -> mav.submitAllMatching("envelopeTransferChain.*"), + signedContentValidation(TRANSACTION_PARTY_CODE_LIST_PROVIDER::validate) + ) + ); jsonContentChecks.add( JsonAttribute.customValidator( "Validate transfer chain checksums", diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/ReceiverScenarioParameters.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/ReceiverScenarioParameters.java index bf8b20d1..ae6044d2 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/ReceiverScenarioParameters.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/ReceiverScenarioParameters.java @@ -8,28 +8,20 @@ @With public record ReceiverScenarioParameters( - String eblPlatform, - String receiverPartyName, - String receiverEPUI, - String receiverEPUICodeListName, + JsonNode receiverParty, String receiverPublicKeyPEM ) { public ObjectNode toJson() { - return OBJECT_MAPPER + var r = OBJECT_MAPPER .createObjectNode() - .put("eblPlatform", eblPlatform) - .put("receiverPartyName", receiverPartyName) - .put("receiverEPUI", receiverEPUI) - .put("receiverEPUICodeListName", receiverEPUICodeListName) .put("receiverPublicKeyPEM", receiverPublicKeyPEM); + r.set("receiverParty", receiverParty); + return r; } public static ReceiverScenarioParameters fromJson(JsonNode jsonNode) { return new ReceiverScenarioParameters( - jsonNode.required("eblPlatform").asText(), - jsonNode.required("receiverPartyName").asText(), - jsonNode.required("receiverEPUI").asText(), - jsonNode.required("receiverEPUICodeListName").asText(), + jsonNode.required("receiverParty"), jsonNode.required("receiverPublicKeyPEM").asText() ); } diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/TDReceiveState.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/TDReceiveState.java index 8b1ae462..26f1b884 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/TDReceiveState.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/TDReceiveState.java @@ -37,8 +37,6 @@ public class TDReceiveState { private static final String EXPECTED_PUBLIC_KEY = "expectedSenderPublicKey"; - private static final String RECEIVING_PLATFORM = "receivingEBLPlatform"; - private static final String TRANSFER_CHAIN_ENTRY_HISTORY = "transferChainEntryHistory"; private final ObjectNode state; @@ -65,11 +63,10 @@ public String getTransportDocumentReference() { return state.path(TRANSPORT_DOCUMENT_REFERENCE).asText(); } - public void setExpectedReceiver(String receiverEPUI) { - this.state.put(EXPECTED_RECEIVER, receiverEPUI); + public void setExpectedReceiver(JsonNode receiver) { + this.state.set(EXPECTED_RECEIVER, receiver); } - public Set<String> getKnownDocumentChecksums() { return StreamSupport.stream(this.state.path(KNOWN_DOCUMENTS).spliterator(), false) .map(JsonNode::asText) @@ -175,13 +172,13 @@ private boolean isEnvelopeTransferChainValid(JsonNode etc) { return true; } - public PintResponseCode recommendedFinishTransferResponse(JsonNode initiateRequest, SignatureVerifier signatureVerifer) { + public PintResponseCode recommendedFinishTransferResponse(JsonNode initiateRequest, SignatureVerifier signatureVerifier) { var etc = initiateRequest.path("envelopeTransferChain"); var lastEtcEntry = etc.path(etc.size() - 1); JsonNode etcEntryParsed, envelopeParsed; try { - etcEntryParsed = parseSignedNode(lastEtcEntry, signatureVerifer); - envelopeParsed = parseSignedNode(initiateRequest.path("envelopeManifestSignedContent"), signatureVerifer); + etcEntryParsed = parseSignedNode(lastEtcEntry, signatureVerifier); + envelopeParsed = parseSignedNode(initiateRequest.path("envelopeManifestSignedContent"), signatureVerifier); } catch (ParseException | JsonProcessingException e) { return PintResponseCode.BENV; } catch (CouldNotValidateSignatureException e) { @@ -193,10 +190,7 @@ public PintResponseCode recommendedFinishTransferResponse(JsonNode initiateReque var transactions = etcEntryParsed.path("transactions"); var lastTransactionNode = transactions.path(transactions.size() - 1); var recipient = lastTransactionNode.path("recipient"); - var recipientPartyCodes = recipient.path("partyCodes"); - var recipientPlatform = recipient.path("eblPlatform").asText("!?"); - var expectedReceiver = state.path(EXPECTED_RECEIVER).asText(); - boolean hasExpectedCode = false; + var expectedReceiver = state.path(EXPECTED_RECEIVER); var transferChainEntryHistory = this.state.path(TRANSFER_CHAIN_ENTRY_HISTORY); for (int i = 0; i < transferChainEntryHistory.size() ; i++) { var transferChainEntry = etc.path(i); @@ -231,22 +225,7 @@ public PintResponseCode recommendedFinishTransferResponse(JsonNode initiateReque newTransactionHistory.add(transaction); } } - - for (var partyCodeNode : recipientPartyCodes) { - if (!partyCodeNode.path("codeListProvider").asText("").equals("EPUI")) { - continue; - } - if (partyCodeNode.path("partyCode").asText("").equals(expectedReceiver)) { - hasExpectedCode = true; - break; - } - } - - if (!state.path(RECEIVING_PLATFORM).asText("?").equals(recipientPlatform)) { - hasExpectedCode = false; - } - - if (!hasExpectedCode) { + if (!Objects.equals(recipient, expectedReceiver)) { return PintResponseCode.BENV; } var missingDocuments = this.state.putArray(MISSING_DOCUMENTS); @@ -316,7 +295,6 @@ public static TDReceiveState newInstance(String transportDocumentReference, Stri var state = OBJECT_MAPPER.createObjectNode() .put(TRANSPORT_DOCUMENT_REFERENCE, transportDocumentReference) .put(TRANSFER_STATE, TransferState.NOT_STARTED.name()) - .put(RECEIVING_PLATFORM, receivingParameters.eblPlatform()) .put(EXPECTED_PUBLIC_KEY, senderPublicKeyPEM); return new TDReceiveState(state); } diff --git a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/TDSendingState.java b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/TDSendingState.java index 9798e952..633d3739 100644 --- a/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/TDSendingState.java +++ b/pint/src/main/java/org/dcsa/conformance/standards/eblinterop/models/TDSendingState.java @@ -7,12 +7,10 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.BinaryNode; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.nimbusds.jose.JWSObject; import java.time.Instant; -import java.util.Map; import java.util.Objects; import java.util.UUID; - -import com.nimbusds.jose.JWSObject; import lombok.SneakyThrows; import org.dcsa.conformance.core.state.JsonNodeMap; import org.dcsa.conformance.standards.ebl.crypto.Checksums; @@ -26,21 +24,6 @@ public class TDSendingState { private static final String ENVELOPE_TRANSFER_CHAIN = "envelopeTransferChain"; private static final String ISSUANCE_MANIFEST = "issuanceManifestSignedContent"; - - private static final Map<String, String> PLATFORM2CODELISTNAME = Map.ofEntries( - Map.entry("WAVE", "Wave"), - Map.entry("CARX", "CargoX"), - Map.entry("EDOX", "EdoxOnline"), - Map.entry("IQAX", "IQAX"), - Map.entry("ESSD", "EssDOCS"), - Map.entry("BOLE", "Bolero"), - Map.entry("TRGO", "TradeGO"), - Map.entry("SECR", "Secro")/*, - Map.entry("", "GSBN"), - Map.entry("", "WiseTech") - */ - ); - private final ObjectNode state; private TDSendingState(ObjectNode state) { @@ -127,39 +110,23 @@ public JsonNode getSignedEnvelopeTransferChain() { return state.path(ENVELOPE_TRANSFER_CHAIN); } - - - public static String platform2CodeListName(String platform) { - // The default is not valid, but it only happens with unknown platforms and null would be even worse - return PLATFORM2CODELISTNAME.getOrDefault(platform, platform); - } - - public static ObjectNode generateTransaction(String action, String sendingPlatform, String sendingPartyName, String sendingEPUI, String receivingPlatform, String receivingPartyName, String receivingEPUI, String receivingCodeListName) { + public static ObjectNode generateTransaction(String action, String sendingPlatform, String sendingPartyName, String sendingEPUI, JsonNode receiverParty) { var actor = OBJECT_MAPPER.createObjectNode() .put("eblPlatform", sendingPlatform) .put("partyName", sendingPartyName); - actor.putArray("partyCodes") + actor.putArray("identifyingCodes") .addObject() .put("partyCode", sendingEPUI) - .put("codeListProvider", "EPUI") - .put("codeListName", platform2CodeListName(sendingPlatform)); - var recipient = OBJECT_MAPPER.createObjectNode() - .put("eblPlatform", receivingPlatform) - .put("partyName", receivingPartyName); - recipient.putArray("partyCodes") - .addObject() - .put("partyCode", receivingEPUI) - .put("codeListProvider", "EPUI") - .put("codeListName", receivingCodeListName); + .put("codeListProvider", sendingPlatform); var transaction = OBJECT_MAPPER.createObjectNode() .put("action", action) .put("timestamp", Instant.now().toEpochMilli()); transaction.set("actor", actor); - transaction.set("recipient", recipient); + transaction.set("recipient", receiverParty); return transaction; } - public static String generateTransactionEntry(PayloadSigner payloadSigner, String previousEnvelopeTransferChainEntrySignedContentChecksum, String tdChecksum, String action, String sendingPlatform, String sendingPartyName, String sendingEPUI, String receivingPlatform, String receivingPartyName, String receivingEPUI, String receivingCodeListName) { + public static String generateTransactionEntry(PayloadSigner payloadSigner, String previousEnvelopeTransferChainEntrySignedContentChecksum, String tdChecksum, String action, String sendingPlatform, String sendingPartyName, String sendingEPUI, JsonNode receivingParty) { var latestEnvelopeTransferChainUnsigned = OBJECT_MAPPER.createObjectNode() .put("eblPlatform", sendingPlatform) .put("transportDocumentChecksum", tdChecksum) @@ -172,10 +139,7 @@ public static String generateTransactionEntry(PayloadSigner payloadSigner, Strin sendingPlatform, sendingPartyName, sendingEPUI, - receivingPlatform, - receivingPartyName, - receivingEPUI, - receivingCodeListName + receivingParty )); @@ -197,12 +161,10 @@ public void manipulateLatestTransaction(PayloadSigner payloadSigner, ReceiverSce var lastSigned = chain.path(chain.size() - 1); var last = parseSignedNode(lastSigned); var sendingPlatform = "BOLE"; - var receivingPlatform = rsp.eblPlatform(); + var receivingPlatform = rsp.receiverParty().path("eblPlatform").asText("!?"); var sendingEPUI = "1234"; var sendingPartyName = "DCSA CTK tester"; - var receivingEPUI = rsp.receiverEPUI(); - var receivingPartyName = rsp.receiverPartyName(); - var receiverCodeListName = rsp.receiverEPUICodeListName(); + var receivingParty = rsp.receiverParty(); if (sendingPlatform.equals(receivingPlatform)) { sendingPlatform = "WAVE"; } @@ -211,10 +173,7 @@ public void manipulateLatestTransaction(PayloadSigner payloadSigner, ReceiverSce sendingPlatform, sendingPartyName, sendingEPUI, - sendingPlatform, - receivingPartyName, - receivingEPUI, - receiverCodeListName + receivingParty ); ((ArrayNode)last.path("transactions")).insert(0, newTransactionEntry); 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 08a0cb89..a3767481 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 @@ -102,7 +102,13 @@ private void initiateState(JsonNode actionPrompt) { var expectedRecipient = "12345-jane-doe"; var receivingParameters = getReceiverScenarioParameters(ssp, scenarioClass, expectedRecipient); var tdState = TDReceiveState.newInstance(tdr, ssp.senderPublicKeyPEM(), receivingParameters); - tdState.setExpectedReceiver(expectedRecipient); + tdState.setExpectedReceiver( + generateReceiverParty( + ssp, + scenarioClass == ScenarioClass.INVALID_RECIPIENT ? ScenarioClass.NO_ISSUES : scenarioClass, + expectedRecipient + ) + ); tdState.setScenarioClass(scenarioClass); tdState.save(persistentMap); asyncOrchestratorPostPartyInput( @@ -111,20 +117,29 @@ private void initiateState(JsonNode actionPrompt) { "Finished ScenarioType"); } - private ReceiverScenarioParameters getReceiverScenarioParameters(SenderScenarioParameters ssp, ScenarioClass scenarioClass, String expectedRecipient) { - String platform, codeListName; + private JsonNode generateReceiverParty(SenderScenarioParameters ssp, ScenarioClass scenarioClass, String expectedRecipient) { + String platform; if ("CARX".equals(ssp.eblPlatform())) { platform = "BOLE"; - codeListName = "Bolero"; } else { platform = "CARX"; - codeListName = "CargoX"; } + var partyCode = OBJECT_MAPPER.createObjectNode() + .put("partyCode", scenarioClass == ScenarioClass.INVALID_RECIPIENT ? "12345-invalid" : expectedRecipient) + .put("codeListProvider", platform); + var receiverParty = OBJECT_MAPPER.createObjectNode(); + receiverParty.put("partyName", "Jane Doe") + .put("eblPlatform", platform) + .putArray("identifyingCodes") + .add(partyCode); + return receiverParty; + } + + private ReceiverScenarioParameters getReceiverScenarioParameters(SenderScenarioParameters ssp, ScenarioClass scenarioClass, String expectedRecipient) { + var receiverParty = generateReceiverParty(ssp, scenarioClass, expectedRecipient); + return new ReceiverScenarioParameters( - platform, - "Jane Doe", - scenarioClass == ScenarioClass.INVALID_RECIPIENT ? "12345-invalid" : expectedRecipient, - codeListName, + receiverParty, payloadSigner.getPublicKeyInPemFormat() ); } 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 d25b6a85..690058cd 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 @@ -3,7 +3,6 @@ import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER; import static org.dcsa.conformance.standards.eblinterop.action.SenderTransmissionClass.*; import static org.dcsa.conformance.standards.eblinterop.models.TDSendingState.generateTransactionEntry; -import static org.dcsa.conformance.standards.eblinterop.models.TDSendingState.platform2CodeListName; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.BinaryNode; @@ -282,12 +281,10 @@ private ObjectNode loadTDR(String tdr) { private String generateTransactions(ObjectNode payload, String tdChecksum, SenderTransmissionClass senderTransmissionClass, ReceiverScenarioParameters rsp) { var sendingPlatform = "BOLE"; - var receivingPlatform = rsp.eblPlatform(); + var receivingPlatform = rsp.receiverParty().path("eblPlatform").asText("!?"); var sendingEPUI = "1234"; var sendingPartyName = "DCSA CTK tester"; - var receivingEPUI = rsp.receiverEPUI(); - var receivingPartyName = rsp.receiverPartyName(); - var receiverCodeListName = rsp.receiverEPUICodeListName(); + var receiver = rsp.receiverParty(); if (sendingPlatform.equals(receivingPlatform)) { sendingPlatform = "WAVE"; } @@ -295,7 +292,6 @@ private String generateTransactions(ObjectNode payload, String tdChecksum, Sende var action = "ISSU"; String previousChecksum = null; if (senderTransmissionClass == VALID_TRANSFER) { - var codeListName = platform2CodeListName(sendingPlatform); var transaction = generateTransactionEntry( payloadSigner, null, @@ -304,10 +300,7 @@ private String generateTransactions(ObjectNode payload, String tdChecksum, Sende sendingPlatform, "DCSA CTK issuer", "5432", - sendingPlatform, - sendingPartyName, - sendingEPUI, - codeListName + receiver ); previousChecksum = Checksums.sha256(transaction); transactions.add(transaction); @@ -319,6 +312,13 @@ private String generateTransactions(ObjectNode payload, String tdChecksum, Sende } else { receivingPlatform = "WAVE"; } + receiver = receiver.deepCopy(); + try { + var obj = (ObjectNode)receiver; + obj.put("eblPlatform", receivingPlatform); + } catch (ClassCastException e) { + /* ignore */ + } } var latest = generateTransactionEntry( payloadSigner, @@ -328,10 +328,7 @@ private String generateTransactions(ObjectNode payload, String tdChecksum, Sende sendingPlatform, sendingPartyName, sendingEPUI, - receivingPlatform, - receivingPartyName, - receivingEPUI, - receiverCodeListName + receiver ); transactions.add(latest); return latest;