diff --git a/booking/src/main/java/org/dcsa/conformance/standards/booking/checks/BookingChecks.java b/booking/src/main/java/org/dcsa/conformance/standards/booking/checks/BookingChecks.java index 75062c54..ef02e31a 100644 --- a/booking/src/main/java/org/dcsa/conformance/standards/booking/checks/BookingChecks.java +++ b/booking/src/main/java/org/dcsa/conformance/standards/booking/checks/BookingChecks.java @@ -508,6 +508,34 @@ private static JsonNode getShipmentLocationTypeCode(JsonNode body, @NonNull Stri return issues; }); + static final JsonContentCheck CHECK_CARGO_GROSS_WEIGHT_CONDITIONS = + JsonAttribute.allIndividualMatchesMustBeValid( + "Check Cargo Gross Weight conditions", + mav -> mav.submitAllMatching("requestedEquipments.*"), + (nodeToValidate, contextPath) -> { + var issues = new LinkedHashSet(); + var cargoGrossWeight = nodeToValidate.path("cargoGrossWeight"); + if (cargoGrossWeight.isMissingNode() || cargoGrossWeight.isNull()) { + var commodities = nodeToValidate.path("commodities"); + if (!(commodities.isMissingNode() || commodities.isNull()) && commodities.isArray()) { + AtomicInteger commodityCounter = new AtomicInteger(0); + StreamSupport.stream(commodities.spliterator(), false) + .forEach( + commodity -> { + var commodityGrossWeight = commodity.path("cargoGrossWeight"); + int currentCommodityCount = commodityCounter.getAndIncrement(); + if (commodityGrossWeight.isMissingNode() + || commodityGrossWeight.isNull()) { + issues.add( + "The '%s' must have cargo gross weight at commodities position %s" + .formatted(contextPath, currentCommodityCount)); + } + }); + } + } + return issues; + }); + private static Supplier delayedValue(Supplier cspSupplier, Function field) { return () -> { var csp = cspSupplier.get(); @@ -611,6 +639,7 @@ private static void generateScenarioRelatedChecks(List checks, VALIDATE_SHIPPER_MINIMUM_REQUEST_FIELDS, VALIDATE_DOCUMENT_PARTY, NATIONAL_COMMODITY_TYPE_CODE_VALIDATION, + CHECK_CARGO_GROSS_WEIGHT_CONDITIONS, JsonAttribute.atLeastOneOf( JsonPointer.compile("/expectedDepartureDate"), JsonPointer.compile("/expectedArrivalAtPlaceOfDeliveryStartDate"), diff --git a/booking/src/test/java/org/dcsa/conformance/standards/booking/checks/BookingChecksTest.java b/booking/src/test/java/org/dcsa/conformance/standards/booking/checks/BookingChecksTest.java new file mode 100644 index 00000000..676850f2 --- /dev/null +++ b/booking/src/test/java/org/dcsa/conformance/standards/booking/checks/BookingChecksTest.java @@ -0,0 +1,96 @@ +package org.dcsa.conformance.standards.booking.checks; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.dcsa.conformance.core.check.JsonContentCheck; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Set; + +import static org.dcsa.conformance.core.toolkit.JsonToolkit.OBJECT_MAPPER; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class BookingChecksTest { + + private ObjectNode booking; + private ObjectNode requestedEquipment; + private ArrayNode requestedEquipments; + private ObjectNode commodity; + private ArrayNode commodities; + + @BeforeEach + void setUp() { + booking = OBJECT_MAPPER.createObjectNode(); + requestedEquipment = OBJECT_MAPPER.createObjectNode(); + requestedEquipments = OBJECT_MAPPER.createArrayNode(); + commodity = OBJECT_MAPPER.createObjectNode(); + commodities = OBJECT_MAPPER.createArrayNode(); + } + + @Test + void testCargoGrossWeightPresentAtRequestedEquipment_valid() { + requestedEquipment.set("cargoGrossWeight", OBJECT_MAPPER.createObjectNode()); + requestedEquipments.add(requestedEquipment); + booking.set("requestedEquipments", requestedEquipments); + JsonContentCheck check = BookingChecks.CHECK_CARGO_GROSS_WEIGHT_CONDITIONS; + Set error = check.validate(booking); + assertTrue(error.isEmpty()); + } + + @Test + void testCargoGrossWeightMissingAtRequestedEquipmentNoCommodities_valid() { + + booking.set("requestedEquipments", requestedEquipments); + JsonContentCheck check = BookingChecks.CHECK_CARGO_GROSS_WEIGHT_CONDITIONS; + Set errors = check.validate(booking); + assertTrue(errors.isEmpty()); + } + + @Test + void testCargoGrossWeightMissingAtRequestedEquipmentPresentAtCommodities_valid() { + commodity.set("cargoGrossWeight", OBJECT_MAPPER.createObjectNode()); + commodities.add(commodity); + requestedEquipment.set("commodities", commodities); + requestedEquipments.add(requestedEquipment); + booking.set("requestedEquipments", requestedEquipments); + JsonContentCheck check = BookingChecks.CHECK_CARGO_GROSS_WEIGHT_CONDITIONS; + Set errors = check.validate(booking); + assertTrue(errors.isEmpty()); + } + + @Test + void testCargoGrossWeightMissingInRequestedEquipmentsAndAlsoInCommodities_invalid() { + + commodities.add(commodity); + requestedEquipment.set("commodities", commodities); + requestedEquipments.add(requestedEquipment); + booking.set("requestedEquipments", requestedEquipments); + + JsonContentCheck check = BookingChecks.CHECK_CARGO_GROSS_WEIGHT_CONDITIONS; + Set errors = check.validate(booking); + assertEquals(1, errors.size()); + assertTrue( + errors.contains( + "The 'requestedEquipments[0]' must have cargo gross weight at commodities position 0")); + } + + @Test + void testCargoGrossWeightMissingInRequestedEquipmentsAndInOneOfTheCommodities_invalid() { + + ObjectNode commodity2 = OBJECT_MAPPER.createObjectNode(); + commodity.set("cargoGrossWeight", OBJECT_MAPPER.createObjectNode()); + commodities.add(commodity2); + commodities.add(commodity); + requestedEquipment.set("commodities", commodities); + requestedEquipments.add(requestedEquipment); + booking.set("requestedEquipments", requestedEquipments); + JsonContentCheck check = BookingChecks.CHECK_CARGO_GROSS_WEIGHT_CONDITIONS; + Set errors = check.validate(booking); + assertEquals(1, errors.size()); + assertTrue( + errors.contains( + "The 'requestedEquipments[0]' must have cargo gross weight at commodities position 0")); + } +}