Merge branch 'RED-8480-B' into 'master'

RED-8480: integrated legal basis  endpoint in recategorize endpoint

Closes RED-8480

See merge request redactmanager/persistence-service!396
This commit is contained in:
Ali Oezyetimoglu 2024-03-20 18:24:09 +01:00
commit 7490402bb7
23 changed files with 171 additions and 20 deletions

View File

@ -253,6 +253,7 @@ public class ManualRedactionController implements ManualRedactionResource {
}
@Deprecated(forRemoval = true)
@PreAuthorize("hasAuthority('" + DO_MANUAL_REDACTION + "')")
public List<ManualAddResponse> legalBasisChangeBulk(@PathVariable(DOSSIER_ID) String dossierId,
@PathVariable(FILE_ID) String fileId,

View File

@ -120,6 +120,7 @@ public interface ManualRedactionResource {
@RequestBody Set<ForceRedactionRequestModel> forceRedactionRequests);
@Deprecated(forRemoval = true)
@ResponseStatus(value = HttpStatus.OK)
@PostMapping(value = MANUAL_REDACTION_REST_PATH
+ "/bulk/redaction/legalBasisChange"

View File

@ -14,6 +14,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Deprecated(forRemoval = true)
@Data
@Builder
@AllArgsConstructor

View File

@ -49,6 +49,8 @@ public class ManualRecategorizationEntity implements IBaseAnnotation {
private boolean addToAllDossiers;
@Column(length = 4000)
private String legalBasis;
@Column(length = 1024)
private String section;
@ManyToOne
private FileEntity fileStatus;

View File

@ -280,6 +280,7 @@ public class EntityLogMergeService {
}
@Deprecated(forRemoval = true)
private void mergeLegalBasisChanges(ManualLegalBasisChange manualLegalBasisChange, List<EntityLogEntry> entityLogEntries, int analysisNumber) {
var entity = entityLogEntries.stream()
@ -305,6 +306,7 @@ public class EntityLogMergeService {
}
@Deprecated(forRemoval = true)
private Map<String, String> getPropertyChanges(ManualLegalBasisChange manualLegalBasisChange) {
Map<String, String> propertyChanges = new HashMap<>();
@ -339,12 +341,28 @@ public class EntityLogMergeService {
.requestedDate(recategorization.getRequestDate())
.processedDate(recategorization.getProcessedDate())
.userId(recategorization.getUser())
.propertyChanges(Map.of("type", recategorization.getType()))
.propertyChanges(getPropertyChanges(recategorization))
.build());
});
}
private Map<String, String> getPropertyChanges(ManualRecategorization recategorization) {
Map<String, String> propertyChanges = new HashMap<>();
if (!Strings.isNullOrEmpty(recategorization.getType())) {
propertyChanges.put("type", recategorization.getType());
}
if (!Strings.isNullOrEmpty(recategorization.getLegalBasis())) {
propertyChanges.put("legalBasis", recategorization.getLegalBasis());
}
if (!Strings.isNullOrEmpty(recategorization.getSection())) {
propertyChanges.put("section", recategorization.getSection());
}
return propertyChanges;
}
private void mergeForceRedactions(ManualForceRedaction forceRedaction, List<EntityLogEntry> entityLogEntries, int analysisNumber) {
var entity = entityLogEntries.stream()

View File

@ -120,6 +120,7 @@ public class ManualRedactionMapper {
}
@Deprecated(forRemoval = true)
public List<LegalBasisChangeRequest> toLegalBasisChangeRequestList(Set<LegalBasisChangeRequestModel> legalBasisChangeRequests) {
return legalBasisChangeRequests.stream()
@ -159,6 +160,7 @@ public class ManualRedactionMapper {
.dossierTemplateTypeId(toTypeId(recategorizationRequest.getType(), dossierTemplateId))
.legalBasis(Optional.ofNullable(recategorizationRequest.getLegalBasis())
.orElse(""))
.section(recategorizationRequest.getSection())
.build();
requests.add(build);
}

View File

@ -197,6 +197,7 @@ public class ManualRedactionService {
}
@Deprecated(forRemoval = true)
@Transactional
public List<ManualAddResponse> addLegalBasisChange(String dossierId, String fileId, List<LegalBasisChangeRequest> legalBasisChangeRequests) {
@ -224,6 +225,8 @@ public class ManualRedactionService {
public List<ManualAddResponse> addRecategorization(String dossierId, String fileId, List<RecategorizationRequest> recategorizationRequests) {
var response = new ArrayList<ManualAddResponse>();
dossierPersistenceService.getAndValidateDossier(dossierId);
for (var recategorizationRequest : recategorizationRequests) {
manualRedactionDictionaryUpdateHandler.validateDictionariesForAdd(recategorizationRequest, recategorizationRequest.getValue());
manualRedactionDictionaryUpdateHandler.validateDictionariesForDelete(recategorizationRequest,

View File

@ -113,7 +113,7 @@ public class ManualRedactionUndoService {
.stream()
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualResizeRedaction)
.map(ManualRedactionWrapperModel::getId)
.collect(Collectors.toList());
.toList();
if (!manualResizeRedactions.isEmpty()) {
deleteResizeRedaction(dossierId, fileId, manualResizeRedactions);
manualResizeRedactions.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
@ -148,7 +148,7 @@ public class ManualRedactionUndoService {
.stream()
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualLegalBasisChange)
.map(ManualRedactionWrapperModel::getId)
.collect(Collectors.toList());
.toList();
if (!manualLegalBasisChanges.isEmpty()) {
deleteLegalBasisChange(dossierId, fileId, manualLegalBasisChanges);
@ -179,19 +179,19 @@ public class ManualRedactionUndoService {
private void undoRecategorization(String dossierId, String fileId, Map<String, ManualRedactionWrapperModel> manualRedactionWrappers, boolean includeUnprocessed) {
List<String> manualImageRecategorizations = manualRedactionWrappers.values()
List<String> manualRecategorizations = manualRedactionWrappers.values()
.stream()
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualRecategorization)
.map(ManualRedactionWrapperModel::getId)
.collect(Collectors.toList());
if (!manualImageRecategorizations.isEmpty()) {
.toList();
if (!manualRecategorizations.isEmpty()) {
deleteRecategorization(dossierId, fileId, manualImageRecategorizations, includeUnprocessed);
manualImageRecategorizations.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
deleteRecategorization(dossierId, fileId, manualRecategorizations, includeUnprocessed);
manualRecategorizations.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
.userId(KeycloakSecurity.getUserId())
.objectId(fileId)
.category(AuditCategory.DOCUMENT.name())
.message("Undo of manual image recategorization was done.")
.message("Undo of manual recategorization was done.")
.details(Map.of(DOSSIER_ID,
dossierId,
FILE_ID,
@ -230,7 +230,7 @@ public class ManualRedactionUndoService {
.stream()
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualForceRedaction)
.map(ManualRedactionWrapperModel::getId)
.collect(Collectors.toList());
.toList();
if (!manualForceRedactions.isEmpty()) {
deleteForceRedaction(dossierId, fileId, manualForceRedactions);
@ -267,7 +267,7 @@ public class ManualRedactionUndoService {
.stream()
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof IdRemoval)
.map(ManualRedactionWrapperModel::getId)
.collect(Collectors.toList());
.toList();
if (!idRemovals.isEmpty()) {
deleteRemoveRedaction(dossierId, fileId, idRemovals);
idRemovals.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
@ -304,7 +304,7 @@ public class ManualRedactionUndoService {
.stream()
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualRedactionEntry)
.map(ManualRedactionWrapperModel::getId)
.collect(Collectors.toList());
.toList();
if (!manualRedactionEntries.isEmpty()) {
deleteAddRedaction(dossierId, fileId, manualRedactionEntries);
manualRedactionEntries.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()

View File

@ -167,7 +167,12 @@ public class PendingDictionaryEntryFactory {
.requestedDate(manualChange.getRequestDate())
.processedDate(manualChange.getProcessedDate())
.userId(manualChange.getUser())
.propertyChanges(Map.of("type", manualChange.getType()))
.propertyChanges(Map.of("type",
manualChange.getType(),
"legalBasis",
manualChange.getLegalBasis(),
"section",
manualChange.getSection()))
.build());
return EntityLogEntry.builder()

View File

@ -22,6 +22,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Deprecated(forRemoval = true)
@Slf4j
@Service
@RequiredArgsConstructor

View File

@ -5,12 +5,14 @@ import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.AnnotationEntityId;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRecategorizationEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.model.ManualChangesQueryOptions;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.annotationentity.RecategorizationRepository;
@ -24,6 +26,8 @@ import lombok.extern.slf4j.Slf4j;
@RequiredArgsConstructor
public class RecategorizationPersistenceService {
private final int SECTION_MAX_LENGTH = 1024;
private final RecategorizationRepository recategorizationRepository;
@ -31,6 +35,7 @@ public class RecategorizationPersistenceService {
ManualRecategorizationEntity manualRecategorization = new ManualRecategorizationEntity();
manualRecategorization.setId(new AnnotationEntityId(recategorizationRequest.getAnnotationId(), fileId));
checkSection(recategorizationRequest.getSection());
BeanUtils.copyProperties(recategorizationRequest, manualRecategorization);
manualRecategorization.setRequestDate(OffsetDateTime.now());
manualRecategorization.setTypeId(recategorizationRequest.getDossierTemplateTypeId());
@ -39,6 +44,14 @@ public class RecategorizationPersistenceService {
}
private void checkSection(String section) {
if (!StringUtils.isEmpty(section) && section.length() > SECTION_MAX_LENGTH) {
throw new BadRequestException(String.format("The section is too long (%s), max length %s", section.length(), SECTION_MAX_LENGTH));
}
}
@Transactional
public void updateModifiedDictionaries(String fileId, String annotationId, Set<String> typeIdsOfDictionaryWithAdd, Set<String> typeIdsOfDictionaryWithDelete) {

View File

@ -12,6 +12,7 @@ import org.springframework.data.repository.query.Param;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.AnnotationEntityId;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualLegalBasisChangeEntity;
@Deprecated(forRemoval = true)
public interface LegalBasisChangeRepository extends JpaRepository<ManualLegalBasisChangeEntity, AnnotationEntityId>, AnnotationEntityRepository {
@Modifying

View File

@ -189,3 +189,5 @@ databaseChangeLog:
file: db/changelog/tenant/121-set-dictionary-entry-type-for-dictionary-adds-where-null.yaml
- include:
file: db/changelog/tenant/sql/206-remove-manual-redactions-on-non-existing-pages.sql
- include:
file: db/changelog/tenant/122-add-legal-basis-variables-to-recategorize.yaml

View File

@ -0,0 +1,11 @@
databaseChangeLog:
- changeSet:
id: add-legal-basis-variables-to-recategorize
author: ali
changes:
- addColumn:
tableName: manual_recategorization
columns:
- column:
name: section
type: VARCHAR(1024)

View File

@ -415,7 +415,7 @@ public class FileTest extends AbstractPersistenceServerServiceTest {
.build()));
manualRedactionClient.recategorizeBulk(dossierId,
fileId,
Set.of(RecategorizationRequestModel.builder().annotationId(annotationId).comment("comment").type("new-type").legalBasis("").build()),
Set.of(RecategorizationRequestModel.builder().annotationId(annotationId).comment("comment").type("new-type").legalBasis("").section("section").build()),
false);
var loadedFile = fileClient.getFileStatus(dossierId, fileId);

View File

@ -1198,6 +1198,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
.addToDictionary(true)
.addToAllDossiers(true)
.legalBasis("")
.section("section")
.build()),
false);
@ -1282,6 +1283,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
.addToDictionary(true)
.addToAllDossiers(false)
.legalBasis("")
.section("section")
.build()),
false);
@ -1652,7 +1654,10 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), any(), anyBoolean())).thenReturn(entityLog);
manualRedactionClient.recategorizeBulk(dossier.getId(), file.getId(), Set.of(RecategorizationRequestModel.builder().annotationId("dv").legalBasis("").build()), false);
manualRedactionClient.recategorizeBulk(dossier.getId(),
file.getId(),
Set.of(RecategorizationRequestModel.builder().annotationId("dv").legalBasis("").section("section").build()),
false);
var allManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), false, true);
assertEquals(allManualRedactions.getRecategorizations().size(), 1);
@ -1676,7 +1681,10 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
.dossierId(dossier.getId())
.build());
manualRedactionClient.recategorizeBulk(dossier.getId(), file.getId(), Set.of(RecategorizationRequestModel.builder().annotationId("dv2").legalBasis("").build()), false);
manualRedactionClient.recategorizeBulk(dossier.getId(),
file.getId(),
Set.of(RecategorizationRequestModel.builder().annotationId("dv2").legalBasis("").section("section").build()),
false);
allManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), false, true);
assertEquals(allManualRedactions.getRecategorizations().size(), 2);
@ -1930,7 +1938,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
EntityLogEntry.builder()
.id("annotationId2")
.type(type.getType())
.value("Johannesbrotkernmehl")
.value("Johannisbrotkernmehl")
.dictionaryEntry(true)
.entryType(EntryType.ENTITY)
.state(EntryState.APPLIED)
@ -1949,7 +1957,6 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
0,
0);
fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog);
fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog);
when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), any(), anyBoolean())).thenReturn(entityLog);
var recatModel = RecategorizationRequestModel.builder()
@ -1958,6 +1965,7 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
.addToDictionary(true)
.addToAllDossiers(true)
.legalBasis("")
.section("section")
.build();
var recatModelLongLegalBasis = RecategorizationRequestModel.builder()
.type(type.getType())
@ -1966,7 +1974,13 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
.addToAllDossiers(true)
.legalBasis(RandomStringUtils.randomAlphanumeric(4001))
.build();
var recatModelNoLegalBasis = RecategorizationRequestModel.builder().type(type.getType()).annotationId("annotationId3").addToDictionary(true).addToAllDossiers(true).build();
var recatModelNoLegalBasis = RecategorizationRequestModel.builder()
.type(type.getType())
.annotationId("annotationId3")
.addToDictionary(true)
.section("section")
.addToAllDossiers(true)
.build();
manualRedactionClient.recategorizeBulk(dossier.getId(), file.getId(), Set.of(recatModel, recatModelNoLegalBasis), false);
@ -1988,4 +2002,74 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
}
@Test
public void testPropertyChangesForLegalBasisInManualRecategorization() {
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
var file = fileTesterAndProvider.testAndProvideFile(dossier);
var type = typeProvider.testAndProvideType(dossierTemplate, null, "type", false);
var entityLog = new EntityLog(1,
1,
List.of(EntityLogEntry.builder()
.id("annotationId")
.type(type.getType())
.value("lukeSkywalker")
.dictionaryEntry(true)
.entryType(EntryType.ENTITY)
.state(EntryState.APPLIED)
.legalBasis("lb1")
.section("section")
.build(),
EntityLogEntry.builder()
.id("annotationId2")
.type(type.getType())
.value("Johannisbrotkernmehl")
.dictionaryEntry(true)
.entryType(EntryType.ENTITY)
.state(EntryState.APPLIED)
.build(),
EntityLogEntry.builder()
.id("annotationId3")
.type(type.getType())
.value("Baustelle")
.dictionaryEntry(true)
.entryType(EntryType.ENTITY)
.state(EntryState.APPLIED)
.build()),
null,
0,
0,
0,
0);
fileManagementStorageService.storeJSONObject(dossier.getId(), file.getId(), FileType.ENTITY_LOG, entityLog);
when(entityLogService.getEntityLog(Mockito.any(), Mockito.any(), any(), anyBoolean())).thenReturn(entityLog);
var recatModel = RecategorizationRequestModel.builder()
.type(type.getType())
.annotationId("annotationId")
.addToDictionary(false)
.addToAllDossiers(false)
.legalBasis("lb2")
.section("section")
.build();
manualRedactionClient.recategorizeBulk(dossier.getId(), file.getId(), Set.of(recatModel), false);
var allManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), false, true);
assertEquals(1, allManualRedactions.getRecategorizations().size());
assertTrue(allManualRedactions.getRecategorizations()
.stream()
.anyMatch(entry -> entry.getAnnotationId().equals("annotationId")));
assertTrue(allManualRedactions.getRecategorizations()
.stream()
.anyMatch(entry -> entry.getLegalBasis().equals("lb2")));
assertTrue(allManualRedactions.getRecategorizations()
.stream()
.anyMatch(entry -> entry.getSection().equals("section")));
}
}

View File

@ -13,7 +13,7 @@ public enum ManualRedactionType {
FORCE,
RECATEGORIZE,
RECATEGORIZE_IN_DICTIONARY,
LEGAL_BASIS_CHANGE,
@Deprecated LEGAL_BASIS_CHANGE,
RESIZE,
RESIZE_IN_DICTIONARY
}

View File

@ -5,6 +5,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Deprecated(forRemoval = true)
@Data
@Builder
@AllArgsConstructor

View File

@ -29,6 +29,7 @@ public class RecategorizationRequest implements ManualRequestWithAddToDictionary
boolean addToAllDossiers;
private DictionaryEntryType dictionaryEntryType;
String legalBasis;
String section;
@Override

View File

@ -6,6 +6,7 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Deprecated(forRemoval = true)
@Data
@SuperBuilder
@NoArgsConstructor

View File

@ -17,6 +17,7 @@ public class ManualRecategorization extends BaseAnnotation {
private String legalBasis;
private boolean addToDictionary;
private boolean addToAllDossiers;
private String section;
@Override

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
@Deprecated(forRemoval = true)
@Data
@Builder
@AllArgsConstructor

View File

@ -20,5 +20,6 @@ public class RecategorizationRequestModel {
boolean addToDictionary;
boolean addToAllDossiers;
String legalBasis;
String section;
}