Merge branch 'RED-9947' into 'master'
RED-9947: Bulk-local redactions (replacement for group redactions) Closes RED-9947 See merge request redactmanager/persistence-service!714
This commit is contained in:
commit
11088ddfef
@ -9,6 +9,7 @@ import static com.iqser.red.service.persistence.management.v1.processor.roles.Ac
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@ -21,12 +22,16 @@ import com.iqser.red.service.persistence.management.v1.processor.service.AccessC
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.CommentService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.DossierManagementService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusManagementService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
|
||||
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.manualredactions.PendingEntryFactory;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService;
|
||||
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.CommentResponse;
|
||||
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.annotations.AnnotationComments;
|
||||
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;
|
||||
@ -35,12 +40,16 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions;
|
||||
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.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.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.RecategorizationBulkLocalRequestModel;
|
||||
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.RemoveRedactionBulkLocalRequestModel;
|
||||
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.mongo.service.EntityLogMongoService;
|
||||
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
@ -57,6 +66,7 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
static final String FILE_ID = "fileId";
|
||||
static final String DOSSIER_ID = "dossierId";
|
||||
static final String ANNOTATION_ID = "annotationId";
|
||||
|
||||
ManualRedactionService manualRedactionService;
|
||||
ManualRedactionUndoService manualRedactionUndoService;
|
||||
DossierManagementService dossierManagementService;
|
||||
@ -64,9 +74,12 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
AccessControlService accessControlService;
|
||||
CommentService commentService;
|
||||
FileStatusManagementService fileStatusManagementService;
|
||||
FileStatusService fileStatusService;
|
||||
EntityLogMongoService entityLogMongoService;
|
||||
PendingEntryFactory pendingEntryFactory;
|
||||
DictionaryPersistenceService dictionaryPersistenceService;
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + DELETE_MANUAL_REDACTION + "')")
|
||||
public void undo(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@ -82,7 +95,6 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + DELETE_COMMENT + "')")
|
||||
public void undoComment(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@ -105,7 +117,6 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + READ_MANUAL_REDACTIONS + "')")
|
||||
public ManualRedactions getManualRedactions(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@ -114,12 +125,12 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
|
||||
accessControlService.checkDossierExistenceAndViewPermissionsToDossier(dossierId);
|
||||
accessControlService.validateFileResourceExistence(fileId);
|
||||
|
||||
return manualRedactionService.getManualRedactions(fileId,
|
||||
ManualChangesQueryOptions.builder().includeOnlyUnprocessed(unprocessed).includeDictChanges(includeDictChanges).build());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + READ_MANUAL_REDACTIONS + "')")
|
||||
public AnnotationComments getComments(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @PathVariable(ANNOTATION_ID) String annotationId) {
|
||||
|
||||
@ -132,7 +143,6 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + ADD_COMMENT + "')")
|
||||
public CommentResponse addComment(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@ -157,21 +167,16 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + DO_MANUAL_REDACTION + "')")
|
||||
public ManualRedactionResponse addRedactionBulk(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestBody Set<AddRedactionRequestModel> addRedactionRequests) {
|
||||
|
||||
var dossier = dossierManagementService.getDossierById(dossierId, false, false);
|
||||
accessControlService.checkAccessPermissionsToDossier(dossierId);
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
if (addRedactionRequests.stream()
|
||||
.anyMatch(AddRedactionRequestModel::isAddToAllDossiers)) {
|
||||
accessControlService.verifyUserIsApprover(dossierId);
|
||||
} else {
|
||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||
}
|
||||
verifyAccessForDossier(dossierId,
|
||||
fileId,
|
||||
addRedactionRequests.stream()
|
||||
.anyMatch(AddRedactionRequestModel::isAddToAllDossiers));
|
||||
|
||||
List<ManualAddResponse> responseList = manualRedactionService.addAddRedaction(dossierId, fileId, addRedactionRequests, dossier);
|
||||
responseList.forEach(response -> auditPersistenceService.audit(AuditRequest.builder()
|
||||
@ -186,6 +191,28 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + DO_MANUAL_REDACTION + "')")
|
||||
public ManualRedactionResponse addRedactionBulkLocal(String dossierId, String fileId, AddRedactionBulkLocalRequestModel addRedactionRequest) {
|
||||
|
||||
verifyAccess(dossierId, fileId);
|
||||
|
||||
// check if type exists before sending the request to redaction service
|
||||
dictionaryPersistenceService.getType(addRedactionRequest.getType());
|
||||
|
||||
fileStatusService.setStatusBulkLocalRedactionsProcessing(dossierId, fileId, addRedactionRequest);
|
||||
|
||||
EntityLogEntry entityLogEntry = pendingEntryFactory.buildAddRedactionBulkLocalEntry(addRedactionRequest);
|
||||
|
||||
return ManualRedactionResponse.builder()
|
||||
.manualAddResponses(List.of(ManualAddResponse.builder()
|
||||
.annotationId(manualRedactionService.getPendingBulkLocalAnnotationId(fileId, addRedactionRequest))
|
||||
.entityLogEntry(entityLogEntry)
|
||||
.build()))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + DO_MANUAL_REDACTION + "')")
|
||||
public ManualRedactionResponse removeRedactionBulk(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@ -193,14 +220,10 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
@RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed) {
|
||||
|
||||
var dossier = dossierManagementService.getDossierById(dossierId, false, false);
|
||||
accessControlService.checkAccessPermissionsToDossier(dossierId);
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
if (removeRedactionRequests.stream()
|
||||
.anyMatch(RemoveRedactionRequestModel::isRemoveFromAllDossiers)) {
|
||||
accessControlService.verifyUserIsApprover(dossierId);
|
||||
} else {
|
||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||
}
|
||||
verifyAccessForDossier(dossierId,
|
||||
fileId,
|
||||
removeRedactionRequests.stream()
|
||||
.anyMatch(RemoveRedactionRequestModel::isRemoveFromAllDossiers));
|
||||
|
||||
List<ManualAddResponse> responseList = manualRedactionService.addRemoveRedaction(dossierId,
|
||||
fileId,
|
||||
@ -220,14 +243,40 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + DO_MANUAL_REDACTION + "')")
|
||||
public ManualRedactionResponse removeRedactionBulkLocal(String dossierId,
|
||||
String fileId,
|
||||
RemoveRedactionBulkLocalRequestModel removeRedactionRequest,
|
||||
boolean removeUnprocessed) {
|
||||
|
||||
verifyAccess(dossierId, fileId);
|
||||
|
||||
Set<String> entryIds;
|
||||
if (!removeRedactionRequest.isRectangle()) {
|
||||
entryIds = entityLogMongoService.findEntryIdsByValueAndEngineManualWithFilters(removeRedactionRequest.getValue(),
|
||||
removeRedactionRequest.getOriginTypes(),
|
||||
removeRedactionRequest.getOriginLegalBases(),
|
||||
removeRedactionRequest.getPageNumbers());
|
||||
} else {
|
||||
entryIds = entityLogMongoService.findEntryIdsByMatchingFullPositionAndEngineManualWithFilters(removeRedactionRequest.getPosition().getRectangle(),
|
||||
removeRedactionRequest.getOriginTypes(),
|
||||
removeRedactionRequest.getOriginLegalBases(),
|
||||
removeRedactionRequest.getPageNumbers());
|
||||
}
|
||||
Set<RemoveRedactionRequestModel> removeRedactionRequestModels = entryIds.stream()
|
||||
.map(entryId -> RemoveRedactionRequestModel.builder().annotationId(entryId).build())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return removeRedactionBulk(dossierId, fileId, removeRedactionRequestModels, removeUnprocessed);
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + DO_MANUAL_REDACTION + "')")
|
||||
public ManualRedactionResponse forceRedactionBulk(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestBody Set<ForceRedactionRequestModel> forceRedactionRequests) {
|
||||
|
||||
accessControlService.checkDossierExistenceAndAccessPermissionsToDossier(dossierId);
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||
verifyAccessAndDossierExistence(dossierId, fileId);
|
||||
|
||||
List<ManualAddResponse> responseList = manualRedactionService.addForceRedaction(dossierId, fileId, forceRedactionRequests);
|
||||
|
||||
@ -248,9 +297,7 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestBody Set<LegalBasisChangeRequestModel> legalBasisChangeRequests) {
|
||||
|
||||
accessControlService.checkDossierExistenceAndAccessPermissionsToDossier(dossierId);
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||
verifyAccessAndDossierExistence(dossierId, fileId);
|
||||
|
||||
List<ManualAddResponse> responseList = manualRedactionService.addLegalBasisChange(dossierId, fileId, legalBasisChangeRequests);
|
||||
|
||||
@ -261,6 +308,7 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
.message("Legal basis reason was changed")
|
||||
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, response.getAnnotationId()))
|
||||
.build()));
|
||||
|
||||
return ManualRedactionResponse.builder().manualAddResponses(responseList).build();
|
||||
}
|
||||
|
||||
@ -272,9 +320,7 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
@RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed) {
|
||||
|
||||
var dossier = dossierManagementService.getDossierById(dossierId, false, false);
|
||||
accessControlService.checkAccessPermissionsToDossier(dossierId);
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||
verifyAccess(dossierId, fileId);
|
||||
|
||||
List<ManualAddResponse> responseList = manualRedactionService.addRecategorization(dossierId, fileId, dossier, recategorizationRequests, includeUnprocessed);
|
||||
|
||||
@ -290,15 +336,47 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + DO_MANUAL_REDACTION + "')")
|
||||
public ManualRedactionResponse recategorizeBulkLocal(String dossierId,
|
||||
String fileId,
|
||||
RecategorizationBulkLocalRequestModel recategorizationRequest,
|
||||
boolean includeUnprocessed) {
|
||||
|
||||
verifyAccess(dossierId, fileId);
|
||||
|
||||
Set<String> entryIds;
|
||||
if (!recategorizationRequest.isRectangle()) {
|
||||
entryIds = entityLogMongoService.findEntryIdsByValueAndEngineManualWithFilters(recategorizationRequest.getValue(),
|
||||
recategorizationRequest.getOriginTypes(),
|
||||
recategorizationRequest.getOriginLegalBases(),
|
||||
recategorizationRequest.getPageNumbers());
|
||||
} else {
|
||||
entryIds = entityLogMongoService.findEntryIdsByMatchingFullPositionAndEngineManualWithFilters(recategorizationRequest.getPosition().getRectangle(),
|
||||
recategorizationRequest.getOriginTypes(),
|
||||
recategorizationRequest.getOriginLegalBases(),
|
||||
recategorizationRequest.getPageNumbers());
|
||||
}
|
||||
Set<RecategorizationRequestModel> recategorizationRequestModels = entryIds.stream()
|
||||
.map(entryId -> RecategorizationRequestModel.builder()
|
||||
.annotationId(entryId)
|
||||
.type(recategorizationRequest.getType())
|
||||
.legalBasis(recategorizationRequest.getLegalBasis())
|
||||
.section(recategorizationRequest.getSection())
|
||||
.value(recategorizationRequest.getValue())
|
||||
.build())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return recategorizeBulk(dossierId, fileId, recategorizationRequestModels, includeUnprocessed);
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + DO_MANUAL_REDACTION + "')")
|
||||
public ManualRedactionResponse resizeRedactionBulk(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestBody Set<ResizeRedactionRequestModel> resizeRedactionRequests,
|
||||
@RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed) {
|
||||
|
||||
accessControlService.checkDossierExistenceAndAccessPermissionsToDossier(dossierId);
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||
verifyAccessAndDossierExistence(dossierId, fileId);
|
||||
|
||||
List<ManualAddResponse> responseList = manualRedactionService.addResizeRedaction(dossierId, fileId, resizeRedactionRequests, includeUnprocessed);
|
||||
|
||||
@ -309,7 +387,36 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
.message("Skipped annotation was resized to be redacted")
|
||||
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, response.getAnnotationId()))
|
||||
.build()));
|
||||
|
||||
return ManualRedactionResponse.builder().manualAddResponses(responseList).build();
|
||||
}
|
||||
|
||||
|
||||
private void verifyAccessForDossier(String dossierId, String fileId, boolean allDossiersAffected) {
|
||||
|
||||
accessControlService.checkAccessPermissionsToDossier(dossierId);
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
if (allDossiersAffected) {
|
||||
accessControlService.verifyUserIsApprover(dossierId);
|
||||
} else {
|
||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void verifyAccess(String dossierId, String fileId) {
|
||||
|
||||
accessControlService.checkAccessPermissionsToDossier(dossierId);
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||
}
|
||||
|
||||
|
||||
private void verifyAccessAndDossierExistence(String dossierId, String fileId) {
|
||||
|
||||
accessControlService.checkDossierExistenceAndAccessPermissionsToDossier(dossierId);
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
accessControlService.verifyUserIsMemberOrApprover(dossierId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -16,11 +16,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.AnnotationComments;
|
||||
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.manual.AddRedactionBulkLocalRequestModel;
|
||||
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.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.RecategorizationBulkLocalRequestModel;
|
||||
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.RemoveRedactionBulkLocalRequestModel;
|
||||
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;
|
||||
|
||||
@ -95,13 +98,38 @@ public interface ManualRedactionResource {
|
||||
@RequestBody Set<AddRedactionRequestModel> addRedactionRequest);
|
||||
|
||||
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@PostMapping(value = MANUAL_REDACTION_REST_PATH
|
||||
+ "/bulk-local/add"
|
||||
+ DOSSIER_ID_PATH_PARAM
|
||||
+ FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Adds a bulk of local redactions", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
|
||||
ManualRedactionResponse addRedactionBulkLocal(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestBody AddRedactionBulkLocalRequestModel addRedactionRequest);
|
||||
|
||||
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@PostMapping(value = MANUAL_REDACTION_REST_PATH
|
||||
+ "/bulk-local/remove"
|
||||
+ DOSSIER_ID_PATH_PARAM
|
||||
+ FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Removes a bulk of local redactions", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
|
||||
ManualRedactionResponse removeRedactionBulkLocal(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestBody RemoveRedactionBulkLocalRequestModel removeRedactionRequest,
|
||||
@RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed);
|
||||
|
||||
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@PostMapping(value = MANUAL_REDACTION_REST_PATH
|
||||
+ "/bulk/redaction/remove"
|
||||
+ DOSSIER_ID_PATH_PARAM
|
||||
+ FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Removes the redactions list", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
|
||||
ManualRedactionResponse removeRedactionBulk(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestBody Set<RemoveRedactionRequestModel> removeRedactionRequests,
|
||||
@ -139,13 +167,26 @@ public interface ManualRedactionResource {
|
||||
+ DOSSIER_ID_PATH_PARAM
|
||||
+ FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Recategorizes the list of redaction log entries", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
|
||||
ManualRedactionResponse recategorizeBulk(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestBody Set<RecategorizationRequestModel> recategorizationRequests,
|
||||
@RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed);
|
||||
|
||||
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@PostMapping(value = MANUAL_REDACTION_REST_PATH
|
||||
+ "/bulk-local/recategorize"
|
||||
+ DOSSIER_ID_PATH_PARAM
|
||||
+ FILE_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Recategorizes the list of redaction log entries", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Request contains error."), @ApiResponse(responseCode = "404", description = "Dossier or file not found"), @ApiResponse(responseCode = "403", description = "Forbidden")})
|
||||
ManualRedactionResponse recategorizeBulkLocal(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestBody RecategorizationBulkLocalRequestModel recategorizationRequest,
|
||||
@RequestParam(value = "includeUnprocessed", required = false, defaultValue = FALSE) boolean includeUnprocessed);
|
||||
|
||||
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@PostMapping(value = MANUAL_REDACTION_REST_PATH
|
||||
+ "/bulk/redaction/resize"
|
||||
|
||||
@ -44,7 +44,7 @@ dependencies {
|
||||
}
|
||||
implementation("com.knecon.fforesight:llm-service-api:1.13.0")
|
||||
api("com.knecon.fforesight:jobs-commons:0.10.0")
|
||||
api("com.knecon.fforesight:tenant-commons:0.29.0")
|
||||
api("com.knecon.fforesight:tenant-commons:0.30.0")
|
||||
api("com.knecon.fforesight:database-tenant-commons:0.24.0") {
|
||||
exclude(group = "com.knecon.fforesight", module = "tenant-commons")
|
||||
}
|
||||
|
||||
@ -36,6 +36,10 @@ public class MessagingConfiguration {
|
||||
public static final String REDACTION_RESPONSE_QUEUE_PREFIX = "redaction_response";
|
||||
public static final String REDACTION_RESPONSE_EXCHANGE = "redaction_response_exchange";
|
||||
|
||||
public static final String SEARCH_BULK_LOCAL_TERM_RESPONSE_QUEUE_PREFIX = "search_bulk_local_term_response";
|
||||
public static final String SEARCH_BULK_LOCAL_TERM_RESPONSE_EXCHANGE = "search_bulk_local_term_response_exchange";
|
||||
public static final String SEARCH_BULK_LOCAL_TERM_DLQ = "search_bulk_local_term_error";
|
||||
|
||||
public static final String PDFTRON_RESPONSE_QUEUE_PREFIX = "pdftron_response";
|
||||
public static final String PDFTRON_RESPONSE_EXCHANGE = "pdftron_response_exchange";
|
||||
|
||||
@ -193,6 +197,20 @@ public class MessagingConfiguration {
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public DirectExchange searchTermOccurrencesResponseExchange() {
|
||||
|
||||
return new DirectExchange(SEARCH_BULK_LOCAL_TERM_RESPONSE_EXCHANGE);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Queue searchTermOccurrencesDLQ() {
|
||||
|
||||
return QueueBuilder.durable(SEARCH_BULK_LOCAL_TERM_DLQ).build();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public DirectExchange reportResponseExchange() {
|
||||
|
||||
@ -451,9 +469,8 @@ public class MessagingConfiguration {
|
||||
return QueueBuilder.durable(ENTITY_DLQ).build();
|
||||
}
|
||||
|
||||
|
||||
// ---- azure-ner-service ----
|
||||
|
||||
|
||||
@Bean
|
||||
public DirectExchange azureNerRequestExchange() {
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@ public enum AnalyseStatus {
|
||||
READ_ONLY_PROCESSING,
|
||||
PROCESSING,
|
||||
OCR_PROCESSING,
|
||||
BULK_LOCAL_REDACTIONS_PROCESSING,
|
||||
BULK_LOCAL_REDACTIONS_PROCESSED,
|
||||
LAYOUT_UPDATE,
|
||||
FINISHED,
|
||||
ERROR
|
||||
|
||||
@ -26,7 +26,7 @@ import com.iqser.red.service.persistence.management.v1.processor.entity.configur
|
||||
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
|
||||
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.service.manualredactions.PendingDictionaryEntryFactory;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.PendingEntryFactory;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService;
|
||||
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;
|
||||
@ -67,7 +67,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class EntityLogMergeService {
|
||||
|
||||
DictionaryPersistenceService dictionaryPersistenceService;
|
||||
PendingDictionaryEntryFactory pendingDictionaryEntryFactory;
|
||||
PendingEntryFactory pendingEntryFactory;
|
||||
EntityLogMongoService entityLogMongoService;
|
||||
|
||||
|
||||
@ -211,7 +211,7 @@ public class EntityLogMergeService {
|
||||
return unprocessedManualRedactions.getEntriesToAdd()
|
||||
.stream()
|
||||
.filter(manualAdd -> !manualAdd.isLocal())
|
||||
.map(pendingDictionaryEntryFactory::buildAddToDictionaryEntry);
|
||||
.map(pendingEntryFactory::buildAddToDictionaryEntry);
|
||||
}
|
||||
|
||||
|
||||
@ -239,11 +239,11 @@ public class EntityLogMergeService {
|
||||
if (dictionaryChange instanceof ManualRedactionEntry) {
|
||||
return null; // pending dictionaries are inserted before the manual changes loop
|
||||
} else if (dictionaryChange instanceof IdRemoval idRemoval) {
|
||||
return pendingDictionaryEntryFactory.buildRemoveFromDictionary(idRemoval, entityLogEntry);
|
||||
return pendingEntryFactory.buildRemoveFromDictionary(idRemoval, entityLogEntry);
|
||||
} else if (dictionaryChange instanceof ManualResizeRedaction manualResizeRedaction) {
|
||||
return pendingDictionaryEntryFactory.buildResizeWithDictionary(manualResizeRedaction, entityLogEntry);
|
||||
return pendingEntryFactory.buildResizeWithDictionary(manualResizeRedaction, entityLogEntry);
|
||||
} else if (dictionaryChange instanceof ManualRecategorization manualRecategorization) {
|
||||
return pendingDictionaryEntryFactory.buildRecategorizeWithDictionary(manualRecategorization, entityLogEntry);
|
||||
return pendingEntryFactory.buildRecategorizeWithDictionary(manualRecategorization, entityLogEntry);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("Manual change of type %s has no defined dictionary action!", dictionaryChange.getClass()));
|
||||
}
|
||||
@ -484,7 +484,7 @@ public class EntityLogMergeService {
|
||||
&& (entityLogEntry.getEntryType().equals(EntryType.IMAGE) || entityLogEntry.getEntryType().equals(EntryType.IMAGE_HINT))) {
|
||||
|
||||
addChanges(entityLogEntry, changes);
|
||||
return pendingDictionaryEntryFactory.buildPendingImageRecategorizationEntry(recategorization, entityLogEntry);
|
||||
return pendingEntryFactory.buildPendingImageRecategorizationEntry(recategorization, entityLogEntry);
|
||||
}
|
||||
|
||||
entityLogEntry.getEngines().add(Engine.MANUAL);
|
||||
|
||||
@ -52,6 +52,7 @@ import com.iqser.red.service.persistence.management.v1.processor.utils.FileModel
|
||||
import com.iqser.red.service.persistence.management.v1.processor.utils.StorageIdUtils;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.AnalyzeRequest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.AnalyzeResult;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.BulkLocalRequest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttribute;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.MessageType;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.NerServiceRequest;
|
||||
@ -60,6 +61,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemp
|
||||
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.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.manual.AddRedactionBulkLocalRequestModel;
|
||||
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.knecon.fforesight.databasetenantcommons.providers.utils.MagicConverter;
|
||||
@ -216,6 +218,31 @@ public class FileStatusService {
|
||||
}
|
||||
|
||||
|
||||
protected void addSearchTermOccurrencesAnalysisRequestToAnalysisQueue(FileEntity fileStatus, BulkLocalRequest bulkLocalRequest) {
|
||||
|
||||
var dossierId = fileStatus.getDossierId();
|
||||
var dossier = dossierPersistenceService.getAndValidateDossier(dossierId);
|
||||
var fileId = fileStatus.getId();
|
||||
int analysisVersion = fileStatus.getAnalysisVersion();
|
||||
|
||||
MessageType searchBulkLocalTerm = MessageType.SEARCH_BULK_LOCAL_TERM;
|
||||
log.info("Add file: {} from dossier {} to Analysis queue with MessageType {}", fileId, dossierId, searchBulkLocalTerm);
|
||||
|
||||
var analyseRequest = AnalyzeRequest.builder()
|
||||
.analysisNumber(analysisVersion)
|
||||
.messageType(searchBulkLocalTerm)
|
||||
.dossierId(dossierId)
|
||||
.fileId(fileId)
|
||||
.dossierTemplateId(dossier.getDossierTemplateId())
|
||||
.bulkLocalRequest(bulkLocalRequest)
|
||||
.build();
|
||||
|
||||
rabbitTemplate.convertAndSend(MessagingConfiguration.REDACTION_PRIORITY_REQUEST_EXCHANGE, TenantContext.getTenantId(), analyseRequest);
|
||||
|
||||
websocketService.sendAnalysisEvent(dossierId, fileId, AnalyseStatus.BULK_LOCAL_REDACTIONS_PROCESSING, analysisVersion);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
protected void addToAnalysisQueue(String dossierId, String fileId, boolean priority, Set<Integer> sectionsToReanalyse, boolean manualRedactionReanalyse) {
|
||||
|
||||
@ -983,4 +1010,27 @@ public class FileStatusService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void setStatusBulkLocalRedactionsProcessing(String dossierId, String fileId, AddRedactionBulkLocalRequestModel addRedactionBulkLocalRequestModel) {
|
||||
|
||||
FileEntity fileStatus = fileStatusPersistenceService.getStatus(fileId);
|
||||
|
||||
if (fileStatus.isExcluded()) {
|
||||
log.debug("File {} is excluded", fileStatus.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
fileStatusPersistenceService.updateProcessingStatus(fileId, ProcessingStatus.BULK_LOCAL_REDACTIONS_PROCESSING);
|
||||
BulkLocalRequest bulkLocalRequest = BulkLocalRequest.builder()
|
||||
.searchTerm(addRedactionBulkLocalRequestModel.getValue())
|
||||
.type(addRedactionBulkLocalRequestModel.getType())
|
||||
.reason(addRedactionBulkLocalRequestModel.getReason())
|
||||
.legalBasis(addRedactionBulkLocalRequestModel.getLegalBasis())
|
||||
.section(addRedactionBulkLocalRequestModel.getSection())
|
||||
.pageNumbers(addRedactionBulkLocalRequestModel.getPageNumbers())
|
||||
.build();
|
||||
addSearchTermOccurrencesAnalysisRequestToAnalysisQueue(fileStatus, bulkLocalRequest);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -71,6 +71,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.entitymapped.ManualResizeRedaction;
|
||||
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.FileModel;
|
||||
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.ForceRedactionRequestModel;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.LegalBasisChangeRequestModel;
|
||||
@ -111,7 +112,7 @@ public class ManualRedactionService {
|
||||
ManualRedactionMapper manualRedactionMapper;
|
||||
RabbitTemplate rabbitTemplate;
|
||||
EntityLogMergeService entityLogMergeService;
|
||||
PendingDictionaryEntryFactory pendingDictionaryEntryFactory;
|
||||
PendingEntryFactory pendingEntryFactory;
|
||||
|
||||
|
||||
@Transactional
|
||||
@ -135,7 +136,7 @@ public class ManualRedactionService {
|
||||
manualRedactionDictionaryUpdateHandler.validateDictionariesForAdd(addRedactionRequest, addRedactionRequest.getValue());
|
||||
validatePositions(fileId, addRedactionRequest);
|
||||
|
||||
String annotationId = hashFunction.hashString(fileId + addRedactionRequest, StandardCharsets.UTF_8).toString();
|
||||
String annotationId = hashString(fileId + addRedactionRequest);
|
||||
|
||||
ManualRedactionEntryEntity manualRedactionEntryEntity = addRedactionPersistenceService.insert(fileId, annotationId, addRedactionRequest);
|
||||
manualRedactionEntryEntities.add(manualRedactionEntryEntity);
|
||||
@ -154,9 +155,9 @@ public class ManualRedactionService {
|
||||
getAnalysisNumber(dossierId, fileId),
|
||||
dossierEntity);
|
||||
} else {
|
||||
entityLogEntry = pendingDictionaryEntryFactory.buildAddToDictionaryEntry(MagicConverter.convert(manualRedactionEntryEntity,
|
||||
ManualRedactionEntry.class,
|
||||
new ManualRedactionEntryMapper()));
|
||||
entityLogEntry = pendingEntryFactory.buildAddToDictionaryEntry(MagicConverter.convert(manualRedactionEntryEntity,
|
||||
ManualRedactionEntry.class,
|
||||
new ManualRedactionEntryMapper()));
|
||||
}
|
||||
Long commentId = commentService.addCommentAndGetId(fileId, annotationId, addRedactionRequest.getComment(), addRedactionRequest.getUser());
|
||||
response.add(ManualAddResponse.builder().annotationId(annotationId).commentId(commentId).entityLogEntry(entityLogEntry).build());
|
||||
@ -254,7 +255,7 @@ public class ManualRedactionService {
|
||||
if (!idRemoval.isRemoveFromAllDossiers() && !idRemoval.isRemoveFromDictionary()) {
|
||||
entityLogMergeService.mergeIdToRemove(MagicConverter.convert(idRemoval, IdRemoval.class), entityLogEntry, getAnalysisNumber(dossierId, fileId));
|
||||
} else {
|
||||
entityLogEntry = pendingDictionaryEntryFactory.buildRemoveFromDictionary(MagicConverter.convert(idRemoval, IdRemoval.class), entityLogEntry);
|
||||
entityLogEntry = pendingEntryFactory.buildRemoveFromDictionary(MagicConverter.convert(idRemoval, IdRemoval.class), entityLogEntry);
|
||||
}
|
||||
response.add(ManualAddResponse.builder().annotationId(removeRedactionRequest.getAnnotationId()).commentId(commentId).entityLogEntry(entityLogEntry).build());
|
||||
}
|
||||
@ -413,9 +414,9 @@ public class ManualRedactionService {
|
||||
entityLogEntry = entry;
|
||||
}
|
||||
} else {
|
||||
entityLogEntry = pendingDictionaryEntryFactory.buildRecategorizeWithDictionary(MagicConverter.convert(recategorizationEntity,
|
||||
ManualRecategorization.class,
|
||||
new ManualRecategorizationMapper()), entityLogEntry);
|
||||
entityLogEntry = pendingEntryFactory.buildRecategorizeWithDictionary(MagicConverter.convert(recategorizationEntity,
|
||||
ManualRecategorization.class,
|
||||
new ManualRecategorizationMapper()), entityLogEntry);
|
||||
}
|
||||
response.add(ManualAddResponse.builder().annotationId(recategorizationRequest.getAnnotationId()).commentId(commentId).entityLogEntry(entityLogEntry).build());
|
||||
|
||||
@ -474,9 +475,9 @@ public class ManualRedactionService {
|
||||
entityLogEntry,
|
||||
getAnalysisNumber(dossierId, fileId));
|
||||
} else {
|
||||
entityLogEntry = pendingDictionaryEntryFactory.buildResizeWithDictionary(MagicConverter.convert(resizeRedaction,
|
||||
ManualResizeRedaction.class,
|
||||
new ManualResizeRedactionMapper()), entityLogEntry);
|
||||
entityLogEntry = pendingEntryFactory.buildResizeWithDictionary(MagicConverter.convert(resizeRedaction,
|
||||
ManualResizeRedaction.class,
|
||||
new ManualResizeRedactionMapper()), entityLogEntry);
|
||||
}
|
||||
response.add(ManualAddResponse.builder().annotationId(resizeRedactionRequest.getAnnotationId()).commentId(commentId).entityLogEntry(entityLogEntry).build());
|
||||
}
|
||||
@ -699,4 +700,16 @@ public class ManualRedactionService {
|
||||
return analysisNumber.orElseThrow(() -> new BadRequestException("Can't load latest analysis number"));
|
||||
}
|
||||
|
||||
|
||||
public String getPendingBulkLocalAnnotationId(String fileId, AddRedactionBulkLocalRequestModel addRedactionBulkLocalRequestModel) {
|
||||
|
||||
return hashString(fileId + addRedactionBulkLocalRequestModel);
|
||||
}
|
||||
|
||||
|
||||
private String hashString(String input) {
|
||||
|
||||
return hashFunction.hashString(input, StandardCharsets.UTF_8).toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package com.iqser.red.service.persistence.management.v1.processor.service.manualredactions;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -9,11 +11,14 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRedactionEntryEntity;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Engine;
|
||||
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.EntryState;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntryType;
|
||||
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.model.analysislog.entitylog.Position;
|
||||
@ -24,9 +29,11 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations
|
||||
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.dossiertemplate.type.DictionaryEntryType;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionBulkLocalRequestModel;
|
||||
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
|
||||
|
||||
@Service
|
||||
public class PendingDictionaryEntryFactory {
|
||||
public class PendingEntryFactory {
|
||||
|
||||
private static String shortenValueIfNecessary(String value) {
|
||||
|
||||
@ -96,6 +103,42 @@ public class PendingDictionaryEntryFactory {
|
||||
}
|
||||
|
||||
|
||||
public EntityLogEntry buildAddRedactionBulkLocalEntry(AddRedactionBulkLocalRequestModel addRedactionBulkLocalRequestModel) {
|
||||
|
||||
var manualChanges = List.of(ManualChange.builder()
|
||||
.manualRedactionType(ManualRedactionType.ADD)
|
||||
.requestedDate(OffsetDateTime.now())
|
||||
.processedDate(null)
|
||||
.userId(KeycloakSecurity.getUserId())
|
||||
.propertyChanges(Map.of("value", addRedactionBulkLocalRequestModel.getValue()))
|
||||
.build());
|
||||
|
||||
return EntityLogEntry.builder()
|
||||
.id("")
|
||||
.value(addRedactionBulkLocalRequestModel.getValue())
|
||||
.type(addRedactionBulkLocalRequestModel.getType())
|
||||
.entryType(EntryType.ENTITY)
|
||||
.state(EntryState.PENDING)
|
||||
.reason(addRedactionBulkLocalRequestModel.getReason())
|
||||
.legalBasis(addRedactionBulkLocalRequestModel.getLegalBasis())
|
||||
.matchedRule("")
|
||||
.containingNodeId(Collections.emptyList())
|
||||
.closestHeadline("")
|
||||
.section(addRedactionBulkLocalRequestModel.getSection())
|
||||
.positions(convertPositions(addRedactionBulkLocalRequestModel.getPositions()))
|
||||
.textAfter("")
|
||||
.textBefore("")
|
||||
.startOffset(-1)
|
||||
.endOffset(-1)
|
||||
.changes(Collections.emptyList())
|
||||
.manualChanges(manualChanges)
|
||||
.engines(Set.of(Engine.MANUAL))
|
||||
.reference(Collections.emptySet())
|
||||
.importedRedactionIntersections(Collections.emptySet())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
private List<Position> convertPositions(List<Rectangle> rectangles) {
|
||||
|
||||
return rectangles.stream()
|
||||
@ -0,0 +1,123 @@
|
||||
package com.iqser.red.service.persistence.management.v1.processor.service.queue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.model.websocket.AnalyseStatus;
|
||||
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.persistence.AuditPersistenceService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.websocket.WebsocketService;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.AuditCategory;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.BulkLocalResponse;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position;
|
||||
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.Rectangle;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.audit.AuditRequest;
|
||||
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.manual.AddRedactionRequestModel;
|
||||
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
|
||||
public class SearchTermOccurrencesResponseReceiver {
|
||||
|
||||
public static final String SEARCH_BULK_LOCAL_TERM_RESPONSE_LISTENER = "search-bulk-local-term-response-listener";
|
||||
|
||||
ObjectMapper objectMapper;
|
||||
|
||||
DossierManagementService dossierManagementService;
|
||||
ManualRedactionService manualRedactionService;
|
||||
AuditPersistenceService auditPersistenceService;
|
||||
FileStatusPersistenceService fileStatusPersistenceService;
|
||||
WebsocketService webSocketService;
|
||||
|
||||
|
||||
@RabbitHandler
|
||||
@RabbitListener(id = SEARCH_BULK_LOCAL_TERM_RESPONSE_LISTENER)
|
||||
public void receive(Message message) throws IOException {
|
||||
|
||||
BulkLocalResponse response = objectMapper.readValue(message.getBody(), new TypeReference<>() {
|
||||
});
|
||||
|
||||
if (message.getMessageProperties().isRedelivered()) {
|
||||
throw new AmqpRejectAndDontRequeueException(String.format("Error during last processing of bulk local term search for file %s in dossier %s, do not retry.",
|
||||
response.getFileId(),
|
||||
response.getDossierId()));
|
||||
}
|
||||
|
||||
receive(response);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void receive(BulkLocalResponse response) {
|
||||
|
||||
var dossier = dossierManagementService.getDossierById(response.getDossierId(), false, false);
|
||||
|
||||
Set<AddRedactionRequestModel> addRedactionRequests = response.getPositions()
|
||||
.stream()
|
||||
.map(positions -> AddRedactionRequestModel.builder()
|
||||
.type(response.getType())
|
||||
.value(response.getSearchTerm())
|
||||
.reason(response.getReason())
|
||||
.legalBasis(response.getLegalBasis())
|
||||
.positions(convertPositions(positions))
|
||||
.section(response.getSection())
|
||||
.build())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
log.info("Received manual redaction requests for file {} in dossier {} after term search", response.getFileId(), dossier.getId());
|
||||
|
||||
List<ManualAddResponse> manualAddResponses = manualRedactionService.addAddRedaction(response.getDossierId(), response.getFileId(), addRedactionRequests, dossier);
|
||||
manualAddResponses.forEach(manualAddResponse -> auditPersistenceService.audit(AuditRequest.builder()
|
||||
.userId(KeycloakSecurity.getUserId())
|
||||
.objectId(response.getFileId())
|
||||
.category(AuditCategory.DOCUMENT.name())
|
||||
.message("Manual annotation was added.")
|
||||
.details(Map.of("dossierId",
|
||||
response.getDossierId(),
|
||||
"fileId",
|
||||
response.getFileId(),
|
||||
"annotationId",
|
||||
manualAddResponse.getAnnotationId()))
|
||||
.build()));
|
||||
|
||||
fileStatusPersistenceService.updateProcessingStatus(response.getFileId(), ProcessingStatus.PROCESSED);
|
||||
int analysisVersion = fileStatusPersistenceService.getStatus(response.getFileId()).getAnalysisVersion();
|
||||
webSocketService.sendAnalysisEvent(response.getDossierId(),
|
||||
response.getFileId(),
|
||||
AnalyseStatus.BULK_LOCAL_REDACTIONS_PROCESSED, analysisVersion);
|
||||
log.info("Finished adding all manual redactions, the file is processed again");
|
||||
|
||||
}
|
||||
|
||||
|
||||
private List<Rectangle> convertPositions(List<Position> positions) {
|
||||
|
||||
return positions.stream()
|
||||
.map(position -> Rectangle.builder().page(position.getPageNumber()).height(position.h()).width(position.w()).topLeftX(position.x()).topLeftY(position.y()).build())
|
||||
.toList();
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,6 +17,7 @@ import static com.iqser.red.service.persistence.management.v1.processor.service.
|
||||
import static com.iqser.red.service.persistence.management.v1.processor.service.queue.OCRProcessingMessageReceiver.OCR_RESPONSE_LISTENER_ID;
|
||||
import static com.iqser.red.service.persistence.management.v1.processor.service.queue.OCRProcessingMessageReceiver.OCR_STATUS_UPDATE_LISTENER_ID;
|
||||
import static com.iqser.red.service.persistence.management.v1.processor.service.queue.RedactionAnalysisResponseReceiver.REDACTION_RESPONSE_LISTENER_ID;
|
||||
import static com.iqser.red.service.persistence.management.v1.processor.service.queue.SearchTermOccurrencesResponseReceiver.SEARCH_BULK_LOCAL_TERM_RESPONSE_LISTENER;
|
||||
import static com.iqser.red.service.persistence.management.v1.processor.service.queue.VisualLayoutParsingMessageReceiver.VISUAL_LAYOUT_PARSING_RESPONSE_LISTENER_ID;
|
||||
|
||||
import java.util.Map;
|
||||
@ -78,6 +79,13 @@ public class TenantExchangeMessageReceiverImpl extends TenantExchangeMessageRece
|
||||
.dlqName(REDACTION_DLQ)
|
||||
.arguments(Map.of("x-max-priority", 2))
|
||||
.build(),
|
||||
TenantQueueConfiguration.builder()
|
||||
.listenerId(SEARCH_BULK_LOCAL_TERM_RESPONSE_LISTENER)
|
||||
.exchangeName(SEARCH_BULK_LOCAL_TERM_RESPONSE_EXCHANGE)
|
||||
.queuePrefix(SEARCH_BULK_LOCAL_TERM_RESPONSE_QUEUE_PREFIX)
|
||||
.dlqName(SEARCH_BULK_LOCAL_TERM_DLQ)
|
||||
.arguments(Map.of("x-max-priority", 2))
|
||||
.build(),
|
||||
TenantQueueConfiguration.builder()
|
||||
.listenerId(PDFTRON_RESPONSE_LISTENER_ID)
|
||||
.exchangeName(PDFTRON_RESPONSE_EXCHANGE)
|
||||
|
||||
@ -34,7 +34,7 @@ import com.iqser.red.service.persistence.management.v1.processor.service.EntityL
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.ManualRedactionProviderService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.PendingDictionaryEntryFactory;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.PendingEntryFactory;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DictionaryPersistenceService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierTemplatePersistenceService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
|
||||
@ -103,7 +103,7 @@ public class EntityLogMergeTest {
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
|
||||
entityLogMergeService = new EntityLogMergeService(dictionaryPersistenceService, new PendingDictionaryEntryFactory(), entityLogMongoService);
|
||||
entityLogMergeService = new EntityLogMergeService(dictionaryPersistenceService, new PendingEntryFactory(), entityLogMongoService);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -3,8 +3,11 @@ package com.iqser.red.service.peristence.v1.server.integration.tests;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -29,6 +32,7 @@ public class EntityLogMongoServiceTest extends AbstractPersistenceServerServiceT
|
||||
private final String ENTITY_LOG2 = "files/entity-log/6f2a9d4b5d4e11211fc0d7732fd45b78.ENTITY_LOG.json";
|
||||
private final String ENTITY_LOG3_BEFORE = "files/entity-log/c3b23116f2d277170d303bfc6fb82e6a-before.ENTITY_LOG.json";
|
||||
private final String ENTITY_LOG3_AFTER = "files/entity-log/c3b23116f2d277170d303bfc6fb82e6a-after.ENTITY_LOG.json";
|
||||
private final String ENTITY_LOG_LOCAL_BULK = "files/entity-log/local-bulk-test.ENTITY_LOG.json";
|
||||
private final String ENTITY_LOG_WITH_CHANGES = "files/entity-log/entitylog-with-changes.json";
|
||||
|
||||
private static final String TEST_DOSSIER_ID = "91ce8e90-9aec-473c-b8c3-cbe16443ad34";
|
||||
@ -326,4 +330,70 @@ public class EntityLogMongoServiceTest extends AbstractPersistenceServerServiceT
|
||||
assertEquals(response.getEntityLogEntry().size(), 14);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void testEntityLogMongoServiceMethodsForLocalBulk() {
|
||||
|
||||
var file = new ClassPathResource(ENTITY_LOG_LOCAL_BULK);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.registerModule(new JavaTimeModule());
|
||||
|
||||
EntityLog entityLog = objectMapper.readValue(file.getInputStream(), EntityLog.class);
|
||||
|
||||
entityLogMongoService.saveEntityLog(TEST_DOSSIER_ID, TEST_FILE1_ID, entityLog);
|
||||
|
||||
String akessonValue = "Akesson";
|
||||
Set<String> akessonSet = entityLogMongoService.findEntryIdsOfManualsWithValue(akessonValue);
|
||||
assertEquals(akessonSet.size(), 3);
|
||||
|
||||
float[] akessonRectangle = {322.63608f, 308.1f, 41.375977f, 12.642f};
|
||||
Set<String> akessonSetByPositions = entityLogMongoService.findEntryIdsOfManualsWithPositionRectangle(akessonRectangle);
|
||||
assertEquals(akessonSetByPositions.size(), 3);
|
||||
|
||||
Set<String> akessonSetFilterQuery = entityLogMongoService.findEntryIdsByMatchingFullPositionAndEngineManualWithFilters(akessonRectangle,
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet());
|
||||
assertEquals(akessonSetFilterQuery.size(), 3);
|
||||
|
||||
Set<String> akessonSetFilterQueryByPositions = entityLogMongoService.findEntryIdsByValueAndEngineManualWithFilters(akessonValue,
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet());
|
||||
assertEquals(akessonSetFilterQueryByPositions.size(), 3);
|
||||
|
||||
akessonSetFilterQuery = entityLogMongoService.findEntryIdsByMatchingFullPositionAndEngineManualWithFilters(akessonRectangle,
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet(),
|
||||
Set.of(1, 3));
|
||||
assertEquals(akessonSetFilterQuery.size(), 2);
|
||||
|
||||
akessonSetFilterQueryByPositions = entityLogMongoService.findEntryIdsByValueAndEngineManualWithFilters(akessonValue,
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet(),
|
||||
Set.of(1, 3));
|
||||
assertEquals(akessonSetFilterQueryByPositions.size(), 2);
|
||||
|
||||
String baldridgeValue = "Baldridge";
|
||||
Set<String> baldridgeSet = entityLogMongoService.findEntryIdsByValueAndEngineManualWithFilters(baldridgeValue,
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet());
|
||||
assertEquals(baldridgeSet.size(), 4);
|
||||
|
||||
Set<String> baldridgeSetWithTypeFilter = entityLogMongoService.findEntryIdsByValueAndEngineManualWithFilters(baldridgeValue,
|
||||
Set.of("CBI_author", "Test"),
|
||||
Collections.emptySet(),
|
||||
Collections.emptySet());
|
||||
assertEquals(baldridgeSetWithTypeFilter.size(), 2);
|
||||
|
||||
Set<String> baldridgeSetWithLegalBasesFilter = entityLogMongoService.findEntryIdsByValueAndEngineManualWithFilters(baldridgeValue,
|
||||
Set.of("CBI_author", "Test"),
|
||||
Set.of("Test"),
|
||||
Collections.emptySet());
|
||||
assertEquals(baldridgeSetWithLegalBasesFilter.size(), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -66,7 +66,9 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemp
|
||||
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.LegalBasisChangeRequestModel;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RecategorizationBulkLocalRequestModel;
|
||||
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.RemoveRedactionBulkLocalRequestModel;
|
||||
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.redactionlog.Point;
|
||||
@ -1736,26 +1738,34 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
|
||||
entityLogMongoService.upsertEntityLog(file.getDossierId(), file.getFileId(), entityLog);
|
||||
|
||||
ManualRedactionResponse forceResponse = manualRedactionClient.forceRedactionBulk(dossier.getId(),
|
||||
file.getId(),
|
||||
Set.of(ForceRedactionRequestModel.builder().annotationId("forceRedactionAnnotation").comment("comment").legalBasis("1").build()));
|
||||
file.getId(),
|
||||
Set.of(ForceRedactionRequestModel.builder()
|
||||
.annotationId("forceRedactionAnnotation")
|
||||
.comment("comment")
|
||||
.legalBasis("1")
|
||||
.build()));
|
||||
|
||||
var allManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), false, true);
|
||||
assertEquals(allManualRedactions.getForceRedactions().size(), 1);
|
||||
assertFalse(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation")));
|
||||
assertTrue(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals(forceResponse.getManualAddResponses().get(0).getAnnotationId())));
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation")));
|
||||
assertTrue(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId()
|
||||
.equals(forceResponse.getManualAddResponses()
|
||||
.get(0).getAnnotationId())));
|
||||
|
||||
var unprocessedManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), true, true);
|
||||
assertEquals(unprocessedManualRedactions.getForceRedactions().size(), 1);
|
||||
assertFalse(unprocessedManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation")));
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation")));
|
||||
assertTrue(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals(forceResponse.getManualAddResponses().get(0).getAnnotationId())));
|
||||
.anyMatch(entry -> entry.getAnnotationId()
|
||||
.equals(forceResponse.getManualAddResponses()
|
||||
.get(0).getAnnotationId())));
|
||||
|
||||
fileProcessingClient.analysisSuccessful(dossier.getId(),
|
||||
file.getId(),
|
||||
@ -1768,32 +1778,42 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
|
||||
.build());
|
||||
|
||||
ManualRedactionResponse forceResponse2 = manualRedactionClient.forceRedactionBulk(dossier.getId(),
|
||||
file.getId(),
|
||||
Set.of(ForceRedactionRequestModel.builder().annotationId("forceRedactionAnnotation2").comment("comment").legalBasis("1").build()));
|
||||
file.getId(),
|
||||
Set.of(ForceRedactionRequestModel.builder()
|
||||
.annotationId("forceRedactionAnnotation2")
|
||||
.comment("comment")
|
||||
.legalBasis("1")
|
||||
.build()));
|
||||
|
||||
allManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), false, true);
|
||||
assertEquals(allManualRedactions.getForceRedactions().size(), 2);
|
||||
assertFalse(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation")));
|
||||
assertTrue(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals(forceResponse.getManualAddResponses().get(0).getAnnotationId())));
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation")));
|
||||
assertTrue(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId()
|
||||
.equals(forceResponse.getManualAddResponses()
|
||||
.get(0).getAnnotationId())));
|
||||
assertFalse(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation2")));
|
||||
assertTrue(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals(forceResponse2.getManualAddResponses().get(0).getAnnotationId())));
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation2")));
|
||||
assertTrue(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId()
|
||||
.equals(forceResponse2.getManualAddResponses()
|
||||
.get(0).getAnnotationId())));
|
||||
|
||||
unprocessedManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), true, true);
|
||||
assertEquals(unprocessedManualRedactions.getForceRedactions().size(), 1);
|
||||
assertFalse(unprocessedManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation2")));
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation2")));
|
||||
assertTrue(unprocessedManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals(forceResponse2.getManualAddResponses().get(0).getAnnotationId())));
|
||||
.anyMatch(entry -> entry.getAnnotationId()
|
||||
.equals(forceResponse2.getManualAddResponses()
|
||||
.get(0).getAnnotationId())));
|
||||
|
||||
fileProcessingClient.analysisSuccessful(dossier.getId(),
|
||||
file.getId(),
|
||||
@ -1812,13 +1832,17 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation")));
|
||||
assertTrue(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals(forceResponse.getManualAddResponses().get(0).getAnnotationId())));
|
||||
.anyMatch(entry -> entry.getAnnotationId()
|
||||
.equals(forceResponse.getManualAddResponses()
|
||||
.get(0).getAnnotationId())));
|
||||
assertFalse(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals("forceRedactionAnnotation2")));
|
||||
assertTrue(allManualRedactions.getForceRedactions()
|
||||
.stream()
|
||||
.anyMatch(entry -> entry.getAnnotationId().equals(forceResponse2.getManualAddResponses().get(0).getAnnotationId())));
|
||||
.anyMatch(entry -> entry.getAnnotationId()
|
||||
.equals(forceResponse2.getManualAddResponses()
|
||||
.get(0).getAnnotationId())));
|
||||
|
||||
unprocessedManualRedactions = manualRedactionClient.getManualRedactions(dossier.getId(), file.getId(), true, true);
|
||||
assertTrue(unprocessedManualRedactions.getForceRedactions().isEmpty());
|
||||
@ -2576,10 +2600,12 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
|
||||
List.of(entityLogEntry),
|
||||
List.of(new EntityLogLegalBasis("1.1 personal data (incl. geolocation); Article 39(e)(3)",
|
||||
"desc",
|
||||
"Article 39(e)(3) of Regulation (EC) No 178/2002",""),
|
||||
"Article 39(e)(3) of Regulation (EC) No 178/2002",
|
||||
""),
|
||||
new EntityLogLegalBasis("4. commercial information",
|
||||
"desc 2",
|
||||
"Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)","")),
|
||||
"Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)",
|
||||
"")),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@ -2646,10 +2672,12 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
|
||||
List.of(entityLogEntry),
|
||||
List.of(new EntityLogLegalBasis("1.1 personal data (incl. geolocation); Article 39(e)(3)",
|
||||
"desc",
|
||||
"Article 39(e)(3) of Regulation (EC) No 178/2002", ""),
|
||||
"Article 39(e)(3) of Regulation (EC) No 178/2002",
|
||||
""),
|
||||
new EntityLogLegalBasis("4. commercial information",
|
||||
"desc 2",
|
||||
"Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)","")),
|
||||
"Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)",
|
||||
"")),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@ -3186,4 +3214,122 @@ public class ManualRedactionTest extends AbstractPersistenceServerServiceTest {
|
||||
assertTrue(result.getMessage().contains("Maximum number of remove from dictionary requests is 100."));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBulkLocal() {
|
||||
|
||||
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
|
||||
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
|
||||
var file = fileTesterAndProvider.testAndProvideFile(dossier);
|
||||
|
||||
var type1 = typeProvider.testAndProvideType(dossierTemplate, dossier, "test1", false, 70);
|
||||
var type2 = typeProvider.testAndProvideType(dossierTemplate, dossier, "test2", false, 71);
|
||||
var type3 = typeProvider.testAndProvideType(dossierTemplate, dossier, "test3", false, 72);
|
||||
var newType = typeProvider.testAndProvideType(dossierTemplate, dossier, "newType", false, 73);
|
||||
|
||||
List<EntityLogEntry> entityLogEntries = new ArrayList<>();
|
||||
String legal3 = "Legal 3";
|
||||
String darthVader = "Darth Vader";
|
||||
for (int i = 0; i < 101; i++) {
|
||||
entityLogEntries.add(EntityLogEntry.builder()
|
||||
.id("AnnotationId1" + i)
|
||||
.type(type1.getType())
|
||||
.value("Luke Skywalker" + i)
|
||||
.entryType(EntryType.ENTITY)
|
||||
.state(EntryState.APPLIED)
|
||||
.section("section")
|
||||
.legalBasis("Legal 1")
|
||||
.engines(Set.of(Engine.MANUAL))
|
||||
.build());
|
||||
entityLogEntries.add(EntityLogEntry.builder()
|
||||
.id("AnnotationId2" + i)
|
||||
.type(type2.getType())
|
||||
.value(darthVader)
|
||||
.entryType(EntryType.ENTITY)
|
||||
.state(EntryState.APPLIED)
|
||||
.section("section")
|
||||
.legalBasis("Legal 2")
|
||||
.engines(Set.of(Engine.MANUAL))
|
||||
.build());
|
||||
entityLogEntries.add(EntityLogEntry.builder()
|
||||
.id("AnnotationId3" + i)
|
||||
.type(type3.getType())
|
||||
.value(darthVader)
|
||||
.entryType(EntryType.ENTITY)
|
||||
.state(EntryState.APPLIED)
|
||||
.section("section")
|
||||
.legalBasis(legal3)
|
||||
.engines(Set.of(Engine.MANUAL))
|
||||
.build());
|
||||
}
|
||||
var entityLog = new EntityLog(1, 1, entityLogEntries, null, 0, 0, 0, 0);
|
||||
fileManagementStorageService.saveEntityLog(dossier.getId(), file.getId(), entityLog);
|
||||
|
||||
when(entityLogService.getEntityLog(any(), any(), anyBoolean())).thenReturn(entityLog);
|
||||
|
||||
String newLegal = "new Legal";
|
||||
String otherSection = "other section";
|
||||
ManualRedactionResponse manualRedactionResponse = manualRedactionClient.recategorizeBulkLocal(dossier.getId(),
|
||||
file.getId(),
|
||||
RecategorizationBulkLocalRequestModel.builder()
|
||||
.rectangle(false)
|
||||
.type(newType.getType())
|
||||
.legalBasis(newLegal)
|
||||
.section(otherSection)
|
||||
.value("Luke Skywalker37")
|
||||
.build(),
|
||||
false);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses().size(), 1);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses()
|
||||
.get(0).getEntityLogEntry().getType(), newType.getType());
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses()
|
||||
.get(0).getEntityLogEntry().getLegalBasis(), newLegal);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses()
|
||||
.get(0).getEntityLogEntry().getSection(), otherSection);
|
||||
|
||||
manualRedactionResponse = manualRedactionClient.recategorizeBulkLocal(dossier.getId(),
|
||||
file.getId(),
|
||||
RecategorizationBulkLocalRequestModel.builder()
|
||||
.rectangle(false)
|
||||
.type(newType.getType())
|
||||
.legalBasis(newLegal)
|
||||
.section(otherSection)
|
||||
.value(darthVader)
|
||||
.originLegalBases(Set.of(legal3))
|
||||
.build(),
|
||||
false);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses().size(), 101);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses()
|
||||
.get(1).getEntityLogEntry().getType(), newType.getType());
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses()
|
||||
.get(29).getEntityLogEntry().getLegalBasis(), newLegal);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses()
|
||||
.get(79).getEntityLogEntry().getSection(), otherSection);
|
||||
|
||||
manualRedactionResponse = manualRedactionClient.recategorizeBulkLocal(dossier.getId(),
|
||||
file.getId(),
|
||||
RecategorizationBulkLocalRequestModel.builder()
|
||||
.rectangle(false)
|
||||
.type(newType.getType())
|
||||
.legalBasis(newLegal)
|
||||
.section(otherSection)
|
||||
.value(darthVader)
|
||||
.originTypes(Set.of(type2.getType()))
|
||||
.build(),
|
||||
false);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses().size(), 101);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses()
|
||||
.get(0).getEntityLogEntry().getType(), newType.getType());
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses()
|
||||
.get(36).getEntityLogEntry().getLegalBasis(), newLegal);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses()
|
||||
.get(98).getEntityLogEntry().getSection(), otherSection);
|
||||
|
||||
manualRedactionResponse = manualRedactionClient.removeRedactionBulkLocal(dossier.getId(),
|
||||
file.getId(),
|
||||
RemoveRedactionBulkLocalRequestModel.builder().rectangle(false).value(darthVader).build(),
|
||||
false);
|
||||
assertEquals(manualRedactionResponse.getManualAddResponses().size(), 202);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
package com.iqser.red.service.peristence.v1.server.integration.tests;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.iqser.red.service.pdftron.redaction.v1.api.model.RedactionResultMessage;
|
||||
import com.iqser.red.service.peristence.v1.server.integration.client.DossierClient;
|
||||
import com.iqser.red.service.peristence.v1.server.integration.client.DownloadClient;
|
||||
import com.iqser.red.service.peristence.v1.server.integration.client.FileClient;
|
||||
import com.iqser.red.service.peristence.v1.server.integration.client.ReportTemplateClient;
|
||||
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.FileTesterAndProvider;
|
||||
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.persistence.management.v1.processor.entity.annotations.ManualRedactionEntryEntity;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.model.DownloadJob;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.download.DownloadCompressionMessageReceiver;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.download.DownloadReportMessageReceiver;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.download.RedactionResultMessageReceiver;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.job.DownloadReadyJob;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.PendingEntryFactory;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DownloadStatusPersistenceService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.annotationentity.ManualRedactionRepository;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.queue.SearchTermOccurrencesResponseReceiver;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.BulkLocalResponse;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierRequest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierTemplateModel;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatus;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.PrepareDownloadWithOptionRequest;
|
||||
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.Position;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle;
|
||||
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.ReportTemplate;
|
||||
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.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.download.DownloadStatus;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.download.DownloadStatusValue;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionBulkLocalRequestModel;
|
||||
import com.iqser.red.service.redaction.report.v1.api.model.ReportResultMessage;
|
||||
import com.iqser.red.service.redaction.report.v1.api.model.StoredFileInformation;
|
||||
import com.iqser.red.storage.commons.service.StorageService;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantcommons.model.TenantResponse;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||
public class SearchTermOccurrencesTest extends AbstractPersistenceServerServiceTest {
|
||||
|
||||
@Autowired
|
||||
FileTesterAndProvider fileTesterAndProvider;
|
||||
@Autowired
|
||||
DossierTesterAndProvider dossierTesterAndProvider;
|
||||
@Autowired
|
||||
DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;
|
||||
@Autowired
|
||||
TypeProvider typeProvider;
|
||||
@Autowired
|
||||
SearchTermOccurrencesResponseReceiver searchTermOccurrencesResponseReceiver;
|
||||
@Autowired
|
||||
FileStatusPersistenceService fileStatusPersistenceService;
|
||||
@Autowired
|
||||
ManualRedactionRepository manualRedactionRepository;
|
||||
@Autowired
|
||||
PendingEntryFactory pendingEntryFactory;
|
||||
|
||||
|
||||
@Test
|
||||
public void testBulkLocal() {
|
||||
|
||||
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
|
||||
var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
|
||||
var file = fileTesterAndProvider.testAndProvideFile(dossier);
|
||||
var type = typeProvider.testAndProvideType(dossierTemplate, dossier, "test", false, 70);
|
||||
|
||||
fileStatusPersistenceService.updateProcessingStatus(file.getFileId(), ProcessingStatus.BULK_LOCAL_REDACTIONS_PROCESSING);
|
||||
|
||||
searchTermOccurrencesResponseReceiver.receive(BulkLocalResponse.builder()
|
||||
.fileId(file.getId())
|
||||
.dossierId(dossier.getId())
|
||||
.searchTerm("searchTerm")
|
||||
.type(type.getType())
|
||||
.legalBasis("legalBasis")
|
||||
.reason("reason")
|
||||
.section("section")
|
||||
.positions(List.of(List.of(new Position(new float[]{1f, 2f, 3f, 4f}, 1))))
|
||||
.build());
|
||||
|
||||
List<ManualRedactionEntryEntity> newEntries = manualRedactionRepository.findByFileIdAndOptions(file.getId(), false, false, false);
|
||||
assertEquals(newEntries.size(), 1);
|
||||
assertEquals(newEntries.get(0).getValue(), "searchTerm");
|
||||
assertEquals(newEntries.get(0).getLegalBasis(), "legalBasis");
|
||||
assertEquals(newEntries.get(0).getReason(), "reason");
|
||||
assertEquals(newEntries.get(0).getSection(), "section");
|
||||
assertEquals(fileStatusPersistenceService.getStatus(file.getId()).getProcessingStatus(), ProcessingStatus.PROCESSED);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPendingEntryCreation() {
|
||||
|
||||
AddRedactionBulkLocalRequestModel addRedactionBulkLocalRequestModel = AddRedactionBulkLocalRequestModel.builder()
|
||||
.value("Max")
|
||||
.type("123")
|
||||
.legalBasis("legalbasis")
|
||||
.reason("reason")
|
||||
.section("section")
|
||||
.positions(List.of(new Rectangle(333.92593f, 446.8f, 19.152008f, 11.81175f, 1)))
|
||||
.build();
|
||||
EntityLogEntry entityLogEntry = pendingEntryFactory.buildAddRedactionBulkLocalEntry(addRedactionBulkLocalRequestModel);
|
||||
List<Position> positions = convertPositions(addRedactionBulkLocalRequestModel.getPositions());
|
||||
assertEquals(entityLogEntry.getPositions().get(0), positions.get(0));
|
||||
assertEquals(entityLogEntry.getValue(), addRedactionBulkLocalRequestModel.getValue());
|
||||
assertEquals(entityLogEntry.getLegalBasis(), addRedactionBulkLocalRequestModel.getLegalBasis());
|
||||
assertEquals(entityLogEntry.getReason(), addRedactionBulkLocalRequestModel.getReason());
|
||||
assertEquals(entityLogEntry.getSection(), addRedactionBulkLocalRequestModel.getSection());
|
||||
|
||||
}
|
||||
|
||||
|
||||
private List<Position> convertPositions(List<Rectangle> rectangles) {
|
||||
|
||||
return rectangles.stream()
|
||||
.map(rectangle -> new Position(rectangle.getTopLeftX(), rectangle.getTopLeftY(), rectangle.getWidth(), rectangle.getHeight(), rectangle.getPage()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -38,5 +38,7 @@ public class AnalyzeRequest {
|
||||
@Builder.Default
|
||||
private List<ComponentMappingMetadata> componentMappings = new ArrayList<>();
|
||||
|
||||
private BulkLocalRequest bulkLocalRequest;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.model;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BulkLocalRequest {
|
||||
|
||||
@NonNull
|
||||
private String searchTerm;
|
||||
|
||||
@NonNull
|
||||
private String type;
|
||||
|
||||
@NonNull
|
||||
private String reason;
|
||||
|
||||
private String legalBasis;
|
||||
|
||||
private String section;
|
||||
|
||||
@Builder.Default
|
||||
private Set<Integer> pageNumbers = Collections.emptySet();
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BulkLocalResponse {
|
||||
|
||||
@NonNull
|
||||
private String dossierId;
|
||||
|
||||
@NonNull
|
||||
private String fileId;
|
||||
|
||||
@NonNull
|
||||
private String searchTerm;
|
||||
|
||||
@NonNull
|
||||
private String type;
|
||||
|
||||
@NonNull
|
||||
private String reason;
|
||||
|
||||
private String legalBasis;
|
||||
|
||||
private String section;
|
||||
|
||||
@NonNull
|
||||
@Builder.Default
|
||||
private List<List<Position>> positions = new ArrayList<>();
|
||||
|
||||
}
|
||||
@ -5,5 +5,6 @@ public enum MessageType {
|
||||
ANALYSE,
|
||||
REANALYSE,
|
||||
SURROUNDING_TEXT_ANALYSIS,
|
||||
IMPORTED_REDACTIONS_ONLY
|
||||
IMPORTED_REDACTIONS_ONLY,
|
||||
SEARCH_BULK_LOCAL_TERM
|
||||
}
|
||||
|
||||
@ -19,5 +19,6 @@ public enum ProcessingStatus {
|
||||
PRE_PROCESSED,
|
||||
FIGURE_DETECTION_ANALYZING,
|
||||
TABLE_PARSING_ANALYZING,
|
||||
VISUAL_LAYOUT_PARSING_ANALYZING
|
||||
VISUAL_LAYOUT_PARSING_ANALYZING,
|
||||
BULK_LOCAL_REDACTIONS_PROCESSING
|
||||
}
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.model.manual;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class AddRedactionBulkLocalRequestModel {
|
||||
|
||||
@NonNull
|
||||
private String type;
|
||||
|
||||
@NonNull
|
||||
private String value;
|
||||
|
||||
@NonNull
|
||||
private String reason;
|
||||
|
||||
private String legalBasis;
|
||||
|
||||
private String section;
|
||||
|
||||
@NonNull
|
||||
@Builder.Default
|
||||
private List<Rectangle> positions = new ArrayList<>();
|
||||
|
||||
@Builder.Default
|
||||
private Set<Integer> pageNumbers = Collections.emptySet();
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.model.manual;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ForceRedactionBulkLocalRequestModel {
|
||||
|
||||
@NonNull
|
||||
private String annotationId;
|
||||
|
||||
@NonNull
|
||||
private String value;
|
||||
|
||||
private String legalBasis;
|
||||
|
||||
private boolean rectangle;
|
||||
|
||||
private Position position;
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.model.manual;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RecategorizationBulkLocalRequestModel {
|
||||
|
||||
private String value;
|
||||
|
||||
private String type;
|
||||
private String legalBasis;
|
||||
private String section;
|
||||
|
||||
private boolean rectangle;
|
||||
|
||||
private Position position;
|
||||
|
||||
@Builder.Default
|
||||
private Set<String> originTypes = Collections.emptySet();
|
||||
|
||||
@Builder.Default
|
||||
private Set<String> originLegalBases = Collections.emptySet();
|
||||
|
||||
@Builder.Default
|
||||
private Set<Integer> pageNumbers = Collections.emptySet();
|
||||
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.model.manual;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RemoveRedactionBulkLocalRequestModel {
|
||||
|
||||
private String value;
|
||||
|
||||
private boolean rectangle;
|
||||
|
||||
private Position position;
|
||||
|
||||
|
||||
@Builder.Default
|
||||
private Set<String> originTypes = Collections.emptySet();
|
||||
|
||||
@Builder.Default
|
||||
private Set<String> originLegalBases = Collections.emptySet();
|
||||
|
||||
@Builder.Default
|
||||
private Set<Integer> pageNumbers = Collections.emptySet();
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface EntityLogEntryDocumentCustomRepository {
|
||||
|
||||
List<String> findEntryIdsByValueAndEngineManualWithFilters(String value, Set<String> originTypes, Set<String> originLegalBases, Set<Integer> pageNumbers);
|
||||
|
||||
|
||||
List<String> findEntryIdsByMatchingPositionAndEngineManualWithFilters(float[] rectangle, Set<String> originTypes, Set<String> originLegalBases, Set<Integer> pageNumbers);
|
||||
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.EntityLogEntryDocument;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
@Repository
|
||||
@AllArgsConstructor
|
||||
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||
public class EntityLogEntryDocumentCustomRepositoryImpl implements EntityLogEntryDocumentCustomRepository {
|
||||
|
||||
MongoTemplate mongoTemplate;
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> findEntryIdsByValueAndEngineManualWithFilters(String value, Set<String> originTypes, Set<String> originLegalBases, Set<Integer> pageNumbers) {
|
||||
|
||||
Query query = new Query();
|
||||
List<Criteria> criteriaList = new ArrayList<>();
|
||||
|
||||
criteriaList.add(Criteria.where("value").is(value));
|
||||
|
||||
addCommonCriteria(originTypes, originLegalBases, pageNumbers, criteriaList);
|
||||
|
||||
Criteria mergedCriteria = new Criteria().andOperator(criteriaList.toArray(new Criteria[0]));
|
||||
query.addCriteria(mergedCriteria);
|
||||
|
||||
return executeQuery(query);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> findEntryIdsByMatchingPositionAndEngineManualWithFilters(float[] rectangle,
|
||||
Set<String> originTypes,
|
||||
Set<String> originLegalBases,
|
||||
Set<Integer> pageNumbers) {
|
||||
|
||||
Query query = new Query();
|
||||
List<Criteria> criteriaList = new ArrayList<>();
|
||||
|
||||
criteriaList.add(Criteria.where("positions").elemMatch(Criteria.where("rectangle").is(rectangle)));
|
||||
|
||||
addCommonCriteria(originTypes, originLegalBases, pageNumbers, criteriaList);
|
||||
|
||||
Criteria mergedCriteria = new Criteria().andOperator(criteriaList.toArray(new Criteria[0]));
|
||||
query.addCriteria(mergedCriteria);
|
||||
|
||||
return executeQuery(query);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private void addCommonCriteria(Set<String> originTypes, Set<String> originLegalBases, Set<Integer> pageNumbers, List<Criteria> criteriaList) {
|
||||
|
||||
criteriaList.add(Criteria.where("engines").is("MANUAL"));
|
||||
|
||||
if (originTypes != null && !originTypes.isEmpty()) {
|
||||
criteriaList.add(Criteria.where("type").in(originTypes));
|
||||
}
|
||||
|
||||
if (originLegalBases != null && !originLegalBases.isEmpty()) {
|
||||
criteriaList.add(Criteria.where("legalBasis").in(originLegalBases));
|
||||
}
|
||||
|
||||
if (pageNumbers != null && !pageNumbers.isEmpty()) {
|
||||
Criteria positionsCriteria = Criteria.where("positions").elemMatch(Criteria.where("pageNumber").in(pageNumbers));
|
||||
criteriaList.add(positionsCriteria);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<String> executeQuery(Query query) {
|
||||
|
||||
query.fields().include("entryId").exclude("id");
|
||||
|
||||
return mongoTemplate.find(query, EntityLogEntryDocument.class)
|
||||
.stream()
|
||||
.map(EntityLogEntryDocument::getEntryId)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@ -68,4 +68,16 @@ public interface EntityLogEntryDocumentRepository extends MongoRepository<Entity
|
||||
@Query(value = "{ 'entityLogId': ?0, 'engines': 'IMPORTED' }", exists = true)
|
||||
boolean existsByEntityLogIdAndEngineImported(String entityLogId);
|
||||
|
||||
|
||||
@Query(value = "{ 'value': ?0, 'engines': 'MANUAL' }", fields = "{ 'entryId': 1, 'id': 0 }")
|
||||
List<String> findEntryIdsByValueAndEngineManual(String value);
|
||||
|
||||
|
||||
@Query(value = "{ 'positions': { $elemMatch: { 'pageNumber': ?0, 'rectangle': ?1 } }, 'engines': 'MANUAL' }", fields = "{ 'entryId': 1, 'id': 0 }")
|
||||
List<String> findEntryIdsByMatchingFullPositionAndEngineManual(int pageNumber, float[] rectangle);
|
||||
|
||||
|
||||
@Query(value = "{ 'positions': { $elemMatch: { 'rectangle': ?0 } }, 'engines': 'MANUAL' }", fields = "{ 'entryId': 1, 'id': 0 }")
|
||||
List<String> findEntryIdsByMatchingPositionAndEngineManual(float[] rectangle);
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.iqser.red.service.persistence.service.v1.api.shared.mongo.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -16,27 +17,23 @@ import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.En
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.exception.DocumentNotFoundException;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.mapper.EntityLogDocumentMapper;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.EntityLogDocumentRepository;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.EntityLogEntryDocumentCustomRepository;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.EntityLogEntryDocumentRepository;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class EntityLogMongoService {
|
||||
|
||||
private final EntityLogDocumentRepository entityLogDocumentRepository;
|
||||
private final EntityLogEntryDocumentRepository entityLogEntryDocumentRepository;
|
||||
private final EntityLogDocumentUpdateService entityLogDocumentUpdateService;
|
||||
private final EntityLogEntryDocumentCustomRepository entityLogEntryDocumentCustomRepository;
|
||||
|
||||
private final EntityLogDocumentMapper mapper = EntityLogDocumentMapper.INSTANCE;
|
||||
|
||||
|
||||
public EntityLogMongoService(EntityLogDocumentRepository entityLogDocumentRepository,
|
||||
EntityLogEntryDocumentRepository entityLogEntryDocumentRepository,
|
||||
EntityLogDocumentUpdateService entityLogDocumentUpdateService) {
|
||||
|
||||
this.entityLogDocumentRepository = entityLogDocumentRepository;
|
||||
this.entityLogEntryDocumentRepository = entityLogEntryDocumentRepository;
|
||||
this.entityLogDocumentUpdateService = entityLogDocumentUpdateService;
|
||||
}
|
||||
|
||||
|
||||
public void insertEntityLog(String dossierId, String fileId, EntityLog entityLog) {
|
||||
|
||||
EntityLogDocument entityLogDocument = entityLogDocumentRepository.insert(mapper.toLogDocument(dossierId, fileId, entityLog));
|
||||
@ -340,4 +337,34 @@ public class EntityLogMongoService {
|
||||
return entityLogEntryDocumentRepository.existsByEntityLogIdAndEngineImported(entityLogId);
|
||||
}
|
||||
|
||||
|
||||
public Set<String> findEntryIdsOfManualsWithValue(String value) {
|
||||
|
||||
return new HashSet<>(entityLogEntryDocumentRepository.findEntryIdsByValueAndEngineManual(value));
|
||||
}
|
||||
|
||||
|
||||
public Set<String> findEntryIdsOfManualsWithPositionRectangle(float[] rectangle) {
|
||||
|
||||
return new HashSet<>(entityLogEntryDocumentRepository.findEntryIdsByMatchingPositionAndEngineManual(rectangle));
|
||||
}
|
||||
|
||||
|
||||
public Set<String> findEntryIdsByValueAndEngineManualWithFilters(String value, Set<String> originTypes, Set<String> originLegalBases, Set<Integer> pageNumbers) {
|
||||
|
||||
return new HashSet<>(entityLogEntryDocumentCustomRepository.findEntryIdsByValueAndEngineManualWithFilters(value, originTypes, originLegalBases, pageNumbers));
|
||||
}
|
||||
|
||||
|
||||
public Set<String> findEntryIdsByMatchingFullPositionAndEngineManualWithFilters(float[] rectangle,
|
||||
Set<String> originTypes,
|
||||
Set<String> originLegalBases,
|
||||
Set<Integer> pageNumbers) {
|
||||
|
||||
return new HashSet<>(entityLogEntryDocumentCustomRepository.findEntryIdsByMatchingPositionAndEngineManualWithFilters(rectangle,
|
||||
originTypes,
|
||||
originLegalBases,
|
||||
pageNumbers));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user