diff --git a/LIQUIBASE/changelog/db-changelog-master.xml b/LIQUIBASE/changelog/db-changelog-master.xml
index 8a3a3fd31..ae2017946 100644
--- a/LIQUIBASE/changelog/db-changelog-master.xml
+++ b/LIQUIBASE/changelog/db-changelog-master.xml
@@ -97,4 +97,5 @@
+
diff --git a/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4660.xml b/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4660.xml
index 0c10a0faf..bc0b72406 100644
--- a/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4660.xml
+++ b/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4660.xml
@@ -498,4 +498,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rule_id = 20004
+
+
+ br_id = 'VP-L03-00-0004'
+
+
+
+
diff --git a/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4945.xml b/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4945.xml
new file mode 100644
index 000000000..4d805ea05
--- /dev/null
+++ b/LIQUIBASE/changelog/v3.4/db-changelog-UNIONVMS-4945.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/MovementDocumentIdDao.java b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/MovementDocumentIdDao.java
new file mode 100644
index 000000000..4694ee1b4
--- /dev/null
+++ b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/MovementDocumentIdDao.java
@@ -0,0 +1,55 @@
+/*
+ Developed by the European Commission - Directorate General for Maritime Affairs and Fisheries @ European Union, 2015-2016.
+
+ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The IFDM Suite is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of
+ the License, or any later version. The IFDM Suite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details. You should have received a copy of the GNU General Public License along with the IFDM Suite. If not, see .
+ */
+
+package eu.europa.ec.fisheries.uvms.rules.dao;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import eu.europa.ec.fisheries.uvms.commons.service.dao.AbstractDAO;
+import eu.europa.ec.fisheries.uvms.rules.entity.MovementDocumentId;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+
+public class MovementDocumentIdDao extends AbstractDAO {
+
+ private EntityManager em;
+
+ public MovementDocumentIdDao(EntityManager em) {
+ this.em = em;
+ }
+
+ @Override public EntityManager getEntityManager() {
+ return em;
+ }
+
+ public List loadMovementDocumentIDByIds(Set ids) {
+ Set stringSet = new HashSet<>();
+ if(CollectionUtils.isEmpty(ids)){
+ return new ArrayList<>();
+ }
+ for (MovementDocumentId id : ids) {
+ String uuid = id.getUuid();
+ if(StringUtils.isNotEmpty(uuid)){
+ stringSet.add(uuid);
+ stringSet.add(uuid.toLowerCase());
+ stringSet.add(uuid.toUpperCase());
+ }
+ }
+ Query query = getEntityManager().createNamedQuery(MovementDocumentId.LOAD_BY_UUID);
+ query.setParameter("uuids", stringSet);
+ return query.getResultList();
+ }
+
+}
diff --git a/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/MovementDocumentIdLockDao.java b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/MovementDocumentIdLockDao.java
new file mode 100644
index 000000000..b06a1f290
--- /dev/null
+++ b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/MovementDocumentIdLockDao.java
@@ -0,0 +1,10 @@
+package eu.europa.ec.fisheries.uvms.rules.dao;
+
+import javax.ejb.Local;
+
+@Local
+public interface MovementDocumentIdLockDao {
+ void takeNoteOfDocumentIdInNewTx(String documentId);
+
+ void lock(String documentId);
+}
diff --git a/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/RulesDao.java b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/RulesDao.java
index be2c80216..acabf0d9c 100644
--- a/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/RulesDao.java
+++ b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/RulesDao.java
@@ -20,6 +20,7 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The
import eu.europa.ec.fisheries.uvms.rules.entity.AlarmReport;
import eu.europa.ec.fisheries.uvms.rules.entity.CustomRule;
import eu.europa.ec.fisheries.uvms.rules.entity.FADocumentID;
+import eu.europa.ec.fisheries.uvms.rules.entity.MovementDocumentId;
import eu.europa.ec.fisheries.uvms.rules.entity.PreviousReport;
import eu.europa.ec.fisheries.uvms.rules.entity.RawMessage;
import eu.europa.ec.fisheries.uvms.rules.entity.RuleSubscription;
@@ -168,13 +169,21 @@ List getTicketListPaginated(Integer page, Integer listSize, String sql,
List getValidationMessagesByRawMsgGuid(String rawMsgGuid, String type) throws DaoException;
List loadFADocumentIDByIdsByIds(Set incomingIDs);
+
+ List loadMovementDocumentIDByIds(Set incomingIDs);
void takeNoteOfDocumentIds(Set incomingIDs);
+
+ void takeNoteOfMovementDocumentIds(Set incomingIDs);
List lockDocumentIds(Set incomingIDs);
+
+ List lockMovementDocumentIds(Set incomingIDs);
void createFaDocumentIdEntity(Set incomingID) throws ServiceException;
-
+
+ void createMovementDocumentIdEntity(Set incomingID) throws ServiceException;
+
void saveFaIdsPerTripList(List tripList);
List loadExistingFaIdsPerTrip(List idsFromIncommingMessage);
diff --git a/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/bean/MovementDocumentIdLockDaoBean.java b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/bean/MovementDocumentIdLockDaoBean.java
new file mode 100644
index 000000000..d979a080f
--- /dev/null
+++ b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/bean/MovementDocumentIdLockDaoBean.java
@@ -0,0 +1,40 @@
+package eu.europa.ec.fisheries.uvms.rules.dao.bean;
+
+import static javax.ejb.TransactionAttributeType.REQUIRES_NEW;
+
+import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.persistence.EntityManager;
+import javax.persistence.LockModeType;
+import javax.persistence.PersistenceContext;
+import java.util.Collections;
+import java.util.Map;
+
+import eu.europa.ec.fisheries.uvms.rules.dao.MovementDocumentIdLockDao;
+import eu.europa.ec.fisheries.uvms.rules.entity.MovementDocumentIdLock;
+
+@Stateless
+public class MovementDocumentIdLockDaoBean implements MovementDocumentIdLockDao {
+
+ private static final Map ZERO_LOCK_TIMEOUT = Collections.singletonMap("javax.persistence.lock.timeout", 0);
+
+ @PersistenceContext(unitName = "rulesPostgresPU")
+ public EntityManager em;
+
+ @TransactionAttribute(REQUIRES_NEW)
+ @Override
+ public void takeNoteOfDocumentIdInNewTx(String documentId) {
+ MovementDocumentIdLock lock = em.find(MovementDocumentIdLock.class, documentId);
+ if( lock == null ) {
+ em.persist(new MovementDocumentIdLock(documentId));
+ }
+ }
+
+ @Override
+ public void lock(String documentId) {
+ MovementDocumentIdLock lock = em.find(MovementDocumentIdLock.class, documentId, LockModeType.PESSIMISTIC_WRITE, ZERO_LOCK_TIMEOUT);
+ if( lock == null ) {
+ throw new IllegalStateException("lock " + documentId + " should have been created");
+ }
+ }
+}
diff --git a/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/bean/RulesDaoBean.java b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/bean/RulesDaoBean.java
index 05888df01..2c8570343 100644
--- a/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/bean/RulesDaoBean.java
+++ b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/dao/bean/RulesDaoBean.java
@@ -33,6 +33,8 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The
import eu.europa.ec.fisheries.uvms.rules.dao.FADocumentIDDAO;
import eu.europa.ec.fisheries.uvms.rules.dao.FaDocumentIdLockDao;
import eu.europa.ec.fisheries.uvms.rules.dao.FaIdsPerTripDao;
+import eu.europa.ec.fisheries.uvms.rules.dao.MovementDocumentIdDao;
+import eu.europa.ec.fisheries.uvms.rules.dao.MovementDocumentIdLockDao;
import eu.europa.ec.fisheries.uvms.rules.dao.RawMessageDao;
import eu.europa.ec.fisheries.uvms.rules.dao.RulesDao;
import eu.europa.ec.fisheries.uvms.rules.dao.TemplateDao;
@@ -41,6 +43,7 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The
import eu.europa.ec.fisheries.uvms.rules.entity.CustomRule;
import eu.europa.ec.fisheries.uvms.rules.entity.FADocumentID;
import eu.europa.ec.fisheries.uvms.rules.entity.FaIdsPerTrip;
+import eu.europa.ec.fisheries.uvms.rules.entity.MovementDocumentId;
import eu.europa.ec.fisheries.uvms.rules.entity.PreviousReport;
import eu.europa.ec.fisheries.uvms.rules.entity.RawMessage;
import eu.europa.ec.fisheries.uvms.rules.entity.RuleSubscription;
@@ -67,10 +70,14 @@ public class RulesDaoBean implements RulesDao {
private ValidationMessageDao validationMessageDao;
private FADocumentIDDAO fishingActivityIdDao;
private FaIdsPerTripDao faIdsPerTripDao;
+ private MovementDocumentIdDao movementDocumentIdDao;
@EJB
private FaDocumentIdLockDao faDocumentIdLockDao;
+ @EJB
+ private MovementDocumentIdLockDao movementDocumentIdLockDao;
+
@PersistenceContext(unitName = "rulesPostgresPU")
public EntityManager em;
@@ -81,6 +88,7 @@ public void init() {
validationMessageDao = new ValidationMessageDao(em);
fishingActivityIdDao = new FADocumentIDDAO(em);
faIdsPerTripDao = new FaIdsPerTripDao(em);
+ movementDocumentIdDao = new MovementDocumentIdDao(em);
}
@Override
@@ -617,6 +625,11 @@ public List loadFADocumentIDByIdsByIds(Set incomingI
return fishingActivityIdDao.loadFADocumentIDByIdsByIds(incomingIDs);
}
+ @Override
+ public List loadMovementDocumentIDByIds(Set incomingIDs) {
+ return movementDocumentIdDao.loadMovementDocumentIDByIds(incomingIDs);
+ }
+
@Override
public void takeNoteOfDocumentIds(Set incomingIDs) {
incomingIDs.stream()
@@ -625,6 +638,14 @@ public void takeNoteOfDocumentIds(Set incomingIDs) {
.forEach(this::takeNoteOfDocumentIdAllowingDuplicates);
}
+ @Override
+ public void takeNoteOfMovementDocumentIds(Set incomingIDs) {
+ incomingIDs.stream()
+ .map(MovementDocumentId::getUuid)
+ .sorted()
+ .forEach(this::takeNoteOfMovementDocumentIdAllowingDuplicates);
+ }
+
private void takeNoteOfDocumentIdAllowingDuplicates(String documentId) {
try {
faDocumentIdLockDao.takeNoteOfDocumentIdInNewTx(documentId);
@@ -633,6 +654,14 @@ private void takeNoteOfDocumentIdAllowingDuplicates(String documentId) {
}
}
+ private void takeNoteOfMovementDocumentIdAllowingDuplicates(String documentId) {
+ try {
+ movementDocumentIdLockDao.takeNoteOfDocumentIdInNewTx(documentId);
+ } catch( EntityExistsException eee ) {
+ // ignore it
+ }
+ }
+
public List lockDocumentIds(Set incomingIDs) {
return incomingIDs.stream()
.map(FADocumentID::getUuid)
@@ -641,6 +670,15 @@ public List lockDocumentIds(Set incomingIDs) {
.collect(Collectors.toList());
}
+ @Override
+ public List lockMovementDocumentIds(Set incomingIDs) {
+ return incomingIDs.stream()
+ .map(MovementDocumentId::getUuid)
+ .sorted()
+ .peek(movementDocumentIdLockDao::lock)
+ .collect(Collectors.toList());
+ }
+
@Override
public void createFaDocumentIdEntity(Set incomingIDsList) throws ServiceException {
if(CollectionUtils.isNotEmpty(incomingIDsList)){
@@ -650,6 +688,13 @@ public void createFaDocumentIdEntity(Set incomingIDsList) throws S
}
}
+ @Override
+ public void createMovementDocumentIdEntity(Set incomingID) throws ServiceException {
+ for(MovementDocumentId movementDocumentId: incomingID) {
+ movementDocumentIdDao.createEntity(movementDocumentId);
+ }
+ }
+
@Override
public void saveFaIdsPerTripList(List tripList) {
if(CollectionUtils.isNotEmpty(tripList)){
diff --git a/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/entity/MovementDocumentId.java b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/entity/MovementDocumentId.java
new file mode 100644
index 000000000..fa897ab00
--- /dev/null
+++ b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/entity/MovementDocumentId.java
@@ -0,0 +1,60 @@
+/*
+ Developed by the European Commission - Directorate General for Maritime Affairs and Fisheries @ European Union, 2015-2016.
+
+ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The IFDM Suite is free software: you can redistribute it
+ and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of
+ the License, or any later version. The IFDM Suite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details. You should have received a copy of the GNU General Public License along with the IFDM Suite. If not, see .
+ */
+
+package eu.europa.ec.fisheries.uvms.rules.entity;
+
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.PrePersist;
+import javax.persistence.Table;
+import java.io.Serializable;
+
+import eu.europa.ec.fisheries.uvms.commons.date.DateUtils;
+import eu.europa.ec.fisheries.uvms.commons.domain.Audit;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+@Table(name = "movement_doc_id")
+@Data
+@Entity
+@EqualsAndHashCode(exclude = {"id", "audit"})
+@NamedQueries({
+ @NamedQuery(name = MovementDocumentId.LOAD_BY_UUID, query = "FROM MovementDocumentId f WHERE f.uuid in (:uuids)")
+})
+@RequiredArgsConstructor
+@NoArgsConstructor
+public class MovementDocumentId implements Serializable {
+
+ public static final String LOAD_BY_UUID = "MovementDocumentId.loadByUUID";
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @NonNull
+ private String uuid;
+
+ @Embedded
+ private Audit audit = new Audit();
+
+ @PrePersist
+ private void prePersist() {
+ audit.setCreatedOn(DateUtils.nowUTC().toDate());
+ }
+
+}
diff --git a/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/entity/MovementDocumentIdLock.java b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/entity/MovementDocumentIdLock.java
new file mode 100644
index 000000000..924b6c409
--- /dev/null
+++ b/domain/src/main/java/eu/europa/ec/fisheries/uvms/rules/entity/MovementDocumentIdLock.java
@@ -0,0 +1,33 @@
+package eu.europa.ec.fisheries.uvms.rules.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+@Entity
+@Table(name = "movement_doc_id_lock")
+@NamedQueries({
+ @NamedQuery(name = MovementDocumentIdLock.LOAD_BY_UUID, query = "FROM MovementDocumentIdLock f WHERE f.uuid in (:uuids)")
+})
+@Data
+@EqualsAndHashCode
+@RequiredArgsConstructor
+@NoArgsConstructor
+public class MovementDocumentIdLock {
+
+ public static final String LOAD_BY_UUID = "MovementDocumentIdLock.loadByUuid";
+
+ @Id
+ @NonNull
+ @Column(name = "uuid")
+ private String uuid;
+}
diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/bean/movement/RulesMovementProcessorBean.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/bean/movement/RulesMovementProcessorBean.java
index c343b9b5c..2a4adb326 100644
--- a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/bean/movement/RulesMovementProcessorBean.java
+++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/bean/movement/RulesMovementProcessorBean.java
@@ -16,6 +16,7 @@
import static eu.europa.ec.fisheries.uvms.movement.model.exception.ErrorCode.MOVEMENT_DUPLICATE_ERROR;
import static eu.europa.ec.fisheries.uvms.rules.service.config.BusinessObjectType.RECEIVING_MOVEMENT_MSG;
import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.DATA_FLOW;
+import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.MOVEMENT_DOC_IDS;
import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.SENDER_RECEIVER;
import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.XML;
@@ -74,6 +75,7 @@
import eu.europa.ec.fisheries.uvms.commons.message.api.MessageException;
import eu.europa.ec.fisheries.uvms.commons.message.impl.JAXBUtils;
import eu.europa.ec.fisheries.uvms.commons.notifications.NotificationMessage;
+import eu.europa.ec.fisheries.uvms.commons.service.exception.ServiceException;
import eu.europa.ec.fisheries.uvms.config.model.mapper.ModuleRequestMapper;
import eu.europa.ec.fisheries.uvms.exchange.model.exception.ExchangeModelMapperException;
import eu.europa.ec.fisheries.uvms.exchange.model.exception.ExchangeModelMarshallException;
@@ -85,6 +87,10 @@
import eu.europa.ec.fisheries.uvms.movement.model.exception.MovementModelException;
import eu.europa.ec.fisheries.uvms.movement.model.mapper.MovementModuleRequestMapper;
import eu.europa.ec.fisheries.uvms.movement.model.mapper.MovementModuleResponseMapper;
+import eu.europa.ec.fisheries.uvms.rules.dao.RulesDao;
+import eu.europa.ec.fisheries.uvms.rules.entity.FADocumentID;
+import eu.europa.ec.fisheries.uvms.rules.entity.FAUUIDType;
+import eu.europa.ec.fisheries.uvms.rules.entity.MovementDocumentId;
import eu.europa.ec.fisheries.uvms.rules.message.consumer.RulesResponseConsumer;
import eu.europa.ec.fisheries.uvms.rules.message.producer.bean.*;
import eu.europa.ec.fisheries.uvms.rules.model.constant.AuditObjectTypeEnum;
@@ -127,8 +133,11 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+import un.unece.uncefact.data.standard.fluxfareportmessage._3.FLUXFAReportMessage;
import un.unece.uncefact.data.standard.fluxvesselpositionmessage._4.FLUXVesselPositionMessage;
import un.unece.uncefact.data.standard.mdr.communication.ObjectRepresentation;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.FAReportDocument;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.FLUXReportDocument;
import un.unece.uncefact.data.standard.unqualifieddatatype._18.IDType;
import javax.annotation.PostConstruct;
@@ -218,6 +227,9 @@ public class RulesMovementProcessorBean {
@AlarmReportCountEvent
private Event alarmReportCountEvent;
+ @Inject
+ private RulesDao rulesDaoBean;
+
private Map mapToMovementType;
private RulesFLUXMessageHelper fluxMessageHelper;
@@ -281,10 +293,16 @@ public void setMovementReportReceived(SetFLUXMovementReportRequest request, Stri
return;
}
+ Set idsFromIncomingMessage = fluxMessageHelper.mapToMovementDocumentID(fluxVesselPositionMessage);
+ rulesDaoBean.takeNoteOfMovementDocumentIds(idsFromIncomingMessage);
+ rulesDaoBean.lockMovementDocumentIds(idsFromIncomingMessage);
+ List storedIds = rulesDaoBean.loadMovementDocumentIDByIds(idsFromIncomingMessage);
+
Map extraValues = new EnumMap<>(ExtraValueType.class);
extraValues.put(SENDER_RECEIVER, request.getSenderOrReceiver());
extraValues.put(XML, request.getRequest());
extraValues.put(DATA_FLOW, request.getFluxDataFlow());
+ extraValues.put(MOVEMENT_DOC_IDS, storedIds);
Collection factsResults = rulesEngine.evaluate(RECEIVING_MOVEMENT_MSG,fluxVesselPositionMessage,extraValues,null);
final String reportId = fluxVesselPositionMessage.getFLUXReportDocument().getIDS().stream()
@@ -300,7 +318,8 @@ public void setMovementReportReceived(SetFLUXMovementReportRequest request, Stri
}
// Decomment this one and comment the other when validation is working! Still work needs to be done after this!
// processReceivedMovementsAsBatch(movementReportsList, pluginType, userName, request.getLogGuid());
- enrichAndSenMovementsAsBatch(validationResult, movementReportsList, userName, request.getLogGuid(), request, request.getLogGuid());
+ idsFromIncomingMessage.removeAll(storedIds);
+ enrichAndSenMovementsAsBatch(validationResult, movementReportsList, userName, request.getLogGuid(), request, request.getLogGuid(), idsFromIncomingMessage);
// Send some response to Movement, if it originated from there (manual movement)
if (MovementSourceType.MANUAL.equals(movementReportsList.get(0).getSource())) {// A person has created a position
ProcessedMovementAck response = MovementModuleResponseMapper.mapProcessedMovementAck(eu.europa.ec.fisheries.schema.movement.common.v1.AcknowledgeTypeType.OK,
@@ -312,7 +331,6 @@ public void setMovementReportReceived(SetFLUXMovementReportRequest request, Stri
}
}
-
/**
* This method is just up until the new movement flow is ready from Swe team!
* It is actually avoiding validation process all together since it doesn't work as of now!
@@ -322,7 +340,7 @@ public void setMovementReportReceived(SetFLUXMovementReportRequest request, Stri
* @param exchangeLogGuid
* @throws RulesServiceException
*/
- private void enrichAndSenMovementsAsBatch(ValidationResult validationResult, List rawMovements, String username, String exchangeLogGuid, SetFLUXMovementReportRequest request, String reportId) throws RulesServiceException {
+ private void enrichAndSenMovementsAsBatch(ValidationResult validationResult, List rawMovements, String username, String exchangeLogGuid, SetFLUXMovementReportRequest request, String reportId, Set idsFromIncomingMessage) throws RulesServiceException {
try {
// Enrich with MobilTerminal and Assets data. Get Mobile Terminal if it exists.
EnrichedMovementWrapper enrichedWrapper = enrichBatchWithMobileTerminalAndAssets(rawMovements);
@@ -330,6 +348,7 @@ private void enrichAndSenMovementsAsBatch(ValidationResult validationResult, Lis
ExchangeLogStatusTypeType status;
if (movementBatchResponse != null && SimpleResponse.OK.equals(movementBatchResponse.getPermitted())) {
if (SimpleResponse.OK.equals(movementBatchResponse.getResponse())) {
+ rulesDaoBean.createMovementDocumentIdEntity(idsFromIncomingMessage);
status = ExchangeLogStatusTypeType.fromValue(fluxMessageHelper.calculateMessageValidationStatus(validationResult).value());
} else {
status = ExchangeLogStatusTypeType.FAILED;
@@ -340,7 +359,7 @@ private void enrichAndSenMovementsAsBatch(ValidationResult validationResult, Lis
}
sendBatchBackToExchange(exchangeLogGuid, rawMovements, MovementRefTypeType.MOVEMENT, username);
updateRequestMessageStatusInExchange(exchangeLogGuid, status);
- } catch (MessageException | MobileTerminalModelMapperException | MobileTerminalUnmarshallException | JMSException | AssetModelMapperException | RulesModelException e) {
+ } catch (MessageException | MobileTerminalModelMapperException | MobileTerminalUnmarshallException | JMSException | AssetModelMapperException | RulesModelException | ServiceException e) {
throw new RulesServiceException(e.getMessage(), e);
}
}
diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/fact/MovementReportDocumentFact.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/fact/MovementReportDocumentFact.java
index 7e7afcedc..45d453442 100644
--- a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/fact/MovementReportDocumentFact.java
+++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/business/fact/MovementReportDocumentFact.java
@@ -40,8 +40,12 @@ public class MovementReportDocumentFact extends AbstractFact {
private VesselCountryType registrationVesselCountry;
private IDType registrationVesselCountryIdType;
private DateTime dateTime;
+ private List existingIds;
-
+ public boolean hasDuplicateId(List ids, List existingIds) {
+ return ids.stream().map(IDType::getValue).anyMatch(existingIds::contains);
+ }
+
public boolean containsTypesOfIdXTimes(List ids,String schemaType,int count){
int counter = 0;
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..ccbf8700b 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
@@ -11,6 +11,15 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The
package eu.europa.ec.fisheries.uvms.rules.service.business.generator;
+import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.DATA_FLOW;
+import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.MOVEMENT_DOC_IDS;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import eu.europa.ec.fisheries.uvms.rules.entity.MovementDocumentId;
import eu.europa.ec.fisheries.uvms.rules.service.business.AbstractFact;
import eu.europa.ec.fisheries.uvms.rules.service.business.MessageType;
import eu.europa.ec.fisheries.uvms.rules.service.exception.RulesValidationException;
@@ -18,14 +27,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;
-
-import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.DATA_FLOW;
-import static eu.europa.ec.fisheries.uvms.rules.service.constants.XPathConstants.MOVEMENT_REPORT_DOCUMENT;
public class MovementFactGenerator extends AbstractGenerator {
@@ -53,7 +54,7 @@ public MovementFactGenerator() {
public List generateAllFacts() {
List facts = new ArrayList<>();
FLUXReportDocumentType fluxReportDocument = vesselPositionMessage.getFLUXReportDocument();
-
+ movementReportDocumentFactMapper.setExistingIds(extractExistingIds());
if (fluxReportDocument != null) {
facts.add(movementReportDocumentFactMapper.generateFactForMovementReportDocument(vesselPositionMessage));
facts.addAll(movementReportDocumentFactMapper.generateFactForMovementReportDocumentId(vesselPositionMessage));
@@ -75,4 +76,13 @@ public void setBusinessObjectMessage(Object businessObject) throws RulesValidati
}
this.vesselPositionMessage = (FLUXVesselPositionMessage) businessObject;
}
+
+ private List extractExistingIds() {
+ @SuppressWarnings("unchecked")
+ List faDocumentIDS = Optional.ofNullable((List) extraValueMap.get(MOVEMENT_DOC_IDS)).orElse(new ArrayList<>());
+ return (faDocumentIDS)
+ .stream()
+ .map(MovementDocumentId::getUuid)
+ .collect(Collectors.toList());
+ }
}
diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/config/ExtraValueType.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/config/ExtraValueType.java
index 036a95740..e127986d7 100644
--- a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/config/ExtraValueType.java
+++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/config/ExtraValueType.java
@@ -22,5 +22,6 @@ public enum ExtraValueType {
CREATION_DATE_OF_MESSAGE,
RESPONSE_IDS,
XML,
- DATA_FLOW
+ DATA_FLOW,
+ MOVEMENT_DOC_IDS
}
diff --git a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/mapper/RulesFLUXMessageHelper.java b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/mapper/RulesFLUXMessageHelper.java
index 60a9c530f..6c57e125f 100644
--- a/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/mapper/RulesFLUXMessageHelper.java
+++ b/service/src/main/java/eu/europa/ec/fisheries/uvms/rules/service/mapper/RulesFLUXMessageHelper.java
@@ -10,15 +10,30 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The
package eu.europa.ec.fisheries.uvms.rules.service.mapper;
-import javax.xml.XMLConstants;
+import static eu.europa.ec.fisheries.schema.rules.rule.v1.RawMsgType.FA_QUERY;
+import static eu.europa.ec.fisheries.schema.rules.rule.v1.RawMsgType.FA_REPORT;
+import static eu.europa.ec.fisheries.schema.rules.rule.v1.RawMsgType.FA_RESPONSE;
+import static eu.europa.ec.fisheries.uvms.rules.entity.FAUUIDType.FA_QUERY_ID;
+import static eu.europa.ec.fisheries.uvms.rules.entity.FAUUIDType.FA_REPORT_REF_ID;
+import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.RESPONSE_IDS;
+import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.SENDER_RECEIVER;
+import static eu.europa.ec.fisheries.uvms.rules.service.mapper.xpath.util.SchemaInitializer.SCHEMA_MAP;
+import static java.util.Collections.singletonList;
+
import javax.xml.bind.UnmarshalException;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-import java.net.URL;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
import eu.europa.ec.fisheries.schema.exchange.v1.ExchangeLogStatusTypeType;
import eu.europa.ec.fisheries.schema.rules.module.v1.RulesModuleMethod;
import eu.europa.ec.fisheries.schema.rules.rule.v1.RawMsgType;
@@ -26,6 +41,7 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The
import eu.europa.ec.fisheries.uvms.commons.message.impl.JAXBUtils;
import eu.europa.ec.fisheries.uvms.rules.entity.FADocumentID;
import eu.europa.ec.fisheries.uvms.rules.entity.FAUUIDType;
+import eu.europa.ec.fisheries.uvms.rules.entity.MovementDocumentId;
import eu.europa.ec.fisheries.uvms.rules.service.bean.RulesConfigurationCache;
import eu.europa.ec.fisheries.uvms.rules.service.business.ValidationResult;
import eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType;
@@ -34,24 +50,24 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
-import org.xml.sax.SAXException;
import un.unece.uncefact.data.standard.fluxfaquerymessage._3.FLUXFAQueryMessage;
import un.unece.uncefact.data.standard.fluxfareportmessage._3.FLUXFAReportMessage;
import un.unece.uncefact.data.standard.fluxresponsemessage._6.FLUXResponseMessage;
-import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.*;
+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._20.FAQuery;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.FAReportDocument;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.FLUXParty;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.FLUXReportDocument;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.FLUXResponseDocument;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.FishingActivity;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.FishingTrip;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.ValidationQualityAnalysis;
+import un.unece.uncefact.data.standard.reusableaggregatebusinessinformationentity._20.ValidationResultDocument;
import un.unece.uncefact.data.standard.unqualifieddatatype._20.CodeType;
import un.unece.uncefact.data.standard.unqualifieddatatype._20.DateTimeType;
import un.unece.uncefact.data.standard.unqualifieddatatype._20.IDType;
import un.unece.uncefact.data.standard.unqualifieddatatype._20.TextType;
-import static eu.europa.ec.fisheries.schema.rules.rule.v1.RawMsgType.FA_QUERY;
-import static eu.europa.ec.fisheries.schema.rules.rule.v1.RawMsgType.FA_REPORT;
-import static eu.europa.ec.fisheries.schema.rules.rule.v1.RawMsgType.FA_RESPONSE;
-import static eu.europa.ec.fisheries.uvms.rules.entity.FAUUIDType.FA_QUERY_ID;
-import static eu.europa.ec.fisheries.uvms.rules.entity.FAUUIDType.FA_REPORT_REF_ID;
-import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.RESPONSE_IDS;
-import static eu.europa.ec.fisheries.uvms.rules.service.config.ExtraValueType.SENDER_RECEIVER;
-import static eu.europa.ec.fisheries.uvms.rules.service.mapper.xpath.util.SchemaInitializer.SCHEMA_MAP;
-import static java.util.Collections.singletonList;
@Slf4j
public class RulesFLUXMessageHelper {
@@ -128,6 +144,17 @@ public Set mapToFADocumentID(FLUXFAReportMessage fluxfaReportMessa
return ids;
}
+ public Set mapToMovementDocumentID(FLUXVesselPositionMessage fluxVesselPositionMessage) {
+ Set ids = new HashSet<>();
+ if (fluxVesselPositionMessage != null){
+ FLUXReportDocumentType fluxReportDocument = fluxVesselPositionMessage.getFLUXReportDocument();
+ if (fluxReportDocument != null){
+ mapFluxReportDocumentIDS(ids, fluxReportDocument);
+ }
+ }
+ return ids;
+ }
+
private void mapFaReportDocuments(Set ids, List faReportDocuments) {
if (CollectionUtils.isNotEmpty(faReportDocuments)){
for (FAReportDocument faReportDocument : faReportDocuments) {
@@ -155,6 +182,19 @@ private void mapFluxReportDocumentIDS(Set ids, FLUXReportDocument
}
}
}
+
+ private void mapFluxReportDocumentIDS(Set ids, FLUXReportDocumentType fluxReportDocument) {
+ if (fluxReportDocument != null){
+ List fluxReportDocumentIDS = fluxReportDocument.getIDS();
+ if (CollectionUtils.isNotEmpty(fluxReportDocumentIDS)){
+ un.unece.uncefact.data.standard.unqualifieddatatype._18.IDType idType = fluxReportDocumentIDS.get(0);
+ if (idType != null){
+ ids.add(new MovementDocumentId(idType.getValue()));
+ }
+
+ }
+ }
+ }
public List collectFaIdsAndTripIds(FLUXFAReportMessage fluxFaRepMessage) {
List idsReqList = new ArrayList<>();
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..722bf5114 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
@@ -41,8 +41,10 @@ This file is part of the Integrated Fisheries Data Management (IFDM) Suite. The
@Slf4j
public class MovementReportDocumentFactMapper {
- private XPathStringWrapper xPathUtil;
public static final String ID = "id";
+
+ private XPathStringWrapper xPathUtil;
+ private List existingIds;
public MovementReportDocumentFactMapper() {
@@ -67,6 +69,7 @@ public MovementReportDocumentFact generateFactForMovementReportDocument(FLUXVess
fact.setCreationDateTime(getDate(creationDateTime));
xPathUtil.appendWithoutWrapping(partialXpath).append(FLUX_REPORT_DOCUMENT, XPathConstants.CREATION_DATE_TIME).storeInRepo(fact, CREATION_DATE_TIME);
fact.setIds(vesselPositionMessage.getFLUXReportDocument().getIDS());
+ fact.setExistingIds(existingIds);
xPathUtil.appendWithoutWrapping(partialXpath).append(FLUX_REPORT_DOCUMENT, XPathConstants.ID).storeInRepo(fact, "id");
CodeType purposeCode = vesselPositionMessage.getFLUXReportDocument().getPurposeCode();
fact.setPurposeCode(purposeCode);
@@ -200,6 +203,9 @@ private static Date getDate(DateTimeType dateTimeType) {
return date;
}
+ public void setExistingIds(List existingIds) {
+ this.existingIds = existingIds;
+ }
}