Merge branch 'master' into 'feature/RED-9472'
# Conflicts: # buildSrc/src/main/kotlin/com.iqser.red.service.java-conventions.gradle.kts
This commit is contained in:
commit
b3c4e670a8
@ -7,23 +7,17 @@ import java.io.BufferedInputStream;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.io.InputStreamResource;
|
import org.springframework.core.io.InputStreamResource;
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
@ -161,7 +155,7 @@ public class DownloadController implements DownloadResource {
|
|||||||
} // otherwise consider the files from dossier
|
} // otherwise consider the files from dossier
|
||||||
|
|
||||||
var validFilesAndNotProcessed = validFiles.stream()
|
var validFilesAndNotProcessed = validFiles.stream()
|
||||||
.filter(f -> !(f.getAnalysisVersion() > 0 && f.getNumberOfAnalyses() > 0))
|
.filter(f -> !(f.getAnalysisVersion() > 0 && f.getNumberOfAnalyses() > 0 && !f.isSoftOrHardDeleted()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
if (!validFilesAndNotProcessed.isEmpty()) {
|
if (!validFilesAndNotProcessed.isEmpty()) {
|
||||||
throw new BadRequestException("At least a file is in its initial analysis process");
|
throw new BadRequestException("At least a file is in its initial analysis process");
|
||||||
|
|||||||
@ -226,7 +226,6 @@ public interface DictionaryResource {
|
|||||||
@RequestParam(value = "addToDictionary") boolean addToDictionary);
|
@RequestParam(value = "addToDictionary") boolean addToDictionary);
|
||||||
|
|
||||||
|
|
||||||
@ResponseStatus(HttpStatus.ACCEPTED)
|
|
||||||
@PostMapping(value = DICTIONARY_REST_PATH + DIFFERENCE + DOSSIER_TEMPLATE_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
@PostMapping(value = DICTIONARY_REST_PATH + DIFFERENCE + DOSSIER_TEMPLATE_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
@Operation(summary = "Returns the difference between the dictionaries of the dossier template and all the dossiers inside the template for a list of given types.", description = "None")
|
@Operation(summary = "Returns the difference between the dictionaries of the dossier template and all the dossiers inside the template for a list of given types.", description = "None")
|
||||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Successfully returned DictionaryDifferenceResponse."), @ApiResponse(responseCode = "400", description = "The request is not valid.")})
|
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Successfully returned DictionaryDifferenceResponse."), @ApiResponse(responseCode = "400", description = "The request is not valid.")})
|
||||||
|
|||||||
@ -0,0 +1,148 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration;
|
||||||
|
|
||||||
|
import com.google.common.hash.HashFunction;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.LegalBasisEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogLegalBasis;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class LegalBasisMappingService {
|
||||||
|
|
||||||
|
private final HashFunction hashFunction;
|
||||||
|
private final LegalBasisMappingPersistenceService legalBasisMappingPersistenceService;
|
||||||
|
|
||||||
|
|
||||||
|
public LegalBasisMappingService(LegalBasisMappingPersistenceService legalBasisMappingPersistenceService) {
|
||||||
|
|
||||||
|
this.hashFunction = Hashing.murmur3_128();
|
||||||
|
this.legalBasisMappingPersistenceService = legalBasisMappingPersistenceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TechnicalNameResult processLegalBasisAndEntityLogLegalBasisList(String currentLegalBasis,
|
||||||
|
Map<String, String> reasonToTechnicalNameMap,
|
||||||
|
List<EntityLogLegalBasis> legalBasisList) {
|
||||||
|
|
||||||
|
TechnicalNameResult result = computeTechnicalName(currentLegalBasis, reasonToTechnicalNameMap);
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
addToLegalBasisList(result.technicalName(), currentLegalBasis, legalBasisList);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public TechnicalNameResult processLegalBasis(String currentLegalBasis, Map<String, String> reasonToTechnicalNameMap) {
|
||||||
|
|
||||||
|
return computeTechnicalName(currentLegalBasis, reasonToTechnicalNameMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private TechnicalNameResult computeTechnicalName(String currentLegalBasis, Map<String, String> reasonToTechnicalNameMap) {
|
||||||
|
|
||||||
|
if (currentLegalBasis == null || currentLegalBasis.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reasonToTechnicalNameMap.containsValue(currentLegalBasis)) {
|
||||||
|
return new TechnicalNameResult(currentLegalBasis, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reasonToTechnicalNameMap.containsKey(currentLegalBasis)) {
|
||||||
|
String technicalName = reasonToTechnicalNameMap.get(currentLegalBasis);
|
||||||
|
return new TechnicalNameResult(technicalName, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
String technicalName = hashFunction.hashString(currentLegalBasis, StandardCharsets.UTF_8).toString();
|
||||||
|
|
||||||
|
return new TechnicalNameResult(technicalName, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String processTextAndEntityLogLegalBasisList(String text, Map<String, String> reasonToTechnicalNameMap, List<EntityLogLegalBasis> legalBasisList) {
|
||||||
|
|
||||||
|
if (text == null || text.isEmpty()) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
String updatedValue = text;
|
||||||
|
boolean updated = false;
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : reasonToTechnicalNameMap.entrySet()) {
|
||||||
|
String reason = entry.getKey();
|
||||||
|
String technicalName = entry.getValue();
|
||||||
|
|
||||||
|
if (updatedValue.contains(reason)) {
|
||||||
|
updatedValue = updatedValue.replace(reason, technicalName);
|
||||||
|
addToLegalBasisList(technicalName, reason, legalBasisList);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!updated) {
|
||||||
|
String technicalName = hashFunction.hashString(text, StandardCharsets.UTF_8).toString();
|
||||||
|
updatedValue = technicalName;
|
||||||
|
addToLegalBasisList(technicalName, text, legalBasisList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void addToLegalBasisList(String technicalName, String reason, List<EntityLogLegalBasis> legalBasisList) {
|
||||||
|
|
||||||
|
boolean exists = legalBasisList.stream()
|
||||||
|
.anyMatch(lb -> lb.getTechnicalName().equals(technicalName));
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
EntityLogLegalBasis newLegalBasis = createEntityLogLegalBasis(technicalName, reason);
|
||||||
|
legalBasisList.add(newLegalBasis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private EntityLogLegalBasis createEntityLogLegalBasis(String technicalName, String reason) {
|
||||||
|
|
||||||
|
EntityLogLegalBasis newLegalBasis = new EntityLogLegalBasis();
|
||||||
|
newLegalBasis.setTechnicalName(technicalName);
|
||||||
|
newLegalBasis.setReason(reason);
|
||||||
|
newLegalBasis.setName("Generated Legal Basis");
|
||||||
|
newLegalBasis.setDescription("");
|
||||||
|
return newLegalBasis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, String> getReasonToTechnicalNameMap(String dossierTemplateId) {
|
||||||
|
|
||||||
|
List<LegalBasisEntity> legalBasisMappings = legalBasisMappingPersistenceService.getLegalBasisMapping(dossierTemplateId);
|
||||||
|
|
||||||
|
if (legalBasisMappings == null) {
|
||||||
|
legalBasisMappings = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> reasonToTechnicalNameMap = new HashMap<>();
|
||||||
|
for (LegalBasisEntity lbEntity : legalBasisMappings) {
|
||||||
|
reasonToTechnicalNameMap.put(lbEntity.getReason(), lbEntity.getTechnicalName());
|
||||||
|
}
|
||||||
|
return reasonToTechnicalNameMap;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public record TechnicalNameResult(String technicalName, boolean hashed) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,259 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration.liquibase;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.hash.HashFunction;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
|
||||||
|
import liquibase.change.custom.CustomTaskChange;
|
||||||
|
import liquibase.database.Database;
|
||||||
|
import liquibase.database.jvm.JdbcConnection;
|
||||||
|
import liquibase.exception.CustomChangeException;
|
||||||
|
import liquibase.exception.ValidationErrors;
|
||||||
|
import liquibase.resource.ResourceAccessor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings("PMD.CloseResource") // we do not want to close the underlying database connection ;)
|
||||||
|
public class TechnicalNameChange implements CustomTaskChange {
|
||||||
|
|
||||||
|
// there is a bug in our liquibase version which causes custom task changes to be run twice
|
||||||
|
// that bug got fixed in liquibase 4.25.1
|
||||||
|
// when we upgrade the dependency this can then be removed
|
||||||
|
@Setter
|
||||||
|
private static boolean skipExecution;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Database database) throws CustomChangeException {
|
||||||
|
|
||||||
|
if (skipExecution) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connection connection;
|
||||||
|
|
||||||
|
try {
|
||||||
|
connection = ((JdbcConnection) database.getConnection()).getUnderlyingConnection();
|
||||||
|
|
||||||
|
String[] tables = {"manual_legal_basis_change", "manual_force_redaction", "manual_recategorization", "manual_redaction"};
|
||||||
|
|
||||||
|
HashFunction hashFunction = Hashing.murmur3_128();
|
||||||
|
|
||||||
|
Set<String> allFileIds = collectAllFileIds(connection, tables);
|
||||||
|
|
||||||
|
if (allFileIds.isEmpty()) {
|
||||||
|
log.info("No rows updated because no files with manual redactions are present.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> fileIdToDossierTemplateIdMap = buildFileIdToDossierTemplateIdMap(connection, allFileIds);
|
||||||
|
|
||||||
|
Map<String, String> reasonDossierTemplateIdToTechnicalNameMap = buildReasonDossierTemplateIdToTechnicalNameMap(connection);
|
||||||
|
|
||||||
|
int totalRowsUpdatedWithTechnicalName = 0;
|
||||||
|
int totalRowsHashed = 0;
|
||||||
|
|
||||||
|
for (String tableName : tables) {
|
||||||
|
int[] counts = updateLegalBasisForTable(connection, tableName, hashFunction, fileIdToDossierTemplateIdMap, reasonDossierTemplateIdToTechnicalNameMap);
|
||||||
|
int rowsUpdatedWithTechnicalName = counts[0];
|
||||||
|
int rowsHashed = counts[1];
|
||||||
|
|
||||||
|
log.info("Table '{}': {} rows updated with technical_name, {} rows hashed.", tableName, rowsUpdatedWithTechnicalName, rowsHashed);
|
||||||
|
|
||||||
|
totalRowsUpdatedWithTechnicalName += rowsUpdatedWithTechnicalName;
|
||||||
|
totalRowsHashed += rowsHashed;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Total rows updated with technical_name: {}", totalRowsUpdatedWithTechnicalName);
|
||||||
|
log.info("Total rows hashed: {}", totalRowsHashed);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CustomChangeException("Error applying technical name change", e);
|
||||||
|
}
|
||||||
|
skipExecution = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Set<String> collectAllFileIds(Connection connection, String[] tables) throws SQLException {
|
||||||
|
|
||||||
|
Set<String> fileIds = new HashSet<>();
|
||||||
|
|
||||||
|
for (String tableName : tables) {
|
||||||
|
String selectSql = "SELECT DISTINCT file_id FROM " + tableName + " WHERE file_id IS NOT NULL";
|
||||||
|
try (PreparedStatement select = connection.prepareStatement(selectSql); ResultSet resultSet = select.executeQuery()) {
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String fileId = resultSet.getString("file_id");
|
||||||
|
fileIds.add(fileId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Map<String, String> buildFileIdToDossierTemplateIdMap(Connection connection, Set<String> fileIds) throws SQLException {
|
||||||
|
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
|
||||||
|
if (!fileIds.isEmpty()) {
|
||||||
|
|
||||||
|
StringBuilder sqlBuilder = new StringBuilder();
|
||||||
|
sqlBuilder.append("SELECT f.id AS file_id, d.dossier_template_id ");
|
||||||
|
sqlBuilder.append("FROM file f ");
|
||||||
|
sqlBuilder.append("JOIN dossier d ON f.dossier_id = d.id ");
|
||||||
|
sqlBuilder.append("WHERE f.id IN (");
|
||||||
|
|
||||||
|
String placeholders = String.join(",", Collections.nCopies(fileIds.size(), "?"));
|
||||||
|
sqlBuilder.append(placeholders);
|
||||||
|
sqlBuilder.append(")");
|
||||||
|
|
||||||
|
String selectSql = sqlBuilder.toString();
|
||||||
|
try (PreparedStatement select = connection.prepareStatement(selectSql)) {
|
||||||
|
int index = 1;
|
||||||
|
for (String fileId : fileIds) {
|
||||||
|
select.setString(index++, fileId);
|
||||||
|
}
|
||||||
|
try (ResultSet rs = select.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
String fileId = rs.getString("file_id");
|
||||||
|
String dossierTemplateId = rs.getString("dossier_template_id");
|
||||||
|
map.put(fileId, dossierTemplateId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Map<String, String> buildReasonDossierTemplateIdToTechnicalNameMap(Connection connection) throws SQLException {
|
||||||
|
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
|
||||||
|
String selectSql = "SELECT reason, legal_basis_mapping_entity_dossier_template_id, technical_name FROM legal_basis_mapping_entity_legal_basis";
|
||||||
|
try (PreparedStatement select = connection.prepareStatement(selectSql); ResultSet resultSet = select.executeQuery()) {
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String reason = resultSet.getString("reason");
|
||||||
|
String dossierTemplateId = resultSet.getString("legal_basis_mapping_entity_dossier_template_id");
|
||||||
|
String technicalName = resultSet.getString("technical_name");
|
||||||
|
|
||||||
|
if (reason != null && dossierTemplateId != null && technicalName != null) {
|
||||||
|
String key = getKey(reason, dossierTemplateId);
|
||||||
|
map.put(key, technicalName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int[] updateLegalBasisForTable(Connection connection,
|
||||||
|
String tableName,
|
||||||
|
HashFunction hashFunction,
|
||||||
|
Map<String, String> fileIdToDossierTemplateIdMap,
|
||||||
|
Map<String, String> reasonDossierTemplateIdToTechnicalNameMap) throws SQLException {
|
||||||
|
|
||||||
|
PreparedStatement select = null;
|
||||||
|
PreparedStatement update = null;
|
||||||
|
ResultSet resultSet = null;
|
||||||
|
|
||||||
|
int rowsUpdatedWithTechnicalName = 0;
|
||||||
|
int rowsHashed = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
String selectSql = "SELECT annotation_id, file_id, legal_basis FROM " + tableName + " WHERE legal_basis IS NOT NULL AND TRIM(legal_basis) <> '';";
|
||||||
|
select = connection.prepareStatement(selectSql);
|
||||||
|
resultSet = select.executeQuery();
|
||||||
|
|
||||||
|
String updateSql = "UPDATE " + tableName + " SET legal_basis = ? WHERE annotation_id = ? AND file_id = ?";
|
||||||
|
update = connection.prepareStatement(updateSql);
|
||||||
|
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String annotationId = resultSet.getString("annotation_id");
|
||||||
|
String fileId = resultSet.getString("file_id");
|
||||||
|
String originalValue = resultSet.getString("legal_basis");
|
||||||
|
|
||||||
|
if (originalValue == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String dossierTemplateId = fileIdToDossierTemplateIdMap.get(fileId);
|
||||||
|
|
||||||
|
String newValue = null;
|
||||||
|
|
||||||
|
if (dossierTemplateId != null) {
|
||||||
|
String key = getKey(originalValue, dossierTemplateId);
|
||||||
|
newValue = reasonDossierTemplateIdToTechnicalNameMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newValue == null || newValue.trim().isEmpty()) {
|
||||||
|
newValue = hashFunction.hashString(originalValue, StandardCharsets.UTF_8).toString();
|
||||||
|
rowsHashed++;
|
||||||
|
} else {
|
||||||
|
rowsUpdatedWithTechnicalName++;
|
||||||
|
}
|
||||||
|
|
||||||
|
update.setString(1, newValue);
|
||||||
|
update.setString(2, annotationId);
|
||||||
|
update.setString(3, fileId);
|
||||||
|
update.executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (resultSet != null) {
|
||||||
|
resultSet.close();
|
||||||
|
}
|
||||||
|
if (select != null) {
|
||||||
|
select.close();
|
||||||
|
}
|
||||||
|
if (update != null) {
|
||||||
|
update.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new int[]{rowsUpdatedWithTechnicalName, rowsHashed};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String getKey(String originalValue, String dossierTemplateId) {
|
||||||
|
|
||||||
|
return originalValue + "|" + dossierTemplateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getConfirmationMessage() {
|
||||||
|
|
||||||
|
return "Technical name change applied to legalbasis fields in specified tables.";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp() {}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFileOpener(ResourceAccessor resourceAccessor) {}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValidationErrors validate(Database database) {
|
||||||
|
|
||||||
|
return new ValidationErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -48,7 +48,7 @@ public class V17MigrateImportedRedactionsFiles extends Migration {
|
|||||||
|
|
||||||
if (fileManagementStorageService.objectExists(file.getDossierId(), file.getId(), FileType.IMPORTED_REDACTIONS)) {
|
if (fileManagementStorageService.objectExists(file.getDossierId(), file.getId(), FileType.IMPORTED_REDACTIONS)) {
|
||||||
|
|
||||||
com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.imported.ImportedRedactions oldImportedRedactions = fileManagementStorageService.getImportedRedactions(
|
com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.imported.ImportedRedactions oldImportedRedactions = fileManagementStorageService.getOldImportedRedactions(
|
||||||
file.getDossierId(),
|
file.getDossierId(),
|
||||||
file.getId());
|
file.getId());
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,151 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration.migrations;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.LegalBasisMappingService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.LegalBasisMappingService.TechnicalNameResult;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.Migration;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierRepository;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Change;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogLegalBasis;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ManualChange;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.EntityLogMongoService;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class V29TechnicalNameEntityLogMigration extends Migration {
|
||||||
|
|
||||||
|
private final DossierRepository dossierRepository;
|
||||||
|
private final FileRepository fileRepository;
|
||||||
|
private final EntityLogMongoService entityLogMongoService;
|
||||||
|
private final LegalBasisMappingService legalBasisMappingService;
|
||||||
|
|
||||||
|
private static final String NAME = "Migration for technical name update in entity logs";
|
||||||
|
private static final long VERSION = 29;
|
||||||
|
|
||||||
|
|
||||||
|
public V29TechnicalNameEntityLogMigration(DossierRepository dossierRepository,
|
||||||
|
FileRepository fileRepository,
|
||||||
|
EntityLogMongoService entityLogMongoService,
|
||||||
|
LegalBasisMappingService legalBasisMappingService) {
|
||||||
|
|
||||||
|
super(NAME, VERSION);
|
||||||
|
this.dossierRepository = dossierRepository;
|
||||||
|
this.fileRepository = fileRepository;
|
||||||
|
this.entityLogMongoService = entityLogMongoService;
|
||||||
|
this.legalBasisMappingService = legalBasisMappingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void migrate() {
|
||||||
|
|
||||||
|
AtomicInteger totalEntriesProcessed = new AtomicInteger(0);
|
||||||
|
AtomicInteger totalValuesHashed = new AtomicInteger(0);
|
||||||
|
AtomicInteger totalValuesUpdatedNormally = new AtomicInteger(0);
|
||||||
|
|
||||||
|
List<DossierEntity> dossiers = dossierRepository.findAll();
|
||||||
|
|
||||||
|
for (DossierEntity dossier : dossiers) {
|
||||||
|
String dossierId = dossier.getId();
|
||||||
|
String dossierTemplateId = dossier.getDossierTemplateId();
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, String> reasonToTechnicalNameMap = legalBasisMappingService.getReasonToTechnicalNameMap(dossierTemplateId);
|
||||||
|
|
||||||
|
List<FileEntity> files = fileRepository.findByDossierId(dossierId);
|
||||||
|
|
||||||
|
for (FileEntity file : files) {
|
||||||
|
String fileId = file.getId();
|
||||||
|
|
||||||
|
Optional<EntityLog> optionalEntityLog = entityLogMongoService.findEntityLogByDossierIdAndFileId(dossierId, fileId);
|
||||||
|
|
||||||
|
if (optionalEntityLog.isPresent()) {
|
||||||
|
EntityLog entityLog = optionalEntityLog.get();
|
||||||
|
|
||||||
|
List<EntityLogLegalBasis> legalBasisList = entityLog.getLegalBasis();
|
||||||
|
if (legalBasisList == null) {
|
||||||
|
legalBasisList = new java.util.ArrayList<>();
|
||||||
|
entityLog.setLegalBasis(legalBasisList);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean updated = false;
|
||||||
|
|
||||||
|
for (EntityLogEntry entry : entityLog.getEntityLogEntry()) {
|
||||||
|
totalEntriesProcessed.getAndIncrement();
|
||||||
|
String currentLegalBasis = entry.getLegalBasis();
|
||||||
|
|
||||||
|
if (currentLegalBasis != null && !currentLegalBasis.isEmpty()) {
|
||||||
|
TechnicalNameResult result = legalBasisMappingService.processLegalBasisAndEntityLogLegalBasisList(currentLegalBasis,
|
||||||
|
reasonToTechnicalNameMap,
|
||||||
|
legalBasisList);
|
||||||
|
|
||||||
|
if (result != null && !currentLegalBasis.equals(result.technicalName())) {
|
||||||
|
entry.setLegalBasis(result.technicalName());
|
||||||
|
updated = true;
|
||||||
|
|
||||||
|
if (result.hashed()) {
|
||||||
|
totalValuesHashed.getAndIncrement();
|
||||||
|
} else {
|
||||||
|
totalValuesUpdatedNormally.getAndIncrement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.getChanges() != null) {
|
||||||
|
for (Change change : entry.getChanges()) {
|
||||||
|
updated |= updatePropertyChanges(change.getPropertyChanges(), reasonToTechnicalNameMap, legalBasisList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.getManualChanges() != null) {
|
||||||
|
for (ManualChange manualChange : entry.getManualChanges()) {
|
||||||
|
updated |= updatePropertyChanges(manualChange.getPropertyChanges(), reasonToTechnicalNameMap, legalBasisList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updated) {
|
||||||
|
entityLogMongoService.saveEntityLog(dossierId, fileId, entityLog);
|
||||||
|
log.info("Updated EntityLog for dossierId: {}, fileId: {}", dossierId, fileId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Migration completed.");
|
||||||
|
log.info("Total entries processed: {}", totalEntriesProcessed.get());
|
||||||
|
log.info("Total values updated normally: {}", totalValuesUpdatedNormally.get());
|
||||||
|
log.info("Total values hashed: {}", totalValuesHashed.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean updatePropertyChanges(Map<String, String> propertyChanges, Map<String, String> reasonToTechnicalNameMap, List<EntityLogLegalBasis> legalBasisList) {
|
||||||
|
|
||||||
|
boolean updated = false;
|
||||||
|
if (propertyChanges != null && propertyChanges.containsKey("legalBasis")) {
|
||||||
|
String legalBasisValue = propertyChanges.get("legalBasis");
|
||||||
|
|
||||||
|
String updatedLegalBasisValue = legalBasisMappingService.processTextAndEntityLogLegalBasisList(legalBasisValue, reasonToTechnicalNameMap, legalBasisList);
|
||||||
|
|
||||||
|
if (!legalBasisValue.equals(updatedLegalBasisValue)) {
|
||||||
|
propertyChanges.put("legalBasis", updatedLegalBasisValue);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration.migrations;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.LegalBasisEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.RuleSetEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierTemplateEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.Migration;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.RulesPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierTemplateRepository;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
|
||||||
|
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||||
|
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Setter
|
||||||
|
@Service
|
||||||
|
public class V30TechnicalNameRuleFileMigration extends Migration {
|
||||||
|
|
||||||
|
private final DossierTemplateRepository dossierTemplateRepository;
|
||||||
|
private final RulesPersistenceService rulesPersistenceService;
|
||||||
|
private final LegalBasisMappingPersistenceService legalBasisMappingPersistenceService;
|
||||||
|
|
||||||
|
private static final String NAME = "Migration for replacing legal basis reasons with technical names in rule files";
|
||||||
|
private static final long VERSION = 30;
|
||||||
|
|
||||||
|
|
||||||
|
public V30TechnicalNameRuleFileMigration(DossierTemplateRepository dossierTemplateRepository,
|
||||||
|
RulesPersistenceService rulesPersistenceService,
|
||||||
|
LegalBasisMappingPersistenceService legalBasisMappingPersistenceService) {
|
||||||
|
|
||||||
|
super(NAME, VERSION);
|
||||||
|
this.dossierTemplateRepository = dossierTemplateRepository;
|
||||||
|
this.rulesPersistenceService = rulesPersistenceService;
|
||||||
|
this.legalBasisMappingPersistenceService = legalBasisMappingPersistenceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void migrate() {
|
||||||
|
|
||||||
|
log.info("Migration: Updating rule files by replacing legal basis reasons with technical names");
|
||||||
|
updateRuleFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void updateRuleFiles() {
|
||||||
|
|
||||||
|
List<DossierTemplateEntity> dossierTemplates = dossierTemplateRepository.findAll();
|
||||||
|
String tenantId = TenantContext.getTenantId();
|
||||||
|
|
||||||
|
dossierTemplates.parallelStream()
|
||||||
|
.forEach(dossierTemplate -> {
|
||||||
|
TenantContext.setTenantId(tenantId);
|
||||||
|
String dossierTemplateId = dossierTemplate.getId();
|
||||||
|
|
||||||
|
List<LegalBasisEntity> legalBasisMappings = legalBasisMappingPersistenceService.getLegalBasisMapping(dossierTemplateId);
|
||||||
|
|
||||||
|
if (legalBasisMappings == null || legalBasisMappings.isEmpty()) {
|
||||||
|
log.warn("No legal basis mappings found for dossierTemplateId: {}", dossierTemplateId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> reasonToTechnicalNameMap = legalBasisMappings.stream()
|
||||||
|
.filter(lb -> StringUtils.isNotBlank(lb.getReason()) && StringUtils.isNotBlank(lb.getTechnicalName()) && !lb.getReason().equals(lb.getTechnicalName()))
|
||||||
|
.collect(Collectors.toMap(LegalBasisEntity::getReason, LegalBasisEntity::getTechnicalName, (existing, replacement) -> replacement));
|
||||||
|
|
||||||
|
if (reasonToTechnicalNameMap.isEmpty()) {
|
||||||
|
log.warn("No valid mappings to replace for dossierTemplateId: {}", dossierTemplateId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<RuleSetEntity> optionalRuleSet = rulesPersistenceService.getRules(dossierTemplateId, RuleFileType.ENTITY);
|
||||||
|
|
||||||
|
if (optionalRuleSet.isPresent()) {
|
||||||
|
String originalRulesContent = optionalRuleSet.get().getValue();
|
||||||
|
String updatedRulesContent = replaceReasonsWithTechnicalNames(originalRulesContent, reasonToTechnicalNameMap);
|
||||||
|
|
||||||
|
if (!updatedRulesContent.equals(originalRulesContent)) {
|
||||||
|
rulesPersistenceService.setRules(updatedRulesContent, dossierTemplateId, RuleFileType.ENTITY);
|
||||||
|
log.info("Updated rule file for dossierTemplateId: {}", dossierTemplateId);
|
||||||
|
} else {
|
||||||
|
log.info("No replacements made for dossierTemplateId: {}", dossierTemplateId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("No rule set found for dossierTemplateId: {}", dossierTemplateId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String replaceReasonsWithTechnicalNames(String rulesContent, Map<String, String> reasonToTechnicalNameMap) {
|
||||||
|
|
||||||
|
String rulesContentResult = rulesContent;
|
||||||
|
for (Map.Entry<String, String> entry : reasonToTechnicalNameMap.entrySet()) {
|
||||||
|
String reason = entry.getKey();
|
||||||
|
String technicalName = entry.getValue();
|
||||||
|
rulesContentResult = StringUtils.replace(rulesContentResult, quoteString(reason), quoteString(technicalName));
|
||||||
|
}
|
||||||
|
return rulesContentResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String quoteString(String string) {
|
||||||
|
|
||||||
|
return "\"" + string + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,128 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration.migrations;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.LegalBasisMappingService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.LegalBasisMappingService.TechnicalNameResult;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.Migration;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierRepository;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedLegalBases;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedLegalBasis;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedaction;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedactionsPerPage;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class V31TechnicalNameImportedFilesMigration extends Migration {
|
||||||
|
|
||||||
|
private static final String NAME = "Migration for replacing legal basis reasons with technical names in imported redactions and legal bases files";
|
||||||
|
private static final long VERSION = 31;
|
||||||
|
|
||||||
|
private final DossierRepository dossierRepository;
|
||||||
|
private final FileRepository fileRepository;
|
||||||
|
private final FileManagementStorageService fileManagementStorageService;
|
||||||
|
private final LegalBasisMappingService legalBasisMappingService;
|
||||||
|
|
||||||
|
|
||||||
|
public V31TechnicalNameImportedFilesMigration(DossierRepository dossierRepository,
|
||||||
|
FileRepository fileRepository,
|
||||||
|
FileManagementStorageService fileManagementStorageService,
|
||||||
|
LegalBasisMappingService legalBasisMappingService) {
|
||||||
|
|
||||||
|
super(NAME, VERSION);
|
||||||
|
this.dossierRepository = dossierRepository;
|
||||||
|
this.fileRepository = fileRepository;
|
||||||
|
this.fileManagementStorageService = fileManagementStorageService;
|
||||||
|
this.legalBasisMappingService = legalBasisMappingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void migrate() {
|
||||||
|
|
||||||
|
log.info("Migration: Updating imported redactions and legal bases files by replacing legal basis reasons with technical names");
|
||||||
|
|
||||||
|
List<DossierEntity> dossiers = dossierRepository.findAll();
|
||||||
|
|
||||||
|
for (DossierEntity dossier : dossiers) {
|
||||||
|
String dossierId = dossier.getId();
|
||||||
|
String dossierTemplateId = dossier.getDossierTemplateId();
|
||||||
|
|
||||||
|
Map<String, String> reasonToTechnicalNameMap = legalBasisMappingService.getReasonToTechnicalNameMap(dossierTemplateId);
|
||||||
|
|
||||||
|
List<FileEntity> files = fileRepository.findByDossierId(dossierId);
|
||||||
|
|
||||||
|
for (FileEntity file : files) {
|
||||||
|
String fileId = file.getId();
|
||||||
|
|
||||||
|
if (fileManagementStorageService.objectExists(dossierId, fileId, FileType.IMPORTED_REDACTIONS)) {
|
||||||
|
ImportedRedactionsPerPage importedRedactions = fileManagementStorageService.getImportedRedactions(dossierId, fileId);
|
||||||
|
|
||||||
|
boolean updated = false;
|
||||||
|
|
||||||
|
for (ImportedRedaction redaction : importedRedactions.getImportedRedactions().values().stream().flatMap(Collection::stream).toList()) {
|
||||||
|
String currentLegalBasis = redaction.getLegalBasis();
|
||||||
|
|
||||||
|
if (currentLegalBasis != null && !currentLegalBasis.isEmpty()) {
|
||||||
|
TechnicalNameResult result = legalBasisMappingService.processLegalBasis(currentLegalBasis, reasonToTechnicalNameMap);
|
||||||
|
|
||||||
|
if (result != null && !currentLegalBasis.equals(result.technicalName())) {
|
||||||
|
redaction.setLegalBasis(result.technicalName());
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updated) {
|
||||||
|
fileManagementStorageService.storeJSONObject(dossierId, fileId, FileType.IMPORTED_REDACTIONS, importedRedactions);
|
||||||
|
log.info("Updated imported redactions for dossierId: {}, fileId: {}", dossierId, fileId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileManagementStorageService.objectExists(dossierId, fileId, FileType.IMPORTED_LEGAL_BASES)) {
|
||||||
|
ImportedLegalBases importedLegalBases = fileManagementStorageService.getImportedLegalBases(dossierId, fileId);
|
||||||
|
|
||||||
|
boolean updated = false;
|
||||||
|
|
||||||
|
List<ImportedLegalBasis> legalBases = importedLegalBases.getImportedLegalBases();
|
||||||
|
|
||||||
|
for (ImportedLegalBasis importedLegalBasis : legalBases) {
|
||||||
|
String currentReason = importedLegalBasis.getReason();
|
||||||
|
String currentTechnicalName = importedLegalBasis.getTechnicalName();
|
||||||
|
|
||||||
|
if (currentTechnicalName == null || currentTechnicalName.isEmpty()) {
|
||||||
|
if (currentReason != null && !currentReason.isEmpty()) {
|
||||||
|
TechnicalNameResult result = legalBasisMappingService.processLegalBasis(currentReason, reasonToTechnicalNameMap);
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
importedLegalBasis.setTechnicalName(result.technicalName());
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updated) {
|
||||||
|
fileManagementStorageService.storeJSONObject(dossierId, fileId, FileType.IMPORTED_LEGAL_BASES, importedLegalBases);
|
||||||
|
log.info("Updated imported legal bases for dossierId: {}, fileId: {}", dossierId, fileId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Migration completed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -51,7 +51,7 @@ public class ApprovalVerificationService {
|
|||||||
addWarning(entry, WarningType.LEGAL_BASIS_MISSING, approveResponse);
|
addWarning(entry, WarningType.LEGAL_BASIS_MISSING, approveResponse);
|
||||||
} else {
|
} else {
|
||||||
var legalBasisEntity = legalBasisMappings.stream()
|
var legalBasisEntity = legalBasisMappings.stream()
|
||||||
.filter(mapping -> mapping.getReason().equals(entry.getLegalBasis()))
|
.filter(mapping -> mapping.getTechnicalName().equals(entry.getLegalBasis()))
|
||||||
.findFirst();
|
.findFirst();
|
||||||
if (legalBasisEntity.isEmpty() || StringUtils.isEmpty(legalBasisEntity.get().getTechnicalName())) {
|
if (legalBasisEntity.isEmpty() || StringUtils.isEmpty(legalBasisEntity.get().getTechnicalName())) {
|
||||||
addWarning(entry, WarningType.UNMAPPED_JUSTIFICATION, approveResponse);
|
addWarning(entry, WarningType.UNMAPPED_JUSTIFICATION, approveResponse);
|
||||||
|
|||||||
@ -239,10 +239,11 @@ public class DictionaryManagementService {
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void addEntries(String typeId, List<String> entries, boolean removeCurrent, boolean ignoreInvalidEntries, DictionaryEntryType dictionaryEntryType) {
|
public void addEntries(String typeId, List<String> entries, boolean removeCurrent, boolean ignoreInvalidEntries, DictionaryEntryType dictionaryEntryType) {
|
||||||
|
|
||||||
addEntries(typeId, entries, removeCurrent, ignoreInvalidEntries, dictionaryEntryType, false);
|
addEntries(typeId, entries, removeCurrent, ignoreInvalidEntries, dictionaryEntryType, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void addEntries(String typeId, List<String> entries, boolean removeCurrent, boolean ignoreInvalidEntries, DictionaryEntryType dictionaryEntryType, boolean isImport) {
|
public void addEntries(String typeId, List<String> entries, boolean removeCurrent, boolean ignoreInvalidEntries, DictionaryEntryType dictionaryEntryType, boolean isImport) {
|
||||||
|
|
||||||
@ -293,7 +294,10 @@ public class DictionaryManagementService {
|
|||||||
// check for the existence of dossier type and create in case it does not exist
|
// check for the existence of dossier type and create in case it does not exist
|
||||||
if (isDossierTypeId(typeId)) {
|
if (isDossierTypeId(typeId)) {
|
||||||
try {
|
try {
|
||||||
dictionaryPersistenceService.getType(typeId);
|
TypeEntity type = dictionaryPersistenceService.getType(typeId, true);
|
||||||
|
if (type.isDeleted()) {
|
||||||
|
dictionaryPersistenceService.undeleteType(typeId);
|
||||||
|
}
|
||||||
} catch (NotFoundException e) {
|
} catch (NotFoundException e) {
|
||||||
// type not found check first dossier is matching the specified dossier template
|
// type not found check first dossier is matching the specified dossier template
|
||||||
var dossierId = getDossierIdFromTypeId(typeId);
|
var dossierId = getDossierIdFromTypeId(typeId);
|
||||||
@ -397,9 +401,13 @@ public class DictionaryManagementService {
|
|||||||
|
|
||||||
dictionaryPersistenceService.deleteType(typeId);
|
dictionaryPersistenceService.deleteType(typeId);
|
||||||
|
|
||||||
entryPersistenceService.deleteAllEntriesForTypeId(typeId, currentVersion + 1, DictionaryEntryType.ENTRY);
|
if (isDossierTypeId(typeId)) {
|
||||||
entryPersistenceService.deleteAllEntriesForTypeId(typeId, currentVersion + 1, DictionaryEntryType.FALSE_POSITIVE);
|
entryPersistenceService.hardDeleteAllEntriesForTypeId(typeId);
|
||||||
entryPersistenceService.deleteAllEntriesForTypeId(typeId, currentVersion + 1, DictionaryEntryType.FALSE_RECOMMENDATION);
|
} else {
|
||||||
|
entryPersistenceService.deleteAllEntriesForTypeId(typeId, currentVersion + 1, DictionaryEntryType.ENTRY);
|
||||||
|
entryPersistenceService.deleteAllEntriesForTypeId(typeId, currentVersion + 1, DictionaryEntryType.FALSE_POSITIVE);
|
||||||
|
entryPersistenceService.deleteAllEntriesForTypeId(typeId, currentVersion + 1, DictionaryEntryType.FALSE_RECOMMENDATION);
|
||||||
|
}
|
||||||
|
|
||||||
dictionaryPersistenceService.incrementVersion(typeId);
|
dictionaryPersistenceService.incrementVersion(typeId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -268,7 +268,7 @@ public class DictionaryService {
|
|||||||
@PreAuthorize("hasAuthority('" + DELETE_DOSSIER_DICTIONARY_TYPE + "')")
|
@PreAuthorize("hasAuthority('" + DELETE_DOSSIER_DICTIONARY_TYPE + "')")
|
||||||
public void deleteDossierType(String type, String dossierTemplateId, String dossierId) {
|
public void deleteDossierType(String type, String dossierTemplateId, String dossierId) {
|
||||||
|
|
||||||
accessControlService.checkDossierExistenceAndAccessPermissionsToDossier(dossierId);
|
accessControlService.checkAccessPermissionsToDossier(dossierId);
|
||||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||||
deleteType(toTypeId(type, dossierTemplateId, dossierId));
|
deleteType(toTypeId(type, dossierTemplateId, dossierId));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,17 +13,17 @@ import java.util.List;
|
|||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.exception.InternalServerErrorException;
|
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
|
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.utils.StorageIdUtils;
|
import com.iqser.red.service.persistence.management.v1.processor.utils.StorageIdUtils;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLog;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLog;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedLegalBases;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedactions;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedactionsPerPage;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.imported.ImportedRedactions;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.section.SectionGrid;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.section.SectionGrid;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.ComponentLogMongoService;
|
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.ComponentLogMongoService;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.EntityLogMongoService;
|
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.EntityLogMongoService;
|
||||||
import com.iqser.red.storage.commons.exception.StorageException;
|
|
||||||
import com.iqser.red.storage.commons.exception.StorageObjectDoesNotExist;
|
import com.iqser.red.storage.commons.exception.StorageObjectDoesNotExist;
|
||||||
import com.iqser.red.storage.commons.service.StorageService;
|
import com.iqser.red.storage.commons.service.StorageService;
|
||||||
import com.knecon.fforesight.service.layoutparser.internal.api.data.redaction.DocumentStructureWrapper;
|
import com.knecon.fforesight.service.layoutparser.internal.api.data.redaction.DocumentStructureWrapper;
|
||||||
@ -170,6 +170,7 @@ public class FileManagementStorageService {
|
|||||||
return entityLogMongoService.entityLogDocumentExists(dossierId, fileId);
|
return entityLogMongoService.entityLogDocumentExists(dossierId, fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean componentLogExists(String dossierId, String fileId) {
|
public boolean componentLogExists(String dossierId, String fileId) {
|
||||||
|
|
||||||
return componentLogMongoService.componentLogDocumentExists(dossierId, fileId);
|
return componentLogMongoService.componentLogDocumentExists(dossierId, fileId);
|
||||||
@ -189,12 +190,12 @@ public class FileManagementStorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ImportedRedactions getImportedRedactions(String dossierId, String fileId) {
|
public ImportedRedactionsPerPage getImportedRedactions(String dossierId, String fileId) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return storageService.readJSONObject(TenantContext.getTenantId(),
|
return storageService.readJSONObject(TenantContext.getTenantId(),
|
||||||
StorageIdUtils.getStorageId(dossierId, fileId, FileType.IMPORTED_REDACTIONS),
|
StorageIdUtils.getStorageId(dossierId, fileId, FileType.IMPORTED_REDACTIONS),
|
||||||
ImportedRedactions.class);
|
ImportedRedactionsPerPage.class);
|
||||||
} catch (StorageObjectDoesNotExist e) {
|
} catch (StorageObjectDoesNotExist e) {
|
||||||
throw new NotFoundException("ImportedRedactions does not exist");
|
throw new NotFoundException("ImportedRedactions does not exist");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -202,11 +203,41 @@ public class FileManagementStorageService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ImportedLegalBases getImportedLegalBases(String dossierId, String fileId) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return storageService.readJSONObject(TenantContext.getTenantId(),
|
||||||
|
StorageIdUtils.getStorageId(dossierId, fileId, FileType.IMPORTED_LEGAL_BASES),
|
||||||
|
ImportedLegalBases.class);
|
||||||
|
} catch (StorageObjectDoesNotExist e) {
|
||||||
|
throw new NotFoundException("ImportedLegalBases does not exist");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Could not convert ImportedLegalBases", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.imported.ImportedRedactions getOldImportedRedactions(String dossierId, String fileId) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return storageService.readJSONObject(TenantContext.getTenantId(),
|
||||||
|
StorageIdUtils.getStorageId(dossierId, fileId, FileType.IMPORTED_REDACTIONS),
|
||||||
|
com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.imported.ImportedRedactions.class);
|
||||||
|
} catch (StorageObjectDoesNotExist e) {
|
||||||
|
throw new NotFoundException("ImportedRedactions does not exist");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Could not convert ImportedRedactions", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean objectExists(String dossierId, String fileId, String fileName, String fileExtension) {
|
public boolean objectExists(String dossierId, String fileId, String fileName, String fileExtension) {
|
||||||
|
|
||||||
return storageService.objectExists(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileName, fileExtension));
|
return storageService.objectExists(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileName, fileExtension));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean objectExists(String dossierId, String fileId, FileType origin) {
|
public boolean objectExists(String dossierId, String fileId, FileType origin) {
|
||||||
|
|
||||||
return storageService.objectExists(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, origin));
|
return storageService.objectExists(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, origin));
|
||||||
@ -224,11 +255,13 @@ public class FileManagementStorageService {
|
|||||||
storageService.deleteObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileType));
|
storageService.deleteObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void deleteObject(String dossierId, String fileId, String fileName, String fileExtension) {
|
public void deleteObject(String dossierId, String fileId, String fileName, String fileExtension) {
|
||||||
|
|
||||||
storageService.deleteObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileName, fileExtension));
|
storageService.deleteObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, fileName, fileExtension));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void deleteDocumentAndNerObjects(String dossierId, String fileId) {
|
public void deleteDocumentAndNerObjects(String dossierId, String fileId) {
|
||||||
|
|
||||||
deleteObject(dossierId, fileId, FileType.DOCUMENT_STRUCTURE);
|
deleteObject(dossierId, fileId, FileType.DOCUMENT_STRUCTURE);
|
||||||
@ -249,6 +282,7 @@ public class FileManagementStorageService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void deleteAllObjects(String dossierId, String fileId) {
|
public void deleteAllObjects(String dossierId, String fileId) {
|
||||||
|
|
||||||
deleteObject(dossierId, fileId, FileType.VIEWER_DOCUMENT);
|
deleteObject(dossierId, fileId, FileType.VIEWER_DOCUMENT);
|
||||||
@ -270,6 +304,7 @@ public class FileManagementStorageService {
|
|||||||
entityLogMongoService.deleteEntityLog(dossierId, fileId);
|
entityLogMongoService.deleteEntityLog(dossierId, fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void deleteComponentLog(String dossierId, String fileId) {
|
public void deleteComponentLog(String dossierId, String fileId) {
|
||||||
|
|
||||||
componentLogMongoService.deleteComponentLog(dossierId, fileId);
|
componentLogMongoService.deleteComponentLog(dossierId, fileId);
|
||||||
|
|||||||
@ -264,7 +264,7 @@ public class FileStatusService {
|
|||||||
var fileEntity = fileStatusPersistenceService.getStatus(fileId);
|
var fileEntity = fileStatusPersistenceService.getStatus(fileId);
|
||||||
|
|
||||||
if (!fileManagementStorageService.objectExists(dossierId, fileId, FileType.ORIGIN)) {
|
if (!fileManagementStorageService.objectExists(dossierId, fileId, FileType.ORIGIN)) {
|
||||||
addToPreprocessingQueue(dossierId, fileId, fileEntity.getFilename());
|
addToPreprocessingQueue(dossier.getDossierTemplateId(), dossierId, fileId, fileEntity.getFilename());
|
||||||
sendReadOnlyAnalysisEvent(dossierId, fileId, fileEntity);
|
sendReadOnlyAnalysisEvent(dossierId, fileId, fileEntity);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -487,9 +487,10 @@ public class FileStatusService {
|
|||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void addToPreprocessingQueue(String dossierId, String fileId, String filename) {
|
public void addToPreprocessingQueue(String dossierTemplateId, String dossierId, String fileId, String filename) {
|
||||||
|
|
||||||
var processUntouchedDocumentRequest = ProcessUntouchedDocumentRequest.builder()
|
var processUntouchedDocumentRequest = ProcessUntouchedDocumentRequest.builder()
|
||||||
|
.dossierTemplateId(dossierTemplateId)
|
||||||
.highlightExtractionEnabled(currentApplicationTypeProvider.isRedactManager())
|
.highlightExtractionEnabled(currentApplicationTypeProvider.isRedactManager())
|
||||||
.dossierId(dossierId)
|
.dossierId(dossierId)
|
||||||
.fileId(fileId)
|
.fileId(fileId)
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import com.iqser.red.service.persistence.management.v1.processor.exception.Confl
|
|||||||
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
|
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierPersistenceService;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.ReanalysisSettings;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.ReanalysisSettings;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedactions;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.DeleteImportedRedactionsRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.DeleteImportedRedactionsRequest;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
||||||
@ -109,7 +110,11 @@ public class ReanalysisService {
|
|||||||
|
|
||||||
private void analyseFiles(boolean repeatStructureAnalysis, List<FileModel> filesToReanalyse, boolean runOcr) {
|
private void analyseFiles(boolean repeatStructureAnalysis, List<FileModel> filesToReanalyse, boolean runOcr) {
|
||||||
|
|
||||||
filesToReanalyse.forEach(file -> fileStatusService.setStatusFullReprocess(file.getDossierId(), file.getId(), filesToReanalyse.size() == 1, repeatStructureAnalysis, runOcr));
|
filesToReanalyse.forEach(file -> fileStatusService.setStatusFullReprocess(file.getDossierId(),
|
||||||
|
file.getId(),
|
||||||
|
filesToReanalyse.size() == 1,
|
||||||
|
repeatStructureAnalysis,
|
||||||
|
runOcr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -281,7 +286,11 @@ public class ReanalysisService {
|
|||||||
|
|
||||||
List<FileModel> rejectedFiles = filterInvalidFiles(files);
|
List<FileModel> rejectedFiles = filterInvalidFiles(files);
|
||||||
|
|
||||||
files.forEach(file -> fileStatusService.setStatusFullReprocess(file.getDossierId(), file.getId(), false, reanalysisSettings.repeatStructureAnalysis(), reanalysisSettings.runOcr()));
|
files.forEach(file -> fileStatusService.setStatusFullReprocess(file.getDossierId(),
|
||||||
|
file.getId(),
|
||||||
|
false,
|
||||||
|
reanalysisSettings.repeatStructureAnalysis(),
|
||||||
|
reanalysisSettings.runOcr()));
|
||||||
|
|
||||||
return rejectedFiles;
|
return rejectedFiles;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -184,6 +184,13 @@ public class EntryPersistenceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void hardDeleteAllEntriesForTypeId(String typeId) {
|
||||||
|
|
||||||
|
entryRepository.hardDeleteAllEntriesForTypeId(typeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void cloneEntries(String originalTypeId, String newTypeId) {
|
public void cloneEntries(String originalTypeId, String newTypeId) {
|
||||||
|
|
||||||
entryRepository.cloneEntries(originalTypeId, newTypeId);
|
entryRepository.cloneEntries(originalTypeId, newTypeId);
|
||||||
|
|||||||
@ -86,7 +86,7 @@ public interface TypeRepository extends JpaRepository<TypeEntity, String> {
|
|||||||
void softDeleteTypeById(@Param("typeId") String typeId);
|
void softDeleteTypeById(@Param("typeId") String typeId);
|
||||||
|
|
||||||
|
|
||||||
@Modifying
|
@Modifying(clearAutomatically = true, flushAutomatically = true)
|
||||||
@Query("Update TypeEntity t set t.softDeletedTime = null where t.id = :typeId and t.softDeletedTime is not null")
|
@Query("Update TypeEntity t set t.softDeletedTime = null where t.id = :typeId and t.softDeletedTime is not null")
|
||||||
int unSoftDeleteTypeById(@Param("typeId") String typeId);
|
int unSoftDeleteTypeById(@Param("typeId") String typeId);
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,11 @@ public interface EntryRepository extends EntryRepositoryCustom, JpaRepository<Di
|
|||||||
void deleteAllEntriesForTypeId(@Param("typeId") String typeId, @Param("version") long version);
|
void deleteAllEntriesForTypeId(@Param("typeId") String typeId, @Param("version") long version);
|
||||||
|
|
||||||
|
|
||||||
|
@Modifying(clearAutomatically = true, flushAutomatically = true)
|
||||||
|
@Query("delete from DictionaryEntryEntity e where e.typeId = :typeId")
|
||||||
|
void hardDeleteAllEntriesForTypeId(@Param("typeId") String typeId);
|
||||||
|
|
||||||
|
|
||||||
@Modifying(flushAutomatically = true, clearAutomatically = true)
|
@Modifying(flushAutomatically = true, clearAutomatically = true)
|
||||||
@Transactional
|
@Transactional
|
||||||
@Query(value = "insert into dictionary_entry (value, version, deleted, type_id) "
|
@Query(value = "insert into dictionary_entry (value, version, deleted, type_id) "
|
||||||
|
|||||||
@ -247,3 +247,5 @@ databaseChangeLog:
|
|||||||
file: db/changelog/tenant/151-add-component-mapping-indexes.yaml
|
file: db/changelog/tenant/151-add-component-mapping-indexes.yaml
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/tenant/152-add-ai-fields-to-entity.yaml
|
file: db/changelog/tenant/152-add-ai-fields-to-entity.yaml
|
||||||
|
- include:
|
||||||
|
file: db/changelog/tenant/153-custom-technical-name-change.yaml
|
||||||
|
|||||||
@ -0,0 +1,30 @@
|
|||||||
|
databaseChangeLog:
|
||||||
|
- changeSet:
|
||||||
|
id: technical-name-change-constraint
|
||||||
|
author: maverick
|
||||||
|
changes:
|
||||||
|
- addUniqueConstraint:
|
||||||
|
constraintName: uq_technical_name
|
||||||
|
tableName: legal_basis_mapping_entity_legal_basis
|
||||||
|
columnNames: technical_name, legal_basis_mapping_entity_dossier_template_id
|
||||||
|
- changeSet:
|
||||||
|
id: technical-name-change-index
|
||||||
|
author: maverick
|
||||||
|
preConditions:
|
||||||
|
- not:
|
||||||
|
indexExists:
|
||||||
|
indexName: idx_legal_basis_mapping_entity_dossier_template_id
|
||||||
|
tableName: legal_basis_mapping_entity_legal_basis
|
||||||
|
changes:
|
||||||
|
- createIndex:
|
||||||
|
indexName: idx_legal_basis_mapping_entity_dossier_template_id
|
||||||
|
tableName: legal_basis_mapping_entity_legal_basis
|
||||||
|
columns:
|
||||||
|
- column:
|
||||||
|
name: legal_basis_mapping_entity_dossier_template_id
|
||||||
|
- changeSet:
|
||||||
|
id: custom-technical-name-change
|
||||||
|
author: maverick
|
||||||
|
changes:
|
||||||
|
- customChange:
|
||||||
|
class: com.iqser.red.service.persistence.management.v1.processor.migration.liquibase.TechnicalNameChange
|
||||||
@ -0,0 +1,373 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.ArgumentMatchers.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.liquibase.TechnicalNameChange;
|
||||||
|
|
||||||
|
import liquibase.database.Database;
|
||||||
|
import liquibase.database.jvm.JdbcConnection;
|
||||||
|
import liquibase.exception.CustomChangeException;
|
||||||
|
|
||||||
|
import com.google.common.hash.HashFunction;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
|
||||||
|
public class TechnicalNameChangeTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Database mockDatabase;
|
||||||
|
@Mock
|
||||||
|
private JdbcConnection mockJdbcConnection;
|
||||||
|
@Mock
|
||||||
|
private Connection mockConnection;
|
||||||
|
@InjectMocks
|
||||||
|
private TechnicalNameChange technicalNameChange;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PreparedStatement mockSelectFileIdsPs;
|
||||||
|
@Mock
|
||||||
|
private PreparedStatement mockDossierPs;
|
||||||
|
@Mock
|
||||||
|
private PreparedStatement mockReasonPs;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ResultSet mockSelectFileIdsRs;
|
||||||
|
@Mock
|
||||||
|
private ResultSet mockDossierRs;
|
||||||
|
@Mock
|
||||||
|
private ResultSet mockReasonRs;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PreparedStatement mockSelectUpdatePs1;
|
||||||
|
@Mock
|
||||||
|
private PreparedStatement mockSelectUpdatePs2;
|
||||||
|
@Mock
|
||||||
|
private PreparedStatement mockSelectUpdatePs3;
|
||||||
|
@Mock
|
||||||
|
private PreparedStatement mockSelectUpdatePs4;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ResultSet mockSelectUpdateRs1;
|
||||||
|
@Mock
|
||||||
|
private ResultSet mockSelectUpdateRs2;
|
||||||
|
@Mock
|
||||||
|
private ResultSet mockSelectUpdateRs3;
|
||||||
|
@Mock
|
||||||
|
private ResultSet mockSelectUpdateRs4;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PreparedStatement mockUpdatePs;
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() {
|
||||||
|
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
when(mockDatabase.getConnection()).thenReturn(mockJdbcConnection);
|
||||||
|
when(mockJdbcConnection.getUnderlyingConnection()).thenReturn(mockConnection);
|
||||||
|
TechnicalNameChange.setSkipExecution(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecute_successfulUpdate() throws Exception {
|
||||||
|
|
||||||
|
String[] tables = {"manual_legal_basis_change", "manual_force_redaction", "manual_recategorization", "manual_redaction"};
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockSelectFileIdsPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT DISTINCT file_id FROM"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockSelectFileIdsRs);
|
||||||
|
when(mockSelectFileIdsRs.next()).thenReturn(true, true, false);
|
||||||
|
when(mockSelectFileIdsRs.getString("file_id")).thenReturn("file1", "file2");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockDossierPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT f.id AS file_id, d.dossier_template_id"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockDossierRs);
|
||||||
|
when(mockDossierRs.next()).thenReturn(true, true, false);
|
||||||
|
when(mockDossierRs.getString("file_id")).thenReturn("file1", "file2");
|
||||||
|
when(mockDossierRs.getString("dossier_template_id")).thenReturn("template1", "template2");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockReasonPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT reason, legal_basis_mapping_entity_dossier_template_id, technical_name"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockReasonRs);
|
||||||
|
when(mockReasonRs.next()).thenReturn(true, true, false);
|
||||||
|
when(mockReasonRs.getString("reason")).thenReturn("reason1", "reason2");
|
||||||
|
when(mockReasonRs.getString("legal_basis_mapping_entity_dossier_template_id")).thenReturn("template1", "template2");
|
||||||
|
when(mockReasonRs.getString("technical_name")).thenReturn("techName1", (String) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupTableMocks(mockSelectUpdatePs1, mockSelectUpdateRs1, "manual_legal_basis_change", "ann1", "ann2", "file1", "file2", "reason1", "reason2");
|
||||||
|
setupTableMocks(mockSelectUpdatePs2, mockSelectUpdateRs2, "manual_force_redaction", "ann3", "ann4", "file3", "file4", "reason3", "reason4");
|
||||||
|
setupTableMocks(mockSelectUpdatePs3, mockSelectUpdateRs3, "manual_recategorization", "ann5", "ann6", "file5", "file6", "reason5", "reason6");
|
||||||
|
setupTableMocks(mockSelectUpdatePs4, mockSelectUpdateRs4, "manual_redaction", "ann7", "ann8", "file7", "file8", "reason7", "reason8");
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockUpdatePs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("UPDATE "))).thenReturn(ps);
|
||||||
|
when(ps.executeUpdate()).thenReturn(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
technicalNameChange.execute(mockDatabase);
|
||||||
|
|
||||||
|
verify(mockConnection, times(4)).prepareStatement(startsWith("SELECT DISTINCT file_id FROM"));
|
||||||
|
verify(mockConnection, times(1)).prepareStatement(startsWith("SELECT f.id AS file_id, d.dossier_template_id"));
|
||||||
|
verify(mockConnection, times(1)).prepareStatement(startsWith("SELECT reason, legal_basis_mapping_entity_dossier_template_id, technical_name"));
|
||||||
|
verify(mockConnection, times(tables.length)).prepareStatement(startsWith("SELECT annotation_id, file_id, legal_basis FROM"));
|
||||||
|
verify(mockConnection, times(tables.length)).prepareStatement(startsWith("UPDATE "));
|
||||||
|
|
||||||
|
verify(mockUpdatePs, times(tables.length * 2)).executeUpdate();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> updatedValueCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
ArgumentCaptor<String> annotationIdCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
ArgumentCaptor<String> fileIdCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
|
||||||
|
verify(mockUpdatePs, times(tables.length * 2)).setString(eq(1), updatedValueCaptor.capture());
|
||||||
|
verify(mockUpdatePs, times(tables.length * 2)).setString(eq(2), annotationIdCaptor.capture());
|
||||||
|
verify(mockUpdatePs, times(tables.length * 2)).setString(eq(3), fileIdCaptor.capture());
|
||||||
|
|
||||||
|
List<String> updatedValues = updatedValueCaptor.getAllValues();
|
||||||
|
List<String> annotationIds = annotationIdCaptor.getAllValues();
|
||||||
|
|
||||||
|
HashFunction hashFunction = Hashing.murmur3_128();
|
||||||
|
Map<String, String> expectedUpdates = createExpectedUpdates(hashFunction);
|
||||||
|
|
||||||
|
for (int i = 0; i < annotationIds.size(); i++) {
|
||||||
|
String annotationId = annotationIds.get(i);
|
||||||
|
String expectedValue = expectedUpdates.get(annotationId);
|
||||||
|
assertEquals(expectedValue, updatedValues.get(i), "Mismatch for annotation_id: " + annotationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecute_withException() {
|
||||||
|
|
||||||
|
when(mockDatabase.getConnection()).thenThrow(new RuntimeException("Connection error"));
|
||||||
|
|
||||||
|
CustomChangeException exception = assertThrows(CustomChangeException.class, () -> {
|
||||||
|
technicalNameChange.execute(mockDatabase);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertTrue(exception.getMessage().contains("Error applying technical name change"));
|
||||||
|
assertEquals("Connection error", exception.getCause().getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecute_noFileIds() throws Exception {
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockSelectFileIdsPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT DISTINCT file_id FROM"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockSelectFileIdsRs);
|
||||||
|
when(mockSelectFileIdsRs.next()).thenReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
technicalNameChange.execute(mockDatabase);
|
||||||
|
|
||||||
|
verify(mockConnection, never()).prepareStatement(startsWith("SELECT f.id AS file_id, d.dossier_template_id"));
|
||||||
|
verify(mockConnection, never()).prepareStatement(startsWith("SELECT reason, legal_basis_mapping_entity_dossier_template_id, technical_name"));
|
||||||
|
|
||||||
|
verify(mockConnection, never()).prepareStatement(startsWith("SELECT annotation_id, file_id, legal_basis FROM"));
|
||||||
|
verify(mockConnection, never()).prepareStatement(startsWith("UPDATE "));
|
||||||
|
verify(mockUpdatePs, never()).executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecute_noDossierMappings() throws Exception {
|
||||||
|
|
||||||
|
String[] tables = {"manual_legal_basis_change", "manual_force_redaction", "manual_recategorization", "manual_redaction"};
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockSelectFileIdsPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT DISTINCT file_id FROM"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockSelectFileIdsRs);
|
||||||
|
when(mockSelectFileIdsRs.next()).thenReturn(true, false);
|
||||||
|
when(mockSelectFileIdsRs.getString("file_id")).thenReturn("file1");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockDossierPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT f.id AS file_id, d.dossier_template_id"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockDossierRs);
|
||||||
|
when(mockDossierRs.next()).thenReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockReasonPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT reason, legal_basis_mapping_entity_dossier_template_id, technical_name"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockReasonRs);
|
||||||
|
when(mockReasonRs.next()).thenReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String table : tables) {
|
||||||
|
try (PreparedStatement mockSelectUpdatePs = mock(PreparedStatement.class); ResultSet mockSelectUpdateRs = mock(ResultSet.class); PreparedStatement mockUpdate = mock(
|
||||||
|
PreparedStatement.class)) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT annotation_id, file_id, legal_basis FROM " + table))).thenReturn(mockSelectUpdatePs);
|
||||||
|
when(mockSelectUpdatePs.executeQuery()).thenReturn(mockSelectUpdateRs);
|
||||||
|
when(mockSelectUpdateRs.next()).thenReturn(true, false);
|
||||||
|
when(mockSelectUpdateRs.getString("annotation_id")).thenReturn("ann1");
|
||||||
|
when(mockSelectUpdateRs.getString("file_id")).thenReturn("file1");
|
||||||
|
when(mockSelectUpdateRs.getString("legal_basis")).thenReturn("reason1");
|
||||||
|
|
||||||
|
when(mockConnection.prepareStatement(startsWith("UPDATE " + table))).thenReturn(mockUpdate);
|
||||||
|
when(mockUpdate.executeUpdate()).thenReturn(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
technicalNameChange.execute(mockDatabase);
|
||||||
|
|
||||||
|
verify(mockUpdatePs, never()).executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecute_allTechnicalNamesPresent() throws Exception {
|
||||||
|
|
||||||
|
String[] tables = {"manual_legal_basis_change", "manual_force_redaction", "manual_recategorization", "manual_redaction"};
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockSelectFileIdsPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT DISTINCT file_id FROM"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockSelectFileIdsRs);
|
||||||
|
when(mockSelectFileIdsRs.next()).thenReturn(true, false);
|
||||||
|
when(mockSelectFileIdsRs.getString("file_id")).thenReturn("file1");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockDossierPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT f.id AS file_id, d.dossier_template_id"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockDossierRs);
|
||||||
|
when(mockDossierRs.next()).thenReturn(true, false);
|
||||||
|
when(mockDossierRs.getString("file_id")).thenReturn("file1");
|
||||||
|
when(mockDossierRs.getString("dossier_template_id")).thenReturn("template1");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockReasonPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT reason, legal_basis_mapping_entity_dossier_template_id, technical_name"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockReasonRs);
|
||||||
|
when(mockReasonRs.next()).thenReturn(true, false);
|
||||||
|
when(mockReasonRs.getString("reason")).thenReturn("reason1");
|
||||||
|
when(mockReasonRs.getString("legal_basis_mapping_entity_dossier_template_id")).thenReturn("template1");
|
||||||
|
when(mockReasonRs.getString("technical_name")).thenReturn("techName1");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String table : tables) {
|
||||||
|
try (PreparedStatement mockSelectUpdatePs = mock(PreparedStatement.class); ResultSet mockSelectUpdateRs = mock(ResultSet.class); PreparedStatement mockUpdate = mock(
|
||||||
|
PreparedStatement.class)) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT annotation_id, file_id, legal_basis FROM " + table))).thenReturn(mockSelectUpdatePs);
|
||||||
|
when(mockSelectUpdatePs.executeQuery()).thenReturn(mockSelectUpdateRs);
|
||||||
|
when(mockSelectUpdateRs.next()).thenReturn(true, false);
|
||||||
|
when(mockSelectUpdateRs.getString("annotation_id")).thenReturn("ann1");
|
||||||
|
when(mockSelectUpdateRs.getString("file_id")).thenReturn("file1");
|
||||||
|
when(mockSelectUpdateRs.getString("legal_basis")).thenReturn("reason1");
|
||||||
|
|
||||||
|
when(mockConnection.prepareStatement(startsWith("UPDATE " + table))).thenReturn(mockUpdate);
|
||||||
|
when(mockUpdate.executeUpdate()).thenReturn(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
technicalNameChange.execute(mockDatabase);
|
||||||
|
|
||||||
|
verify(mockUpdatePs, never()).executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecute_sqlExceptionDuringUpdate() throws Exception {
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockSelectFileIdsPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT DISTINCT file_id FROM"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockSelectFileIdsRs);
|
||||||
|
when(mockSelectFileIdsRs.next()).thenReturn(true, false);
|
||||||
|
when(mockSelectFileIdsRs.getString("file_id")).thenReturn("file1");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockDossierPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT f.id AS file_id, d.dossier_template_id"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockDossierRs);
|
||||||
|
when(mockDossierRs.next()).thenReturn(true, false);
|
||||||
|
when(mockDossierRs.getString("file_id")).thenReturn("file1");
|
||||||
|
when(mockDossierRs.getString("dossier_template_id")).thenReturn("template1");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement ps = mockReasonPs) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT reason, legal_basis_mapping_entity_dossier_template_id, technical_name"))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(mockReasonRs);
|
||||||
|
when(mockReasonRs.next()).thenReturn(true, false);
|
||||||
|
when(mockReasonRs.getString("reason")).thenReturn("reason1");
|
||||||
|
when(mockReasonRs.getString("legal_basis_mapping_entity_dossier_template_id")).thenReturn("template1");
|
||||||
|
when(mockReasonRs.getString("technical_name")).thenReturn("techName1");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement mockSelectUpdatePs = mock(PreparedStatement.class); ResultSet mockSelectUpdateRs = mock(ResultSet.class)) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT annotation_id, file_id, legal_basis FROM manual_legal_basis_change"))).thenReturn(mockSelectUpdatePs);
|
||||||
|
when(mockSelectUpdatePs.executeQuery()).thenReturn(mockSelectUpdateRs);
|
||||||
|
when(mockSelectUpdateRs.next()).thenReturn(true, false);
|
||||||
|
when(mockSelectUpdateRs.getString("annotation_id")).thenReturn("ann1");
|
||||||
|
when(mockSelectUpdateRs.getString("file_id")).thenReturn("file1");
|
||||||
|
when(mockSelectUpdateRs.getString("legal_basis")).thenReturn("reason1");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (PreparedStatement mockUpdate = mock(PreparedStatement.class)) {
|
||||||
|
when(mockConnection.prepareStatement(startsWith("UPDATE manual_legal_basis_change"))).thenReturn(mockUpdate);
|
||||||
|
when(mockUpdate.executeUpdate()).thenThrow(new SQLException("Update failed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomChangeException exception = assertThrows(CustomChangeException.class, () -> {
|
||||||
|
technicalNameChange.execute(mockDatabase);
|
||||||
|
});
|
||||||
|
|
||||||
|
assertTrue(exception.getMessage().contains("Error applying technical name change"));
|
||||||
|
assertInstanceOf(SQLException.class, exception.getCause());
|
||||||
|
assertEquals("Update failed", exception.getCause().getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setupTableMocks(PreparedStatement ps,
|
||||||
|
ResultSet rs,
|
||||||
|
String tableName,
|
||||||
|
String annotationId1,
|
||||||
|
String annotationId2,
|
||||||
|
String fileId1,
|
||||||
|
String fileId2,
|
||||||
|
String legalBasis1,
|
||||||
|
String legalBasis2) throws SQLException {
|
||||||
|
|
||||||
|
when(mockConnection.prepareStatement(startsWith("SELECT annotation_id, file_id, legal_basis FROM " + tableName))).thenReturn(ps);
|
||||||
|
when(ps.executeQuery()).thenReturn(rs);
|
||||||
|
when(rs.next()).thenReturn(true, true, false);
|
||||||
|
when(rs.getString("annotation_id")).thenReturn(annotationId1, annotationId2);
|
||||||
|
when(rs.getString("file_id")).thenReturn(fileId1, fileId2);
|
||||||
|
when(rs.getString("legal_basis")).thenReturn(legalBasis1, legalBasis2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Map<String, String> createExpectedUpdates(HashFunction hashFunction) {
|
||||||
|
|
||||||
|
Map<String, String> expectedUpdates = new HashMap<>();
|
||||||
|
expectedUpdates.put("ann1", "techName1");
|
||||||
|
expectedUpdates.put("ann2", hashFunction.hashString("reason2", StandardCharsets.UTF_8).toString());
|
||||||
|
expectedUpdates.put("ann3", hashFunction.hashString("reason3", StandardCharsets.UTF_8).toString());
|
||||||
|
expectedUpdates.put("ann4", hashFunction.hashString("reason4", StandardCharsets.UTF_8).toString());
|
||||||
|
expectedUpdates.put("ann5", hashFunction.hashString("reason5", StandardCharsets.UTF_8).toString());
|
||||||
|
expectedUpdates.put("ann6", hashFunction.hashString("reason6", StandardCharsets.UTF_8).toString());
|
||||||
|
expectedUpdates.put("ann7", hashFunction.hashString("reason7", StandardCharsets.UTF_8).toString());
|
||||||
|
expectedUpdates.put("ann8", hashFunction.hashString("reason8", StandardCharsets.UTF_8).toString());
|
||||||
|
return expectedUpdates;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,636 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import com.google.common.hash.HashFunction;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.LegalBasisEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.migrations.V29TechnicalNameEntityLogMigration;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.MigrationPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierRepository;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Change;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ChangeType;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogLegalBasis;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ManualChange;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ManualRedactionType;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.EntityLogMongoService;
|
||||||
|
|
||||||
|
public class TechnicalNameEntityLogMigrationTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DossierRepository dossierRepository;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private FileRepository fileRepository;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private EntityLogMongoService entityLogMongoService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LegalBasisMappingPersistenceService legalBasisMappingPersistenceService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private MigrationPersistenceService migrationPersistenceService;
|
||||||
|
|
||||||
|
private V29TechnicalNameEntityLogMigration migration;
|
||||||
|
|
||||||
|
private final HashFunction hashFunction = Hashing.murmur3_128();
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
|
||||||
|
when(migrationPersistenceService.getLatestProcessedVersion()).thenReturn(0L);
|
||||||
|
when(migrationPersistenceService.isProcessed(anyLong(), anyLong())).thenReturn(false);
|
||||||
|
|
||||||
|
LegalBasisMappingService legalBasisMappingService = new LegalBasisMappingService(legalBasisMappingPersistenceService);
|
||||||
|
|
||||||
|
migration = new V29TechnicalNameEntityLogMigration(dossierRepository, fileRepository, entityLogMongoService, legalBasisMappingService);
|
||||||
|
|
||||||
|
migration.setMigrationPersistenceService(migrationPersistenceService);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationUpdatesMappedLegalBasisTechnicalNames() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_TechName").reason("LB1_Reason").build();
|
||||||
|
LegalBasisEntity lb2 = LegalBasisEntity.builder().technicalName("LB2_TechName").reason("LB2_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Arrays.asList(lb1, lb2));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
|
||||||
|
EntityLogEntry entry1 = EntityLogEntry.builder().legalBasis("LB1_Reason").build();
|
||||||
|
EntityLogEntry entry2 = EntityLogEntry.builder().legalBasis("LB2_Reason").build();
|
||||||
|
EntityLog entityLog = createEntityLog(Arrays.asList(entry1, entry2));
|
||||||
|
|
||||||
|
entityLog.setLegalBasis(List.of(EntityLogLegalBasis.builder().technicalName("LB1_TechName").reason("LB1_Reason").build(),
|
||||||
|
EntityLogLegalBasis.builder().technicalName("LB2_TechName").reason("LB2_Reason").build()));
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertAll(() -> assertEquals("LB1_TechName", entry1.getLegalBasis()), () -> assertEquals("LB2_TechName", entry2.getLegalBasis()));
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationHashesUnmappedLegalBasis() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
|
||||||
|
EntityLogEntry entry1 = EntityLogEntry.builder().legalBasis("Unmapped_LB1").build();
|
||||||
|
EntityLogEntry entry2 = EntityLogEntry.builder().legalBasis("Unmapped_LB2").build();
|
||||||
|
EntityLog entityLog = createEntityLog(Arrays.asList(entry1, entry2));
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
String hashedLB1 = hashFunction.hashString("Unmapped_LB1", StandardCharsets.UTF_8).toString();
|
||||||
|
String hashedLB2 = hashFunction.hashString("Unmapped_LB2", StandardCharsets.UTF_8).toString();
|
||||||
|
assertAll(() -> assertEquals(hashedLB1, entry1.getLegalBasis()), () -> assertEquals(hashedLB2, entry2.getLegalBasis()));
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationSkipsEntriesWithoutLegalBasis() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
|
||||||
|
EntityLogEntry entry1 = EntityLogEntry.builder().legalBasis(null).build();
|
||||||
|
EntityLogEntry entry2 = EntityLogEntry.builder().legalBasis("").build();
|
||||||
|
EntityLog entityLog = createEntityLog(Arrays.asList(entry1, entry2));
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertAll(() -> assertNull(entry1.getLegalBasis()), () -> assertEquals("", entry2.getLegalBasis()));
|
||||||
|
verify(entityLogMongoService, never()).saveEntityLog(anyString(), anyString(), any(EntityLog.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationSkipsFilesWithoutEntityLog() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(entityLogMongoService, never()).saveEntityLog(anyString(), anyString(), any(EntityLog.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithNoDossiers() {
|
||||||
|
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(fileRepository, never()).findByDossierId(anyString());
|
||||||
|
verify(entityLogMongoService, never()).findEntityLogByDossierIdAndFileId(anyString(), anyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithMixedEntries() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity mappedLB = LegalBasisEntity.builder().technicalName("Mapped_TechName").reason("Mapped_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(List.of(mappedLB));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
|
||||||
|
EntityLogEntry mappedEntry = EntityLogEntry.builder().legalBasis("Mapped_Reason").build();
|
||||||
|
EntityLogEntry unmappedEntry = EntityLogEntry.builder().legalBasis("Unmapped_Reason").build();
|
||||||
|
EntityLogEntry nullEntry = EntityLogEntry.builder().legalBasis(null).build();
|
||||||
|
EntityLog entityLog = createEntityLog(Arrays.asList(mappedEntry, unmappedEntry, nullEntry));
|
||||||
|
|
||||||
|
entityLog.setLegalBasis(new ArrayList<>());
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
String hashedUnmapped = hashFunction.hashString("Unmapped_Reason", StandardCharsets.UTF_8).toString();
|
||||||
|
|
||||||
|
assertAll(() -> assertEquals("Mapped_TechName", mappedEntry.getLegalBasis()),
|
||||||
|
() -> assertEquals(hashedUnmapped, unmappedEntry.getLegalBasis()),
|
||||||
|
() -> assertNull(nullEntry.getLegalBasis()));
|
||||||
|
|
||||||
|
assertEquals(2, entityLog.getLegalBasis().size());
|
||||||
|
assertTrue(entityLog.getLegalBasis()
|
||||||
|
.stream()
|
||||||
|
.anyMatch(lb -> lb.getTechnicalName().equals("Mapped_TechName") && lb.getReason().equals("Mapped_Reason")));
|
||||||
|
assertTrue(entityLog.getLegalBasis()
|
||||||
|
.stream()
|
||||||
|
.anyMatch(lb -> lb.getTechnicalName().equals(hashedUnmapped) && lb.getReason().equals("Unmapped_Reason")));
|
||||||
|
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationDoesNotUpdateWhenNoChanges() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.singletonList(LegalBasisEntity.builder()
|
||||||
|
.technicalName("LB1_Tech")
|
||||||
|
.reason("LB1_Reason")
|
||||||
|
.build()));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
|
||||||
|
EntityLogEntry entry = EntityLogEntry.builder().legalBasis("LB1_Tech").build();
|
||||||
|
EntityLog entityLog = createEntityLog(List.of(entry));
|
||||||
|
|
||||||
|
entityLog.setLegalBasis(new ArrayList<>(List.of(EntityLogLegalBasis.builder().technicalName("LB1_Tech").reason("LB1_Reason").build())));
|
||||||
|
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(entityLogMongoService, never()).saveEntityLog(anyString(), anyString(), any(EntityLog.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationProcessesMultipleDossiers() {
|
||||||
|
|
||||||
|
DossierEntity dossier1 = createDossier("dossier1", "template1");
|
||||||
|
DossierEntity dossier2 = createDossier("dossier2", "template2");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier1, dossier2));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_Tech").reason("LB1_Reason").build();
|
||||||
|
LegalBasisEntity lb2 = LegalBasisEntity.builder().technicalName("LB2_Tech").reason("LB2_Reason").build();
|
||||||
|
LegalBasisEntity lb3 = LegalBasisEntity.builder().technicalName("LB3_Tech").reason("LB3_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(List.of(lb1, lb2));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template2")).thenReturn(List.of(lb3));
|
||||||
|
|
||||||
|
FileEntity file1 = createFile("file1", "dossier1");
|
||||||
|
FileEntity file2 = createFile("file2", "dossier2");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file1));
|
||||||
|
when(fileRepository.findByDossierId("dossier2")).thenReturn(List.of(file2));
|
||||||
|
|
||||||
|
EntityLogEntry entry1 = EntityLogEntry.builder().legalBasis("LB1_Reason").build();
|
||||||
|
EntityLog entityLog1 = createEntityLog(List.of(entry1));
|
||||||
|
entityLog1.setLegalBasis(List.of(EntityLogLegalBasis.builder().technicalName("LB1_Tech").reason("LB1_Reason").build(),
|
||||||
|
EntityLogLegalBasis.builder().technicalName("LB2_Tech").reason("LB2_Reason").build()));
|
||||||
|
|
||||||
|
EntityLogEntry entry2 = EntityLogEntry.builder().legalBasis("LB3_Reason").build();
|
||||||
|
EntityLog entityLog2 = createEntityLog(List.of(entry2));
|
||||||
|
entityLog2.setLegalBasis(List.of(EntityLogLegalBasis.builder().technicalName("LB3_Tech").reason("LB3_Reason").build()));
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog1));
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier2", "file2")).thenReturn(Optional.of(entityLog2));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertAll(() -> assertEquals("LB1_Tech", entry1.getLegalBasis()), () -> assertEquals("LB3_Tech", entry2.getLegalBasis()));
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog1);
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier2", "file2", entityLog2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationProcessesMultipleFilesPerDossier() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_Tech").reason("LB1_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(List.of(lb1));
|
||||||
|
|
||||||
|
FileEntity file1 = createFile("file1", "dossier1");
|
||||||
|
FileEntity file2 = createFile("file2", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file1, file2));
|
||||||
|
|
||||||
|
EntityLogEntry entry1 = EntityLogEntry.builder().legalBasis("LB1_Reason").build();
|
||||||
|
EntityLog entityLog1 = createEntityLog(List.of(entry1));
|
||||||
|
entityLog1.setLegalBasis(List.of(EntityLogLegalBasis.builder().technicalName("LB1_Tech").reason("LB1_Reason").build()));
|
||||||
|
|
||||||
|
EntityLogEntry entry2 = EntityLogEntry.builder().legalBasis("Unmapped_LB").build();
|
||||||
|
EntityLog entityLog2 = createEntityLog(List.of(entry2));
|
||||||
|
entityLog2.setLegalBasis(new ArrayList<>());
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog1));
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file2")).thenReturn(Optional.of(entityLog2));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
String expectedHash = hashFunction.hashString("Unmapped_LB", StandardCharsets.UTF_8).toString();
|
||||||
|
|
||||||
|
assertAll(() -> assertEquals("LB1_Tech", entry1.getLegalBasis()), () -> assertEquals(expectedHash, entry2.getLegalBasis()));
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog1);
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file2", entityLog2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationDoesNotAddDuplicateLegalBasis() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
|
||||||
|
String hashedLB = hashFunction.hashString("Unmapped_LB", StandardCharsets.UTF_8).toString();
|
||||||
|
EntityLogLegalBasis existingLB = createEntityLogLegalBasisForUnmappedLegalBasis(hashedLB);
|
||||||
|
|
||||||
|
EntityLogEntry entry = EntityLogEntry.builder().legalBasis("Unmapped_LB").build();
|
||||||
|
EntityLog entityLog = createEntityLog(List.of(entry));
|
||||||
|
entityLog.setLegalBasis(new ArrayList<>(List.of(existingLB)));
|
||||||
|
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertEquals(hashedLB, entry.getLegalBasis());
|
||||||
|
assertEquals(1, entityLog.getLegalBasis().size());
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationInitializesLegalBasisListWhenNull() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
|
||||||
|
EntityLogEntry entry = EntityLogEntry.builder().legalBasis("Unmapped_LB").build();
|
||||||
|
EntityLog entityLog = createEntityLog(List.of(entry));
|
||||||
|
entityLog.setLegalBasis(null);
|
||||||
|
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertNotNull(entityLog.getLegalBasis());
|
||||||
|
assertEquals(1, entityLog.getLegalBasis().size());
|
||||||
|
|
||||||
|
String expectedHash = hashFunction.hashString("Unmapped_LB", StandardCharsets.UTF_8).toString();
|
||||||
|
assertEquals(expectedHash, entry.getLegalBasis());
|
||||||
|
|
||||||
|
EntityLogLegalBasis newLB = entityLog.getLegalBasis()
|
||||||
|
.get(0);
|
||||||
|
assertEquals(expectedHash, newLB.getTechnicalName());
|
||||||
|
assertEquals("Unmapped_LB", newLB.getReason());
|
||||||
|
assertEquals("Generated Legal Basis", newLB.getName());
|
||||||
|
assertEquals("", newLB.getDescription());
|
||||||
|
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationUpdates() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_Tech").reason("LB1_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(List.of(lb1));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
|
||||||
|
EntityLogEntry entry1 = EntityLogEntry.builder().legalBasis("LB1_Reason").build();
|
||||||
|
EntityLogEntry entry2 = EntityLogEntry.builder().legalBasis("Unmapped_LB").build();
|
||||||
|
EntityLogEntry entry3 = EntityLogEntry.builder().legalBasis("Another_Unmapped_LB").build();
|
||||||
|
EntityLog entityLog = createEntityLog(Arrays.asList(entry1, entry2, entry3));
|
||||||
|
|
||||||
|
entityLog.setLegalBasis(new ArrayList<>());
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
String hashedUnmappedLB = hashFunction.hashString("Unmapped_LB", StandardCharsets.UTF_8).toString();
|
||||||
|
String hashedAnotherUnmappedLB = hashFunction.hashString("Another_Unmapped_LB", StandardCharsets.UTF_8).toString();
|
||||||
|
|
||||||
|
assertAll(() -> assertEquals("LB1_Tech", entry1.getLegalBasis()),
|
||||||
|
() -> assertEquals(hashedUnmappedLB, entry2.getLegalBasis()),
|
||||||
|
() -> assertEquals(hashedAnotherUnmappedLB, entry3.getLegalBasis()));
|
||||||
|
|
||||||
|
assertEquals(3, entityLog.getLegalBasis().size());
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationHandlesDuplicateEntityLogEntries() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_Tech").reason("LB1_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(List.of(lb1));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
|
||||||
|
EntityLogEntry entry1 = EntityLogEntry.builder().legalBasis("LB1_Reason").build();
|
||||||
|
EntityLogEntry entry2 = EntityLogEntry.builder().legalBasis("LB1_Reason").build();
|
||||||
|
EntityLog entityLog = createEntityLog(List.of(entry1, entry2));
|
||||||
|
|
||||||
|
entityLog.setLegalBasis(new ArrayList<>());
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertAll(() -> assertEquals("LB1_Tech", entry1.getLegalBasis()),
|
||||||
|
() -> assertEquals("LB1_Tech", entry2.getLegalBasis()),
|
||||||
|
() -> assertEquals(1, entityLog.getLegalBasis().size()));
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationHandlesExistingHashedTechnicalName() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
|
||||||
|
String hashedLB = hashFunction.hashString("Unmapped_LB", StandardCharsets.UTF_8).toString();
|
||||||
|
EntityLogLegalBasis existingLB = createEntityLogLegalBasisForUnmappedLegalBasis(hashedLB);
|
||||||
|
|
||||||
|
EntityLogEntry entry = EntityLogEntry.builder().legalBasis("Unmapped_LB").build();
|
||||||
|
EntityLog entityLog = createEntityLog(List.of(entry));
|
||||||
|
entityLog.setLegalBasis(new ArrayList<>(List.of(existingLB)));
|
||||||
|
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertEquals(hashedLB, entry.getLegalBasis());
|
||||||
|
assertEquals(1, entityLog.getLegalBasis().size());
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationSkipsSavingWhenNoEntriesUpdated() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_Tech").reason("LB1_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(List.of(lb1));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
|
||||||
|
EntityLogEntry entry = EntityLogEntry.builder().legalBasis("LB1_Tech").build();
|
||||||
|
EntityLogLegalBasis lb = EntityLogLegalBasis.builder()
|
||||||
|
.technicalName("LB1_Tech")
|
||||||
|
.reason("LB1_Reason")
|
||||||
|
.name("Generated Legal Basis")
|
||||||
|
.description("")
|
||||||
|
.build();
|
||||||
|
EntityLog entityLog = createEntityLog(List.of(entry));
|
||||||
|
entityLog.setLegalBasis(new ArrayList<>(List.of(lb)));
|
||||||
|
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(entityLogMongoService, never()).saveEntityLog(anyString(), anyString(), any(EntityLog.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationUpdatesPropertyChangesLegalBasis() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(List.of(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("personal_data_geolocation_article_39e3").reason("Article 39(e)(3) of Regulation (EC) No 178/2002").build();
|
||||||
|
|
||||||
|
LegalBasisEntity lb2 = LegalBasisEntity.builder()
|
||||||
|
.technicalName("article_63_2_a_regulation_1107_2009")
|
||||||
|
.reason("Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(List.of(lb1, lb2));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(List.of(file));
|
||||||
|
|
||||||
|
Change change1 = new Change();
|
||||||
|
change1.setAnalysisNumber(18);
|
||||||
|
change1.setType(ChangeType.CHANGED);
|
||||||
|
change1.setDateTime(OffsetDateTime.now());
|
||||||
|
|
||||||
|
Map<String, String> propertyChanges1 = new HashMap<>();
|
||||||
|
propertyChanges1.put("legalBasis", "personal_data_geolocation_article_39e3 -> Article 39(e)(3) of Regulation (EC) No 178/2002");
|
||||||
|
change1.setPropertyChanges(propertyChanges1);
|
||||||
|
|
||||||
|
Change change2 = new Change();
|
||||||
|
change2.setAnalysisNumber(19);
|
||||||
|
change2.setType(ChangeType.CHANGED);
|
||||||
|
change2.setDateTime(OffsetDateTime.now());
|
||||||
|
|
||||||
|
Map<String, String> propertyChanges2 = new HashMap<>();
|
||||||
|
propertyChanges2.put("legalBasis", "Article 39(e)(3) of Regulation (EC) No 178/2002 -> personal_data_geolocation_article_39e3");
|
||||||
|
change2.setPropertyChanges(propertyChanges2);
|
||||||
|
|
||||||
|
ManualChange manualChange = new ManualChange();
|
||||||
|
manualChange.setManualRedactionType(ManualRedactionType.RECATEGORIZE);
|
||||||
|
manualChange.setProcessedDate(OffsetDateTime.now());
|
||||||
|
manualChange.setRequestedDate(OffsetDateTime.now());
|
||||||
|
manualChange.setUserId("user123");
|
||||||
|
|
||||||
|
Map<String, String> manualPropertyChanges = new HashMap<>();
|
||||||
|
manualPropertyChanges.put("legalBasis", "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)");
|
||||||
|
manualChange.setPropertyChanges(manualPropertyChanges);
|
||||||
|
|
||||||
|
EntityLogEntry entry = EntityLogEntry.builder()
|
||||||
|
.legalBasis("personal_data_geolocation_article_39e3")
|
||||||
|
.changes(List.of(change1, change2))
|
||||||
|
.manualChanges(List.of(manualChange))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
EntityLog entityLog = createEntityLog(List.of(entry));
|
||||||
|
entityLog.setLegalBasis(new ArrayList<>());
|
||||||
|
|
||||||
|
when(entityLogMongoService.findEntityLogByDossierIdAndFileId("dossier1", "file1")).thenReturn(Optional.of(entityLog));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
String expectedLegalBasis1 = "personal_data_geolocation_article_39e3 -> personal_data_geolocation_article_39e3";
|
||||||
|
String expectedLegalBasis2 = "personal_data_geolocation_article_39e3 -> personal_data_geolocation_article_39e3";
|
||||||
|
String expectedManualLegalBasis = "article_63_2_a_regulation_1107_2009";
|
||||||
|
|
||||||
|
assertEquals(expectedLegalBasis1,
|
||||||
|
change1.getPropertyChanges()
|
||||||
|
.get("legalBasis"));
|
||||||
|
assertEquals(expectedLegalBasis2,
|
||||||
|
change2.getPropertyChanges()
|
||||||
|
.get("legalBasis"));
|
||||||
|
assertEquals(expectedManualLegalBasis,
|
||||||
|
manualChange.getPropertyChanges()
|
||||||
|
.get("legalBasis"));
|
||||||
|
|
||||||
|
verify(entityLogMongoService).saveEntityLog("dossier1", "file1", entityLog);
|
||||||
|
|
||||||
|
assertEquals(2, entityLog.getLegalBasis().size());
|
||||||
|
assertTrue(entityLog.getLegalBasis()
|
||||||
|
.stream()
|
||||||
|
.anyMatch(lb -> lb.getTechnicalName().equals("personal_data_geolocation_article_39e3")));
|
||||||
|
assertTrue(entityLog.getLegalBasis()
|
||||||
|
.stream()
|
||||||
|
.anyMatch(lb -> lb.getTechnicalName().equals("article_63_2_a_regulation_1107_2009")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DossierEntity createDossier(String id, String templateId) {
|
||||||
|
|
||||||
|
DossierEntity dossier = new DossierEntity();
|
||||||
|
dossier.setId(id);
|
||||||
|
dossier.setDossierTemplateId(templateId);
|
||||||
|
return dossier;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private FileEntity createFile(String id, String dossierId) {
|
||||||
|
|
||||||
|
FileEntity file = new FileEntity();
|
||||||
|
file.setId(id);
|
||||||
|
file.setDossierId(dossierId);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private EntityLog createEntityLog(List<EntityLogEntry> entries) {
|
||||||
|
|
||||||
|
EntityLog entityLog = new EntityLog();
|
||||||
|
entityLog.setEntityLogEntry(entries);
|
||||||
|
return entityLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private EntityLogLegalBasis createEntityLogLegalBasisForUnmappedLegalBasis(String technicalName) {
|
||||||
|
|
||||||
|
return EntityLogLegalBasis.builder()
|
||||||
|
.technicalName(technicalName)
|
||||||
|
.reason("Unmapped_LB")
|
||||||
|
.name("Generated Legal Basis")
|
||||||
|
.description("")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,366 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
|
import static org.mockito.Mockito.any;
|
||||||
|
import static org.mockito.Mockito.anyString;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.LegalBasisEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.migrations.V31TechnicalNameImportedFilesMigration;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.MigrationPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierRepository;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedLegalBases;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedLegalBasis;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedaction;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.imported.ImportedRedactionsPerPage;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
||||||
|
|
||||||
|
public class TechnicalNameImportedFilesMigrationTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DossierRepository dossierRepository;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private FileRepository fileRepository;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private FileManagementStorageService fileManagementStorageService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LegalBasisMappingPersistenceService legalBasisMappingPersistenceService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private MigrationPersistenceService migrationPersistenceService;
|
||||||
|
|
||||||
|
private LegalBasisMappingService legalBasisMappingService;
|
||||||
|
|
||||||
|
private V31TechnicalNameImportedFilesMigration migration;
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
|
||||||
|
when(migrationPersistenceService.getLatestProcessedVersion()).thenReturn(0L);
|
||||||
|
when(migrationPersistenceService.isProcessed(anyLong(), anyLong())).thenReturn(false);
|
||||||
|
|
||||||
|
legalBasisMappingService = new LegalBasisMappingService(legalBasisMappingPersistenceService);
|
||||||
|
|
||||||
|
migration = new V31TechnicalNameImportedFilesMigration(dossierRepository, fileRepository, fileManagementStorageService, legalBasisMappingService);
|
||||||
|
|
||||||
|
migration.setMigrationPersistenceService(migrationPersistenceService);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationUpdatesMappedLegalBasisTechnicalNamesInImportedRedactions() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Collections.singletonList(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_TechName").reason("LB1_Reason").build();
|
||||||
|
LegalBasisEntity lb2 = LegalBasisEntity.builder().technicalName("LB2_TechName").reason("LB2_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Arrays.asList(lb1, lb2));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(Collections.singletonList(file));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.objectExists("dossier1", "file1", FileType.IMPORTED_REDACTIONS)).thenReturn(true);
|
||||||
|
|
||||||
|
ImportedRedaction redaction1 = new ImportedRedaction();
|
||||||
|
redaction1.setLegalBasis("LB1_Reason");
|
||||||
|
|
||||||
|
ImportedRedaction redaction2 = new ImportedRedaction();
|
||||||
|
redaction2.setLegalBasis("LB2_Reason");
|
||||||
|
|
||||||
|
ImportedRedactionsPerPage importedRedactions = new ImportedRedactionsPerPage();
|
||||||
|
importedRedactions.setImportedRedactions(Map.of(1, Arrays.asList(redaction1, redaction2)));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.getImportedRedactions("dossier1", "file1")).thenReturn(importedRedactions);
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertEquals("LB1_TechName", redaction1.getLegalBasis());
|
||||||
|
assertEquals("LB2_TechName", redaction2.getLegalBasis());
|
||||||
|
|
||||||
|
verify(fileManagementStorageService).storeJSONObject("dossier1", "file1", FileType.IMPORTED_REDACTIONS, importedRedactions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationHashesUnmappedLegalBasisInImportedRedactions() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Collections.singletonList(dossier));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(Collections.singletonList(file));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.objectExists("dossier1", "file1", FileType.IMPORTED_REDACTIONS)).thenReturn(true);
|
||||||
|
|
||||||
|
ImportedRedaction redaction1 = new ImportedRedaction();
|
||||||
|
redaction1.setLegalBasis("Unmapped_LB1");
|
||||||
|
|
||||||
|
ImportedRedaction redaction2 = new ImportedRedaction();
|
||||||
|
redaction2.setLegalBasis("Unmapped_LB2");
|
||||||
|
|
||||||
|
ImportedRedactionsPerPage importedRedactions = new ImportedRedactionsPerPage();
|
||||||
|
importedRedactions.setImportedRedactions(Map.of(1, Arrays.asList(redaction1, redaction2)));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.getImportedRedactions("dossier1", "file1")).thenReturn(importedRedactions);
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
String hashedLB1 = legalBasisMappingService.processLegalBasis("Unmapped_LB1", new HashMap<>()).technicalName();
|
||||||
|
String hashedLB2 = legalBasisMappingService.processLegalBasis("Unmapped_LB2", new HashMap<>()).technicalName();
|
||||||
|
|
||||||
|
assertEquals(hashedLB1, redaction1.getLegalBasis());
|
||||||
|
assertEquals(hashedLB2, redaction2.getLegalBasis());
|
||||||
|
|
||||||
|
verify(fileManagementStorageService).storeJSONObject("dossier1", "file1", FileType.IMPORTED_REDACTIONS, importedRedactions);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationUpdatesTechnicalNamesInImportedLegalBases() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Collections.singletonList(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_TechName").reason("LB1_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(Collections.singletonList(file));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.objectExists("dossier1", "file1", FileType.IMPORTED_LEGAL_BASES)).thenReturn(true);
|
||||||
|
|
||||||
|
ImportedLegalBasis importedLegalBasis = new ImportedLegalBasis();
|
||||||
|
importedLegalBasis.setReason("LB1_Reason");
|
||||||
|
importedLegalBasis.setTechnicalName(null);
|
||||||
|
|
||||||
|
ImportedLegalBases importedLegalBases = new ImportedLegalBases();
|
||||||
|
importedLegalBases.setImportedLegalBases(Collections.singletonList(importedLegalBasis));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.getImportedLegalBases("dossier1", "file1")).thenReturn(importedLegalBases);
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertEquals("LB1_TechName", importedLegalBasis.getTechnicalName());
|
||||||
|
|
||||||
|
verify(fileManagementStorageService).storeJSONObject("dossier1", "file1", FileType.IMPORTED_LEGAL_BASES, importedLegalBases);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationHandlesFilesWithoutImportedRedactionsOrLegalBases() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Collections.singletonList(dossier));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(Collections.singletonList(file));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.objectExists("dossier1", "file1", FileType.IMPORTED_REDACTIONS)).thenReturn(false);
|
||||||
|
when(fileManagementStorageService.objectExists("dossier1", "file1", FileType.IMPORTED_LEGAL_BASES)).thenReturn(false);
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(fileManagementStorageService, never()).getImportedRedactions(anyString(), anyString());
|
||||||
|
verify(fileManagementStorageService, never()).getImportedLegalBases(anyString(), anyString());
|
||||||
|
|
||||||
|
verify(fileManagementStorageService, never()).storeJSONObject(anyString(), anyString(), any(FileType.class), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationSkipsDossiersWithNoFiles() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Collections.singletonList(dossier));
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(fileManagementStorageService, never()).objectExists(anyString(), anyString(), any(FileType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationProcessesMultipleDossiersAndFiles() {
|
||||||
|
|
||||||
|
DossierEntity dossier1 = createDossier("dossier1", "template1");
|
||||||
|
DossierEntity dossier2 = createDossier("dossier2", "template2");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Arrays.asList(dossier1, dossier2));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_TechName").reason("LB1_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
LegalBasisEntity lb2 = LegalBasisEntity.builder().technicalName("LB2_TechName").reason("LB2_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template2")).thenReturn(Collections.singletonList(lb2));
|
||||||
|
|
||||||
|
FileEntity file1 = createFile("file1", "dossier1");
|
||||||
|
FileEntity file2 = createFile("file2", "dossier2");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(Collections.singletonList(file1));
|
||||||
|
when(fileRepository.findByDossierId("dossier2")).thenReturn(Collections.singletonList(file2));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.objectExists("dossier1", "file1", FileType.IMPORTED_REDACTIONS)).thenReturn(true);
|
||||||
|
when(fileManagementStorageService.objectExists("dossier2", "file2", FileType.IMPORTED_REDACTIONS)).thenReturn(true);
|
||||||
|
|
||||||
|
ImportedRedaction redaction1 = new ImportedRedaction();
|
||||||
|
redaction1.setLegalBasis("LB1_Reason");
|
||||||
|
|
||||||
|
ImportedRedactionsPerPage importedRedactions1 = new ImportedRedactionsPerPage();
|
||||||
|
importedRedactions1.setImportedRedactions(Map.of(1, Collections.singletonList(redaction1)));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.getImportedRedactions("dossier1", "file1")).thenReturn(importedRedactions1);
|
||||||
|
|
||||||
|
ImportedRedaction redaction2 = new ImportedRedaction();
|
||||||
|
redaction2.setLegalBasis("LB2_Reason");
|
||||||
|
|
||||||
|
ImportedRedactionsPerPage importedRedactions2 = new ImportedRedactionsPerPage();
|
||||||
|
importedRedactions2.setImportedRedactions(Map.of(1, Collections.singletonList(redaction2)));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.getImportedRedactions("dossier2", "file2")).thenReturn(importedRedactions2);
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertEquals("LB1_TechName", redaction1.getLegalBasis());
|
||||||
|
assertEquals("LB2_TechName", redaction2.getLegalBasis());
|
||||||
|
|
||||||
|
verify(fileManagementStorageService).storeJSONObject("dossier1", "file1", FileType.IMPORTED_REDACTIONS, importedRedactions1);
|
||||||
|
verify(fileManagementStorageService).storeJSONObject("dossier2", "file2", FileType.IMPORTED_REDACTIONS, importedRedactions2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationDoesNotUpdateWhenNoChangesNeeded() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Collections.singletonList(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_TechName").reason("LB1_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(Collections.singletonList(file));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.objectExists("dossier1", "file1", FileType.IMPORTED_REDACTIONS)).thenReturn(true);
|
||||||
|
|
||||||
|
ImportedRedaction redaction = new ImportedRedaction();
|
||||||
|
redaction.setLegalBasis("LB1_TechName");
|
||||||
|
|
||||||
|
ImportedRedactionsPerPage importedRedactions = new ImportedRedactionsPerPage();
|
||||||
|
importedRedactions.setImportedRedactions(Map.of(1,Collections.singletonList(redaction)));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.getImportedRedactions("dossier1", "file1")).thenReturn(importedRedactions);
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertEquals("LB1_TechName", redaction.getLegalBasis());
|
||||||
|
|
||||||
|
verify(fileManagementStorageService, never()).storeJSONObject(anyString(), anyString(), any(FileType.class), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationHandlesImportedLegalBasesWithExistingTechnicalNames() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Collections.singletonList(dossier));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = LegalBasisEntity.builder().technicalName("LB1_TechName").reason("LB1_Reason").build();
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(Collections.singletonList(file));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.objectExists("dossier1", "file1", FileType.IMPORTED_LEGAL_BASES)).thenReturn(true);
|
||||||
|
|
||||||
|
ImportedLegalBasis importedLegalBasis = new ImportedLegalBasis();
|
||||||
|
importedLegalBasis.setReason("LB1_Reason");
|
||||||
|
importedLegalBasis.setTechnicalName("LB1_TechName");
|
||||||
|
|
||||||
|
ImportedLegalBases importedLegalBases = new ImportedLegalBases();
|
||||||
|
importedLegalBases.setImportedLegalBases(Collections.singletonList(importedLegalBasis));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.getImportedLegalBases("dossier1", "file1")).thenReturn(importedLegalBases);
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
assertEquals("LB1_TechName", importedLegalBasis.getTechnicalName());
|
||||||
|
|
||||||
|
verify(fileManagementStorageService, never()).storeJSONObject(anyString(), anyString(), any(FileType.class), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationHashesUnmappedReasonsInImportedLegalBases() {
|
||||||
|
|
||||||
|
DossierEntity dossier = createDossier("dossier1", "template1");
|
||||||
|
when(dossierRepository.findAll()).thenReturn(Collections.singletonList(dossier));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping("template1")).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
FileEntity file = createFile("file1", "dossier1");
|
||||||
|
when(fileRepository.findByDossierId("dossier1")).thenReturn(Collections.singletonList(file));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.objectExists("dossier1", "file1", FileType.IMPORTED_LEGAL_BASES)).thenReturn(true);
|
||||||
|
|
||||||
|
ImportedLegalBasis importedLegalBasis = new ImportedLegalBasis();
|
||||||
|
importedLegalBasis.setReason("Unmapped_Reason");
|
||||||
|
importedLegalBasis.setTechnicalName(null);
|
||||||
|
|
||||||
|
ImportedLegalBases importedLegalBases = new ImportedLegalBases();
|
||||||
|
importedLegalBases.setImportedLegalBases(Collections.singletonList(importedLegalBasis));
|
||||||
|
|
||||||
|
when(fileManagementStorageService.getImportedLegalBases("dossier1", "file1")).thenReturn(importedLegalBases);
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
String hashedTechnicalName = legalBasisMappingService.processLegalBasis("Unmapped_Reason", new HashMap<>()).technicalName();
|
||||||
|
|
||||||
|
assertEquals(hashedTechnicalName, importedLegalBasis.getTechnicalName());
|
||||||
|
|
||||||
|
verify(fileManagementStorageService).storeJSONObject("dossier1", "file1", FileType.IMPORTED_LEGAL_BASES, importedLegalBases);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DossierEntity createDossier(String id, String templateId) {
|
||||||
|
|
||||||
|
DossierEntity dossier = new DossierEntity();
|
||||||
|
dossier.setId(id);
|
||||||
|
dossier.setDossierTemplateId(templateId);
|
||||||
|
return dossier;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private FileEntity createFile(String id, String dossierId) {
|
||||||
|
|
||||||
|
FileEntity file = new FileEntity();
|
||||||
|
file.setId(id);
|
||||||
|
file.setDossierId(dossierId);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,672 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.*;
|
||||||
|
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.LegalBasisEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.RuleSetEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierTemplateEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.migrations.V30TechnicalNameRuleFileMigration;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.LegalBasisMappingPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.MigrationPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.RulesPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.DossierTemplateRepository;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
|
||||||
|
|
||||||
|
public class TechnicalNameRuleFileMigrationTest {
|
||||||
|
|
||||||
|
private static final String TEMPLATE_ID_1 = "template1";
|
||||||
|
private static final String TEMPLATE_ID_2 = "template2";
|
||||||
|
|
||||||
|
private static final String RULES_WITH_REASONS = "rule \"CBI.0.4: Redact CBI Authors (vertebrate Study)\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " FileAttribute(label == \"Vertebrate Study\", value soundslike \"Yes\" || value.toLowerCase() == \"y\")\n"
|
||||||
|
+ " $entity: TextEntity(type() == \"CBI_author\", dictionaryEntry)\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " $entity.redact(\"CBI.0.4\", \"Author found\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n"
|
||||||
|
+ " end\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "rule \"CBI.0.3: Redact CBI Authors (non vertebrate Study)\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " not FileAttribute(label == \"Vertebrate Study\", value soundslike \"Yes\" || value.toLowerCase() == \"y\")\n"
|
||||||
|
+ " $entity: TextEntity(type() == \"CBI_author\", dictionaryEntry)\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " $entity.redact(\"CBI.0.3\", \"Author found\", \"Article 39(e)(3) of Regulation (EC) No 178/2002\");\n"
|
||||||
|
+ " end";
|
||||||
|
|
||||||
|
private static final String RULES_WITH_SPECIAL_CHARACTERS = "rule \"Special Characters Rule\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " // conditions\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " // actions\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)\");\n"
|
||||||
|
+ " end";
|
||||||
|
|
||||||
|
private static final String RULES_WITH_NO_REASONS = "rule \"Some Rule\"\n" + " when\n" + " // conditions\n" + " then\n" + " // actions\n" + " end";
|
||||||
|
|
||||||
|
private static final String RULES_WITH_PARTIAL_MATCH = "rule \"Partial Match Rule\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " // conditions\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " // actions\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"Some Article 39(e)(2) of Regulation (EC) No 178/2002 Additional Text\");\n"
|
||||||
|
+ " end";
|
||||||
|
|
||||||
|
private static final String RULES_WITH_IDENTICAL_REASON_AND_TECHNICAL_NAME = "rule \"Identical Reason and Technical Name Rule\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " // conditions\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " // actions\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"same_name\");\n"
|
||||||
|
+ " end";
|
||||||
|
|
||||||
|
private static final String RULES_WITH_MULTIPLE_TEMPLATES = "rule \"Composition Rule\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " // conditions\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " // actions\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"Article 63(2)(d) of Regulation (EC) No 1107/2009\");\n"
|
||||||
|
+ " end";
|
||||||
|
|
||||||
|
private static final String RULES_WITH_NULL_VALUES = "rule \"Null Values Rule\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " // conditions\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " // actions\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n"
|
||||||
|
+ " end";
|
||||||
|
|
||||||
|
private static final String RULES_WITH_PARTIAL_VALID_MAPPINGS = "rule \"Partial Valid Mappings Rule\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " // conditions\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " // actions\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"Some Other Reason\");\n"
|
||||||
|
+ " end";
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private DossierTemplateRepository dossierTemplateRepository;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private RulesPersistenceService rulesPersistenceService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LegalBasisMappingPersistenceService legalBasisMappingPersistenceService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private MigrationPersistenceService migrationPersistenceService;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private V30TechnicalNameRuleFileMigration migration;
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
migration.setMigrationPersistenceService(migrationPersistenceService);
|
||||||
|
when(migrationPersistenceService.getLatestProcessedVersion()).thenReturn(0L);
|
||||||
|
when(migrationPersistenceService.isProcessed(anyLong(), anyLong())).thenReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DossierTemplateEntity createDossierTemplate(String id) {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = new DossierTemplateEntity();
|
||||||
|
dossierTemplate.setId(id);
|
||||||
|
return dossierTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private LegalBasisEntity createLegalBasis(String reason, String technicalName) {
|
||||||
|
|
||||||
|
return LegalBasisEntity.builder().reason(reason).technicalName(technicalName).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private RuleSetEntity createRuleSet(String content) {
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = new RuleSetEntity();
|
||||||
|
ruleSet.setValue(content);
|
||||||
|
return ruleSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationReplacesLegalBasisReasonsWithTechnicalNames() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
List<LegalBasisEntity> mappings = Arrays.asList(createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002",
|
||||||
|
"vertebrate_study_personal_data_geolocation_article_39e2"),
|
||||||
|
createLegalBasis("Article 39(e)(3) of Regulation (EC) No 178/2002", "personal_data_geolocation_article_39e3"));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(mappings);
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_REASONS);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules = rulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedRules.contains("vertebrate_study_personal_data_geolocation_article_39e2")),
|
||||||
|
() -> assertTrue(updatedRules.contains("personal_data_geolocation_article_39e3")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 39(e)(3) of Regulation (EC) No 178/2002")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithNoLegalBasisMappings() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verifyNoInteractions(rulesPersistenceService);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithNoRuleSet() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "vertebrate_study_personal_data_geolocation_article_39e2");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(rulesPersistenceService, never()).setRules(anyString(), anyString(), any(RuleFileType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithNoReplacementsNeeded() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Nonexistent Reason", "nonexistent_technical_name");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_NO_REASONS);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(rulesPersistenceService, never()).setRules(anyString(), anyString(), any(RuleFileType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationHandlesSpecialCharactersInReasons() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)",
|
||||||
|
"manufacturing_production_process");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_SPECIAL_CHARACTERS);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules = rulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedRules.contains("manufacturing_production_process")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationDoesNotReplacePartialMatches() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "vertebrate_study_personal_data_geolocation_article_39e2");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_PARTIAL_MATCH);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(rulesPersistenceService, never()).setRules(anyString(), anyString(), any(RuleFileType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationSkipsIdenticalReasonAndTechnicalName() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("same_name", "same_name");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_IDENTICAL_REASON_AND_TECHNICAL_NAME);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(rulesPersistenceService, never()).setRules(anyString(), anyString(), any(RuleFileType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationProcessesMultipleDossierTemplates() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate1 = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
DossierTemplateEntity dossierTemplate2 = createDossierTemplate(TEMPLATE_ID_2);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Arrays.asList(dossierTemplate1, dossierTemplate2));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "vertebrate_study_personal_data_geolocation_article_39e2");
|
||||||
|
LegalBasisEntity lb2 = createLegalBasis("Article 63(2)(d) of Regulation (EC) No 1107/2009", "composition_plant_protection_product");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_2)).thenReturn(Collections.singletonList(lb2));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet1 = createRuleSet(RULES_WITH_REASONS);
|
||||||
|
RuleSetEntity ruleSet2 = createRuleSet(RULES_WITH_MULTIPLE_TEMPLATES);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet1));
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_2, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet2));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor1 = ArgumentCaptor.forClass(String.class);
|
||||||
|
ArgumentCaptor<String> rulesCaptor2 = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService, times(2)).setRules(any(), any(), eq(RuleFileType.ENTITY));
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor1.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor2.capture(), eq(TEMPLATE_ID_2), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules1 = rulesCaptor1.getValue();
|
||||||
|
String updatedRules2 = rulesCaptor2.getValue();
|
||||||
|
|
||||||
|
assertAll(() -> {
|
||||||
|
assertTrue(updatedRules1.contains("vertebrate_study_personal_data_geolocation_article_39e2"));
|
||||||
|
assertFalse(updatedRules1.contains("Article 39(e)(2) of Regulation (EC) No 178/2002"));
|
||||||
|
}, () -> {
|
||||||
|
assertTrue(updatedRules2.contains("composition_plant_protection_product"));
|
||||||
|
assertFalse(updatedRules2.contains("Article 63(2)(d) of Regulation (EC) No 1107/2009"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationHandlesNullValuesGracefully() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis(null, "personal_data_geolocation_article_39e3");
|
||||||
|
LegalBasisEntity lb2 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", null);
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Arrays.asList(lb1, lb2));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_NULL_VALUES);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(rulesPersistenceService, never()).setRules(anyString(), anyString(), any(RuleFileType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationUpdatesRuleSetWhenOnlySomeMappingsAreValid() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "vertebrate_study_personal_data_geolocation_article_39e2");
|
||||||
|
LegalBasisEntity lb2 = createLegalBasis(null, "some_technical_name");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Arrays.asList(lb1, lb2));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_PARTIAL_VALID_MAPPINGS);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules = rulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedRules.contains("vertebrate_study_personal_data_geolocation_article_39e2")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002")),
|
||||||
|
() -> assertTrue(updatedRules.contains("Some Other Reason")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithEmptyRulesContent() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "vertebrate_study_personal_data_geolocation_article_39e2");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet("");
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(rulesPersistenceService, never()).setRules(anyString(), anyString(), any(RuleFileType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationReplacesMultipleOccurrencesOfSameReason() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "tech_name_39e2");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
String duplicatedRules = RULES_WITH_REASONS + "\n" + RULES_WITH_REASONS;
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(duplicatedRules);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules = rulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertEquals(2, StringUtils.countMatches(updatedRules, "tech_name_39e2")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationDoesNotReplaceOverlappingReasonStrings() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "tech_name_39e2");
|
||||||
|
LegalBasisEntity lb2 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002 Extended", "tech_name_extended");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Arrays.asList(lb1, lb2));
|
||||||
|
|
||||||
|
String overlappingRules = "rule \"Test Rule\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " $entity: TextEntity(type() == \"CBI_author\", dictionaryEntry)\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"Article 39(e)(2) of Regulation (EC) No 178/2002\");\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"Article 39(e)(2) of Regulation (EC) No 178/2002 Extended\");\n"
|
||||||
|
+ " end";
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(overlappingRules);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules = rulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedRules.contains("tech_name_39e2")),
|
||||||
|
() -> assertTrue(updatedRules.contains("tech_name_extended")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002 Extended")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithDuplicateLegalBasisMappings() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "tech_name_39e2");
|
||||||
|
LegalBasisEntity lb2 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "tech_name_39e2_duplicate");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Arrays.asList(lb1, lb2));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_REASONS);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules = rulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedRules.contains("tech_name_39e2_duplicate")),
|
||||||
|
() -> assertFalse(updatedRules.contains("\"tech_name_39e2\"")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithTechnicalNamesContainingQuotes() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "tech_name_with_\"quotes\"");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_REASONS);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules = rulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedRules.contains("tech_name_with_\"quotes\"")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationDoesNotAlterOtherRuleFileTypes() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "tech_name_39e2");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
RuleSetEntity entityRuleSet = createRuleSet(RULES_WITH_REASONS);
|
||||||
|
RuleSetEntity componentRuleSet = createRuleSet("component rules content");
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(entityRuleSet));
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.COMPONENT)).thenReturn(Optional.of(componentRuleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> entityRulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(entityRulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedEntityRules = entityRulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedEntityRules.contains("tech_name_39e2")),
|
||||||
|
() -> assertFalse(updatedEntityRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002")));
|
||||||
|
|
||||||
|
verify(rulesPersistenceService, never()).setRules(eq("component rules content"), eq(TEMPLATE_ID_1), eq(RuleFileType.COMPONENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationDoesNotReprocessAlreadyMigratedRuleSets() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
when(migrationPersistenceService.getLatestProcessedVersion()).thenReturn(28L);
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verifyNoInteractions(rulesPersistenceService);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithLargeRuleSetsAndMappings() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
List<LegalBasisEntity> largeMappings = IntStream.range(0, 1000).mapToObj(i -> createLegalBasis("Article " + i + "(e)(2) of Regulation (EC) No 178/2002", "tech_name_" + i))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(largeMappings);
|
||||||
|
|
||||||
|
String largeRules = IntStream.range(0, 1000)
|
||||||
|
.mapToObj(i -> "rule \"Rule "
|
||||||
|
+ i
|
||||||
|
+ "\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " $entity: TextEntity(type() == \"CBI_author\", dictionaryEntry)\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " $entity.redact(\"RuleCode\", \"Description\", \"Article "
|
||||||
|
+ i
|
||||||
|
+ "(e)(2) of Regulation (EC) No 178/2002\");\n"
|
||||||
|
+ " end\n\n")
|
||||||
|
.collect(Collectors.joining());
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(largeRules);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules = rulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedRules.contains("tech_name_0")),
|
||||||
|
() -> assertTrue(updatedRules.contains("tech_name_500")),
|
||||||
|
() -> assertTrue(updatedRules.contains("tech_name_999")),
|
||||||
|
() -> {
|
||||||
|
assertFalse(updatedRules.contains("Article 0(e)(2) of Regulation (EC) No 178/2002"));
|
||||||
|
assertFalse(updatedRules.contains("Article 500(e)(2) of Regulation (EC) No 178/2002"));
|
||||||
|
assertFalse(updatedRules.contains("Article 999(e)(2) of Regulation (EC) No 178/2002"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationSkipsMappingsWithMissingTechnicalNames() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", null);
|
||||||
|
LegalBasisEntity lb2 = createLegalBasis("Article 39(e)(3) of Regulation (EC) No 178/2002", "tech_name_39e3");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Arrays.asList(lb1, lb2));
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(RULES_WITH_REASONS);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> rulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(rulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedRules = rulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedRules.contains("tech_name_39e3")),
|
||||||
|
() -> assertFalse(updatedRules.contains("Article 39(e)(3) of Regulation (EC) No 178/2002")),
|
||||||
|
() -> assertTrue(updatedRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithEmptyLegalBasisMappingsList() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verifyNoInteractions(rulesPersistenceService);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationProcessesOnlySpecifiedRuleFileType() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "tech_name_39e2");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
RuleSetEntity entityRuleSet = createRuleSet(RULES_WITH_REASONS);
|
||||||
|
RuleSetEntity componentRuleSet = createRuleSet("component rules content");
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(entityRuleSet));
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.COMPONENT)).thenReturn(Optional.of(componentRuleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
ArgumentCaptor<String> entityRulesCaptor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(rulesPersistenceService).setRules(entityRulesCaptor.capture(), eq(TEMPLATE_ID_1), eq(RuleFileType.ENTITY));
|
||||||
|
|
||||||
|
String updatedEntityRules = entityRulesCaptor.getValue();
|
||||||
|
assertAll(() -> assertTrue(updatedEntityRules.contains("tech_name_39e2")),
|
||||||
|
() -> assertFalse(updatedEntityRules.contains("Article 39(e)(2) of Regulation (EC) No 178/2002")));
|
||||||
|
|
||||||
|
verify(rulesPersistenceService, never()).setRules(eq("component rules content"), eq(TEMPLATE_ID_1), eq(RuleFileType.COMPONENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithInvalidRuleFileContent() {
|
||||||
|
|
||||||
|
DossierTemplateEntity dossierTemplate = createDossierTemplate(TEMPLATE_ID_1);
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.singletonList(dossierTemplate));
|
||||||
|
|
||||||
|
LegalBasisEntity lb1 = createLegalBasis("Article 39(e)(2) of Regulation (EC) No 178/2002", "tech_name_39e2");
|
||||||
|
when(legalBasisMappingPersistenceService.getLegalBasisMapping(TEMPLATE_ID_1)).thenReturn(Collections.singletonList(lb1));
|
||||||
|
|
||||||
|
String malformedRules = "rule \"Malformed Rule\"\n"
|
||||||
|
+ " when\n"
|
||||||
|
+ " $entity: TextEntity(type() == \"CBI_author\", dictionaryEntry)\n"
|
||||||
|
+ " then\n"
|
||||||
|
+ " $entity.redact(RuleCode, Description, Article 39(e)(2) of Regulation (EC) No 178/2002);\n"
|
||||||
|
+ " end";
|
||||||
|
|
||||||
|
RuleSetEntity ruleSet = createRuleSet(malformedRules);
|
||||||
|
when(rulesPersistenceService.getRules(TEMPLATE_ID_1, RuleFileType.ENTITY)).thenReturn(Optional.of(ruleSet));
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verify(rulesPersistenceService, never()).setRules(anyString(), anyString(), any(RuleFileType.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMigrationWithNoDossierTemplates() {
|
||||||
|
|
||||||
|
when(dossierTemplateRepository.findAll()).thenReturn(Collections.emptyList());
|
||||||
|
|
||||||
|
migration.run();
|
||||||
|
|
||||||
|
verifyNoInteractions(rulesPersistenceService, legalBasisMappingPersistenceService);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -14,6 +14,7 @@ import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryC
|
|||||||
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
|
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.client.LegalBasisClient;
|
import com.iqser.red.service.peristence.v1.server.integration.client.LegalBasisClient;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.client.RulesClient;
|
import com.iqser.red.service.peristence.v1.server.integration.client.RulesClient;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.CurrentApplicationTypeProvider;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierTemplateModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierTemplateModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DownloadFileType;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DownloadFileType;
|
||||||
@ -36,6 +37,9 @@ public class DossierTemplateTesterAndProvider {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DictionaryClient dictionaryClient;
|
private DictionaryClient dictionaryClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CurrentApplicationTypeProvider currentApplicationTypeProvider;
|
||||||
|
|
||||||
|
|
||||||
public Colors provideDefaultColors(String dossierTemplateId) {
|
public Colors provideDefaultColors(String dossierTemplateId) {
|
||||||
|
|
||||||
@ -82,6 +86,9 @@ public class DossierTemplateTesterAndProvider {
|
|||||||
rulesClient.upload(new RulesUploadRequestModel("ABCD", loadedTemplate.getDossierTemplateId(), RuleFileType.ENTITY));
|
rulesClient.upload(new RulesUploadRequestModel("ABCD", loadedTemplate.getDossierTemplateId(), RuleFileType.ENTITY));
|
||||||
legalBasisClient.setLegalBasisMapping(List.of(new LegalBasis("name", "description", "reason","technicalName")), loadedTemplate.getDossierTemplateId());
|
legalBasisClient.setLegalBasisMapping(List.of(new LegalBasis("name", "description", "reason","technicalName")), loadedTemplate.getDossierTemplateId());
|
||||||
|
|
||||||
|
if (currentApplicationTypeProvider.isDocuMine()) {
|
||||||
|
rulesClient.upload(new RulesUploadRequestModel("ABCD", loadedTemplate.getDossierTemplateId(), RuleFileType.COMPONENT));
|
||||||
|
}
|
||||||
loadedTemplate = dossierTemplateClient.getDossierTemplate(result.getDossierTemplateId());
|
loadedTemplate = dossierTemplateClient.getDossierTemplate(result.getDossierTemplateId());
|
||||||
|
|
||||||
return loadedTemplate;
|
return loadedTemplate;
|
||||||
|
|||||||
@ -70,7 +70,7 @@ public class ApprovalTest extends AbstractPersistenceServerServiceTest {
|
|||||||
.id("id1")
|
.id("id1")
|
||||||
.positions(List.of(new Position(1, 1, 1, 1, 1)))
|
.positions(List.of(new Position(1, 1, 1, 1, 1)))
|
||||||
.state(EntryState.APPLIED)
|
.state(EntryState.APPLIED)
|
||||||
.legalBasis("legalBasis")
|
.legalBasis("legal_basis")
|
||||||
.entryType(EntryType.ENTITY)
|
.entryType(EntryType.ENTITY)
|
||||||
.value("value")
|
.value("value")
|
||||||
.build()));
|
.build()));
|
||||||
|
|||||||
@ -64,8 +64,6 @@ public class ComponentOverrideTest extends AbstractPersistenceServerServiceTest
|
|||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
|
||||||
// todo: fix me
|
|
||||||
public void testOverrides() throws IOException {
|
public void testOverrides() throws IOException {
|
||||||
|
|
||||||
var dossier = dossierTesterAndProvider.provideTestDossier();
|
var dossier = dossierTesterAndProvider.provideTestDossier();
|
||||||
@ -187,8 +185,6 @@ public class ComponentOverrideTest extends AbstractPersistenceServerServiceTest
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Disabled
|
|
||||||
//todo: fix me
|
|
||||||
public void testDeletedFileOverrides() throws IOException {
|
public void testDeletedFileOverrides() throws IOException {
|
||||||
|
|
||||||
var dossier = dossierTesterAndProvider.provideTestDossier();
|
var dossier = dossierTesterAndProvider.provideTestDossier();
|
||||||
@ -257,7 +253,7 @@ public class ComponentOverrideTest extends AbstractPersistenceServerServiceTest
|
|||||||
assertTrue(overrides.getComponentOverrides().isEmpty());
|
assertTrue(overrides.getComponentOverrides().isEmpty());
|
||||||
|
|
||||||
// case 2: re-upload file that was deleted before overrides should also not be returned anymore
|
// case 2: re-upload file that was deleted before overrides should also not be returned anymore
|
||||||
fileTesterAndProvider.testAndProvideFile(dossier, "filename3");
|
fileTesterAndProvider.testAndProvideFile(dossier, "filename2");
|
||||||
|
|
||||||
var e = assertThrows(FeignException.class, () -> componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId()));
|
var e = assertThrows(FeignException.class, () -> componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId()));
|
||||||
assertEquals(e.status(), 404);
|
assertEquals(e.status(), 404);
|
||||||
|
|||||||
@ -20,13 +20,18 @@ import org.springframework.beans.BeanUtils;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
|
import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
|
||||||
|
import com.iqser.red.service.peristence.v1.server.integration.client.DossierClient;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
|
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
|
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
|
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.service.TypeProvider;
|
import com.iqser.red.service.peristence.v1.server.integration.service.TypeProvider;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
|
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.DictionaryEntryEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.TypeEntity;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.DictionaryManagementService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.DictionaryManagementService;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.DictionaryService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.DictionaryService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.TypeRepository;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.dictionaryentry.EntryRepository;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.external.model.UpdateEntries;
|
import com.iqser.red.service.persistence.service.v1.api.external.model.UpdateEntries;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.CreateTypeValue;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.CreateTypeValue;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.TypeValue;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.TypeValue;
|
||||||
@ -60,6 +65,15 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DossierTemplateClient dossierTemplateClient;
|
private DossierTemplateClient dossierTemplateClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DossierClient dossierClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TypeRepository typeRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EntryRepository entryRepository;
|
||||||
|
|
||||||
private final List<String> testList1 = List.of("William c. Spare", "Charalampos", "Carina Wilson", "PATRICIA A. SHEEHY", "William C. Spare", "carlsen", "Patricia A. Sheehy");
|
private final List<String> testList1 = List.of("William c. Spare", "Charalampos", "Carina Wilson", "PATRICIA A. SHEEHY", "William C. Spare", "carlsen", "Patricia A. Sheehy");
|
||||||
private final List<String> testList2 = List.of("William C. Spare", "Charalampos", "Carina Wilson", "Patricia A. Sheehy", "William c. Spare", "carlsen", "PATRICIA A. SHEEHY");
|
private final List<String> testList2 = List.of("William C. Spare", "Charalampos", "Carina Wilson", "Patricia A. Sheehy", "William c. Spare", "carlsen", "PATRICIA A. SHEEHY");
|
||||||
|
|
||||||
@ -409,19 +423,19 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
|
|||||||
.build());
|
.build());
|
||||||
assertThat(returnedtype1.isDossierDictionaryOnly()).isTrue();
|
assertThat(returnedtype1.isDossierDictionaryOnly()).isTrue();
|
||||||
|
|
||||||
assertThat(dictionaryClient.getAllTypes(dossier.getDossierTemplateId(), null, false)
|
assertThat(dictionaryClient.getAllTypes(dossier.getDossierTemplateId(), null, false).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(1);
|
.collect(Collectors.toList()).size()).isEqualTo(1);
|
||||||
assertThat(dictionaryClient.getAllTypes(dossier.getDossierTemplateId(), dossier.getId(), false)
|
assertThat(dictionaryClient.getAllTypes(dossier.getDossierTemplateId(), dossier.getId(), false).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(2);
|
.collect(Collectors.toList()).size()).isEqualTo(2);
|
||||||
var dictionary = dictionaryClient.getDictionaryForType(returnedtype1.getType(), dossier.getDossierTemplateId(), dossier2.getId());
|
var dictionary = dictionaryClient.getDictionaryForType(returnedtype1.getType(), dossier.getDossierTemplateId(), dossier2.getId());
|
||||||
assertThat(dictionaryClient.getAllTypes(dossier.getDossierTemplateId(), dossier2.getId(), false)
|
assertThat(dictionaryClient.getAllTypes(dossier.getDossierTemplateId(), dossier2.getId(), false).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(2);
|
.collect(Collectors.toList()).size()).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -461,9 +475,10 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
|
|||||||
assertThat(actualEntries).usingComparator(new ListContentWithoutOrderAndWithoutDuplicatesComparator<>()).isEqualTo(entries);
|
assertThat(actualEntries).usingComparator(new ListContentWithoutOrderAndWithoutDuplicatesComparator<>()).isEqualTo(entries);
|
||||||
|
|
||||||
dictionaryClient.deleteType(createdType.getType(), createdType.getDossierTemplateId());
|
dictionaryClient.deleteType(createdType.getType(), createdType.getDossierTemplateId());
|
||||||
assertThat(dictionaryClient.getAllTypes(createdType.getDossierTemplateId(), null, false)
|
assertThat(dictionaryClient.getAllTypes(createdType.getDossierTemplateId(), null, false).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList()).size()).isEqualTo(0);
|
.filter(t -> !t.isSystemManaged())
|
||||||
|
.collect(Collectors.toList()).size()).isEqualTo(0);
|
||||||
|
|
||||||
dictionaryClient.addType(type);
|
dictionaryClient.addType(type);
|
||||||
|
|
||||||
@ -1019,20 +1034,20 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
|
|||||||
.build());
|
.build());
|
||||||
assertThat(dtType.getRank()).isEqualTo(100);
|
assertThat(dtType.getRank()).isEqualTo(100);
|
||||||
assertThat(dtType.isDossierDictionaryOnly()).isFalse();
|
assertThat(dtType.isDossierDictionaryOnly()).isFalse();
|
||||||
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true)
|
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(1);
|
.collect(Collectors.toList()).size()).isEqualTo(1);
|
||||||
|
|
||||||
dictionaryClient.deleteType(dtType.getType(), dtType.getDossierTemplateId());
|
dictionaryClient.deleteType(dtType.getType(), dtType.getDossierTemplateId());
|
||||||
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, false)
|
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, false).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(0);
|
.collect(Collectors.toList()).size()).isEqualTo(0);
|
||||||
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true)
|
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(1);
|
.collect(Collectors.toList()).size()).isEqualTo(1);
|
||||||
|
|
||||||
var dtType2 = dictionaryClient.addType(CreateTypeValue.builder()
|
var dtType2 = dictionaryClient.addType(CreateTypeValue.builder()
|
||||||
.type("test2")
|
.type("test2")
|
||||||
@ -1046,24 +1061,24 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
|
|||||||
.dossierTemplateId(dossierTemplate.getId())
|
.dossierTemplateId(dossierTemplate.getId())
|
||||||
.dossierDictionaryOnly(false)
|
.dossierDictionaryOnly(false)
|
||||||
.build());
|
.build());
|
||||||
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, false)
|
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, false).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(1);
|
.collect(Collectors.toList()).size()).isEqualTo(1);
|
||||||
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true)
|
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(2);
|
.collect(Collectors.toList()).size()).isEqualTo(2);
|
||||||
|
|
||||||
assertThat(dtType2.getRank()).isEqualTo(dtType.getRank());
|
assertThat(dtType2.getRank()).isEqualTo(dtType.getRank());
|
||||||
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), false)
|
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), false).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(2);
|
.collect(Collectors.toList()).size()).isEqualTo(2);
|
||||||
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), true)
|
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), true).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(3);
|
.collect(Collectors.toList()).size()).isEqualTo(3);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1096,7 +1111,10 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
|
|||||||
.dossierDictionaryOnly(false)
|
.dossierDictionaryOnly(false)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
List<TypeValue> types = dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true).getTypes().stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList());
|
List<TypeValue> types = dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true).getTypes()
|
||||||
|
.stream()
|
||||||
|
.filter(t -> !t.isSystemManaged())
|
||||||
|
.collect(Collectors.toList());
|
||||||
assertThat(types.size()).isEqualTo(1);
|
assertThat(types.size()).isEqualTo(1);
|
||||||
|
|
||||||
String dictionaryEntry = "entry1";
|
String dictionaryEntry = "entry1";
|
||||||
@ -1129,10 +1147,10 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
|
|||||||
.build());
|
.build());
|
||||||
assertThat(dtType.getRank()).isEqualTo(100);
|
assertThat(dtType.getRank()).isEqualTo(100);
|
||||||
assertThat(dtType.isDossierDictionaryOnly()).isFalse();
|
assertThat(dtType.isDossierDictionaryOnly()).isFalse();
|
||||||
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true)
|
assertThat(dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true).getTypes()
|
||||||
.getTypes()
|
.stream()
|
||||||
.stream().filter(t -> !t.isSystemManaged()).collect(Collectors.toList())
|
.filter(t -> !t.isSystemManaged())
|
||||||
.size()).isEqualTo(1);
|
.collect(Collectors.toList()).size()).isEqualTo(1);
|
||||||
|
|
||||||
assertThatThrownBy(() -> dictionaryManagementService.addEntries(dtType.getTypeId(),
|
assertThatThrownBy(() -> dictionaryManagementService.addEntries(dtType.getTypeId(),
|
||||||
List.of("entry1", "entry2"),
|
List.of("entry1", "entry2"),
|
||||||
@ -1143,6 +1161,137 @@ public class DictionaryTest extends AbstractPersistenceServerServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteDossierThenDeleteType() {
|
||||||
|
|
||||||
|
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
|
||||||
|
|
||||||
|
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "TestDossier");
|
||||||
|
|
||||||
|
CreateTypeValue createTypeValue = CreateTypeValue.builder()
|
||||||
|
.type("test_type")
|
||||||
|
.label("Test Type")
|
||||||
|
.hexColor("#fcba03")
|
||||||
|
.rank(100)
|
||||||
|
.hint(false)
|
||||||
|
.caseInsensitive(false)
|
||||||
|
.recommendation(false)
|
||||||
|
.addToDictionaryAction(true)
|
||||||
|
.dossierTemplateId(dossierTemplate.getId())
|
||||||
|
.dossierDictionaryOnly(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var type = dictionaryClient.addType(createTypeValue);
|
||||||
|
|
||||||
|
List<TypeValue> customTypes = dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), false).getTypes()
|
||||||
|
.stream()
|
||||||
|
.filter(t -> !t.isSystemManaged())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
assertEquals(2, customTypes.size());
|
||||||
|
|
||||||
|
dossierClient.deleteDossier(dossier.getId());
|
||||||
|
|
||||||
|
dictionaryClient.deleteType(type.getType(), type.getDossierTemplateId());
|
||||||
|
|
||||||
|
var types = dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), false).getTypes()
|
||||||
|
.stream()
|
||||||
|
.filter(t -> !t.isSystemManaged())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
assertThat(types).isEmpty();
|
||||||
|
|
||||||
|
dictionaryClient.addType(createTypeValue);
|
||||||
|
|
||||||
|
customTypes = dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), false).getTypes()
|
||||||
|
.stream()
|
||||||
|
.filter(t -> !t.isSystemManaged())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
assertEquals(2, customTypes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRecreateTypeAndCheckMergedDictionary() {
|
||||||
|
|
||||||
|
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
|
||||||
|
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "TestDossier");
|
||||||
|
|
||||||
|
var type = typeProvider.testAndProvideType(dossierTemplate, null, "type1", false);
|
||||||
|
|
||||||
|
List<String> templateEntries = List.of("aaa", "bbb");
|
||||||
|
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), templateEntries, false, null, DictionaryEntryType.ENTRY);
|
||||||
|
var templateDictionary = dictionaryClient.getDictionaryForType(type.getType(), dossierTemplate.getId(), null);
|
||||||
|
assertThat(templateDictionary.getEntries()).containsExactlyInAnyOrderElementsOf(templateEntries);
|
||||||
|
|
||||||
|
List<String> dossierEntries = List.of("ccc");
|
||||||
|
dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), dossierEntries, false, dossier.getId(), DictionaryEntryType.ENTRY);
|
||||||
|
var dossierDictionary = dictionaryClient.getDictionaryForType(type.getType(), dossierTemplate.getId(), dossier.getId());
|
||||||
|
assertThat(dossierDictionary.getEntries()).containsExactlyInAnyOrderElementsOf(dossierEntries);
|
||||||
|
|
||||||
|
Dictionary mergedDictionary = dictionaryClient.getMergedDictionaries(type.getType(), type.getDossierTemplateId(), dossier.getId());
|
||||||
|
assertThat(mergedDictionary).isNotNull();
|
||||||
|
List<String> allEntries = new ArrayList<>(templateEntries);
|
||||||
|
allEntries.addAll(dossierEntries);
|
||||||
|
assertThat(mergedDictionary.getEntries()).containsExactlyInAnyOrderElementsOf(allEntries);
|
||||||
|
|
||||||
|
List<String> newDossierEntries = List.of("entry d");
|
||||||
|
UpdateEntries updateEntries = new UpdateEntries(newDossierEntries, allEntries);
|
||||||
|
dictionaryClient.updateEntries(type.getType(), type.getDossierTemplateId(), updateEntries, dossier.getId(), DictionaryEntryType.ENTRY);
|
||||||
|
|
||||||
|
List<DictionaryEntryEntity> deleted = entryRepository.findAll().stream().filter(DictionaryEntryEntity::isDeleted).toList();
|
||||||
|
assertEquals(3, deleted.size());
|
||||||
|
|
||||||
|
var updatedDossierDictionary = dictionaryClient.getDictionaryForType(type.getType(), dossierTemplate.getId(), dossier.getId());
|
||||||
|
assertThat(updatedDossierDictionary.getEntries()).containsExactlyInAnyOrderElementsOf(newDossierEntries);
|
||||||
|
|
||||||
|
// deletion
|
||||||
|
dictionaryClient.deleteType(type.getType(), type.getDossierTemplateId());
|
||||||
|
Assertions.assertThrows(FeignException.NotFound.class, () -> dictionaryClient.getDictionaryForType(type.getType(), dossierTemplate.getId(), null));
|
||||||
|
|
||||||
|
List<TypeEntity> deletedType1Entities = typeRepository.findAllTypesByDossierTemplateIdOrDossierId(dossierTemplate.getId(), dossier.getId())
|
||||||
|
.stream()
|
||||||
|
.filter(typeEntity -> typeEntity.getType().equals("type1") && typeEntity.isDeleted())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
assertEquals(2, deletedType1Entities.size());
|
||||||
|
|
||||||
|
deleted = entryRepository.findAll().stream().filter(DictionaryEntryEntity::isDeleted).toList();
|
||||||
|
assertEquals(2, deleted.size());
|
||||||
|
|
||||||
|
// recreation
|
||||||
|
var type2 = typeProvider.testAndProvideType(dossierTemplate, null, "type1", false);
|
||||||
|
|
||||||
|
dictionaryClient.addEntry(type2.getType(), type2.getDossierTemplateId(), templateEntries, false, null, DictionaryEntryType.ENTRY);
|
||||||
|
|
||||||
|
deleted = entryRepository.findAll().stream().filter(DictionaryEntryEntity::isDeleted).toList();
|
||||||
|
assertEquals(0, deleted.size());
|
||||||
|
|
||||||
|
deletedType1Entities = typeRepository.findAllTypesByDossierTemplateIdOrDossierId(dossierTemplate.getId(), dossier.getId())
|
||||||
|
.stream()
|
||||||
|
.filter(typeEntity -> typeEntity.getType().equals("type1") && typeEntity.isDeleted())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
assertEquals(1, deletedType1Entities.size());
|
||||||
|
|
||||||
|
// problematic call because it creates/update entities on a get
|
||||||
|
dictionaryClient.getAllTypes(dossierTemplate.getId(), dossier.getId(), false);
|
||||||
|
|
||||||
|
deletedType1Entities = typeRepository.findAllTypesByDossierTemplateIdOrDossierId(dossierTemplate.getId(), dossier.getId())
|
||||||
|
.stream()
|
||||||
|
.filter(typeEntity -> typeEntity.getType().equals("type1") && typeEntity.isDeleted())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
assertEquals(0, deletedType1Entities.size());
|
||||||
|
|
||||||
|
Dictionary mergedDictionary2 = dictionaryClient.getMergedDictionaries(type2.getType(), type2.getDossierTemplateId(), dossier.getId());
|
||||||
|
assertThat(mergedDictionary2).isNotNull();
|
||||||
|
assertThat(mergedDictionary2.getEntries()).containsExactlyInAnyOrderElementsOf(templateEntries);
|
||||||
|
assertThat(mergedDictionary2.getEntries()).doesNotContain("entry d");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static final class ListContentWithoutOrderAndWithoutDuplicatesComparator<T> implements Comparator<List<? extends T>> {
|
private static final class ListContentWithoutOrderAndWithoutDuplicatesComparator<T> implements Comparator<List<? extends T>> {
|
||||||
|
|
||||||
@SuppressWarnings("SuspiciousMethodCalls")
|
@SuppressWarnings("SuspiciousMethodCalls")
|
||||||
|
|||||||
@ -19,12 +19,10 @@ import static org.mockito.Mockito.when;
|
|||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@ -32,6 +30,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import com.iqser.red.service.dictionarymerge.commons.DictionaryEntry;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
|
import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.client.FileClient;
|
import com.iqser.red.service.peristence.v1.server.integration.client.FileClient;
|
||||||
import com.iqser.red.service.peristence.v1.server.integration.client.FileProcessingClient;
|
import com.iqser.red.service.peristence.v1.server.integration.client.FileProcessingClient;
|
||||||
@ -59,7 +58,6 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist
|
|||||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.RecategorizationPersistenceService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.RecategorizationPersistenceService;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.queue.SearchTermOccurrencesResponseReceiver;
|
import com.iqser.red.service.persistence.management.v1.processor.service.queue.SearchTermOccurrencesResponseReceiver;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.redactionlog.RedactionRequest;
|
import com.iqser.red.service.persistence.management.v1.processor.service.redactionlog.RedactionRequest;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.utils.DossierMapper;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.AnalyzeResult;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.AnalyzeResult;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.BulkLocalResponse;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.BulkLocalResponse;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierTemplateModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierTemplateModel;
|
||||||
@ -80,10 +78,12 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations
|
|||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactionResponse;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactionResponse;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRedactionEntry;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dictionary.Dictionary;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dictionary.Dictionary;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddCommentRequestModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionBulkLocalRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionBulkLocalRequestModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionRequestModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ForceRedactionRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ForceRedactionRequestModel;
|
||||||
@ -4175,6 +4175,90 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddRedactionWithCommentToDossierAndTemplateDictionary() {
|
||||||
|
|
||||||
|
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
|
||||||
|
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
|
||||||
|
var file = fileTesterAndProvider.testAndProvideFile(dossier);
|
||||||
|
|
||||||
|
// Create a type that allows adding to dictionary and not to template dictionary
|
||||||
|
var type = typeProvider.testAndProvideType(dossierTemplate, dossier, "typeWithComment", true, 50);
|
||||||
|
assertThat(type.isDossierDictionaryOnly()).isTrue();
|
||||||
|
|
||||||
|
// Verify initial state of dictionaries
|
||||||
|
var initialDossierDictionary = internalDictionaryClient.getDictionaryForType(
|
||||||
|
toTypeId(type.getType(), dossierTemplate.getId(), dossier.getId()), null);
|
||||||
|
assertThat(initialDossierDictionary.getEntries()).isEmpty();
|
||||||
|
|
||||||
|
var initialTemplateDictionary = internalDictionaryClient.getDictionaryForType(
|
||||||
|
toTypeId(type.getType(), dossierTemplate.getId()), null);
|
||||||
|
assertThat(initialTemplateDictionary.getEntries()).isEmpty();
|
||||||
|
|
||||||
|
// Add a manual redaction with a comment to the dossier dictionary
|
||||||
|
String comment = "This is a test comment for the redaction.";
|
||||||
|
String redactionValue = "Leia Organa";
|
||||||
|
|
||||||
|
ManualRedactionResponse addRedactionResponse = manualRedactionClient.addRedactionBulk(
|
||||||
|
dossier.getId(),
|
||||||
|
file.getId(),
|
||||||
|
Set.of(AddRedactionRequestModel.builder()
|
||||||
|
.positions(List.of(Rectangle.builder()
|
||||||
|
.topLeftX(100)
|
||||||
|
.topLeftY(200)
|
||||||
|
.width(50)
|
||||||
|
.height(20)
|
||||||
|
.page(1)
|
||||||
|
.build()))
|
||||||
|
.section("Confidential Section")
|
||||||
|
.addToDictionary(true)
|
||||||
|
.addToAllDossiers(false)
|
||||||
|
.type(type.getType())
|
||||||
|
.reason("Confidential Information")
|
||||||
|
.value(redactionValue)
|
||||||
|
.legalBasis("GDPR")
|
||||||
|
.comment(new AddCommentRequestModel(comment))
|
||||||
|
.build())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Extract the annotation ID from the response for verification
|
||||||
|
String annotationId = addRedactionResponse.getManualAnnotationResponses()
|
||||||
|
.stream()
|
||||||
|
.findFirst()
|
||||||
|
.map(ManualAnnotationResponse::getAnnotationId)
|
||||||
|
.orElseThrow(() -> new AssertionError("No annotation ID returned"));
|
||||||
|
|
||||||
|
// Verify the redaction is present
|
||||||
|
var manualRedactions = manualRedactionClient.getManualRedactions(
|
||||||
|
dossier.getId(), file.getId(), false, true);
|
||||||
|
|
||||||
|
assertThat(manualRedactions.getEntriesToAdd()).hasSize(1);
|
||||||
|
ManualRedactionEntry addedRedaction = manualRedactions.getEntriesToAdd()
|
||||||
|
.stream()
|
||||||
|
.filter(entry -> entry.getAnnotationId().equals(annotationId))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new AssertionError("Redaction not found in manual redactions"));
|
||||||
|
|
||||||
|
assertThat(addedRedaction.getValue()).isEqualTo(redactionValue);
|
||||||
|
|
||||||
|
// Verify the comment was created
|
||||||
|
List<CommentEntity> comments = commentRepository.findAll();
|
||||||
|
assertFalse(comments.isEmpty());
|
||||||
|
assertEquals(comments.get(0).getText(), comment);
|
||||||
|
assertEquals(comments.get(0).getAnnotationId(), annotationId);
|
||||||
|
|
||||||
|
// Verify the redaction is added to the dossier dictionary
|
||||||
|
var updatedDossierDictionary = internalDictionaryClient.getDictionaryForType(
|
||||||
|
toTypeId(type.getType(), dossierTemplate.getId(), dossier.getId()), null);
|
||||||
|
assertThat(updatedDossierDictionary.getEntries().stream().map(DictionaryEntry::getValue)).containsExactly(redactionValue);
|
||||||
|
|
||||||
|
// Verify the redaction was not added to the template dictionary
|
||||||
|
var updatedTemplateDictionary = internalDictionaryClient.getDictionaryForType(
|
||||||
|
toTypeId(type.getType(), dossierTemplate.getId()), null);
|
||||||
|
assertThat(updatedTemplateDictionary.getEntries()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSingleForceAndBulkForceOnDictEntryAutomaticAnalysisOff() {
|
public void testSingleForceAndBulkForceOnDictEntryAutomaticAnalysisOff() {
|
||||||
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
hub.image.name.prefix=docker-dev.knecon.com/tests/
|
hub.image.name.prefix=docker-dev.knecon.com/tests/
|
||||||
@ -1,12 +1,14 @@
|
|||||||
package com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog;
|
package com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
public class EntityLogLegalBasis {
|
public class EntityLogLegalBasis {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import lombok.NoArgsConstructor;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ImportedLegalBasis {
|
public class ImportedLegalBasis {
|
||||||
|
|
||||||
|
private String technicalName;
|
||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user