diff --git a/adoption/src/main/java/org/dcsa/conformance/standards/adoption/action/SupplyScenarioParametersAction.java b/adoption/src/main/java/org/dcsa/conformance/standards/adoption/action/SupplyScenarioParametersAction.java index f072b798..6d5d6169 100644 --- a/adoption/src/main/java/org/dcsa/conformance/standards/adoption/action/SupplyScenarioParametersAction.java +++ b/adoption/src/main/java/org/dcsa/conformance/standards/adoption/action/SupplyScenarioParametersAction.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.Arrays; import java.util.LinkedHashSet; @@ -13,13 +12,12 @@ import lombok.Getter; import org.dcsa.conformance.core.UserFacingException; import org.dcsa.conformance.core.scenario.ConformanceAction; +import org.dcsa.conformance.core.toolkit.JsonToolkit; import org.dcsa.conformance.standards.adoption.party.FilterParameter; import org.dcsa.conformance.standards.adoption.party.SuppliedScenarioParameters; @Getter public class SupplyScenarioParametersAction extends ConformanceAction { - public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - private SuppliedScenarioParameters suppliedScenarioParameters = null; private final LinkedHashSet filterParameters; @@ -86,7 +84,7 @@ public JsonNode getJsonForHumanReadablePrompt() { filterParameter -> switch (filterParameter) { case INTERVAL -> "day"; - case DATE -> LocalDateTime.now().format(DATE_FORMAT); + case DATE -> LocalDateTime.now().format(JsonToolkit.DEFAULT_DATE_FORMAT); }))) .toJson(); } @@ -108,7 +106,7 @@ public void handlePartyInput(JsonNode partyInput) { throw new UserFacingException("Invalid interval supplied: %s".formatted(interval)); } String date = input.required("date").asText(); - DATE_FORMAT.parse(date); + JsonToolkit.DEFAULT_DATE_FORMAT.parse(date); suppliedScenarioParameters = SuppliedScenarioParameters.fromJson(input); } catch (IllegalArgumentException | DateTimeParseException e) { throw new UserFacingException("Invalid input: %s".formatted(e.getMessage())); diff --git a/adoption/src/test/java/org/dcsa/conformance/standards/adoption/action/SupplyScenarioParametersActionTest.java b/adoption/src/test/java/org/dcsa/conformance/standards/adoption/action/SupplyScenarioParametersActionTest.java index 3022c96e..716d9a8c 100644 --- a/adoption/src/test/java/org/dcsa/conformance/standards/adoption/action/SupplyScenarioParametersActionTest.java +++ b/adoption/src/test/java/org/dcsa/conformance/standards/adoption/action/SupplyScenarioParametersActionTest.java @@ -2,7 +2,6 @@ import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER; import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.assertThrows; import com.fasterxml.jackson.databind.JsonNode; import org.dcsa.conformance.core.UserFacingException; diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/Carrier_SupplyScenarioParametersAction.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/Carrier_SupplyScenarioParametersAction.java index 0a4b254b..57b26021 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/Carrier_SupplyScenarioParametersAction.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/Carrier_SupplyScenarioParametersAction.java @@ -4,9 +4,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import java.util.function.Consumer; import java.util.function.Supplier; - import lombok.NonNull; import org.dcsa.conformance.standards.booking.checks.ScenarioType; +import org.dcsa.conformance.standards.booking.party.BookingCarrier; import org.dcsa.conformance.standards.booking.party.CarrierScenarioParameters; public class Carrier_SupplyScenarioParametersAction extends BookingAction { @@ -59,80 +59,7 @@ public String getHumanReadablePrompt() { @Override public JsonNode getJsonForHumanReadablePrompt() { - var csp = switch (scenarioType) { - case REGULAR, REGULAR_SHIPPER_OWNED -> new CarrierScenarioParameters( "SCR-1234-REGULAR", - "Example Carrier Service", - "402E", - "service Name", - "640510", - "Shoes - black, 400 boxes", - null, - null, - "DKAAR", - "DEBRV"); - case REGULAR_2RE1C, REGULAR_2RE2C -> new CarrierScenarioParameters( "SCR-1234-REGULAR-2REC", - "Example Carrier Service", - "402E", - "service Name", - "630260", - "Tableware and kitchenware", - "691010", - "Kitchen pots and pans", - "DKAAR", - "DEBRV"); - case REGULAR_CHO_DEST -> new CarrierScenarioParameters("SCR-1234-REGULAR-CHO-DEST", - "Example Carrier Service", - "402E", - "service Name", - "640510", - "Shoes - black, 400 boxes", - null, - null, - "DKAAR", - "USGBO"); - case REGULAR_CHO_ORIG -> new CarrierScenarioParameters("SCR-1234-REGULAR-CHO-ORIG", - "Example Carrier Service", - "402E", - "service Name", - "640510", - "Shoes - black, 400 boxes", - null, - null, - "DKAAR", - "DKAAR"); - case REGULAR_NON_OPERATING_REEFER -> new CarrierScenarioParameters("SCR-1234-NON-OPERATING-REEFER", - "Example Carrier Service", - "402E", - "service Name", - "220291", - "Non alcoholic beverages", - null, - null, - "DKAAR", - "DEBRV"); - case REEFER, REEFER_TEMP_CHANGE -> new CarrierScenarioParameters( "SCR-1234-REEFER", - "Example Carrier Service", - "402E", - "service Name", - "04052090", - "Dairy products", - null, - null, - "DKAAR", - "DEBRV"); - case DG -> new CarrierScenarioParameters("SCR-1234-DG", - "Example Carrier Service", - "403W", - "TA1", - "293499", - "Environmentally hazardous substance, liquid, N.O.S (Propiconazole)", - null, - null, - "DKAAR", - "DEBRV"); - }; - - return csp.toJson(); + return BookingCarrier.getCarrierScenarioParameters(scenarioType).toJson(); } @Override diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC10_Carrier_DeclineBookingAction.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC10_Carrier_DeclineBookingAction.java index 5544267d..ca33ce99 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC10_Carrier_DeclineBookingAction.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC10_Carrier_DeclineBookingAction.java @@ -47,7 +47,6 @@ public ConformanceCheck createCheck(String expectedApiVersion) { return new ConformanceCheck(getActionTitle()) { @Override protected Stream createSubChecks() { - var dsp = getDspSupplier().get(); return Stream.of( new UrlPathCheck( BookingRole::isCarrier, getMatchedExchangeUuid(), "/v2/booking-notifications"), diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC11_Shipper_CancelBookingRequestAction.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC11_Shipper_CancelBookingRequestAction.java index f30818c1..4416ba5e 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC11_Shipper_CancelBookingRequestAction.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC11_Shipper_CancelBookingRequestAction.java @@ -1,12 +1,10 @@ package org.dcsa.conformance.standards.booking.action; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; 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.booking.checks.CarrierBookingRefStatusPayloadResponseConformanceCheck; import org.dcsa.conformance.standards.booking.party.BookingRole; import org.dcsa.conformance.standards.booking.party.BookingState; diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC13ShipperCancelConfirmedBookingAction.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC13ShipperCancelConfirmedBookingAction.java index aecdc57b..850a8d68 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC13ShipperCancelConfirmedBookingAction.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC13ShipperCancelConfirmedBookingAction.java @@ -7,13 +7,11 @@ import org.dcsa.conformance.core.check.*; import org.dcsa.conformance.core.traffic.ConformanceExchange; import org.dcsa.conformance.core.traffic.HttpMessageType; -import org.dcsa.conformance.standards.booking.checks.CarrierBookingRefStatusPayloadResponseConformanceCheck; import org.dcsa.conformance.standards.booking.party.BookingCancellationState; import org.dcsa.conformance.standards.booking.party.BookingRole; import org.dcsa.conformance.standards.booking.party.BookingState; import org.dcsa.conformance.standards.booking.party.DynamicScenarioParameters; -import java.util.Objects; import java.util.stream.Stream; @Getter diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC1_Shipper_SubmitBookingRequestAction.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC1_Shipper_SubmitBookingRequestAction.java index d067a32b..6e90fe12 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC1_Shipper_SubmitBookingRequestAction.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC1_Shipper_SubmitBookingRequestAction.java @@ -9,7 +9,6 @@ import org.dcsa.conformance.core.traffic.ConformanceExchange; import org.dcsa.conformance.core.traffic.HttpMessageType; import org.dcsa.conformance.standards.booking.checks.BookingChecks; -import org.dcsa.conformance.standards.booking.checks.CarrierBookingRefStatusPayloadResponseConformanceCheck; import org.dcsa.conformance.standards.booking.party.BookingRole; import org.dcsa.conformance.standards.booking.party.BookingState; import org.dcsa.conformance.standards.booking.party.DynamicScenarioParameters; diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC7_Shipper_SubmitBookingAmendment.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC7_Shipper_SubmitBookingAmendment.java index b02b91d0..6c046a39 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC7_Shipper_SubmitBookingAmendment.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC7_Shipper_SubmitBookingAmendment.java @@ -1,19 +1,16 @@ package org.dcsa.conformance.standards.booking.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.ConformanceExchange; import org.dcsa.conformance.core.traffic.HttpMessageType; -import org.dcsa.conformance.standards.booking.checks.BookingChecks; -import org.dcsa.conformance.standards.booking.checks.CarrierBookingRefStatusPayloadResponseConformanceCheck; import org.dcsa.conformance.standards.booking.party.BookingRole; import org.dcsa.conformance.standards.booking.party.BookingState; import org.dcsa.conformance.standards.booking.party.DynamicScenarioParameters; -import java.util.stream.Stream; - @Getter @Slf4j public class UC7_Shipper_SubmitBookingAmendment extends StateChangingBookingAction { diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC9_Shipper_CancelBookingAmendment.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC9_Shipper_CancelBookingAmendment.java index 187eb1ae..bf4fbb32 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC9_Shipper_CancelBookingAmendment.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/action/UC9_Shipper_CancelBookingAmendment.java @@ -5,7 +5,6 @@ import lombok.extern.slf4j.Slf4j; import org.dcsa.conformance.core.check.*; import org.dcsa.conformance.core.traffic.HttpMessageType; -import org.dcsa.conformance.standards.booking.checks.CarrierBookingRefStatusPayloadResponseConformanceCheck; import org.dcsa.conformance.standards.booking.party.BookingRole; import org.dcsa.conformance.standards.booking.party.BookingState; diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/checks/PayloadContentConformanceCheck.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/checks/PayloadContentConformanceCheck.java index 10be968f..0f6e210d 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/checks/PayloadContentConformanceCheck.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/checks/PayloadContentConformanceCheck.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; import org.dcsa.conformance.core.check.ActionCheck; import org.dcsa.conformance.core.check.ConformanceCheck; import org.dcsa.conformance.core.traffic.ConformanceExchange; diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/party/BookingCarrier.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/party/BookingCarrier.java index bffe7205..13e15fe5 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/party/BookingCarrier.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/party/BookingCarrier.java @@ -27,8 +27,12 @@ @Slf4j public class BookingCarrier extends ConformanceParty { private static final Random RANDOM = new Random(); - private final Map cbrrToCbr = new HashMap<>(); - private final Map cbrToCbrr = new HashMap<>(); + private static final String EXAMPLE_CARRIER_SERVICE = "Example Carrier Service"; + private static final String MESSAGE = "message"; + private static final String DKAAR = "DKAAR"; + private static final String DEBRV = "DEBRV"; + private static final String CARRIER_SERVICE = "Carrier Service %d"; + private static final String BOOKING_STATUS = "bookingStatus"; private static final String REASON_INFO = "Declined as required by the conformance scenario"; private static final String CANCEL_AMENDMENT_OPERATION = "cancelAmendment"; private static final String CANCEL_BOOKING_OPERATION = "cancelBooking"; @@ -37,6 +41,9 @@ public class BookingCarrier extends ConformanceParty { private static final String CARRIER_BOOKING_REFERENCE = "carrierBookingReference"; private static final String BOOKING_CANCELLATION_STATUS = "bookingCancellationStatus"; + private final Map cbrrToCbr = new HashMap<>(); + private final Map cbrToCbrr = new HashMap<>(); + public BookingCarrier( String apiVersion, @@ -94,84 +101,102 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { if (log.isInfoEnabled()) log.info("Carrier.supplyScenarioParameters({})", actionPrompt.toPrettyString()); var scenarioType = ScenarioType.valueOf(actionPrompt.required("scenarioType").asText()); - CarrierScenarioParameters carrierScenarioParameters = switch (scenarioType) { - case REGULAR, REGULAR_SHIPPER_OWNED -> new CarrierScenarioParameters("SCR-1234-REGULAR", - "Example Carrier Service", - "402E", - "Carrier Service %d".formatted(RANDOM.nextInt(999999)), - "640510", - "Shoes - black, 400 boxes", - null, - null, - "DKAAR", - "DEBRV"); - case REGULAR_2RE1C, REGULAR_2RE2C -> new CarrierScenarioParameters("SCR-1234-REGULAR-2REC", - "Example Carrier Service", - "402E", - "Carrier Service %d".formatted(RANDOM.nextInt(999999)), - "630260", - "Tableware and kitchenware", - "691010", - "Kitchen pots and pans", - "DKAAR", - "DEBRV"); - case REGULAR_CHO_DEST -> new CarrierScenarioParameters("SCR-1234-REGULAR-CHO-DEST", - "Example Carrier Service", - "402E", - "Carrier Service %d".formatted(RANDOM.nextInt(999999)), - "640510", - "Shoes - black, 400 boxes", - null, - null, - "DKAAR", - "USGBO"); - case REGULAR_CHO_ORIG -> new CarrierScenarioParameters("SCR-1234-REGULAR-CHO-ORIG", - "Example Carrier Service", - "402E", - "Carrier Service %d".formatted(RANDOM.nextInt(999999)), - "640510", - "Shoes - black, 400 boxes", - null, - null, - "DKAAR", - "DKAAR"); - case REGULAR_NON_OPERATING_REEFER -> new CarrierScenarioParameters("SCR-1234-NON-OPERATING-REEFER", - "Example Carrier Service", - "402E", - "Carrier Service %d".formatted(RANDOM.nextInt(999999)), - "220291", - "Non alcoholic beverages", - null, - null, - "DKAAR", - "DEBRV"); - case REEFER, REEFER_TEMP_CHANGE -> new CarrierScenarioParameters("SCR-1234-REEFER", - "Example Carrier Service", - "402E", - "Carrier Service %d".formatted(RANDOM.nextInt(999999)), - "04052090", - "Dairy products", - null, - null, - "DKAAR", - "DEBRV"); - case DG -> new CarrierScenarioParameters("SCR-1234-DG", - "Example Carrier Service", - "403W", - "TA1", - "293499", - "Environmentally hazardous substance, liquid, N.O.S (Propiconazole)", - null, - null, - "DKAAR", - "DEBRV"); - }; - + CarrierScenarioParameters carrierScenarioParameters = getCarrierScenarioParameters(scenarioType); asyncOrchestratorPostPartyInput( actionPrompt.get("actionId").asText(), carrierScenarioParameters.toJson()); addOperatorLogEntry( "Provided CarrierScenarioParameters: %s".formatted(carrierScenarioParameters)); } + + public static CarrierScenarioParameters getCarrierScenarioParameters(ScenarioType scenarioType) { + return switch (scenarioType) { + case REGULAR, REGULAR_SHIPPER_OWNED -> + new CarrierScenarioParameters( + "SCR-1234-REGULAR", + EXAMPLE_CARRIER_SERVICE, + "402E", + CARRIER_SERVICE.formatted(RANDOM.nextInt(999999)), + "640510", + "Shoes - black, 400 boxes", + null, + null, + DKAAR, + DEBRV); + case REGULAR_2RE1C, REGULAR_2RE2C -> + new CarrierScenarioParameters( + "SCR-1234-REGULAR-2REC", + EXAMPLE_CARRIER_SERVICE, + "402E", + CARRIER_SERVICE.formatted(RANDOM.nextInt(999999)), + "630260", + "Tableware and kitchenware", + "691010", + "Kitchen pots and pans", + DKAAR, + DEBRV); + case REGULAR_CHO_DEST -> + new CarrierScenarioParameters( + "SCR-1234-REGULAR-CHO-DEST", + EXAMPLE_CARRIER_SERVICE, + "402E", + CARRIER_SERVICE.formatted(RANDOM.nextInt(999999)), + "640510", + "Shoes - black, 400 boxes", + null, + null, + DKAAR, + "USGBO"); + case REGULAR_CHO_ORIG -> + new CarrierScenarioParameters( + "SCR-1234-REGULAR-CHO-ORIG", + EXAMPLE_CARRIER_SERVICE, + "402E", + CARRIER_SERVICE.formatted(RANDOM.nextInt(999999)), + "640510", + "Shoes - black, 400 boxes", + null, + null, + DKAAR, + DKAAR); + case REGULAR_NON_OPERATING_REEFER -> + new CarrierScenarioParameters( + "SCR-1234-NON-OPERATING-REEFER", + EXAMPLE_CARRIER_SERVICE, + "402E", + CARRIER_SERVICE.formatted(RANDOM.nextInt(999999)), + "220291", + "Non alcoholic beverages", + null, + null, + DKAAR, + DEBRV); + case REEFER, REEFER_TEMP_CHANGE -> + new CarrierScenarioParameters( + "SCR-1234-REEFER", + EXAMPLE_CARRIER_SERVICE, + "402E", + CARRIER_SERVICE.formatted(RANDOM.nextInt(999999)), + "04052090", + "Dairy products", + null, + null, + DKAAR, + DEBRV); + case DG -> + new CarrierScenarioParameters( + "SCR-1234-DG", + EXAMPLE_CARRIER_SERVICE, + "403W", + "TA1", + "293499", + "Environmentally hazardous substance, liquid, N.O.S (Propiconazole)", + null, + null, + DKAAR, + DEBRV); + }; + } + private void processBookingAmendment(JsonNode actionPrompt) { log.info("Carrier.processBookingAmendment(%s)".formatted(actionPrompt.toPrettyString())); @@ -226,7 +251,7 @@ private void confirmBookingRequest(JsonNode actionPrompt) { var persistableCarrierBooking = PersistableCarrierBooking.fromPersistentStore(persistentMap, cbrr); - var bookingStatus = persistableCarrierBooking.getBooking().get("bookingStatus").asText(); + var bookingStatus = persistableCarrierBooking.getBooking().get(BOOKING_STATUS).asText(); if (bookingStatus.equals(BookingState.CONFIRMED.name())) { persistableCarrierBooking .getBooking() @@ -283,7 +308,7 @@ private void requestUpdateToBookingRequest(JsonNode actionPrompt) { .put("severity", "ERROR") .put("code", "PROPERTY_VALUE_MUST_CHANGE") .put( - "message", + MESSAGE, "Please perform the changes requested by the Conformance orchestrator"); String cbr = actionPrompt.path("cbr").asText(null); String cbrr = actionPrompt.required("cbrr").asText(); @@ -327,7 +352,7 @@ private void requestToAmendConfirmedBooking(JsonNode actionPrompt) { .put("severity", "ERROR") .put("code", "PROPERTY_VALUE_MUST_CHANGE") .put( - "message", + MESSAGE, "Please perform the changes requested by the Conformance orchestrator"); var persistableCarrierBooking = @@ -380,14 +405,14 @@ private ConformanceResponse return405(ConformanceRequest request, String... allo new ConformanceMessageBody( OBJECT_MAPPER .createObjectNode() - .put("message", "Returning 405 because the method was not supported"))); + .put(MESSAGE, "Returning 405 because the method was not supported"))); } private ConformanceResponse return400(ConformanceRequest request, String message) { return request.createResponse( 400, Map.of(API_VERSION, List.of(apiVersion)), - new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put("message", message))); + new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put(MESSAGE, message))); } private ConformanceResponse return404(ConformanceRequest request) { @@ -398,14 +423,14 @@ private ConformanceResponse return404(ConformanceRequest request, String message return request.createResponse( 404, Map.of(API_VERSION, List.of(apiVersion)), - new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put("message", message))); + new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put(MESSAGE, message))); } private ConformanceResponse return409(ConformanceRequest request, String message) { return request.createResponse( 409, Map.of(API_VERSION, List.of(apiVersion)), - new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put("message", message))); + new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put(MESSAGE, message))); } @Override @@ -443,10 +468,10 @@ private String readCancelOperation(ConformanceRequest request) { } var cancelJsonBody = requestPayload.body().getJsonBody(); - if (cancelJsonBody.get("bookingStatus") != null && cancelJsonBody.get("amendedBookingStatus") != null) { + if (cancelJsonBody.get(BOOKING_STATUS) != null && cancelJsonBody.get("amendedBookingStatus") != null) { return "#INVALID"; } - if (cancelJsonBody.get("bookingStatus") != null) { + if (cancelJsonBody.get(BOOKING_STATUS) != null) { return CANCEL_BOOKING_OPERATION; } if(cancelJsonBody.get("amendedBookingStatus") != null ) { @@ -554,7 +579,7 @@ private ConformanceResponse _handlePatchBookingRequest(ConformanceRequest reques private ConformanceResponse returnBookingCBRRResponse(ConformanceRequest request, ObjectNode booking, String bookingReference) { var cbrr = booking.get(CARRIER_BOOKING_REQUEST_REFERENCE).asText(); - var bookingStatus = booking.get("bookingStatus").asText(); + var bookingStatus = booking.get(BOOKING_STATUS).asText(); var statusObject = OBJECT_MAPPER .createObjectNode() @@ -575,7 +600,7 @@ private ConformanceResponse returnBookingCBRRResponse(ConformanceRequest request } private ConformanceResponse returnEmpty202Response(ConformanceRequest request, ObjectNode booking, String bookingReference) { - var bookingStatus = booking.get("bookingStatus").asText(); + var bookingStatus = booking.get(BOOKING_STATUS).asText(); ConformanceResponse response = request.createResponse( 202, @@ -704,7 +729,7 @@ public ObjectNode asJsonNode() { setBookingProvidedField( data, CARRIER_BOOKING_REFERENCE, carrierBookingReference); } - setBookingProvidedField(data, "bookingStatus", bookingStatus); + setBookingProvidedField(data, BOOKING_STATUS, bookingStatus); setBookingProvidedField(data, "amendedBookingStatus", amendedBookingStatus); setBookingProvidedField(data, BOOKING_CANCELLATION_STATUS, bookingCancellationStatus); setBookingProvidedField(data, "reason", reason); diff --git a/commercial-schedules/src/main/java/org/dcsa/conformance/standards/cs/action/SupplyScenarioParametersAction.java b/commercial-schedules/src/main/java/org/dcsa/conformance/standards/cs/action/SupplyScenarioParametersAction.java index b5a8daec..1b27be0d 100644 --- a/commercial-schedules/src/main/java/org/dcsa/conformance/standards/cs/action/SupplyScenarioParametersAction.java +++ b/commercial-schedules/src/main/java/org/dcsa/conformance/standards/cs/action/SupplyScenarioParametersAction.java @@ -7,7 +7,7 @@ import java.util.LinkedHashSet; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; + import lombok.Getter; import org.dcsa.conformance.standards.cs.model.CsDateUtils; import org.dcsa.conformance.standards.cs.party.CsFilterParameter; diff --git a/commercial-schedules/src/main/java/org/dcsa/conformance/standards/cs/model/CsDateUtils.java b/commercial-schedules/src/main/java/org/dcsa/conformance/standards/cs/model/CsDateUtils.java index 0ac6d808..ac34d94d 100644 --- a/commercial-schedules/src/main/java/org/dcsa/conformance/standards/cs/model/CsDateUtils.java +++ b/commercial-schedules/src/main/java/org/dcsa/conformance/standards/cs/model/CsDateUtils.java @@ -1,5 +1,8 @@ package org.dcsa.conformance.standards.cs.model; +import lombok.NoArgsConstructor; +import org.dcsa.conformance.core.toolkit.JsonToolkit; + import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; @@ -7,18 +10,18 @@ import java.time.format.DateTimeFormatter; import java.util.*; +@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) public class CsDateUtils { public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX"); - public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); public static String getEndDateAfter3Months() { LocalDate futureDate = LocalDate.now().plusMonths(3); - return futureDate.format(DATE_FORMAT); + return futureDate.format(JsonToolkit.DEFAULT_DATE_FORMAT); } public static String getCurrentDate() { - return LocalDate.now().format(DATE_FORMAT); + return LocalDate.now().format(JsonToolkit.DEFAULT_DATE_FORMAT); } public static void handleArrivalAndDepartureDates( @@ -95,9 +98,9 @@ private static String getDepartureDateTime(String departureStartDate, String dep private static String processDate(String startDate, String endDate, String type) { return switch (type) { case "startDate", "range", "date" -> - convertDateToDateTime(LocalDate.parse(startDate, CsDateUtils.DATE_FORMAT).plusDays(1)); + convertDateToDateTime(LocalDate.parse(startDate, JsonToolkit.DEFAULT_DATE_FORMAT).plusDays(1)); case "endDate" -> - convertDateToDateTime(LocalDate.parse(endDate, CsDateUtils.DATE_FORMAT).minusDays(1)); + convertDateToDateTime(LocalDate.parse(endDate, JsonToolkit.DEFAULT_DATE_FORMAT).minusDays(1)); default -> ""; }; } @@ -105,7 +108,6 @@ private static String processDate(String startDate, String endDate, String type) private static String convertDateToDateTime(LocalDate date) { LocalDateTime dateTime = date.atStartOfDay(); ZonedDateTime zonedDateTime = dateTime.atZone(ZoneId.systemDefault()); - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX"); - return zonedDateTime.format(dateTimeFormatter); + return zonedDateTime.format(CsDateUtils.DATE_TIME_FORMATTER); } } diff --git a/core/src/main/java/org/dcsa/conformance/core/check/ConformanceResult.java b/core/src/main/java/org/dcsa/conformance/core/check/ConformanceResult.java index a50ee7cc..c37bfc2e 100644 --- a/core/src/main/java/org/dcsa/conformance/core/check/ConformanceResult.java +++ b/core/src/main/java/org/dcsa/conformance/core/check/ConformanceResult.java @@ -1,10 +1,9 @@ package org.dcsa.conformance.core.check; +import java.util.*; import lombok.Getter; import org.dcsa.conformance.core.traffic.ConformanceExchange; -import java.util.*; - @Getter public class ConformanceResult { private final String checkedPartyName; @@ -12,17 +11,6 @@ public class ConformanceResult { private final boolean conformant; private final Set errors; - private ConformanceResult( - String checkedPartyName, - LinkedList checkedExchanges, - boolean conformant, - Set errors) { - this.checkedPartyName = checkedPartyName; - this.checkedExchanges = checkedExchanges; - this.conformant = conformant; - this.errors = Collections.unmodifiableSet(errors); - } - private ConformanceResult( String checkedPartyName, ConformanceExchange checkedExchange, @@ -34,16 +22,6 @@ private ConformanceResult( this.errors = Collections.unmodifiableSet(errors); } - public static ConformanceResult forSourceParty(ConformanceExchange exchange, boolean conformant) { - return new ConformanceResult( - exchange.getRequest().message().sourcePartyName(), exchange, conformant, Collections.emptySet()); - } - - public static ConformanceResult forTargetParty(ConformanceExchange exchange, boolean conformant) { - return new ConformanceResult( - exchange.getRequest().message().targetPartyName(), exchange, conformant, Collections.emptySet()); - } - public static ConformanceResult forSourceParty(ConformanceExchange exchange, Set errors) { return new ConformanceResult( exchange.getRequest().message().sourcePartyName(), exchange, errors.isEmpty(), errors); @@ -54,39 +32,4 @@ public static ConformanceResult forTargetParty(ConformanceExchange exchange, Set exchange.getRequest().message().targetPartyName(), exchange, errors.isEmpty(), errors); } - public static ConformanceResult forSourceParty( - LinkedList exchanges, boolean conformant) { - return new ConformanceResult( - Objects.requireNonNull(exchanges.peekLast()).getRequest().message().sourcePartyName(), - exchanges, - conformant, - Collections.emptySet()); - } - - public static ConformanceResult forTargetParty( - LinkedList exchanges, boolean conformant) { - return new ConformanceResult( - Objects.requireNonNull(exchanges.peekLast()).getRequest().message().targetPartyName(), - exchanges, - conformant, - Collections.emptySet()); - } - - public static ConformanceResult forSourceParty( - LinkedList exchanges, Set errors) { - return new ConformanceResult( - Objects.requireNonNull(exchanges.peekLast()).getRequest().message().sourcePartyName(), - exchanges, - errors.isEmpty(), - errors); - } - - public static ConformanceResult forTargetParty( - LinkedList exchanges, Set errors) { - return new ConformanceResult( - Objects.requireNonNull(exchanges.peekLast()).getRequest().message().targetPartyName(), - exchanges, - errors.isEmpty(), - errors); - } } diff --git a/core/src/main/java/org/dcsa/conformance/core/check/JsonAttribute.java b/core/src/main/java/org/dcsa/conformance/core/check/JsonAttribute.java index 5d3aac69..4ca9e54c 100644 --- a/core/src/main/java/org/dcsa/conformance/core/check/JsonAttribute.java +++ b/core/src/main/java/org/dcsa/conformance/core/check/JsonAttribute.java @@ -11,6 +11,7 @@ public class JsonAttribute { private static final BiFunction> EMPTY_VALIDATOR = (ignoredA, ignoredB) -> Set.of(); + public static final String VALUE_WARNING = "The value of '%s' was '%s' instead of '%s'"; public static ActionCheck contentChecks( Predicate isRelevantForRoleName, @@ -19,19 +20,7 @@ public static ActionCheck contentChecks( String standardsVersion, JsonContentCheck ... checks ) { - return contentChecks("", isRelevantForRoleName, matchedExchangeUuid, httpMessageType, standardsVersion, Arrays.asList(checks)); - } - - @Deprecated - public static ActionCheck contentChecks( - String titlePrefix, - Predicate isRelevantForRoleName, - UUID matchedExchangeUuid, - HttpMessageType httpMessageType, - String standardsVersion, - JsonContentCheck ... checks - ) { - return contentChecks(titlePrefix, isRelevantForRoleName, matchedExchangeUuid, httpMessageType, standardsVersion, Arrays.asList(checks)); + return contentChecks("", null, isRelevantForRoleName, matchedExchangeUuid, httpMessageType, standardsVersion, Arrays.asList(checks)); } public static ActionCheck contentChecks( @@ -46,7 +35,6 @@ public static ActionCheck contentChecks( return contentChecks(titlePrefix, title, isRelevantForRoleName, matchedExchangeUuid, httpMessageType, standardsVersion, Arrays.asList(checks)); } - public static ActionCheck contentChecks( Predicate isRelevantForRoleName, UUID matchedExchangeUuid, @@ -54,27 +42,7 @@ public static ActionCheck contentChecks( String standardsVersion, List checks ) { - return contentChecks("", isRelevantForRoleName, matchedExchangeUuid, httpMessageType, standardsVersion, checks); - } - - public static ActionCheck contentChecks( - String titlePrefix, - Predicate isRelevantForRoleName, - UUID matchedExchangeUuid, - HttpMessageType httpMessageType, - String standardVersion, - List checks - ) { - return contentChecks( - titlePrefix, - "The HTTP %s has valid content (conditional validation rules)" - .formatted(httpMessageType.name().toLowerCase()), - isRelevantForRoleName, - matchedExchangeUuid, - httpMessageType, - standardVersion, - checks - ); + return contentChecks("", null, isRelevantForRoleName, matchedExchangeUuid, httpMessageType, standardsVersion, checks); } public static ActionCheck contentChecks( @@ -86,6 +54,10 @@ public static ActionCheck contentChecks( String standardsVersion, List checks ) { + if (title == null) { + title = "The HTTP %s has valid content (conditional validation rules)" + .formatted(httpMessageType.name().toLowerCase()); + } return new JsonAttributeBasedCheck( titlePrefix, title, @@ -396,7 +368,7 @@ public static JsonRebaseableContentCheck mustEqual( var actualValue = node.asText(null); if (!Objects.equals(expectedValue, actualValue)) { return Set.of( - "The value of '%s' was '%s' instead of '%s'" + VALUE_WARNING .formatted( renderJsonPointer(jsonPointer, contextPath), renderValue(node), @@ -417,7 +389,7 @@ public static JsonRebaseableContentCheck mustEqual( var node = body.at(jsonPointer); if (!node.isBoolean() || node.asBoolean() != expectedValue) { return Set.of( - "The value of '%s' was '%s' instead of '%s'" + VALUE_WARNING .formatted( renderJsonPointer(jsonPointer, contextPath), renderValue(node), @@ -462,7 +434,7 @@ public static JsonRebaseableContentCheck mustEqual( } if (!Objects.equals(expectedValue, actualValue)) { return Set.of( - "The value of '%s' was '%s' instead of '%s'" + VALUE_WARNING .formatted(renderJsonPointer(jsonPointer, contextPath), renderValue(node), renderValue(expectedValue))); } return Collections.emptySet(); @@ -495,7 +467,7 @@ public static JsonRebaseableContentCheck mustEqual( } if (!Objects.equals(expectedValue, actualValue)) { return Set.of( - "The value of '%s' was '%s' instead of '%s'" + VALUE_WARNING .formatted(nodePath, renderValue(node), renderValue(expectedValue))); } return Collections.emptySet(); @@ -525,7 +497,7 @@ public static JsonContentMatchedValidation matchedMustEqual(Supplier exp } if (!Objects.equals(expectedValue, actualValue)) { return Set.of( - "The value of '%s' was '%s' instead of '%s'" + VALUE_WARNING .formatted(contextPath, renderValue(nodeToValidate), renderValue(expectedValue))); } return Collections.emptySet(); @@ -822,7 +794,7 @@ public static JsonRebaseableContentCheck ifThenElse( @NonNull JsonRebaseableContentCheck elseCheck ) { - return ifThenElse(name, when, (BiFunction>) then::validate, elseCheck::validate); + return ifThenElse(name, when, then::validate, elseCheck::validate); } public static JsonContentMatchedValidation ifMatchedThen( @@ -870,18 +842,9 @@ public static JsonRebaseableContentCheck customValidator( } private static Function at(JsonPointer jsonPointer) { - return (refNode) -> refNode.at(jsonPointer); - } - - private static Function> at(JsonPointer jsonPointer, Function> validator) { - return at(jsonPointer).andThen(validator); - } - - private static Function> atMatched(JsonPointer jsonPointer, JsonContentMatchedValidation validator) { - return (refNode) -> validator.validate(refNode.at(jsonPointer), renderJsonPointer(jsonPointer)); + return refNode -> refNode.at(jsonPointer); } - static String renderValue(JsonNode node) { if (node == null || node.isMissingNode()) { return "(absent)"; @@ -978,9 +941,5 @@ private static JsonContentCheck of(String description, Function loadCsvDataset(resourceName, SelectColumn.withName(columnName))); } - static KeywordDataset fromCSVCombiningColumns(String resourceName, String delimiter, String ... columnNames) { - checkResource(resourceName); - return KeywordDataset.lazyLoaded(() -> loadCsvDataset(resourceName, new CombineColumnSelector(delimiter, columnNames))); - } - - static KeywordDataset fromVersionedCSV(String nameTemplate) { - return VersionedKeywordDataset.of(nameTemplate, SELECT_FIRST_COLUMN); - } - - static KeywordDataset fromVersionedCSV(String nameTemplate, String columnName) { + static KeywordDataset fromVersionedCSV(Class resourceClass, String nameTemplate, String columnName) { return VersionedKeywordDataset.of(nameTemplate, SelectColumn.withName(columnName)); } - static KeywordDataset fromVersionedCSV(String nameTemplate, String delimiter, String ... columnNames) { + static KeywordDataset fromVersionedCSV(Class resourceClass, String nameTemplate, String delimiter, String ... columnNames) { return VersionedKeywordDataset.of(nameTemplate, new CombineColumnSelector(delimiter, columnNames)); } } diff --git a/core/src/main/java/org/dcsa/conformance/core/check/LostAttributeCheck.java b/core/src/main/java/org/dcsa/conformance/core/check/LostAttributeCheck.java index 1955ea23..2774fd3f 100644 --- a/core/src/main/java/org/dcsa/conformance/core/check/LostAttributeCheck.java +++ b/core/src/main/java/org/dcsa/conformance/core/check/LostAttributeCheck.java @@ -51,23 +51,21 @@ private void checkNode(JsonNode leftNode, JsonNode rightNode, String contextPath @Override public Set validate(JsonNode nodeToValidate, String contextPath) { - var left = baseNode.get(); + var left = baseNode.get(); var right = nodeToValidate; if (left == null) { return Set.of(); } - var normalizer = this.normalizer; if (normalizer != null) { left = left.deepCopy(); right = right.deepCopy(); - this.normalizer.accept(left, right); + normalizer.accept(left, right); } var issues = new LinkedHashSet(); this.checkNode(left, right, contextPath, issues); return issues; } - @Override public String description() { return this.description; diff --git a/core/src/main/java/org/dcsa/conformance/core/check/VersionedStaticKeywordSet.java b/core/src/main/java/org/dcsa/conformance/core/check/VersionedStaticKeywordSet.java index 540145c8..89c3b52a 100644 --- a/core/src/main/java/org/dcsa/conformance/core/check/VersionedStaticKeywordSet.java +++ b/core/src/main/java/org/dcsa/conformance/core/check/VersionedStaticKeywordSet.java @@ -8,13 +8,6 @@ public interface VersionedStaticKeywordSet { Set keywordsFor(String standardsVersion); - static VersionedStaticKeywordSet versionedKeywords( - Predicate versionGuard, - Set thenKeywords - ) { - return versionedKeywords(versionGuard, thenKeywords, Set.of()); - } - static VersionedStaticKeywordSet versionedKeywords( Predicate versionGuard, Set thenKeywords, diff --git a/core/src/main/java/org/dcsa/conformance/core/party/CounterpartConfiguration.java b/core/src/main/java/org/dcsa/conformance/core/party/CounterpartConfiguration.java index c164c911..20fd1345 100644 --- a/core/src/main/java/org/dcsa/conformance/core/party/CounterpartConfiguration.java +++ b/core/src/main/java/org/dcsa/conformance/core/party/CounterpartConfiguration.java @@ -2,7 +2,6 @@ import java.net.URI; import java.net.URISyntaxException; -import java.util.List; import java.util.stream.Stream; import lombok.Getter; diff --git a/core/src/main/java/org/dcsa/conformance/core/scenario/ScenarioListBuilder.java b/core/src/main/java/org/dcsa/conformance/core/scenario/ScenarioListBuilder.java index 3ffd9227..e2807add 100644 --- a/core/src/main/java/org/dcsa/conformance/core/scenario/ScenarioListBuilder.java +++ b/core/src/main/java/org/dcsa/conformance/core/scenario/ScenarioListBuilder.java @@ -24,13 +24,9 @@ protected T thisAsT() { } public List buildScenarioList(long moduleIndex) { - return _buildScenarioList(moduleIndex); - } - - protected List _buildScenarioList(long moduleIndex) { AtomicInteger nextScenarioIndex = new AtomicInteger(); return parent != null - ? parent._buildScenarioList(moduleIndex) + ? parent.buildScenarioList(moduleIndex) : asBuilderListList().stream() .map( builderList -> { diff --git a/core/src/main/java/org/dcsa/conformance/core/toolkit/JsonToolkit.java b/core/src/main/java/org/dcsa/conformance/core/toolkit/JsonToolkit.java index 680f7bf4..537d861a 100644 --- a/core/src/main/java/org/dcsa/conformance/core/toolkit/JsonToolkit.java +++ b/core/src/main/java/org/dcsa/conformance/core/toolkit/JsonToolkit.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.StreamSupport; @@ -16,6 +17,7 @@ public class JsonToolkit { public static final String JSON_UTF_8 = "application/json"; public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + public static final DateTimeFormatter DEFAULT_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @SneakyThrows public static JsonNode stringToJsonNode(String string) { 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 d36749b1..b20f7103 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 @@ -4,11 +4,10 @@ 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 com.fasterxml.jackson.core.JsonPointer; import java.util.Set; import java.util.UUID; import java.util.function.Supplier; - -import com.fasterxml.jackson.core.JsonPointer; import org.dcsa.conformance.core.check.*; import org.dcsa.conformance.core.traffic.HttpMessageType; import org.dcsa.conformance.standards.ebl.checks.SignatureChecks; @@ -51,6 +50,7 @@ private static JsonRebaseableContentCheck hasEndorseeScenarioCheck(String standa public static ActionCheck tdScenarioChecks(UUID matched, String standardsVersion, EblType eblType) { return JsonAttribute.contentChecks( "Complex validations of transport document", + null, EblIssuanceRole::isCarrier, matched, HttpMessageType.REQUEST, diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/action/Carrier_SupplyScenarioParametersAction.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/action/Carrier_SupplyScenarioParametersAction.java index 7042f332..89b23fc1 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/action/Carrier_SupplyScenarioParametersAction.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/action/Carrier_SupplyScenarioParametersAction.java @@ -9,6 +9,8 @@ import org.dcsa.conformance.standards.ebl.party.CarrierScenarioParameters; public class Carrier_SupplyScenarioParametersAction extends EblAction { + public static final String DKAAR = "DKAAR"; + public static final String BOOKING_REFERENCE = "Booking Reference"; private CarrierScenarioParameters carrierScenarioParameters = null; private ScenarioType scenarioType; @@ -64,13 +66,13 @@ public String getHumanReadablePrompt() { public JsonNode getJsonForHumanReadablePrompt() { var csp = switch (scenarioType) { case REGULAR_SWB, REGULAR_STRAIGHT_BL, REGULAR_SWB_AMF, REGULAR_CLAD, REGULAR_NEGOTIABLE_BL -> new CarrierScenarioParameters( - "Booking Reference", + BOOKING_REFERENCE, "Commodity subreference for regular (non-DG, non-reefer) cargo", null, // Any valid regular equipment reference will do as an example. "NARU3472484", null, - "DKAAR", + DKAAR, "640510", null, "Shoes - black, 400 boxes", @@ -78,13 +80,13 @@ public JsonNode getJsonForHumanReadablePrompt() { "Fibreboard boxes" ); case REGULAR_NO_COMMODITY_SUBREFERENCE -> new CarrierScenarioParameters( - "Booking Reference", + BOOKING_REFERENCE, null, null, // Any valid regular equipment reference will do as an example. "NARU3472484", null, - "DKAAR", + DKAAR, "640510", null, "Shoes - black, 400 boxes", @@ -92,13 +94,13 @@ public JsonNode getJsonForHumanReadablePrompt() { "Fibreboard boxes" ); case ACTIVE_REEFER -> new CarrierScenarioParameters( - "Booking Reference", + BOOKING_REFERENCE, "Commodity subreference for cargo requiring an *active* reefer", null, // Any valid reefer equipment reference will do as an example. "KKFU6671914", null, - "DKAAR", + DKAAR, "04052090", null, "Dairy products", @@ -106,13 +108,13 @@ public JsonNode getJsonForHumanReadablePrompt() { "Bottles" ); case NON_OPERATING_REEFER -> new CarrierScenarioParameters( - "Booking Reference", + BOOKING_REFERENCE, "Commodity subreference for cargo requiring an non-operating reefer", null, // Any valid reefer equipment reference will do as an example. "KKFU6671914", null, - "DKAAR", + DKAAR, "220299", null, "Non alcoholic beverages", @@ -120,41 +122,27 @@ public JsonNode getJsonForHumanReadablePrompt() { "Bottles" ); case DG -> new CarrierScenarioParameters( - "Booking Reference", + BOOKING_REFERENCE, "Commodity subreference for dangerous goods cargo", null, // Any valid regular equipment reference will do as an example. "NARU3472484", null, - "DKAAR", + DKAAR, "293499", null, "Environmentally hazardous substance", null, null ); - case REGULAR_2C_2U_1E -> new CarrierScenarioParameters( - "Booking Reference", + case REGULAR_2C_2U_1E, REGULAR_2C_2U_2E -> new CarrierScenarioParameters( + BOOKING_REFERENCE, "Commodity Subreference for regular cargo 1", "Commodity Subreference for regular cargo 2", // Any valid reefer equipment reference will do as an example. "MSKU3963442", "MSKU7895860", - "DKAAR", - "691110", - "732391", - "Tableware and kitchenware", - "Kitchen pots and pans", - "Fibreboard boxes" - ); - case REGULAR_2C_2U_2E -> new CarrierScenarioParameters( - "Booking Reference", - "Commodity Subreference for regular cargo 1", - "Commodity Subreference for regular cargo 2", - // Any valid reefer equipment reference will do as an example. - "MSKU3963442", - "MSKU7895860", - "DKAAR", + DKAAR, "691110", "732391", "Tableware and kitchenware", @@ -162,12 +150,12 @@ public JsonNode getJsonForHumanReadablePrompt() { "Fibreboard boxes" ); case REGULAR_SWB_SOC_AND_REFERENCES -> new CarrierScenarioParameters( - "Booking Reference", + BOOKING_REFERENCE, "Commodity Subreference for regular cargo", null, null, null, - "DKAAR", + DKAAR, "691110", null, "Tableware and kitchenware", diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/action/UC5_Shipper_CancelUpdateToShippingInstructionsAction.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/action/UC5_Shipper_CancelUpdateToShippingInstructionsAction.java index 7985a09c..133a8b9a 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/action/UC5_Shipper_CancelUpdateToShippingInstructionsAction.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/action/UC5_Shipper_CancelUpdateToShippingInstructionsAction.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import java.util.Objects; -import java.util.Set; import java.util.stream.Stream; import lombok.Getter; import lombok.extern.slf4j.Slf4j; diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/ArrayOrderHelper.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/ArrayOrderHelper.java index fbb55cf4..92147684 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/ArrayOrderHelper.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/ArrayOrderHelper.java @@ -5,7 +5,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import lombok.experimental.UtilityClass; -import java.util.Comparator; import java.util.function.Function; @UtilityClass 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 684606c1..76e19f9c 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 @@ -39,6 +39,12 @@ public class EBLChecks { private static final JsonPointer TD_TDR = JsonPointer.compile("/transportDocumentReference"); private static final JsonPointer TD_TRANSPORT_DOCUMENT_STATUS = JsonPointer.compile("/transportDocumentStatus"); + private static final String CONSIGNMENT_ITEMS = "consignmentItems"; + private static final String UTILIZED_TRANSPORT_EQUIPMENTS = "utilizedTransportEquipments"; + private static final String DOCUMENT_PARTIES = "documentParties"; + private static final String CUSTOMS_REFERENCES = "customsReferences"; + + private static final BiConsumer> DOC_PARTY_ARRAY_ORDER_DEFINITIONS = (documentPartyNode, arrayNodeHandler) -> { arrayNodeHandler.accept( @@ -81,7 +87,7 @@ public class EBLChecks { arrayNodeHandler.accept( rootNode, "routingOfConsignmentCountries", ArrayOrderHandler.inputPreservedArrayOrder()); - for (var ci : rootNode.path("consignmentItems")) { + for (var ci : rootNode.path(CONSIGNMENT_ITEMS)) { arrayNodeHandler.accept( ci, "descriptionOfGoods", ArrayOrderHandler.toStringSortableArray()); arrayNodeHandler.accept( @@ -92,51 +98,51 @@ public class EBLChecks { ci, "shippingMarks", ArrayOrderHandler.toStringSortableArray()); for (var cargoItem : ci.path("cargoItems")) { arrayNodeHandler.accept(cargoItem, "nationalCommodityCodes", ArrayOrderHandler.toStringSortableArray()); - for (var cr : cargoItem.path("customsReferences")) { + for (var cr : cargoItem.path(CUSTOMS_REFERENCES)) { arrayNodeHandler.accept(cr, "values", ArrayOrderHandler.toStringSortableArray()); } arrayNodeHandler.accept( - ci, "customsReferences", ArrayOrderHandler.toStringSortableArray()); + ci, CUSTOMS_REFERENCES, ArrayOrderHandler.toStringSortableArray()); } arrayNodeHandler.accept(ci, "cargoItems", ArrayOrderHandler.toStringSortableArray()); - for (var cr : ci.path("customsReferences")) { + for (var cr : ci.path(CUSTOMS_REFERENCES)) { arrayNodeHandler.accept(cr, "values", ArrayOrderHandler.toStringSortableArray()); } arrayNodeHandler.accept( - ci, "customsReferences", ArrayOrderHandler.toStringSortableArray()); + ci, CUSTOMS_REFERENCES, ArrayOrderHandler.toStringSortableArray()); } arrayNodeHandler.accept( - rootNode, "consignmentItems", ArrayOrderHandler.toStringSortableArray()); - for (var ute : rootNode.path("utilizedTransportEquipments")) { + rootNode, CONSIGNMENT_ITEMS, ArrayOrderHandler.toStringSortableArray()); + for (var ute : rootNode.path(UTILIZED_TRANSPORT_EQUIPMENTS)) { arrayNodeHandler.accept( ute, "shippingMarks", ArrayOrderHandler.toStringSortableArray()); arrayNodeHandler.accept( ute, "seals", ArrayOrderHandler.toStringSortableArray()); arrayNodeHandler.accept( ute, "references", ArrayOrderHandler.toStringSortableArray()); - for (var cr : ute.path("customsReferences")) { + for (var cr : ute.path(CUSTOMS_REFERENCES)) { arrayNodeHandler.accept(cr, "values", ArrayOrderHandler.toStringSortableArray()); } arrayNodeHandler.accept( - ute, "customsReferences", ArrayOrderHandler.toStringSortableArray()); + ute, CUSTOMS_REFERENCES, ArrayOrderHandler.toStringSortableArray()); } arrayNodeHandler.accept( - rootNode, "utilizedTransportEquipments", ArrayOrderHandler.toStringSortableArray()); + rootNode, UTILIZED_TRANSPORT_EQUIPMENTS, ArrayOrderHandler.toStringSortableArray()); arrayNodeHandler.accept( rootNode, "advanceManifestFilings", ArrayOrderHandler.toStringSortableArray()); arrayNodeHandler.accept( rootNode, "references", ArrayOrderHandler.toStringSortableArray()); - for (var cr : rootNode.path("customsReferences")) { + for (var cr : rootNode.path(CUSTOMS_REFERENCES)) { arrayNodeHandler.accept(cr, "values", ArrayOrderHandler.toStringSortableArray()); } arrayNodeHandler.accept( - rootNode, "customsReferences", ArrayOrderHandler.toStringSortableArray()); + rootNode, CUSTOMS_REFERENCES, ArrayOrderHandler.toStringSortableArray()); - DOC_PARTIES_ARRAY_ORDER_DEFINITIONS.accept(rootNode.path("documentParties"), arrayNodeHandler); + DOC_PARTIES_ARRAY_ORDER_DEFINITIONS.accept(rootNode.path(DOCUMENT_PARTIES), arrayNodeHandler); for (var hbl : rootNode.path("houseBillOfLadings")) { - DOC_PARTIES_ARRAY_ORDER_DEFINITIONS.accept(hbl.path("documentParties"), arrayNodeHandler); + DOC_PARTIES_ARRAY_ORDER_DEFINITIONS.accept(hbl.path(DOCUMENT_PARTIES), arrayNodeHandler); } arrayNodeHandler.accept( rootNode, "houseBillOfLadings", ArrayOrderHandler.toStringSortableArray()); @@ -299,6 +305,8 @@ public class EBLChecks { return isReeferContainerSizeTypeCode(isoEquipmentNode.asText("")); }; + public static final String IS_NON_OPERATING_REEFER = "isNonOperatingReefer"; + public static final String ACTIVE_REEFER_SETTINGS = "activeReeferSettings"; private static final JsonRebaseableContentCheck ISO_EQUIPMENT_CODE_IMPLIES_REEFER = JsonAttribute.allIndividualMatchesMustBeValid( "Validate utilizedTransportEquipment and reefer attributes", ALL_UTE, @@ -306,17 +314,17 @@ public class EBLChecks { HAS_ISO_EQUIPMENT_CODE, JsonAttribute.ifMatchedThenElse( IS_ISO_EQUIPMENT_CONTAINER_REEFER, - JsonAttribute.path("isNonOperatingReefer", JsonAttribute.matchedMustBePresent()), + JsonAttribute.path(IS_NON_OPERATING_REEFER, JsonAttribute.matchedMustBePresent()), JsonAttribute.combine( - JsonAttribute.path("isNonOperatingReefer", JsonAttribute.matchedMustBeAbsent()), - JsonAttribute.path("activeReeferSettings", JsonAttribute.matchedMustBeAbsent()) + JsonAttribute.path(IS_NON_OPERATING_REEFER, JsonAttribute.matchedMustBeAbsent()), + JsonAttribute.path(ACTIVE_REEFER_SETTINGS, JsonAttribute.matchedMustBeAbsent()) ) ), // If there is no ISOEquipmentCode, then we can only say that `activeReeferSettings` implies // `isNonOperatingReefer=False` (the `=False` part is checked elsewhere). JsonAttribute.presenceImpliesOtherField( - "activeReeferSettings", - "isNonOperatingReefer" + ACTIVE_REEFER_SETTINGS, + IS_NON_OPERATING_REEFER ) ) ); @@ -325,8 +333,8 @@ public class EBLChecks { "All utilizedTransportEquipments where 'isNonOperatingReefer' is 'false' must have 'activeReeferSettings'", ALL_UTE, JsonAttribute.ifMatchedThen( - JsonAttribute.isFalse("isNonOperatingReefer"), - JsonAttribute.path("activeReeferSettings", JsonAttribute.matchedMustBePresent()) + JsonAttribute.isFalse(IS_NON_OPERATING_REEFER), + JsonAttribute.path(ACTIVE_REEFER_SETTINGS, JsonAttribute.matchedMustBePresent()) ) ); @@ -334,8 +342,8 @@ public class EBLChecks { "All utilizedTransportEquipments where 'isNonOperatingReefer' is 'true' cannot have 'activeReeferSettings'", ALL_UTE, JsonAttribute.ifMatchedThen( - JsonAttribute.isTrue("isNonOperatingReefer"), - JsonAttribute.path("activeReeferSettings", JsonAttribute.matchedMustBeAbsent()) + JsonAttribute.isTrue(IS_NON_OPERATING_REEFER), + JsonAttribute.path(ACTIVE_REEFER_SETTINGS, JsonAttribute.matchedMustBeAbsent()) ) ); @@ -343,7 +351,7 @@ public class EBLChecks { private static final JsonRebaseableContentCheck CR_CC_T_CODES_UNIQUE = JsonAttribute.allIndividualMatchesMustBeValid( "The combination of 'countryCode' and 'type' in '*.customsReferences' must be unique", mav -> { - mav.submitAllMatching("customsReferences"); + mav.submitAllMatching(CUSTOMS_REFERENCES); mav.submitAllMatching("consignmentItems.*.customsReferences"); mav.submitAllMatching("consignmentItems.*.cargoItems.*.customsReferences"); mav.submitAllMatching("utilizedTransportEquipments.*.customsReferences"); @@ -362,7 +370,7 @@ public class EBLChecks { private static final JsonRebaseableContentCheck DOCUMENT_PARTY_FUNCTIONS_MUST_BE_UNIQUE = JsonAttribute.customValidator( "Each document party can be used at most once", JsonAttribute.path( - "documentParties", + DOCUMENT_PARTIES, JsonAttribute.path("other", JsonAttribute.unique("partyFunction")) )); @@ -371,7 +379,7 @@ public class EBLChecks { "Validate documentParties match the EBL type", (body, contextPath) -> { var issues = new LinkedHashSet(); - var documentParties = body.path("documentParties"); + var documentParties = body.path(DOCUMENT_PARTIES); var isToOrder = body.path("isToOrder").asBoolean(false); if (!documentParties.has("shipper")) { @@ -400,17 +408,19 @@ public class EBLChecks { }); private static Consumer allDg(Consumer consumer) { - return mav -> consumer.accept(mav.path("consignmentItems").all().path("cargoItems").all().path("outerPackaging").path("dangerousGoods").all()); + return mav -> consumer.accept(mav.path(CONSIGNMENT_ITEMS).all().path("cargoItems").all().path("outerPackaging").path("dangerousGoods").all()); } + public static final String EQUIPMENT_REFERENCE = "equipmentReference"; private static final JsonRebaseableContentCheck CARGO_ITEM_REFERENCES_KNOWN_EQUIPMENT = JsonAttribute.customValidator( "Equipment References in 'cargoItems' must be present in 'utilizedTransportEquipments'", (body, contextPath) -> { var knownEquipmentReferences = allEquipmentReferences(body); var missing = new LinkedHashSet(); - for (var consignmentItem : body.path("consignmentItems")) { + for (var consignmentItem : body.path(CONSIGNMENT_ITEMS)) { for (var cargoItem : consignmentItem.path("cargoItems")) { - var ref = cargoItem.path("equipmentReference").asText(null); + var ref = cargoItem.path( + EQUIPMENT_REFERENCE).asText(null); if (ref == null) { // Schema validated continue; @@ -420,7 +430,7 @@ private static Consumer allDg(Consumer "The equipment reference '%s' was used in a cargoItem but was not present in '%s'".formatted(ref, path)) .collect(Collectors.toSet()); @@ -432,7 +442,7 @@ private static Consumer allDg(Consumer { var duplicates = new LinkedHashSet(); allEquipmentReferences(body, duplicates); - var path = concatContextPath(contextPath, "utilizedTransportEquipments"); + var path = concatContextPath(contextPath, UTILIZED_TRANSPORT_EQUIPMENTS); return duplicates.stream() .map(ref -> "The equipment reference '%s' was used more than once in '%s'".formatted(ref, path)) .collect(Collectors.toSet()); @@ -623,7 +633,7 @@ private static void generateScenarioRelatedChecks(List checks, var dsp = dspSupplier.get(); return dsp.shippingInstructions().path("isCarriersAgentAtDestinationRequired").asBoolean(false) || dsp.scenarioType().isCarriersAgentAtDestinationRequired(); }, - JsonAttribute.path("documentParties", JsonAttribute.path("carriersAgentAtDestination", JsonAttribute.matchedMustBePresent())) + JsonAttribute.path(DOCUMENT_PARTIES, JsonAttribute.path("carriersAgentAtDestination", JsonAttribute.matchedMustBePresent())) )); } else { checks.add( @@ -635,7 +645,7 @@ private static void generateScenarioRelatedChecks(List checks, checks.add( JsonAttribute.customValidator( "[Scenario] Verify that the correct 'commoditySubreference' is used", - JsonAttribute.path("consignmentItems", checkCommoditySubreference(cspSupplier)))); + JsonAttribute.path(CONSIGNMENT_ITEMS, checkCommoditySubreference(cspSupplier)))); checks.add( JsonAttribute.allIndividualMatchesMustBeValid( @@ -651,15 +661,15 @@ private static void generateScenarioRelatedChecks(List checks, } checks.add(JsonAttribute.customValidator( "[Scenario] Verify that the correct 'equipmentReference' values are used", - JsonAttribute.path("utilizedTransportEquipments", checkEquipmentReference(cspSupplier)) + JsonAttribute.path(UTILIZED_TRANSPORT_EQUIPMENTS, checkEquipmentReference(cspSupplier)) )); checks.add(JsonAttribute.customValidator( "[Scenario] Verify that the correct 'HSCodes' are used", - JsonAttribute.path("consignmentItems", checkHSCodes(cspSupplier)) + JsonAttribute.path(CONSIGNMENT_ITEMS, checkHSCodes(cspSupplier)) )); checks.add(JsonAttribute.customValidator( "[Scenario] Verify that the correct 'descriptionOfGoods' is used", - JsonAttribute.path("consignmentItems", checkDescriptionOfGoods(cspSupplier)) + JsonAttribute.path(CONSIGNMENT_ITEMS, checkDescriptionOfGoods(cspSupplier)) )); checks.add(JsonAttribute.mustEqual( @@ -685,9 +695,9 @@ private static JsonContentMatchedValidation scenarioCustomsReferencesCheck(Suppl if (!scenarioType.isCustomsReferencesRequired()) { return Set.of(); } - var allReferencesParents = nodeToValidate.findParents("customsReferences"); + var allReferencesParents = nodeToValidate.findParents(CUSTOMS_REFERENCES); for (var referencesParent : allReferencesParents) { - if (isNonEmptyNode(referencesParent.path("customsReferences"))) { + if (isNonEmptyNode(referencesParent.path(CUSTOMS_REFERENCES))) { return Set.of(); } } @@ -708,19 +718,19 @@ private static JsonContentMatchedValidation scenarioReferencesCheck(Supplier dspSupplier.get().scenarioType().isReferencesRequired(), JsonAttribute.atLeastOneOfMatched((body, ptrs) -> { ptrs.addAll(Arrays.asList(REFERENCE_PATHS)); - var uteCount = body.path("utilizedTransportEquipments").size(); + var uteCount = body.path(UTILIZED_TRANSPORT_EQUIPMENTS).size(); for (int i = 0 ; i < uteCount ; i++) { ptrs.add(JsonPointer.compile("/utilizedTransportEquipments/%d/references".formatted(i))); } - var ciCount = body.path("consignmentItems").size(); + var ciCount = body.path(CONSIGNMENT_ITEMS).size(); for (int i = 0 ; i < ciCount ; i++) { ptrs.add(JsonPointer.compile("/consignmentItems/%d/references".formatted(i))); } - var notifyPartyCount = body.path("documentParties").path("notifyParties").size(); + var notifyPartyCount = body.path(DOCUMENT_PARTIES).path("notifyParties").size(); for (int i = 0 ; i < notifyPartyCount ; i++) { ptrs.add(JsonPointer.compile("/documentParties/notifyParties/%d/party/reference".formatted(i))); } - var otherPartyCount = body.path("documentParties").path("other").size(); + var otherPartyCount = body.path(DOCUMENT_PARTIES).path("other").size(); for (int i = 0 ; i < otherPartyCount ; i++) { ptrs.add(JsonPointer.compile("/documentParties/other/%d/party/reference".formatted(i))); } @@ -858,12 +868,12 @@ private static JsonContentMatchedValidation checkCSPAllUsedAtLeastOnce( private static JsonContentMatchedValidation checkEquipmentReference(Supplier cspSupplier) { BiFunction resolver = (ute, pathBuilder) -> { - var equipmentReferenceNode = ute.get("equipmentReference"); + var equipmentReferenceNode = ute.get(EQUIPMENT_REFERENCE); if (equipmentReferenceNode != null) { pathBuilder.append(".equipmentReference"); } else { pathBuilder.append(".equipment.equipmentReference"); - equipmentReferenceNode = ute.path("equipment").path("equipmentReference"); + equipmentReferenceNode = ute.path("equipment").path(EQUIPMENT_REFERENCE); } return equipmentReferenceNode; }; @@ -889,7 +899,7 @@ private static JsonContentMatchedValidation checkEquipmentReference(Supplier expectedReferences, resolver) + return checkCSPAllUsedAtLeastOnce(EQUIPMENT_REFERENCE, () -> expectedReferences, resolver) .validate(nodes, contextPath); }; } @@ -1066,6 +1076,7 @@ public static ActionCheck siNotificationContentChecks(UUID matched, String stand jsonContentChecks.add(updatedStatusCheck); return JsonAttribute.contentChecks( titlePrefix, + null, EblRole::isCarrier, matched, HttpMessageType.REQUEST, @@ -1083,6 +1094,7 @@ public static ActionCheck tdNotificationContentChecks(UUID matched, String stand )); return JsonAttribute.contentChecks( titlePrefix, + null, EblRole::isCarrier, matched, HttpMessageType.REQUEST, @@ -1128,8 +1140,8 @@ public static ActionCheck tdPlusScenarioContentChecks(UUID matched, String stand mav-> mav.submitAllMatching("utilizedTransportEquipments.*"), (nodeToValidate, contextPath) -> { var scenario = dspSupplier.get().scenarioType(); - var activeReeferNode = nodeToValidate.path("activeReeferSettings"); - var nonOperatingReeferNode = nodeToValidate.path("isNonOperatingReefer"); + var activeReeferNode = nodeToValidate.path(ACTIVE_REEFER_SETTINGS); + var nonOperatingReeferNode = nodeToValidate.path(IS_NON_OPERATING_REEFER); var issues = new LinkedHashSet(); switch (scenario) { case ACTIVE_REEFER -> { @@ -1188,12 +1200,12 @@ private static Set allEquipmentReferences(JsonNode body) { private static Set allEquipmentReferences(JsonNode body, Set duplicates) { var seen = new HashSet(); - for (var ute : body.path("utilizedTransportEquipments")) { + for (var ute : body.path(UTILIZED_TRANSPORT_EQUIPMENTS)) { // TD or SI with SOC - var ref = ute.path("equipment").path("equipmentReference").asText(null); + var ref = ute.path("equipment").path(EQUIPMENT_REFERENCE).asText(null); if (ref == null) { // SI with COC - ref = ute.path("equipmentReference").asText(null); + ref = ute.path(EQUIPMENT_REFERENCE).asText(null); } if (ref == null) { continue; diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/ToStringComparator.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/ToStringComparator.java index dba21c8c..3f7a6e40 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/ToStringComparator.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/checks/ToStringComparator.java @@ -14,16 +14,17 @@ public class ToStringComparator implements Comparator { @Override public int compare(JsonNode o1, JsonNode o2) { - var r = o1.getNodeType().compareTo(o2.getNodeType()); - if (r != 0) return r; - var o1sb = new StringBuffer(); - var o2sb = new StringBuffer(); + var compared = o1.getNodeType().compareTo(o2.getNodeType()); + if (compared != 0) return compared; + + var o1sb = new StringBuilder(); + var o2sb = new StringBuilder(); stringify(o1sb, o1); stringify(o2sb, o2); return o1.toString().compareTo(o2.toString()); } - private static void stringify(StringBuffer builder, JsonNode node) { + private static void stringify(StringBuilder builder, JsonNode node) { switch (node.getNodeType()) { case ARRAY -> { builder.append("["); diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/crypto/impl/RSAPayloadSigner.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/crypto/impl/RSAPayloadSigner.java index 520b4e61..546b5c20 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/crypto/impl/RSAPayloadSigner.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/crypto/impl/RSAPayloadSigner.java @@ -2,7 +2,6 @@ import org.dcsa.conformance.standards.ebl.crypto.JWSSignerDetails; import org.dcsa.conformance.standards.ebl.crypto.PayloadSignerWithKey; -import org.dcsa.conformance.standards.ebl.crypto.SignatureVerifierWithKey; import java.security.interfaces.RSAPublicKey; diff --git a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/party/EblCarrier.java b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/party/EblCarrier.java index ac726bb8..a1206220 100644 --- a/ebl/src/main/java/org/dcsa/conformance/standards/ebl/party/EblCarrier.java +++ b/ebl/src/main/java/org/dcsa/conformance/standards/ebl/party/EblCarrier.java @@ -32,6 +32,13 @@ @Slf4j public class EblCarrier extends ConformanceParty { + private static final String DOCUMENT_REFERENCE = "documentReference"; + private static final String MESSAGE = "message"; + private static final String DKAAR = "DKAAR"; + private static final String ACTION_ID = "actionId"; + private static final String TRANSPORT_DOCUMENT_REFERENCE = "transportDocumentReference"; + private static final String FIBREBOARD_BOXES = "Fibreboard boxes"; + private final Map tdrToSir = new HashMap<>(); public EblCarrier( @@ -96,12 +103,12 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { // A "22G1" container - keep aligned with the fixupUtilizedTransportEquipments() "NARU3472484", null, - "DKAAR", + DKAAR, "640510", null, "Shoes - black, 400 boxes", null, - "Fibreboard boxes" + FIBREBOARD_BOXES ); case REGULAR_NO_COMMODITY_SUBREFERENCE -> new CarrierScenarioParameters( "CBR_123_NO_SUBREF", @@ -110,12 +117,12 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { // A "22G1" container - keep aligned with the fixupUtilizedTransportEquipments() "NARU3472484", null, - "DKAAR", + DKAAR, "640510", null, "Shoes - black, 400 boxes", null, - "Fibreboard boxes" + FIBREBOARD_BOXES ); case ACTIVE_REEFER -> new CarrierScenarioParameters( "CBR_123_REEFER", @@ -124,7 +131,7 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { // A "45R1" container - keep aligned with the fixupUtilizedTransportEquipments() "KKFU6671914", null, - "DKAAR", + DKAAR, "04052090", null, "Dairy products", @@ -138,7 +145,7 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { // A "45R1" container - keep aligned with the fixupUtilizedTransportEquipments() "KKFU6671914", null, - "DKAAR", + DKAAR, "220299", null, "Non alcoholic beverages", @@ -152,40 +159,26 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { // A "22GP" container - keep aligned with the fixupUtilizedTransportEquipments() "HLXU1234567", null, - "DKAAR", + DKAAR, "293499", null, "Environmentally hazardous substance", null, null ); - case REGULAR_2C_2U_1E -> new CarrierScenarioParameters( - "RG-2C-2U-1E", - "Commodity Subreference 123", - "Commodity Subreference 456", - // A "22G1" container - keep aligned with the fixupUtilizedTransportEquipments() - "MSKU3963442", - "MSKU7895860", - "DKAAR", - "691110", - "732391", - "Tableware and kitchenware", - "Kitchen pots and pans", - "Fibreboard boxes" - ); - case REGULAR_2C_2U_2E -> new CarrierScenarioParameters( + case REGULAR_2C_2U_1E, REGULAR_2C_2U_2E -> new CarrierScenarioParameters( "RG-2C-2U-2E", "Commodity Subreference 123", "Commodity Subreference 456", // A "22G1" container - keep aligned with the fixupUtilizedTransportEquipments() "MSKU3963442", "MSKU7895860", - "DKAAR", + DKAAR, "691110", "732391", "Tableware and kitchenware", "Kitchen pots and pans", - "Fibreboard boxes" + FIBREBOARD_BOXES ); case REGULAR_SWB_SOC_AND_REFERENCES -> new CarrierScenarioParameters( "RG-SOC-REFERENCES", @@ -193,17 +186,17 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { null, null, null, - "DKAAR", + DKAAR, "691110", null, "Tableware and kitchenware", null, - "Fibreboard boxes" + FIBREBOARD_BOXES ); }; var json = carrierScenarioParameters.toJson(); asyncOrchestratorPostPartyInput( - actionPrompt.required("actionId").asText(), json); + actionPrompt.required(ACTION_ID).asText(), json); addOperatorLogEntry( "Prompt answer for supplyScenarioParameters: %s".formatted(json.toString())); } @@ -211,14 +204,14 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { private void requestUpdateToShippingInstructions(JsonNode actionPrompt) { log.info("Carrier.requestUpdateToShippingInstructions(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); var si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir); si.provideFeedbackToShippingInstructions(documentReference, feedbacks -> feedbacks.addObject() .put("severity", "ERROR") .put("code", "PROPERTY_VALUE_MUST_CHANGE") - .put("message", "Please perform the changes requested by the Conformance orchestrator") + .put(MESSAGE, "Please perform the changes requested by the Conformance orchestrator") ); si.save(persistentMap); generateAndEmitNotificationFromShippingInstructions(actionPrompt, si, true); @@ -230,7 +223,7 @@ private void requestUpdateToShippingInstructions(JsonNode actionPrompt) { private void processUpdatedShippingInstructions(JsonNode actionPrompt) { log.info("Carrier.processUpdatedShippingInstructions(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var accept = actionPrompt.required("acceptChanges").asBoolean(true); var sir = tdrToSir.getOrDefault(documentReference, documentReference); @@ -251,14 +244,14 @@ private void processUpdatedShippingInstructions(JsonNode actionPrompt) { private void processOutOfBandUpdateOrAmendmentRequestTransportDocumentAction(JsonNode actionPrompt) { log.info("Carrier.processOutOfBandUpdateOrAmendmentRequestTransportDocumentAction(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); var si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir); var updatedSI = EblShipper.updateShippingInstructions(si.getShippingInstructions()); si.putShippingInstructions(documentReference, updatedSI); si.acceptUpdatedShippingInstructions(documentReference); asyncOrchestratorPostPartyInput( - actionPrompt.required("actionId").asText(), OBJECT_MAPPER.createObjectNode()); + actionPrompt.required(ACTION_ID).asText(), OBJECT_MAPPER.createObjectNode()); addOperatorLogEntry("Process out of band amendment for transport document '%s'".formatted(documentReference)); } @@ -279,7 +272,7 @@ private void publishDraftTransportDocument(JsonNode actionPrompt) { si = CarrierShippingInstructions.initializeFromShippingInstructionsRequest(jsonRequestBody, apiVersion); documentReference = si.getShippingInstructionsReference(); } else { - documentReference = actionPrompt.required("documentReference").asText(); + documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir); } @@ -287,7 +280,7 @@ private void publishDraftTransportDocument(JsonNode actionPrompt) { si.save(persistentMap); tdrToSir.put(si.getTransportDocumentReference(), si.getShippingInstructionsReference()); if (skipSI) { - var json = OBJECT_MAPPER.createObjectNode().put("transportDocumentReference", si.getTransportDocumentReference()); + var json = OBJECT_MAPPER.createObjectNode().put(TRANSPORT_DOCUMENT_REFERENCE, si.getTransportDocumentReference()); addOperatorLogEntry("Prompt answer for publishDraftTransportDocument: %s".formatted(json.toString())); } generateAndEmitNotificationFromTransportDocument(actionPrompt, si, true); @@ -298,7 +291,7 @@ private void publishDraftTransportDocument(JsonNode actionPrompt) { private void issueTransportDocument(JsonNode actionPrompt) { log.info("Carrier.issueTransportDocument(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); var si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir); @@ -312,7 +305,7 @@ private void issueTransportDocument(JsonNode actionPrompt) { private void notifyOfSurrenderForAmendment(JsonNode actionPrompt) { log.info("Carrier.notifyOfSurrenderForAmendment(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); var si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir); @@ -326,7 +319,7 @@ private void notifyOfSurrenderForAmendment(JsonNode actionPrompt) { private void notifyOfSurrenderForDelivery(JsonNode actionPrompt) { log.info("Carrier.notifyOfSurrenderForDelivery(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); var si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir); si.surrenderForDeliveryRequest(documentReference); @@ -339,7 +332,7 @@ private void notifyOfSurrenderForDelivery(JsonNode actionPrompt) { private void processSurrenderRequestForAmendment(JsonNode actionPrompt) { log.info("Carrier.processSurrenderRequestForAmendment(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); var accept = actionPrompt.required("acceptAmendmentRequest").asBoolean(true); @@ -358,7 +351,7 @@ private void processSurrenderRequestForAmendment(JsonNode actionPrompt) { private void voidTransportDocument(JsonNode actionPrompt) { log.info("Carrier.voidTransportDocument(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); var si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir); si.voidTransportDocument(documentReference); @@ -371,7 +364,7 @@ private void voidTransportDocument(JsonNode actionPrompt) { private void issueAmendedTransportDocument(JsonNode actionPrompt) { log.info("Carrier.issueAmendedTransportDocument(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var scenarioType = ScenarioType.valueOf(actionPrompt.required("scenarioType").asText()); var sir = tdrToSir.getOrDefault(documentReference, documentReference); @@ -387,7 +380,7 @@ private void issueAmendedTransportDocument(JsonNode actionPrompt) { private void processSurrenderRequestForDelivery(JsonNode actionPrompt) { log.info("Carrier.processSurrenderRequestForDelivery(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); var accept = actionPrompt.required("acceptDeliveryRequest").asBoolean(true); @@ -406,7 +399,7 @@ private void processSurrenderRequestForDelivery(JsonNode actionPrompt) { private void confirmShippingInstructionsComplete(JsonNode actionPrompt) { log.info("Carrier.confirmShippingInstructionsComplete(%s)".formatted(actionPrompt.toPrettyString())); - var documentReference = actionPrompt.required("documentReference").asText(); + var documentReference = actionPrompt.required(DOCUMENT_REFERENCE).asText(); var sir = tdrToSir.getOrDefault(documentReference, documentReference); var si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir); @@ -427,7 +420,7 @@ private void generateAndEmitNotificationFromShippingInstructions(JsonNode action .build() .asJsonNode(); asyncCounterpartNotification( - actionPrompt.required("actionId").asText(), + actionPrompt.required(ACTION_ID).asText(), "/v3/shipping-instructions-notifications", notification); } @@ -443,7 +436,7 @@ private void generateAndEmitNotificationFromTransportDocument(JsonNode actionPro .build() .asJsonNode(); asyncCounterpartNotification( - actionPrompt.required("actionId").asText(), + actionPrompt.required(ACTION_ID).asText(), "/v3/transport-document-notifications", notification); } @@ -456,14 +449,14 @@ private ConformanceResponse return405(ConformanceRequest request, String... allo new ConformanceMessageBody( OBJECT_MAPPER .createObjectNode() - .put("message", "Returning 405 because the method was not supported"))); + .put(MESSAGE, "Returning 405 because the method was not supported"))); } private ConformanceResponse return400(ConformanceRequest request, String message) { return request.createResponse( 400, Map.of(API_VERSION, List.of(apiVersion)), - new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put("message", message))); + new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put(MESSAGE, message))); } private ConformanceResponse return404(ConformanceRequest request) { @@ -476,14 +469,14 @@ private ConformanceResponse return404(ConformanceRequest request, String message new ConformanceMessageBody( OBJECT_MAPPER .createObjectNode() - .put("message", message))); + .put(MESSAGE, message))); } private ConformanceResponse return409(ConformanceRequest request, String message) { return request.createResponse( 409, Map.of(API_VERSION, List.of(apiVersion)), - new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put("message", message))); + new ConformanceMessageBody(OBJECT_MAPPER.createObjectNode().put(MESSAGE, message))); } private static final Set QUERY_BOOLEAN = Set.of("true", "false"); @@ -500,7 +493,7 @@ private String readAmendedContent(ConformanceRequest request) { return operation; } - private ConformanceResponse _handleGetShippingInstructionsRequest(ConformanceRequest request, String documentReference) { + private ConformanceResponse handleGetShippingInstructionsRequest(ConformanceRequest request, String documentReference) { var amendedContentRaw = readAmendedContent(request); boolean amendedContent; if (amendedContentRaw.equals("true") || amendedContentRaw.equals("false")) { @@ -539,7 +532,7 @@ private ConformanceResponse _handleGetShippingInstructionsRequest(ConformanceReq return return404(request); } - private ConformanceResponse _handleGetTransportDocument(ConformanceRequest request, String documentReference) { + private ConformanceResponse handleGetTransportDocument(ConformanceRequest request, String documentReference) { // bookingReference can either be a CBR or CBRR. var sir = tdrToSir.get(documentReference); if (sir == null) { @@ -564,7 +557,7 @@ private ConformanceResponse _handleGetTransportDocument(ConformanceRequest reque } - private ConformanceResponse _handlePatchShippingInstructions(ConformanceRequest request, String documentReference) { + private ConformanceResponse handlePatchShippingInstructions(ConformanceRequest request, String documentReference) { var sir = tdrToSir.getOrDefault(documentReference, documentReference); var persistedSi = persistentMap.load(sir); if (persistedSi == null) { @@ -592,7 +585,7 @@ private ConformanceResponse _handlePatchShippingInstructions(ConformanceRequest ); } - private ConformanceResponse _handlePatchTransportDocument(ConformanceRequest request, String documentReference) { + private ConformanceResponse handlePatchTransportDocument(ConformanceRequest request, String documentReference) { var sir = tdrToSir.get(documentReference); if (sir == null) { return return404(request); @@ -661,13 +654,13 @@ private ConformanceResponse returnEmpty202Response(ConformanceRequest request, O private ConformanceResponse returnTransportDocumentRefStatusResponse( int responseCode, ConformanceRequest request, ObjectNode transportDocument, String documentReference) { - var tdr = transportDocument.required("transportDocumentReference").asText(); + var tdr = transportDocument.required(TRANSPORT_DOCUMENT_REFERENCE).asText(); var tdStatus = transportDocument.required("transportDocumentStatus").asText(); var statusObject = OBJECT_MAPPER .createObjectNode() .put("transportDocumentStatus", tdStatus) - .put("transportDocumentReference", tdr); + .put(TRANSPORT_DOCUMENT_REFERENCE, tdr); ConformanceResponse response = request.createResponse( responseCode, @@ -680,7 +673,7 @@ private ConformanceResponse returnTransportDocumentRefStatusResponse( } @SneakyThrows - private ConformanceResponse _handlePostShippingInstructions(ConformanceRequest request) { + private ConformanceResponse handlePostShippingInstructions(ConformanceRequest request) { ObjectNode siPayload = (ObjectNode) OBJECT_MAPPER.readTree(request.message().body().getJsonBody().toString()); var si = CarrierShippingInstructions.initializeFromShippingInstructionsRequest(siPayload, apiVersion); @@ -706,7 +699,7 @@ private ConformanceResponse _handlePostShippingInstructions(ConformanceRequest r @SneakyThrows - private ConformanceResponse _handlePutShippingInstructions(ConformanceRequest request) { + private ConformanceResponse handlePutShippingInstructions(ConformanceRequest request) { var url = uriContextPath(request.url()); var documentReference = lastUrlSegment(url); var sir = tdrToSir.getOrDefault(documentReference, documentReference); @@ -753,16 +746,16 @@ public ConformanceResponse handleRequest(ConformanceRequest request) { var lastSegment = lastUrlSegment(url); var urlStem = url.substring(0, url.length() - lastSegment.length()).replaceAll("/++$", ""); if (urlStem.endsWith("/v3/shipping-instructions")) { - yield _handleGetShippingInstructionsRequest(request, lastSegment); + yield handleGetShippingInstructionsRequest(request, lastSegment); } if (urlStem.endsWith("/v3/transport-documents")) { - yield _handleGetTransportDocument(request, lastSegment); + yield handleGetTransportDocument(request, lastSegment); } yield return404(request); } case "POST" -> { if (url.endsWith("/v3/shipping-instructions")) { - yield _handlePostShippingInstructions(request); + yield handlePostShippingInstructions(request); } yield return404(request); } @@ -770,14 +763,14 @@ public ConformanceResponse handleRequest(ConformanceRequest request) { var lastSegment = lastUrlSegment(url); var urlStem = url.substring(0, url.length() - lastSegment.length()).replaceAll("/++$", ""); if (urlStem.endsWith("/v3/shipping-instructions")) { - yield _handlePatchShippingInstructions(request, lastSegment); + yield handlePatchShippingInstructions(request, lastSegment); } if (urlStem.endsWith("/v3/transport-documents")) { - yield _handlePatchTransportDocument(request, lastSegment); + yield handlePatchTransportDocument(request, lastSegment); } yield return404(request); } - case "PUT" -> _handlePutShippingInstructions(request); + case "PUT" -> handlePutShippingInstructions(request); default -> return405(request, "GET", "POST", "PUT", "PATCH"); }; addOperatorLogEntry( @@ -845,7 +838,7 @@ public ObjectNode asJsonNode() { notification.put("datacontenttype", "application/json"); var data = OBJECT_MAPPER.createObjectNode(); - setDocumentProvidedField(data, "transportDocumentReference", transportDocumentReference); + setDocumentProvidedField(data, TRANSPORT_DOCUMENT_REFERENCE, transportDocumentReference); if (includeShippingInstructionsReference) { setDocumentProvidedField( data, "shippingInstructionsReference", shippingInstructionsReference); diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/action/SupplyScenarioParametersAction.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/action/SupplyScenarioParametersAction.java index 0e7e69af..a853b89d 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/action/SupplyScenarioParametersAction.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/action/SupplyScenarioParametersAction.java @@ -3,14 +3,13 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import java.text.SimpleDateFormat; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; + import lombok.Getter; import org.dcsa.conformance.core.scenario.ConformanceAction; import org.dcsa.conformance.standards.jit.party.JitFilterParameter; @@ -18,7 +17,6 @@ @Getter public class SupplyScenarioParametersAction extends ConformanceAction { - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); private SuppliedScenarioParameters suppliedScenarioParameters = null; private final LinkedHashSet jitFilterParameters; diff --git a/ovs/src/main/java/org/dcsa/conformance/standards/ovs/action/SupplyScenarioParametersAction.java b/ovs/src/main/java/org/dcsa/conformance/standards/ovs/action/SupplyScenarioParametersAction.java index 0f5be04a..dd9fdf27 100644 --- a/ovs/src/main/java/org/dcsa/conformance/standards/ovs/action/SupplyScenarioParametersAction.java +++ b/ovs/src/main/java/org/dcsa/conformance/standards/ovs/action/SupplyScenarioParametersAction.java @@ -3,23 +3,19 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; - -import java.text.SimpleDateFormat; +import java.time.LocalDateTime; import java.util.Arrays; -import java.util.Date; import java.util.LinkedHashSet; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; import lombok.Getter; import org.dcsa.conformance.core.scenario.ConformanceAction; +import org.dcsa.conformance.core.toolkit.JsonToolkit; import org.dcsa.conformance.standards.ovs.party.OvsFilterParameter; import org.dcsa.conformance.standards.ovs.party.SuppliedScenarioParameters; @Getter public class SupplyScenarioParametersAction extends ConformanceAction { - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - private SuppliedScenarioParameters suppliedScenarioParameters = null; private final LinkedHashSet ovsFilterParameters; @@ -86,7 +82,7 @@ public JsonNode getJsonForHumanReadablePrompt() { ovsFilterParameter -> switch (ovsFilterParameter) { case LIMIT -> "100"; - case START_DATE, END_DATE -> DATE_FORMAT.format(new Date()); + case START_DATE, END_DATE -> LocalDateTime.now().format(JsonToolkit.DEFAULT_DATE_FORMAT); default -> "TODO"; }))) .toJson(); diff --git a/ovs/src/main/java/org/dcsa/conformance/standards/ovs/party/OvsPublisher.java b/ovs/src/main/java/org/dcsa/conformance/standards/ovs/party/OvsPublisher.java index d945ecea..3321ddb2 100644 --- a/ovs/src/main/java/org/dcsa/conformance/standards/ovs/party/OvsPublisher.java +++ b/ovs/src/main/java/org/dcsa/conformance/standards/ovs/party/OvsPublisher.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import java.text.SimpleDateFormat; +import java.time.LocalDateTime; import java.util.*; import java.util.function.Consumer; import java.util.function.Function; @@ -24,8 +24,6 @@ @Slf4j public class OvsPublisher extends ConformanceParty { - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - public OvsPublisher( String apiVersion, PartyConfiguration partyConfiguration, @@ -82,7 +80,7 @@ private void supplyScenarioParameters(JsonNode actionPrompt) { case UNIVERSAL_VOYAGE_REFERENCE -> "2201N"; case UN_LOCATION_CODE -> "NLAMS"; case FACILITY_SMDG_CODE -> "APM"; - case START_DATE, END_DATE -> DATE_FORMAT.format(new Date()); + case START_DATE, END_DATE -> LocalDateTime.now().format(JsonToolkit.DEFAULT_DATE_FORMAT); case LIMIT -> "100"; }))); 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 17850c0e..058feb7f 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 @@ -2,7 +2,6 @@ import static org.dcsa.conformance.standards.ebl.crypto.SignedNodeSupport.parseSignedNodeNoErrors; import static org.dcsa.conformance.standards.eblinterop.checks.PintChecks.*; -import static org.dcsa.conformance.standards.eblinterop.checks.PintChecks.validateInnerRequestSchemas; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; 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 e1a35fe7..f7b34e38 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 @@ -2,7 +2,6 @@ import static org.dcsa.conformance.standards.ebl.crypto.SignedNodeSupport.parseSignedNodeNoErrors; import static org.dcsa.conformance.standards.eblinterop.checks.PintChecks.*; -import static org.dcsa.conformance.standards.eblinterop.checks.PintChecks.validateInnerRequestSchemas; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; diff --git a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceSandbox.java b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceSandbox.java index 7c691cae..dc4a2d23 100644 --- a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceSandbox.java +++ b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceSandbox.java @@ -41,6 +41,9 @@ @Slf4j public class ConformanceSandbox { + protected static final String SANDBOX = "sandbox#"; + protected static final String SESSION = "session#"; + public static final AbstractStandard[] SUPPORTED_STANDARDS = { AdoptionStandard.INSTANCE, BookingStandard.INSTANCE, @@ -69,7 +72,7 @@ public void run() { .getStatefulExecutor() .execute( description, - "session#" + currentSessionId, + SESSION + currentSessionId, "state#orchestrator", originalOrchestratorState -> { SandboxConfiguration sandboxConfiguration = @@ -83,10 +86,10 @@ public void run() { sandboxConfiguration, componentFactory, new TrafficRecorder( - persistenceProvider.getNonLockingMap(), "session#" + currentSessionId), + persistenceProvider.getNonLockingMap(), SESSION + currentSessionId), new JsonNodeMap( persistenceProvider.getNonLockingMap(), - "session#" + currentSessionId, + SESSION + currentSessionId, "map#orchestrator#"), asyncWebClient); if (originalOrchestratorState != null && !originalOrchestratorState.isEmpty()) { @@ -118,7 +121,7 @@ public void run() { .getStatefulExecutor() .execute( description, - "session#" + currentSessionId, + SESSION + currentSessionId, "state#party#" + partyName, originalPartyState -> { SandboxConfiguration sandboxConfiguration = @@ -180,7 +183,7 @@ public ConformanceResponse syncRequest( sandboxConfiguration.getCounterparts(), new JsonNodeMap( persistenceProvider.getNonLockingMap(), - "session#" + currentSessionId, + SESSION + currentSessionId, "map#party#" + partyName), partyWebClient, orchestratorAuthHeader) @@ -208,7 +211,7 @@ private static JsonNode _loadSandboxState( .getStatefulExecutor() .execute( "loading state of sandbox " + sandboxId, - "sandbox#" + sandboxId, + SANDBOX + sandboxId, "state", originalSandboxState -> { sandboxStateNodeReference.set(originalSandboxState); @@ -416,7 +419,7 @@ public static ObjectNode getSandboxStatus( private static LinkedList _getWaitingFor( ConformancePersistenceProvider persistenceProvider, String sandboxId) { JsonNode waitingJsonNode = - persistenceProvider.getNonLockingMap().getItemValue("sandbox#" + sandboxId, "waiting"); + persistenceProvider.getNonLockingMap().getItemValue(SANDBOX + sandboxId, "waiting"); LinkedList waitingList = new LinkedList<>(); if (waitingJsonNode != null && waitingJsonNode.isArray()) { waitingJsonNode.forEach( @@ -441,7 +444,7 @@ private static void _setWaitingFor( log.info("Sandbox %s waiting: %s".formatted(sandboxId, waitingArrayNode.toPrettyString())); persistenceProvider .getNonLockingMap() - .setItemValue("sandbox#" + sandboxId, "waiting", waitingArrayNode); + .setItemValue(SANDBOX + sandboxId, "waiting", waitingArrayNode); } public static ObjectNode getScenarioStatus( @@ -691,21 +694,21 @@ private static ConformanceResponse _syncHandleOutboundRequest( partyConfiguration -> Objects.equals( partyConfiguration.getName(), - conformanceRequest.message().targetPartyName()))) { - if (sandboxConfiguration.getOrchestrator().isActive()) { - new OrchestratorTask( - persistenceProvider, - conformanceWebRequest -> - ConformanceSandbox._asyncSendOutboundWebRequest( - deferredSandboxTaskConsumer, conformanceWebRequest), - sandboxId, - "handling outbound conformance request", - orchestrator -> - orchestrator.handlePartyTrafficExchange( - new ConformanceExchange(conformanceRequest, conformanceResponse))) - .run(); - } + conformanceRequest.message().targetPartyName())) + && sandboxConfiguration.getOrchestrator().isActive()) { + new OrchestratorTask( + persistenceProvider, + conformanceWebRequest -> + ConformanceSandbox._asyncSendOutboundWebRequest( + deferredSandboxTaskConsumer, conformanceWebRequest), + sandboxId, + "handling outbound conformance request", + orchestrator -> + orchestrator.handlePartyTrafficExchange( + new ConformanceExchange(conformanceRequest, conformanceResponse))) + .run(); } + return conformanceResponse; } @@ -723,6 +726,9 @@ private static void _syncSendOutboundWebRequest(ConformanceWebRequest conformanc (name, values) -> values.forEach(value -> httpRequestBuilder.header(name, value))); IOToolkit.HTTP_CLIENT.send(httpRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()); } catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } log.error( "Failed to send outbound request: {}", conformanceWebRequest.toJson().toPrettyString(), @@ -830,14 +836,14 @@ private static ConformanceWebResponse _handleReset( .getStatefulExecutor() .execute( "update sandbox currentSessionId", - "sandbox#" + sandboxId, + SANDBOX + sandboxId, "state", originalSandboxState -> OBJECT_MAPPER.createObjectNode().put("currentSessionId", newSessionId)); persistenceProvider .getNonLockingMap() .setItemValue( - "sandbox#" + sandboxId, + SANDBOX + sandboxId, "SK=session#%s#%s".formatted(Instant.now().toString(), newSessionId), OBJECT_MAPPER.createObjectNode()); @@ -861,7 +867,7 @@ private static ConformanceWebResponse _handleReset( public static SandboxConfiguration loadSandboxConfiguration( ConformancePersistenceProvider persistenceProvider, String sandboxId) { return SandboxConfiguration.fromJsonNode( - persistenceProvider.getNonLockingMap().getItemValue("sandbox#" + sandboxId, "config")); + persistenceProvider.getNonLockingMap().getItemValue(SANDBOX + sandboxId, "config")); } public static void saveSandboxConfiguration( @@ -872,7 +878,7 @@ public static void saveSandboxConfiguration( .getNonLockingMap() .setItemValue( "environment#" + environmentId, - "sandbox#" + sandboxConfiguration.getId(), + SANDBOX + sandboxConfiguration.getId(), OBJECT_MAPPER .createObjectNode() .put("id", sandboxConfiguration.getId()) @@ -880,7 +886,7 @@ public static void saveSandboxConfiguration( persistenceProvider .getNonLockingMap() .setItemValue( - "sandbox#" + sandboxConfiguration.getId(), "config", sandboxConfiguration.toJsonNode()); + SANDBOX + sandboxConfiguration.getId(), "config", sandboxConfiguration.toJsonNode()); } private static AbstractComponentFactory _createComponentFactory( diff --git a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceWebuiHandler.java b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceWebuiHandler.java index e5c2dc8a..65700819 100644 --- a/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceWebuiHandler.java +++ b/sandbox/src/main/java/org/dcsa/conformance/sandbox/ConformanceWebuiHandler.java @@ -23,6 +23,8 @@ @Slf4j public class ConformanceWebuiHandler { + private static final String SANDBOX_ID = "sandboxId"; + private final ConformanceAccessChecker accessChecker; private final String environmentBaseUrl; private final ConformancePersistenceProvider persistenceProvider; @@ -73,7 +75,7 @@ public JsonNode _doHandleRequest(String userId, JsonNode requestNode) { case "getSandboxConfig" -> _getSandboxConfig(userId, requestNode); case "getSandboxStatus" -> _getSandboxStatus(userId, requestNode); case "updateSandboxConfig" -> _updateSandboxConfig(userId, requestNode); - case "getAvailableStandards" -> _getAvailableStandards(userId); + case "getAvailableStandards" -> _getAvailableStandards(); case "getAllSandboxes" -> _getAllSandboxes(userId); case "getSandbox" -> _getSandbox(userId, requestNode); case "notifyParty" -> _notifyParty(userId, requestNode); @@ -175,11 +177,11 @@ private JsonNode _createSandbox(String userId, JsonNode requestNode) { log.info("Created sandbox: " + sandboxConfiguration.toJsonNode().toPrettyString()); - return OBJECT_MAPPER.createObjectNode().put("sandboxId", sandboxId); + return OBJECT_MAPPER.createObjectNode().put(SANDBOX_ID, sandboxId); } private JsonNode _getSandboxConfig(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); SandboxConfiguration sandboxConfiguration = ConformanceSandbox.loadSandboxConfiguration(persistenceProvider, sandboxId); @@ -204,7 +206,7 @@ private JsonNode _getSandboxConfig(String userId, JsonNode requestNode) { ObjectNode jsonSandboxConfig = OBJECT_MAPPER .createObjectNode() - .put("sandboxId", sandboxConfiguration.getId()) + .put(SANDBOX_ID, sandboxConfiguration.getId()) .put("sandboxName", sandboxConfiguration.getName()) .put("sandboxUrl", sandboxPartyCounterpartConfig.getUrl()) .put("sandboxAuthHeaderName", sandboxConfiguration.getAuthHeaderName()) @@ -227,13 +229,13 @@ private JsonNode _getSandboxConfig(String userId, JsonNode requestNode) { } private JsonNode _getSandboxStatus(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); return ConformanceSandbox.getSandboxStatus(persistenceProvider, sandboxId); } private JsonNode _updateSandboxConfig(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); SandboxConfiguration sandboxConfiguration = ConformanceSandbox.loadSandboxConfiguration(persistenceProvider, sandboxId); @@ -300,7 +302,7 @@ private JsonNode _updateSandboxConfig(String userId, JsonNode requestNode) { return OBJECT_MAPPER.createObjectNode(); } - private JsonNode _getAvailableStandards(String ignoredUserId) { + private JsonNode _getAvailableStandards() { /* [ { @@ -324,44 +326,44 @@ private JsonNode _getAvailableStandards(String ignoredUserId) { TreeSet sortedStandardNames = new TreeSet<>(String::compareToIgnoreCase); sortedStandardNames.addAll(standardsByName.keySet()); sortedStandardNames.forEach( - standardName -> { - ObjectNode standardNode = OBJECT_MAPPER.createObjectNode().put("name", standardName); - standardsNode.add(standardNode); - { - ArrayNode versionsNode = OBJECT_MAPPER.createArrayNode(); - standardNode.set("versions", versionsNode); - AbstractStandard standard = standardsByName.get(standardName); - SortedMap> scenarioSuitesByStandardVersion = - standard.getScenarioSuitesByStandardVersion(); - scenarioSuitesByStandardVersion - .keySet() - .forEach( - standardVersion -> { - ObjectNode versionNode = - OBJECT_MAPPER.createObjectNode().put("number", standardVersion); - versionsNode.add(versionNode); - - SortedSet scenarioSuites = - scenarioSuitesByStandardVersion.get(standardVersion); - { // scoped - ArrayNode suitesNode = OBJECT_MAPPER.createArrayNode(); - versionNode.set("suites", suitesNode); - scenarioSuites.forEach(suitesNode::add); - } - { // scoped - ArrayNode rolesNode = OBJECT_MAPPER.createArrayNode(); - versionNode.set("roles", rolesNode); - standard - .createComponentFactory(standardVersion, scenarioSuites.first()) - .getRoleNames() - .forEach(rolesNode::add); - } - }); - } - }); + standardName -> addStandardToNode(standardName, standardsNode)); return standardsNode; } + private void addStandardToNode(String standardName, ArrayNode standardsNode) { + ObjectNode standardNode = OBJECT_MAPPER.createObjectNode().put("name", standardName); + standardsNode.add(standardNode); + ArrayNode versionsNode = OBJECT_MAPPER.createArrayNode(); + standardNode.set("versions", versionsNode); + AbstractStandard standard = standardsByName.get(standardName); + SortedMap> scenarioSuitesByStandardVersion = + standard.getScenarioSuitesByStandardVersion(); + scenarioSuitesByStandardVersion + .keySet() + .forEach( + standardVersion -> addStandardDetails(standardVersion, versionsNode, scenarioSuitesByStandardVersion, standard)); + } + + private static void addStandardDetails( + String standardVersion, + ArrayNode versionsNode, + SortedMap> scenarioSuitesByStandardVersion, + AbstractStandard standard) { + ObjectNode versionNode = OBJECT_MAPPER.createObjectNode().put("number", standardVersion); + versionsNode.add(versionNode); + + SortedSet scenarioSuites = scenarioSuitesByStandardVersion.get(standardVersion); + ArrayNode suitesNode = OBJECT_MAPPER.createArrayNode(); + versionNode.set("suites", suitesNode); + scenarioSuites.forEach(suitesNode::add); + ArrayNode rolesNode = OBJECT_MAPPER.createArrayNode(); + versionNode.set("roles", rolesNode); + standard + .createComponentFactory(standardVersion, scenarioSuites.first()) + .getRoleNames() + .forEach(rolesNode::add); + } + private JsonNode _getAllSandboxes(String userId) { TreeMap sortedSandboxesByLowercaseName = new TreeMap<>(); persistenceProvider @@ -377,7 +379,7 @@ private JsonNode _getAllSandboxes(String userId) { } private JsonNode _getSandbox(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); ObjectNode sandboxNode = (ObjectNode) @@ -399,41 +401,41 @@ private JsonNode _getSandbox(String userId, JsonNode requestNode) { } private JsonNode _notifyParty(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); ConformanceSandbox.notifyParty(persistenceProvider, deferredSandboxTaskConsumer, sandboxId); return OBJECT_MAPPER.createObjectNode(); } private JsonNode _resetParty(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); ConformanceSandbox.resetParty(persistenceProvider, deferredSandboxTaskConsumer, sandboxId); return OBJECT_MAPPER.createObjectNode(); } private JsonNode _getScenarioDigests(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); return ConformanceSandbox.getScenarioDigests(persistenceProvider, sandboxId); } private JsonNode _getScenario(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); return ConformanceSandbox.getScenarioDigest( persistenceProvider, sandboxId, requestNode.get("scenarioId").asText()); } private JsonNode _getScenarioStatus(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); return ConformanceSandbox.getScenarioStatus( persistenceProvider, sandboxId, requestNode.get("scenarioId").asText()); } private JsonNode _handleActionInput(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); JsonNode actionInputNode = requestNode.get("actionInput"); return ConformanceSandbox.handleActionInput( @@ -445,7 +447,7 @@ private JsonNode _handleActionInput(String userId, JsonNode requestNode) { } private JsonNode _startOrStopScenario(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); ConformanceSandbox.startOrStopScenario( persistenceProvider, @@ -457,7 +459,7 @@ private JsonNode _startOrStopScenario(String userId, JsonNode requestNode) { } private JsonNode _completeCurrentAction(String userId, JsonNode requestNode) { - String sandboxId = requestNode.get("sandboxId").asText(); + String sandboxId = requestNode.get(SANDBOX_ID).asText(); accessChecker.checkUserSandboxAccess(userId, sandboxId); return ConformanceSandbox.completeCurrentAction( persistenceProvider, deferredSandboxTaskConsumer, sandboxId); diff --git a/spring-boot/src/test/java/org/dcsa/conformance/springboot/ConformanceApplicationTest.java b/spring-boot/src/test/java/org/dcsa/conformance/springboot/ConformanceApplicationTest.java index 389e5b25..6a837d3e 100644 --- a/spring-boot/src/test/java/org/dcsa/conformance/springboot/ConformanceApplicationTest.java +++ b/spring-boot/src/test/java/org/dcsa/conformance/springboot/ConformanceApplicationTest.java @@ -5,7 +5,6 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.time.StopWatch; -import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; @@ -47,7 +46,7 @@ void testEachSuite(final String sandboxId) throws InterruptedException { log.info("Starting scenario suite: {}", sandboxId); // validate if scenario is listed String rootURL = restTemplate.getForObject("http://localhost:" + port + "/", String.class); - Assumptions.assumeTrue(rootURL.contains(sandboxId), sandboxId + " not found in root URL, skipping in this branch!"); + assertTrue(rootURL.contains(sandboxId), sandboxId + " not found in root URL, skipping in this branch!"); // Start the scenario String value = restTemplate.getForObject("http://localhost:" + port + getAppURL(sandboxId, "reset"), String.class);