RED-7317: add getComment Endpoint
* moved manual redaction undo code
This commit is contained in:
parent
0b173ec930
commit
d1d5331202
@ -8,8 +8,6 @@ import static com.iqser.red.service.persistence.management.v1.processor.roles.Ac
|
|||||||
import static com.iqser.red.service.persistence.management.v1.processor.utils.TypeIdUtils.toTypeId;
|
import static com.iqser.red.service.persistence.management.v1.processor.utils.TypeIdUtils.toTypeId;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -20,10 +18,10 @@ 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.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
|
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.AccessControlService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.AccessControlService;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.DossierManagementService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.DossierManagementService;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.ManualRedactionService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.ManualRedactionService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.ManualRedactionUndoService;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.external.resource.ManualRedactionResource;
|
import com.iqser.red.service.persistence.service.v1.api.external.resource.ManualRedactionResource;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.AuditCategory;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.AuditCategory;
|
||||||
@ -31,20 +29,14 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.CommentResp
|
|||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AddRedactionRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AddRedactionRequest;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AnnotationStatus;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AnnotationStatus;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.CommentRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.CommentRequest;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comments;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualAddResponse;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualAddResponse;
|
||||||
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.entitymapped.IdRemoval;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualForceRedaction;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualImageRecategorization;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualLegalBasisChange;
|
|
||||||
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.annotations.entitymapped.ManualResizeRedaction;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.audit.AuditRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.audit.AuditRequest;
|
||||||
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.AddCommentRequestModel;
|
||||||
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;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.LegalBasisChangeRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.LegalBasisChangeRequestModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ManualRedactionWrapperModel;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RecategorizationRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RecategorizationRequestModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RemoveRedactionRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RemoveRedactionRequestModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ResizeRedactionRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ResizeRedactionRequestModel;
|
||||||
@ -62,182 +54,20 @@ public class ManualRedactionController implements ManualRedactionResource {
|
|||||||
private static final String DOSSIER_ID = "dossierId";
|
private static final String DOSSIER_ID = "dossierId";
|
||||||
private static final String ANNOTATION_ID = "annotationId";
|
private static final String ANNOTATION_ID = "annotationId";
|
||||||
private final ManualRedactionService manualRedactionService;
|
private final ManualRedactionService manualRedactionService;
|
||||||
|
private final ManualRedactionUndoService manualRedactionUndoService;
|
||||||
private final DossierManagementService dossierManagementService;
|
private final DossierManagementService dossierManagementService;
|
||||||
private final AuditPersistenceService auditPersistenceService;
|
private final AuditPersistenceService auditPersistenceService;
|
||||||
private final AccessControlService accessControlService;
|
private final AccessControlService accessControlService;
|
||||||
|
|
||||||
|
|
||||||
private ManualRedactionWrapperModel getLatestManualRedactionForAnnotationId(ManualRedactions manualRedactions, String annotationId) {
|
|
||||||
|
|
||||||
final List<ManualRedactionWrapperModel> manualRedactionWrappers = new ArrayList<>();
|
|
||||||
|
|
||||||
manualRedactions.getEntriesToAdd()
|
|
||||||
.stream()
|
|
||||||
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
|
||||||
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
|
||||||
|
|
||||||
manualRedactions.getImageRecategorization()
|
|
||||||
.stream()
|
|
||||||
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
|
||||||
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
|
||||||
|
|
||||||
manualRedactions.getIdsToRemove()
|
|
||||||
.stream()
|
|
||||||
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
|
||||||
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
|
||||||
|
|
||||||
manualRedactions.getForceRedactions()
|
|
||||||
.stream()
|
|
||||||
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
|
||||||
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
|
||||||
|
|
||||||
manualRedactions.getLegalBasisChanges()
|
|
||||||
.stream()
|
|
||||||
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
|
||||||
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
|
||||||
|
|
||||||
manualRedactions.getResizeRedactions()
|
|
||||||
.stream()
|
|
||||||
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
|
||||||
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
|
||||||
|
|
||||||
var sortedManualRedactionWrappers = manualRedactionWrappers.stream()
|
|
||||||
.sorted(Comparator.comparing(ManualRedactionWrapperModel::getDate, Comparator.nullsLast(Comparator.reverseOrder())))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
return sortedManualRedactionWrappers.isEmpty() ? null : sortedManualRedactionWrappers.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@PreAuthorize("hasAuthority('" + DELETE_MANUAL_REDACTION + "')")
|
@PreAuthorize("hasAuthority('" + DELETE_MANUAL_REDACTION + "')")
|
||||||
public void undo(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @RequestBody Set<String> annotationIds) {
|
public void undo(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @RequestBody Set<String> annotationIds) {
|
||||||
|
|
||||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||||
accessControlService.verifyUserIsApprover(dossierId);
|
accessControlService.verifyUserIsApprover(dossierId);
|
||||||
|
manualRedactionUndoService.undo(dossierId, fileId, annotationIds);
|
||||||
|
|
||||||
ManualRedactions manualRedactions = manualRedactionService.getManualRedactions(fileId);
|
|
||||||
|
|
||||||
Map<String, ManualRedactionWrapperModel> manualRedactionWrappers = getLatestManualRedactionsForAnnotationIds(manualRedactions, annotationIds);
|
|
||||||
|
|
||||||
if (manualRedactionWrappers.isEmpty()) {
|
|
||||||
throw new NotFoundException(String.format("ManualRedaction with annotationIds %s could not be found.", annotationIds));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> manualRedactionEntries = manualRedactionWrappers.values()
|
|
||||||
.stream()
|
|
||||||
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualRedactionEntry)
|
|
||||||
.map(ManualRedactionWrapperModel::getId)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (!manualRedactionEntries.isEmpty()) {
|
|
||||||
manualRedactionService.deleteAddRedaction(dossierId, fileId, manualRedactionEntries);
|
|
||||||
manualRedactionEntries.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
|
||||||
.userId(KeycloakSecurity.getUserId())
|
|
||||||
.objectId(fileId)
|
|
||||||
.category(AuditCategory.DOCUMENT.name())
|
|
||||||
.message("Undo of manual add redaction was done.")
|
|
||||||
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
|
||||||
.build()));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> idRemovals = manualRedactionWrappers.values()
|
|
||||||
.stream()
|
|
||||||
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof IdRemoval)
|
|
||||||
.map(ManualRedactionWrapperModel::getId)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (!idRemovals.isEmpty()) {
|
|
||||||
|
|
||||||
manualRedactionService.deleteRemoveRedaction(dossierId, fileId, idRemovals);
|
|
||||||
idRemovals.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
|
||||||
.userId(KeycloakSecurity.getUserId())
|
|
||||||
.objectId(fileId)
|
|
||||||
.category(AuditCategory.DOCUMENT.name())
|
|
||||||
.message("Undo of manual remove redaction was done.")
|
|
||||||
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
|
||||||
.build()));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> manualForceRedactions = manualRedactionWrappers.values()
|
|
||||||
.stream()
|
|
||||||
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualForceRedaction)
|
|
||||||
.map(ManualRedactionWrapperModel::getId)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (!manualForceRedactions.isEmpty()) {
|
|
||||||
|
|
||||||
manualRedactionService.deleteForceRedaction(dossierId, fileId, manualForceRedactions);
|
|
||||||
manualForceRedactions.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
|
||||||
.userId(KeycloakSecurity.getUserId())
|
|
||||||
.objectId(fileId)
|
|
||||||
.category(AuditCategory.DOCUMENT.name())
|
|
||||||
.message("Undo of manual force redaction was done.")
|
|
||||||
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
|
||||||
.build()));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> manualImageRecategorizations = manualRedactionWrappers.values()
|
|
||||||
.stream()
|
|
||||||
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualImageRecategorization)
|
|
||||||
.map(ManualRedactionWrapperModel::getId)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (!manualImageRecategorizations.isEmpty()) {
|
|
||||||
|
|
||||||
manualRedactionService.deleteImageRecategorization(dossierId, fileId, manualImageRecategorizations);
|
|
||||||
manualImageRecategorizations.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
|
||||||
.userId(KeycloakSecurity.getUserId())
|
|
||||||
.objectId(fileId)
|
|
||||||
.category(AuditCategory.DOCUMENT.name())
|
|
||||||
.message("Undo of manual image recategorization was done.")
|
|
||||||
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
|
||||||
.build()));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> manualLegalBasisChanges = manualRedactionWrappers.values()
|
|
||||||
.stream()
|
|
||||||
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualLegalBasisChange)
|
|
||||||
.map(ManualRedactionWrapperModel::getId)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (!manualLegalBasisChanges.isEmpty()) {
|
|
||||||
|
|
||||||
manualRedactionService.deleteLegalBasisChange(dossierId, fileId, manualLegalBasisChanges);
|
|
||||||
manualLegalBasisChanges.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
|
||||||
.userId(KeycloakSecurity.getUserId())
|
|
||||||
.objectId(fileId)
|
|
||||||
.category(AuditCategory.DOCUMENT.name())
|
|
||||||
.message("Undo of legal basis change was done.")
|
|
||||||
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
|
||||||
.build()));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> manualResizeRedactions = manualRedactionWrappers.values()
|
|
||||||
.stream()
|
|
||||||
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualResizeRedaction)
|
|
||||||
.map(ManualRedactionWrapperModel::getId)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (!manualResizeRedactions.isEmpty()) {
|
|
||||||
|
|
||||||
manualRedactionService.deleteResizeRedaction(dossierId, fileId, manualResizeRedactions);
|
|
||||||
manualResizeRedactions.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
|
||||||
.userId(KeycloakSecurity.getUserId())
|
|
||||||
.objectId(fileId)
|
|
||||||
.category(AuditCategory.DOCUMENT.name())
|
|
||||||
.message("Undo of manual resize redaction was done.")
|
|
||||||
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
|
||||||
.build()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Map<String, ManualRedactionWrapperModel> getLatestManualRedactionsForAnnotationIds(ManualRedactions manualRedactions, Set<String> annotationIds) {
|
|
||||||
|
|
||||||
Map<String, ManualRedactionWrapperModel> result = new HashMap<>();
|
|
||||||
annotationIds.forEach(annotationId -> {
|
|
||||||
var last = getLatestManualRedactionForAnnotationId(manualRedactions, annotationId);
|
|
||||||
if (last != null) {
|
|
||||||
result.put(annotationId, last);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -270,6 +100,13 @@ public class ManualRedactionController implements ManualRedactionResource {
|
|||||||
return manualRedactionService.getManualRedactions(fileId);
|
return manualRedactionService.getManualRedactions(fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@PreAuthorize("hasAuthority('" + READ_MANUAL_REDACTIONS + "')")
|
||||||
|
public Comments getComments(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId) {
|
||||||
|
|
||||||
|
return manualRedactionService.getComments(fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@PreAuthorize("hasAuthority('" + ADD_COMMENT + "')")
|
@PreAuthorize("hasAuthority('" + ADD_COMMENT + "')")
|
||||||
|
|||||||
@ -13,13 +13,14 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.CommentResponse;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.CommentResponse;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comments;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualAddResponse;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualAddResponse;
|
||||||
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.manual.AddCommentRequestModel;
|
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.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;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RecategorizationRequestModel;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.LegalBasisChangeRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.LegalBasisChangeRequestModel;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RecategorizationRequestModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RemoveRedactionRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RemoveRedactionRequestModel;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ResizeRedactionRequestModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ResizeRedactionRequestModel;
|
||||||
|
|
||||||
@ -132,4 +133,12 @@ public interface ManualRedactionResource {
|
|||||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||||
ManualRedactions getManualRedactions(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId);
|
ManualRedactions getManualRedactions(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ResponseStatus(value = HttpStatus.OK)
|
||||||
|
@GetMapping(value = MANUAL_REDACTION_REST_PATH + "/comments" + DOSSIER_ID_PATH_PARAM + FILE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
@Operation(summary = "Returns the comments for a specific file", description = "None")
|
||||||
|
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||||
|
Comments getComments(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -45,7 +47,9 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist
|
|||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AddRedactionRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AddRedactionRequest;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AnnotationStatus;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.AnnotationStatus;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.BaseManualRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.BaseManualRequest;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comment;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.CommentRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.CommentRequest;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comments;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ForceRedactionRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ForceRedactionRequest;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.LegalBasisChangeRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.LegalBasisChangeRequest;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualAddResponse;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualAddResponse;
|
||||||
@ -55,6 +59,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations
|
|||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.RemoveRedactionRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.RemoveRedactionRequest;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ResizeRedactionRequest;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ResizeRedactionRequest;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.IdRemoval;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.IdRemoval;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.ProcessingStatus;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.WorkflowStatus;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.WorkflowStatus;
|
||||||
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.redactionlog.RedactionLog;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.RedactionLog;
|
||||||
@ -104,16 +109,10 @@ public class ManualRedactionService {
|
|||||||
|
|
||||||
String annotationId = hashFunction.hashString(fileId + addRedactionRequest, StandardCharsets.UTF_8).toString();
|
String annotationId = hashFunction.hashString(fileId + addRedactionRequest, StandardCharsets.UTF_8).toString();
|
||||||
|
|
||||||
if (addRedactionRequest.isAddToDictionary()) {
|
|
||||||
Set<String> typeIdsOfModifiedDictionaries = manualRedactionDictionaryUpdateHandler.handleAddToDictionary(fileId, dossierId, addRedactionRequest);
|
|
||||||
addRedactionPersistenceService.updateStatus(fileId, annotationId, addRedactionRequest.getStatus(), true, typeIdsOfModifiedDictionaries);
|
|
||||||
} else {
|
|
||||||
addRedactionPersistenceService.updateStatus(fileId, annotationId, addRedactionRequest.getStatus(), false, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
addRedactionPersistenceService.insert(fileId, annotationId, addRedactionRequest);
|
addRedactionPersistenceService.insert(fileId, annotationId, addRedactionRequest);
|
||||||
|
manualRedactionDictionaryUpdateHandler.handleAddToDictionary(fileId, annotationId, addRedactionRequest);
|
||||||
|
|
||||||
Long commentId = addComment(fileId, annotationId, addRedactionRequest.getComment(), addRedactionRequest.getUser()).getId();
|
Long commentId = addCommentAndGetId(fileId, annotationId, addRedactionRequest.getComment(), addRedactionRequest.getUser());
|
||||||
|
|
||||||
response.add(ManualAddResponse.builder().annotationId(annotationId).commentId(commentId).build());
|
response.add(ManualAddResponse.builder().annotationId(annotationId).commentId(commentId).build());
|
||||||
}
|
}
|
||||||
@ -160,6 +159,15 @@ public class ManualRedactionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Long addCommentAndGetId(String fileId, String annotationId, String comment, String user) {
|
||||||
|
|
||||||
|
if (comment == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return addComment(fileId, annotationId, comment, user).getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private CommentEntity addComment(String fileId, String annotationId, String comment, String user) {
|
private CommentEntity addComment(String fileId, String annotationId, String comment, String user) {
|
||||||
|
|
||||||
if (comment == null) {
|
if (comment == null) {
|
||||||
@ -242,7 +250,7 @@ public class ManualRedactionService {
|
|||||||
log.info("add removeRedaction for file {} and annotation {}", fileId, removeRedactionRequest.getAnnotationId());
|
log.info("add removeRedaction for file {} and annotation {}", fileId, removeRedactionRequest.getAnnotationId());
|
||||||
IdRemoval idRemoval = MagicConverter.convert(removeRedactionPersistenceService.insert(fileId, removeRedactionRequest), IdRemoval.class);
|
IdRemoval idRemoval = MagicConverter.convert(removeRedactionPersistenceService.insert(fileId, removeRedactionRequest), IdRemoval.class);
|
||||||
|
|
||||||
Long commentId = addComment(fileId, removeRedactionRequest.getAnnotationId(), removeRedactionRequest.getComment(), removeRedactionRequest.getUser()).getId();
|
Long commentId = addCommentAndGetId(fileId, removeRedactionRequest.getAnnotationId(), removeRedactionRequest.getComment(), removeRedactionRequest.getUser());
|
||||||
boolean matchingEntryFound = false;
|
boolean matchingEntryFound = false;
|
||||||
if (!removeRedactionRequest.isRemoveFromDictionary() && AnnotationStatus.APPROVED.equals(removeRedactionRequest.getStatus())) {
|
if (!removeRedactionRequest.isRemoveFromDictionary() && AnnotationStatus.APPROVED.equals(removeRedactionRequest.getStatus())) {
|
||||||
try {
|
try {
|
||||||
@ -255,7 +263,6 @@ public class ManualRedactionService {
|
|||||||
requiresReAnalysis = requiresReAnalysis || matchingEntryFound;
|
requiresReAnalysis = requiresReAnalysis || matchingEntryFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean removedFromDictionary = handleRemoveFromDictionary(getRedactionLogEntry(redactionLog, removeRedactionRequest.getAnnotationId()),
|
boolean removedFromDictionary = handleRemoveFromDictionary(getRedactionLogEntry(redactionLog, removeRedactionRequest.getAnnotationId()),
|
||||||
dossier,
|
dossier,
|
||||||
fileId,
|
fileId,
|
||||||
@ -293,7 +300,7 @@ public class ManualRedactionService {
|
|||||||
if (!idRemoval.getStatus().equals(AnnotationStatus.APPROVED)) {
|
if (!idRemoval.getStatus().equals(AnnotationStatus.APPROVED)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (idRemoval.isRemoveFromDictionary()) {
|
if (!idRemoval.isRemoveFromDictionary()) {
|
||||||
removeRedactionPersistenceService.updateStatus(fileId, annotationId, idRemoval.getStatus(), false, Collections.emptySet());
|
removeRedactionPersistenceService.updateStatus(fileId, annotationId, idRemoval.getStatus(), false, Collections.emptySet());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -373,7 +380,7 @@ public class ManualRedactionService {
|
|||||||
for (var forceRedactionRequest : forceRedactionRequests) {
|
for (var forceRedactionRequest : forceRedactionRequests) {
|
||||||
forceRedactionPersistenceService.insert(fileId, forceRedactionRequest);
|
forceRedactionPersistenceService.insert(fileId, forceRedactionRequest);
|
||||||
|
|
||||||
Long commentId = addComment(fileId, forceRedactionRequest.getAnnotationId(), forceRedactionRequest.getComment(), forceRedactionRequest.getUser()).getId();
|
Long commentId = addCommentAndGetId(fileId, forceRedactionRequest.getAnnotationId(), forceRedactionRequest.getComment(), forceRedactionRequest.getUser());
|
||||||
|
|
||||||
requiresReanalysis = requiresReanalysis || forceRedactionRequest.isApproved();
|
requiresReanalysis = requiresReanalysis || forceRedactionRequest.isApproved();
|
||||||
response.add(ManualAddResponse.builder().annotationId(forceRedactionRequest.getAnnotationId()).commentId(commentId).build());
|
response.add(ManualAddResponse.builder().annotationId(forceRedactionRequest.getAnnotationId()).commentId(commentId).build());
|
||||||
@ -398,7 +405,7 @@ public class ManualRedactionService {
|
|||||||
for (var legalBasisChangeRequest : legalBasisChangeRequests) {
|
for (var legalBasisChangeRequest : legalBasisChangeRequests) {
|
||||||
legalBasisChangePersistenceService.insert(fileId, legalBasisChangeRequest);
|
legalBasisChangePersistenceService.insert(fileId, legalBasisChangeRequest);
|
||||||
|
|
||||||
Long commentId = addComment(fileId, legalBasisChangeRequest.getAnnotationId(), legalBasisChangeRequest.getComment(), legalBasisChangeRequest.getUser()).getId();
|
Long commentId = addCommentAndGetId(fileId, legalBasisChangeRequest.getAnnotationId(), legalBasisChangeRequest.getComment(), legalBasisChangeRequest.getUser());
|
||||||
|
|
||||||
response.add(ManualAddResponse.builder().annotationId(legalBasisChangeRequest.getAnnotationId()).commentId(commentId).build());
|
response.add(ManualAddResponse.builder().annotationId(legalBasisChangeRequest.getAnnotationId()).commentId(commentId).build());
|
||||||
}
|
}
|
||||||
@ -412,19 +419,19 @@ public class ManualRedactionService {
|
|||||||
public List<ManualAddResponse> addRecategorization(String dossierId, String fileId, List<RecategorizationRequest> recategorizationRequests) {
|
public List<ManualAddResponse> addRecategorization(String dossierId, String fileId, List<RecategorizationRequest> recategorizationRequests) {
|
||||||
|
|
||||||
var response = new ArrayList<ManualAddResponse>();
|
var response = new ArrayList<ManualAddResponse>();
|
||||||
var actionPerformed = false;
|
var requiresReanalysis = false;
|
||||||
dossierPersistenceService.getAndValidateDossier(dossierId);
|
dossierPersistenceService.getAndValidateDossier(dossierId);
|
||||||
|
|
||||||
for (var recategorizationRequest : recategorizationRequests) {
|
for (var recategorizationRequest : recategorizationRequests) {
|
||||||
recategorizationPersistenceService.insert(fileId, recategorizationRequest);
|
recategorizationPersistenceService.insert(fileId, recategorizationRequest);
|
||||||
|
|
||||||
Long commentId = addComment(fileId, recategorizationRequest.getAnnotationId(), recategorizationRequest.getComment(), recategorizationRequest.getUser()).getId();
|
Long commentId = addCommentAndGetId(fileId, recategorizationRequest.getAnnotationId(), recategorizationRequest.getComment(), recategorizationRequest.getUser());
|
||||||
|
|
||||||
actionPerformed = actionPerformed || recategorizationRequest.getStatus().equals(AnnotationStatus.APPROVED);
|
requiresReanalysis = requiresReanalysis || recategorizationRequest.getStatus().equals(AnnotationStatus.APPROVED);
|
||||||
|
|
||||||
response.add(ManualAddResponse.builder().annotationId(recategorizationRequest.getAnnotationId()).commentId(commentId).build());
|
response.add(ManualAddResponse.builder().annotationId(recategorizationRequest.getAnnotationId()).commentId(commentId).build());
|
||||||
}
|
}
|
||||||
if (actionPerformed) {
|
if (requiresReanalysis) {
|
||||||
reprocess(dossierId, fileId);
|
reprocess(dossierId, fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,17 +455,19 @@ public class ManualRedactionService {
|
|||||||
public void deleteAddRedaction(String dossierId, String fileId, List<String> annotationIds) {
|
public void deleteAddRedaction(String dossierId, String fileId, List<String> annotationIds) {
|
||||||
|
|
||||||
var dossier = dossierPersistenceService.getAndValidateDossier(dossierId);
|
var dossier = dossierPersistenceService.getAndValidateDossier(dossierId);
|
||||||
var changedDictionary = false;
|
var requiresReanalysis = false;
|
||||||
|
|
||||||
for (String annotationId : annotationIds) {
|
for (String annotationId : annotationIds) {
|
||||||
|
|
||||||
ManualRedactionEntryEntity addRedaction = getAddRedaction(fileId, annotationId);
|
ManualRedactionEntryEntity addRedaction = getAddRedaction(fileId, annotationId);
|
||||||
|
|
||||||
changedDictionary = manualRedactionDictionaryUpdateHandler.revertAddToDictionary(fileId, dossier.getId(), addRedaction) || changedDictionary;
|
boolean dictionaryChanged = manualRedactionDictionaryUpdateHandler.revertAddToDictionary(fileId, dossier.getId(), addRedaction);
|
||||||
|
requiresReanalysis = requiresReanalysis || dictionaryChanged;
|
||||||
addRedactionPersistenceService.updateStatus(fileId, annotationId, AnnotationStatus.APPROVED, false, null);
|
addRedactionPersistenceService.updateStatus(fileId, annotationId, AnnotationStatus.APPROVED, false, null);
|
||||||
addRedactionPersistenceService.softDelete(fileId, annotationId, OffsetDateTime.now());
|
addRedactionPersistenceService.softDelete(fileId, annotationId, OffsetDateTime.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedDictionary) {
|
if (requiresReanalysis) {
|
||||||
reprocess(dossierId, fileId);
|
reprocess(dossierId, fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +480,7 @@ public class ManualRedactionService {
|
|||||||
|
|
||||||
var dossier = dossierPersistenceService.getAndValidateDossier(dossierId);
|
var dossier = dossierPersistenceService.getAndValidateDossier(dossierId);
|
||||||
var requiresReanalysis = false;
|
var requiresReanalysis = false;
|
||||||
RedactionLog redactionLog = redactionLogService.getRedactionLog(dossierId, fileId, true, true);
|
RedactionLog redactionLog = redactionLogService.getRedactionLog(dossierId, fileId);
|
||||||
|
|
||||||
for (String annotationId : annotationIds) {
|
for (String annotationId : annotationIds) {
|
||||||
|
|
||||||
@ -522,38 +531,48 @@ public class ManualRedactionService {
|
|||||||
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void deleteImageRecategorization(String dossierId, String fileId, List<String> annotationIds) {
|
public void deleteRecategorization(String dossierId, String fileId, List<String> annotationIds) {
|
||||||
|
|
||||||
var actionPerformed = false;
|
var requiresReanalysis = false;
|
||||||
for (var annotationId : annotationIds) {
|
for (var annotationId : annotationIds) {
|
||||||
var imageRecategorization = getImageRecategorization(fileId, annotationId);
|
var imageRecategorization = getRecategorization(fileId, annotationId);
|
||||||
|
|
||||||
recategorizationPersistenceService.softDelete(fileId, annotationId, OffsetDateTime.now());
|
recategorizationPersistenceService.softDelete(fileId, annotationId, OffsetDateTime.now());
|
||||||
|
|
||||||
actionPerformed = actionPerformed || !AnnotationStatus.REQUESTED.equals(imageRecategorization.getStatus());
|
requiresReanalysis = requiresReanalysis || !AnnotationStatus.REQUESTED.equals(imageRecategorization.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionPerformed) {
|
if (requiresReanalysis) {
|
||||||
reprocess(dossierId, fileId);
|
reprocess(dossierId, fileId);
|
||||||
}
|
}
|
||||||
analysisFlagsCalculationService.calculateFlags(dossierId, fileId);
|
analysisFlagsCalculationService.calculateFlags(dossierId, fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private ManualImageRecategorizationEntity getImageRecategorization(String fileId, String annotationId) {
|
private ManualImageRecategorizationEntity getRecategorization(String fileId, String annotationId) {
|
||||||
|
|
||||||
return recategorizationPersistenceService.findRecategorization(fileId, annotationId);
|
return recategorizationPersistenceService.findRecategorization(fileId, annotationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void deleteComment(String fileId, List<Long> commentIds) {
|
public void deleteComment(String dossierId, String fileId, List<Long> commentIds) {
|
||||||
|
|
||||||
for (var commentId : commentIds) {
|
for (var commentId : commentIds) {
|
||||||
commentPersistenceService.softDelete(commentId, OffsetDateTime.now());
|
commentPersistenceService.softDelete(commentId, OffsetDateTime.now());
|
||||||
}
|
}
|
||||||
// update indicator
|
// update indicator
|
||||||
fileStatusPersistenceService.updateHasComments(fileId, commentPersistenceService.fileHasComments(fileId));
|
fileStatusPersistenceService.updateHasComments(fileId, commentPersistenceService.fileHasComments(fileId));
|
||||||
|
// if file is currently not analyzing, we can quickly change the redaction log, else we must wait for the analysis to finish.
|
||||||
|
if (!fileStatusService.getStatus(fileId).getProcessingStatus().equals(ProcessingStatus.PROCESSED)) {
|
||||||
|
reprocess(dossierId, fileId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fileStatusService.setStatusProcessing(fileId);
|
||||||
|
RedactionLog redactionLog = redactionLogService.getRedactionLog(dossierId, fileId);
|
||||||
|
redactionLog.getRedactionLogEntry().forEach(entry -> entry.getComments().removeIf(comment -> commentIds.contains(comment.getId())));
|
||||||
|
fileManagementStorageService.storeRedactionLog(dossierId, fileId, redactionLog);
|
||||||
|
fileStatusService.setStatusProcessed(fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -573,14 +592,14 @@ public class ManualRedactionService {
|
|||||||
|
|
||||||
List<ManualAddResponse> response = new ArrayList<>();
|
List<ManualAddResponse> response = new ArrayList<>();
|
||||||
|
|
||||||
RedactionLog redactionLog = redactionLogService.getRedactionLog(dossierId, fileId, true, true);
|
RedactionLog redactionLog = redactionLogService.getRedactionLog(dossierId, fileId);
|
||||||
|
|
||||||
for (ResizeRedactionRequest resizeRedactionRequest : resizeRedactionRequests) {
|
for (ResizeRedactionRequest resizeRedactionRequest : resizeRedactionRequests) {
|
||||||
|
|
||||||
var resizeRedaction = resizeRedactionPersistenceService.insert(fileId, resizeRedactionRequest);
|
var resizeRedaction = resizeRedactionPersistenceService.insert(fileId, resizeRedactionRequest);
|
||||||
|
|
||||||
if (resizeRedactionRequest.getComment() != null) {
|
if (resizeRedactionRequest.getComment() != null) {
|
||||||
Long commentId = addComment(fileId, resizeRedactionRequest.getAnnotationId(), resizeRedactionRequest.getComment(), resizeRedactionRequest.getUser()).getId();
|
Long commentId = addCommentAndGetId(fileId, resizeRedactionRequest.getAnnotationId(), resizeRedactionRequest.getComment(), resizeRedactionRequest.getUser());
|
||||||
response.add(ManualAddResponse.builder().annotationId(resizeRedactionRequest.getAnnotationId()).commentId(commentId).build());
|
response.add(ManualAddResponse.builder().annotationId(resizeRedactionRequest.getAnnotationId()).commentId(commentId).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,7 +694,7 @@ public class ManualRedactionService {
|
|||||||
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void updateProcessedDate(String fileId, ManualRedactions manualRedactions) {
|
public void updateProcessedDate(ManualRedactions manualRedactions) {
|
||||||
|
|
||||||
if (manualRedactions != null) {
|
if (manualRedactions != null) {
|
||||||
|
|
||||||
@ -717,4 +736,13 @@ public class ManualRedactionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Comments getComments(String fileId) {
|
||||||
|
|
||||||
|
return new Comments(commentPersistenceService.findCommentsByFileID(fileId, false)
|
||||||
|
.entrySet()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, entry -> MagicConverter.convert(entry.getValue(), Comment.class))));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,247 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.service.manualredactions;
|
||||||
|
|
||||||
|
import static com.iqser.red.service.persistence.service.v1.api.external.resource.ManualRedactionResource.ANNOTATION_ID;
|
||||||
|
import static com.iqser.red.service.persistence.service.v1.api.external.resource.ManualRedactionResource.DOSSIER_ID;
|
||||||
|
import static com.iqser.red.service.persistence.service.v1.api.external.resource.ManualRedactionResource.FILE_ID;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.AuditCategory;
|
||||||
|
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.entitymapped.IdRemoval;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualForceRedaction;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualImageRecategorization;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualLegalBasisChange;
|
||||||
|
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.annotations.entitymapped.ManualResizeRedaction;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.audit.AuditRequest;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ManualRedactionWrapperModel;
|
||||||
|
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ManualRedactionUndoService {
|
||||||
|
|
||||||
|
private final ManualRedactionService manualRedactionService;
|
||||||
|
private final AuditPersistenceService auditPersistenceService;
|
||||||
|
private final FileStatusService fileStatusService;
|
||||||
|
|
||||||
|
|
||||||
|
public void undo(String dossierId, String fileId, Set<String> annotationIds) {
|
||||||
|
|
||||||
|
// undo the latest manual redaction for each annotationId
|
||||||
|
ManualRedactions manualRedactions = manualRedactionService.getManualRedactions(fileId);
|
||||||
|
|
||||||
|
Map<String, ManualRedactionWrapperModel> manualRedactionWrappers = getLatestManualRedactionsForAnnotationIds(manualRedactions, annotationIds);
|
||||||
|
|
||||||
|
if (manualRedactionWrappers.isEmpty()) {
|
||||||
|
throw new NotFoundException(String.format("ManualRedaction with annotationIds %s could not be found.", annotationIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
undoManualRedactionEntries(dossierId, fileId, manualRedactionWrappers);
|
||||||
|
undoIdRemovals(dossierId, fileId, manualRedactionWrappers);
|
||||||
|
undoForceRedactions(dossierId, fileId, manualRedactionWrappers);
|
||||||
|
undoRecategorization(dossierId, fileId, manualRedactionWrappers);
|
||||||
|
undoLegalBasisChange(dossierId, fileId, manualRedactionWrappers);
|
||||||
|
undoResize(dossierId, fileId, manualRedactionWrappers);
|
||||||
|
reprocess(dossierId, fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reprocess(String dossierId, String fileId) {
|
||||||
|
|
||||||
|
fileStatusService.setStatusReprocessForManual(dossierId, fileId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void undoResize(String dossierId, String fileId, Map<String, ManualRedactionWrapperModel> manualRedactionWrappers) {
|
||||||
|
|
||||||
|
List<String> manualResizeRedactions = manualRedactionWrappers.values()
|
||||||
|
.stream()
|
||||||
|
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualResizeRedaction)
|
||||||
|
.map(ManualRedactionWrapperModel::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (!manualResizeRedactions.isEmpty()) {
|
||||||
|
manualRedactionService.deleteResizeRedaction(dossierId, fileId, manualResizeRedactions);
|
||||||
|
manualResizeRedactions.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
||||||
|
.userId(KeycloakSecurity.getUserId())
|
||||||
|
.objectId(fileId)
|
||||||
|
.category(AuditCategory.DOCUMENT.name())
|
||||||
|
.message("Undo of manual resize redaction was done.")
|
||||||
|
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void undoLegalBasisChange(String dossierId, String fileId, Map<String, ManualRedactionWrapperModel> manualRedactionWrappers) {
|
||||||
|
|
||||||
|
List<String> manualLegalBasisChanges = manualRedactionWrappers.values()
|
||||||
|
.stream()
|
||||||
|
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualLegalBasisChange)
|
||||||
|
.map(ManualRedactionWrapperModel::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (!manualLegalBasisChanges.isEmpty()) {
|
||||||
|
|
||||||
|
manualRedactionService.deleteLegalBasisChange(dossierId, fileId, manualLegalBasisChanges);
|
||||||
|
manualLegalBasisChanges.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
||||||
|
.userId(KeycloakSecurity.getUserId())
|
||||||
|
.objectId(fileId)
|
||||||
|
.category(AuditCategory.DOCUMENT.name())
|
||||||
|
.message("Undo of legal basis change was done.")
|
||||||
|
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void undoRecategorization(String dossierId, String fileId, Map<String, ManualRedactionWrapperModel> manualRedactionWrappers) {
|
||||||
|
|
||||||
|
List<String> manualImageRecategorizations = manualRedactionWrappers.values()
|
||||||
|
.stream()
|
||||||
|
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualImageRecategorization)
|
||||||
|
.map(ManualRedactionWrapperModel::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (!manualImageRecategorizations.isEmpty()) {
|
||||||
|
|
||||||
|
manualRedactionService.deleteRecategorization(dossierId, fileId, manualImageRecategorizations);
|
||||||
|
manualImageRecategorizations.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
||||||
|
.userId(KeycloakSecurity.getUserId())
|
||||||
|
.objectId(fileId)
|
||||||
|
.category(AuditCategory.DOCUMENT.name())
|
||||||
|
.message("Undo of manual image recategorization was done.")
|
||||||
|
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void undoForceRedactions(String dossierId, String fileId, Map<String, ManualRedactionWrapperModel> manualRedactionWrappers) {
|
||||||
|
|
||||||
|
List<String> manualForceRedactions = manualRedactionWrappers.values()
|
||||||
|
.stream()
|
||||||
|
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualForceRedaction)
|
||||||
|
.map(ManualRedactionWrapperModel::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (!manualForceRedactions.isEmpty()) {
|
||||||
|
|
||||||
|
manualRedactionService.deleteForceRedaction(dossierId, fileId, manualForceRedactions);
|
||||||
|
manualForceRedactions.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
||||||
|
.userId(KeycloakSecurity.getUserId())
|
||||||
|
.objectId(fileId)
|
||||||
|
.category(AuditCategory.DOCUMENT.name())
|
||||||
|
.message("Undo of manual force redaction was done.")
|
||||||
|
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void undoIdRemovals(String dossierId, String fileId, Map<String, ManualRedactionWrapperModel> manualRedactionWrappers) {
|
||||||
|
|
||||||
|
List<String> idRemovals = manualRedactionWrappers.values()
|
||||||
|
.stream()
|
||||||
|
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof IdRemoval)
|
||||||
|
.map(ManualRedactionWrapperModel::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (!idRemovals.isEmpty()) {
|
||||||
|
manualRedactionService.deleteRemoveRedaction(dossierId, fileId, idRemovals);
|
||||||
|
idRemovals.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
||||||
|
.userId(KeycloakSecurity.getUserId())
|
||||||
|
.objectId(fileId)
|
||||||
|
.category(AuditCategory.DOCUMENT.name())
|
||||||
|
.message("Undo of manual remove redaction was done.")
|
||||||
|
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void undoManualRedactionEntries(String dossierId, String fileId, Map<String, ManualRedactionWrapperModel> manualRedactionWrappers) {
|
||||||
|
|
||||||
|
List<String> manualRedactionEntries = manualRedactionWrappers.values()
|
||||||
|
.stream()
|
||||||
|
.filter(manualRedactionWrapper -> manualRedactionWrapper.getItem() instanceof ManualRedactionEntry)
|
||||||
|
.map(ManualRedactionWrapperModel::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (!manualRedactionEntries.isEmpty()) {
|
||||||
|
manualRedactionService.deleteAddRedaction(dossierId, fileId, manualRedactionEntries);
|
||||||
|
manualRedactionEntries.forEach(annotationId -> auditPersistenceService.audit(AuditRequest.builder()
|
||||||
|
.userId(KeycloakSecurity.getUserId())
|
||||||
|
.objectId(fileId)
|
||||||
|
.category(AuditCategory.DOCUMENT.name())
|
||||||
|
.message("Undo of manual add redaction was done.")
|
||||||
|
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Map<String, ManualRedactionWrapperModel> getLatestManualRedactionsForAnnotationIds(ManualRedactions manualRedactions, Set<String> annotationIds) {
|
||||||
|
|
||||||
|
Map<String, ManualRedactionWrapperModel> result = new HashMap<>();
|
||||||
|
annotationIds.forEach(annotationId -> {
|
||||||
|
var last = getLatestManualRedactionForAnnotationId(manualRedactions, annotationId);
|
||||||
|
if (last != null) {
|
||||||
|
result.put(annotationId, last);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ManualRedactionWrapperModel getLatestManualRedactionForAnnotationId(ManualRedactions manualRedactions, String annotationId) {
|
||||||
|
|
||||||
|
final List<ManualRedactionWrapperModel> manualRedactionWrappers = new ArrayList<>();
|
||||||
|
|
||||||
|
manualRedactions.getEntriesToAdd()
|
||||||
|
.stream()
|
||||||
|
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
||||||
|
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
||||||
|
|
||||||
|
manualRedactions.getImageRecategorization()
|
||||||
|
.stream()
|
||||||
|
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
||||||
|
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
||||||
|
|
||||||
|
manualRedactions.getIdsToRemove()
|
||||||
|
.stream()
|
||||||
|
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
||||||
|
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
||||||
|
|
||||||
|
manualRedactions.getForceRedactions()
|
||||||
|
.stream()
|
||||||
|
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
||||||
|
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
||||||
|
|
||||||
|
manualRedactions.getLegalBasisChanges()
|
||||||
|
.stream()
|
||||||
|
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
||||||
|
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
||||||
|
|
||||||
|
manualRedactions.getResizeRedactions()
|
||||||
|
.stream()
|
||||||
|
.filter(item -> item.getSoftDeletedTime() == null && item.getAnnotationId().equals(annotationId))
|
||||||
|
.forEach(item -> manualRedactionWrappers.add(new ManualRedactionWrapperModel(item.getAnnotationId(), item.getRequestDate(), item)));
|
||||||
|
|
||||||
|
var sortedManualRedactionWrappers = manualRedactionWrappers.stream()
|
||||||
|
.sorted(Comparator.comparing(ManualRedactionWrapperModel::getDate, Comparator.nullsLast(Comparator.reverseOrder())))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return sortedManualRedactionWrappers.isEmpty() ? null : sortedManualRedactionWrappers.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.iqser.red.service.persistence.service.v1.api.shared.model.annotations;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Comments {
|
||||||
|
|
||||||
|
Map<String, List<Comment>> comments;
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user