diff --git a/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4660.xml b/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4660.xml index 0c10a0faf..5a53562ee 100644 --- a/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4660.xml +++ b/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4660.xml @@ -498,4 +498,358 @@ + + + + + + + + + + template_id = 2004 + + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20301 + + + br_id = 'VP-L01-00-0301' + + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20302 + + + br_id = 'VP-L01-00-20302' + + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20321 + + + br_id = 'VP-L01-00-0321' + + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20331 + + + br_id = 'VP-L01-00-0331' + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20311 + + + br_id = 'VP-L01-00-0311' + + + + + + + + + + + + + + template_id = 2004 + + + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20321 + + + br_id = 'VP-L01-00-0321' + + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20331 + + + br_id = 'VP-L01-00-0331' + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20401 + + + br_id = 'VP-L01-00-0401' + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20411 + + + br_id = 'VP-L01-00-0411' + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20330 + + + br_id = 'VP-L03-00-0330' + + + + + + + + + + + + + + + + + + + + + + + + + + rule_id = 20320 + + + br_id = 'VP-L03-00-0320' + + + + diff --git a/model/src/main/resources/contract/Template.xsd b/model/src/main/resources/contract/Template.xsd index e07152f21..2e7a2b952 100755 --- a/model/src/main/resources/contract/Template.xsd +++ b/model/src/main/resources/contract/Template.xsd @@ -91,6 +91,7 @@ + \ No newline at end of file diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/bean/ContainerType.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/bean/ContainerType.java index 7d529af6d..857cbff64 100644 --- a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/bean/ContainerType.java +++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/bean/ContainerType.java @@ -48,7 +48,7 @@ public enum ContainerType { FactType.SALES_AUCTION_SALE, FactType.SALES_FLUX_SALES_QUERY_MESSAGE, FactType.SALES_QUERY_PARAMETER, FactType.SALES_FLUX_SALES_RESPONSE_MESSAGE), MOVEMENTS("movement","ec.europa.eu.movement", FactType.MOVEMENT_REPORT_DOCUMENT, FactType.MOVEMENT_REPORT_DOCUMENT_ID, - FactType.MOVEMENT_REPORT_DOC_OWNER_FLUX_PARTY_ID, FactType.MOVEMENT_VESSEL_TRANSPORT_MEANS_ID); + FactType.MOVEMENT_REPORT_DOC_OWNER_FLUX_PARTY_ID, FactType.MOVEMENT_VESSEL_TRANSPORT_MEANS_ID, FactType.MOVEMENT_SPECIFIED_VESSEL_POSITION_EVENT); private final String packageName; private final String containerName; diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/fact/MovementSpecifiedVesselPositionEventFact.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/fact/MovementSpecifiedVesselPositionEventFact.java new file mode 100644 index 000000000..91c44b5c6 --- /dev/null +++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/fact/MovementSpecifiedVesselPositionEventFact.java @@ -0,0 +1,68 @@ +package eu.europa.ec.fisheries.uvms.rules.service.business.fact; + +import eu.europa.ec.fisheries.schema.rules.template.v1.FactType; +import eu.europa.ec.fisheries.uvms.rules.service.business.AbstractFact; +import lombok.Data; +import org.joda.time.DateTime; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._18.VesselGeographicalCoordinateType; +import un.unece.uncefact.data.standard.unqualifieddatatype._18.CodeType; +import un.unece.uncefact.data.standard.unqualifieddatatype._18.DateTimeType; + +import java.math.BigDecimal; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoField; + +@Data +public class MovementSpecifiedVesselPositionEventFact extends AbstractFact { + private CodeType typeCode; + private DateTime creationDateTime; + private BigDecimal speedValue; + private BigDecimal courseValue; + private String creationDateTimeString; + private BigDecimal latitudeMeasure; + private BigDecimal longitudeMeasure; + + public boolean hasValidSpeedValue(BigDecimal speedValue) { + return speedValue.signum() > 0 && speedValue.scale() < 3; + } + + public boolean hasValidCourseValue(BigDecimal courseValue) { + return courseValue.compareTo(new BigDecimal(360)) <= 0 && courseValue.compareTo(BigDecimal.ZERO) >= 0; + } + + public boolean hasValidTypeCodeValueListID(CodeType typeCode) { + return typeCode.getListID().equals("FLUX_VESSEL_POSITION_TYPE"); + } + + public boolean hasValidCreationDateTime(String creationDateTimeString) { + DateTimeFormatter formatter = new DateTimeFormatterBuilder() + .parseStrict() + .appendPattern("yyyy-MM-dd'T'HH:mm:ss") + .optionalStart() + .appendFraction(ChronoField.MICRO_OF_SECOND, 1, 6, true) + .optionalEnd() + .appendLiteral('Z')//timezone must always be utc, thus the literal Z + .parseStrict().toFormatter(); + try { + formatter.parse(creationDateTimeString); + } catch (DateTimeParseException e) { + return false; + } + return true; + } + + public boolean hasValidLatitudeMeasure(BigDecimal latitudeMeasure) { + return latitudeMeasure.compareTo(new BigDecimal(90)) <= 0 && latitudeMeasure.compareTo(new BigDecimal(-90)) >= 0 && latitudeMeasure.scale() >= 3 && latitudeMeasure.scale() <= 6; + } + + public boolean hasValidLongitudeMeasure(BigDecimal longitudeMeasure) { + return longitudeMeasure.compareTo(new BigDecimal(180)) <= 0 && longitudeMeasure.compareTo(new BigDecimal(-180)) >= 0 && longitudeMeasure.scale() >= 3 && longitudeMeasure.scale() <= 6; + } + + @Override + public void setFactType() { + this.factType = FactType.MOVEMENT_SPECIFIED_VESSEL_POSITION_EVENT; + } +} \ No newline at end of file diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/generator/MovementFactGenerator.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/generator/MovementFactGenerator.java index 29e8c48ab..cbc5e64a8 100644 --- a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/generator/MovementFactGenerator.java +++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/generator/MovementFactGenerator.java @@ -18,8 +18,6 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The import eu.europa.ec.fisheries.uvms.rules.service.mapper.xpath.util.XPathStringWrapper; import un.unece.uncefact.data.standard.fluxvesselpositionmessage._4.FLUXVesselPositionMessage; import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._18.FLUXReportDocumentType; -import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._18.VesselTransportMeansType; -import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.VesselTransportMeans; import java.util.ArrayList; import java.util.List; @@ -59,6 +57,7 @@ public List generateAllFacts() { facts.addAll(movementReportDocumentFactMapper.generateFactForMovementReportDocumentId(vesselPositionMessage)); facts.addAll(movementReportDocumentFactMapper.generateFactForMovementReportDocOwnerFluxPartyId(vesselPositionMessage)); facts.addAll(movementReportDocumentFactMapper.generateFactForMovementVesselTransportMeansId(vesselPositionMessage)); + facts.addAll(movementReportDocumentFactMapper.generateFactForSpecifiedVesselPositionEvent(vesselPositionMessage)); } String df = (String) extraValueMap.get(DATA_FLOW); diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/helper/DrtPathHelper.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/helper/DrtPathHelper.java index fbb8663d2..5447865bb 100644 --- a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/helper/DrtPathHelper.java +++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/helper/DrtPathHelper.java @@ -38,6 +38,7 @@ public enum DrtPathHelper { MOVEMENT_REPORT_DOCUMENT_ID("/templates/MovementReportDocumentId.drt"), MOVEMENT_REPORT_DOC_OWNER_FLUX_PARTY_ID("/templates/MovementReportDocOwnerFluxPartyId.drt"), MOVEMENT_VESSEL_TRANSPORT_MEANS_ID("/templates/MovementVesselTransportMeansId.drt"), + MOVEMENT_SPECIFIED_VESSEL_POSITION_EVENT("/templates/MovementSpecifiedVesselPositionEvent.drt"), FA_RELOCATION("/templates/FaRelocation.drt"), FA_RESPONSE("/templates/FaResponse.drt"), FA_TRANSHIPMENT("/templates/FaTranshipment.drt"), diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/constants/XPathConstants.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/constants/XPathConstants.java index a65bb751b..8511ef1c6 100644 --- a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/constants/XPathConstants.java +++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/constants/XPathConstants.java @@ -118,5 +118,10 @@ public class XPathConstants { public static final String RESPONSE_CODE = "ResponseCode"; public static final String RESPONDENT_FLUX_PARTY = "RespondentFLUXParty"; public static final String SPECIFIED_VESSELPOSITION_EVENT = "SpecifiedVesselPositionEvent"; - + public static final String SPEED_VALUE_MEASURE = "SpeedValueMeasure"; + public static final String COURSE_VALUE_MEASURE = "CourseValueMeasure"; + public static final String OBTAINED_OCCURRENCE_DATE_TIME = "ObtainedOccurrenceDateTime"; + public static final String SPECIFIED_VESSEL_GEOGRAPHICAL_COORDINATE = "SpecifiedVesselGeographicalCoordinate"; + public static final String LATITUDE_MEASURE = "LatitudeMeasure"; + public static final String LONGITUDE_MEASURE = "LongitudeMeasure"; } diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/mapper/fact/MovementReportDocumentFactMapper.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/mapper/fact/MovementReportDocumentFactMapper.java index e9cf509d7..e11817e9e 100644 --- a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/mapper/fact/MovementReportDocumentFactMapper.java +++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/mapper/fact/MovementReportDocumentFactMapper.java @@ -11,6 +11,7 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The package eu.europa.ec.fisheries.uvms.rules.service.mapper.fact; + import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.CREATION_DATE_TIME; import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.FLUX_REPORT_DOCUMENT; import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.MOVEMENT_REPORT_DOCUMENT; @@ -19,7 +20,14 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.REGISTRATION_VESSEL_COUNTRY; import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.VESSEL_TRANSPORT_MEANS; import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.VESSEL_TRANSPORT_MEANS_ID; - +import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.TYPE_CODE; +import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.SPEED_VALUE_MEASURE; +import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.SPECIFIED_VESSELPOSITION_EVENT; +import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.COURSE_VALUE_MEASURE; +import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.OBTAINED_OCCURRENCE_DATE_TIME; +import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.SPECIFIED_VESSEL_GEOGRAPHICAL_COORDINATE; +import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.LATITUDE_MEASURE; +import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.LONGITUDE_MEASURE; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -28,12 +36,14 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The import eu.europa.ec.fisheries.uvms.rules.service.business.fact.MovementReportDocOwnerFluxPartyIdFact; import eu.europa.ec.fisheries.uvms.rules.service.business.fact.MovementReportDocumentFact; import eu.europa.ec.fisheries.uvms.rules.service.business.fact.MovementReportDocumentIdFact; +import eu.europa.ec.fisheries.uvms.rules.service.business.fact.MovementSpecifiedVesselPositionEventFact; import eu.europa.ec.fisheries.uvms.rules.service.business.fact.MovementVesselTransportMeansIdFact; import eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants; import eu.europa.ec.fisheries.uvms.rules.service.mapper.xpath.util.XPathStringWrapper; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import un.unece.uncefact.data.standard.fluxvesselpositionmessage._4.FLUXVesselPositionMessage; +import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._18.VesselPositionEventType; import un.unece.uncefact.data.standard.unqualifieddatatype._18.CodeType; import un.unece.uncefact.data.standard.unqualifieddatatype._18.DateTimeType; import un.unece.uncefact.data.standard.unqualifieddatatype._18.IDType; @@ -157,6 +167,58 @@ public List generateFactForMovementVesselTra return factList; } + public List generateFactForSpecifiedVesselPositionEvent(FLUXVesselPositionMessage vesselPositionMessage) { + + String partialXpath = xPathUtil.append(MOVEMENT_REPORT_DOCUMENT).append(VESSEL_TRANSPORT_MEANS).getValue(); + List factList = new ArrayList<>(); + + if(vesselPositionMessage == null || vesselPositionMessage.getVesselTransportMeans() == null || vesselPositionMessage.getVesselTransportMeans().getSpecifiedVesselPositionEvents().isEmpty()){ + xPathUtil.clear(); + return factList; + } + + List specifiedVesselPositionEvents= vesselPositionMessage.getVesselTransportMeans().getSpecifiedVesselPositionEvents(); + Date creationDate = getDate(vesselPositionMessage.getFLUXReportDocument().getCreationDateTime()); + int index = 1; + for(VesselPositionEventType vesselPositionEventType: specifiedVesselPositionEvents) { + MovementSpecifiedVesselPositionEventFact fact = new MovementSpecifiedVesselPositionEventFact(); + fact.setCreationDateTime(new DateTime(creationDate)); + + fact.setTypeCode(vesselPositionEventType.getTypeCode()); + xPathUtil.appendWithoutWrapping(partialXpath).appendWithIndex(SPECIFIED_VESSELPOSITION_EVENT, index).append(TYPE_CODE).storeInRepo(fact, "typeCode"); + + if (vesselPositionEventType.getSpeedValueMeasure() != null) { + fact.setSpeedValue(vesselPositionEventType.getSpeedValueMeasure().getValue()); + xPathUtil.appendWithoutWrapping(partialXpath).appendWithIndex(SPECIFIED_VESSELPOSITION_EVENT, index).append(SPEED_VALUE_MEASURE).storeInRepo(fact, "speedValue"); + } else { + xPathUtil.appendWithoutWrapping(partialXpath).appendWithIndex(SPECIFIED_VESSELPOSITION_EVENT, index).storeInRepo(fact, "speedValue"); + } + + + if (vesselPositionEventType.getCourseValueMeasure() != null) { + fact.setCourseValue(vesselPositionEventType.getCourseValueMeasure().getValue()); + xPathUtil.appendWithoutWrapping(partialXpath).appendWithIndex(SPECIFIED_VESSELPOSITION_EVENT, index).append(COURSE_VALUE_MEASURE).storeInRepo(fact, "courseValue"); + } else { + fact.setCourseValue(null); + xPathUtil.appendWithoutWrapping(partialXpath).appendWithIndex(SPECIFIED_VESSELPOSITION_EVENT, index).storeInRepo(fact, "courseValue"); + } + + fact.setCreationDateTimeString(dateTimeAsString(vesselPositionEventType.getObtainedOccurrenceDateTime())); + xPathUtil.appendWithoutWrapping(partialXpath).appendWithIndex(SPECIFIED_VESSELPOSITION_EVENT, index).append(OBTAINED_OCCURRENCE_DATE_TIME).storeInRepo(fact, "creationDateTimeString"); + + fact.setLatitudeMeasure(vesselPositionEventType.getSpecifiedVesselGeographicalCoordinate().getLatitudeMeasure().getValue()); + xPathUtil.appendWithoutWrapping(partialXpath).appendWithIndex(SPECIFIED_VESSELPOSITION_EVENT, index).append(SPECIFIED_VESSEL_GEOGRAPHICAL_COORDINATE).append(LATITUDE_MEASURE).storeInRepo(fact, "latitudeMeasure"); + + fact.setLongitudeMeasure(vesselPositionEventType.getSpecifiedVesselGeographicalCoordinate().getLongitudeMeasure().getValue()); + xPathUtil.appendWithoutWrapping(partialXpath).appendWithIndex(SPECIFIED_VESSELPOSITION_EVENT, index).append(SPECIFIED_VESSEL_GEOGRAPHICAL_COORDINATE).append(LONGITUDE_MEASURE).storeInRepo(fact, "longitudeMeasure"); + + factList.add(fact); + index ++; + } + + return factList; + } + public static MovementReportDocumentFact mapToMovementReportDocumentFact(FLUXVesselPositionMessage vesselPositionMessage){ if(vesselPositionMessage == null || vesselPositionMessage.getFLUXReportDocument() == null){ diff --git a/service/src/main/resources/templates/MovementSpecifiedVesselPositionEvent.drt b/service/src/main/resources/templates/MovementSpecifiedVesselPositionEvent.drt new file mode 100644 index 000000000..8e2985dac --- /dev/null +++ b/service/src/main/resources/templates/MovementSpecifiedVesselPositionEvent.drt @@ -0,0 +1,34 @@ +template header + +tname +expression +brid +rulemsg +type +level +propertyNames +context + +package eu.europa.ec.fisheries.uvms.rules.service.business.activity; + +import eu.europa.ec.fisheries.uvms.rules.service.business.fact.MovementSpecifiedVesselPositionEventFact; +import java.util.Arrays; +global eu.europa.ec.fisheries.uvms.rules.service.business.helper.RuleApplicabilityChecker appliChecker; +global eu.europa.ec.fisheries.uvms.rules.service.MDRCacheRuleService mdrService; + + +template "@{tname}" + +rule "Specified Vessel Position Event Type Code Fact @{tname} - @{brid} - Context : @{context}" + +when + + $fact : MovementSpecifiedVesselPositionEventFact((appliChecker.isApplicable("@{brid}", "@{context}", getMessageDataFlow(), getCreationDateOfMessage(), mdrService)) && (@{expression})) + +then + $fact.setOk(false); + $fact.addWarningOrError(mdrService.getErrorTypeStrForForBrIAndDFAndValidity("@{brid}", "@{context}", $fact.getCreationJavaDateOfMessage()), mdrService.getErrorMessageForBrIAndDFAndValidity("@{brid}", "@{context}", $fact.getCreationJavaDateOfMessage()), "@{brid}", "@{level}", "@{propertyNames}"); + +end + +end template \ No newline at end of file