RED-7838: merge numberOfComments into EntityLog #198
@ -28,8 +28,9 @@ import com.iqser.red.service.persistence.service.v1.api.external.resource.Manual
|
||||
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.annotations.AddRedactionRequest;
|
||||
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;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comments;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ForceRedactionRequest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.LegalBasisChangeRequest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualAddResponse;
|
||||
@ -99,14 +100,15 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
.message("Comment was removed.")
|
||||
.details(Map.of(DOSSIER_ID, dossierId, FILE_ID, fileId, ANNOTATION_ID, annotationId))
|
||||
.build());
|
||||
commentService.deleteComment(dossierId, fileId, List.of(Long.valueOf(commentId)));
|
||||
commentService.deleteComment(fileId, List.of(Long.valueOf(commentId)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + READ_MANUAL_REDACTIONS + "')")
|
||||
public ManualRedactions getManualRedactions(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId,
|
||||
public ManualRedactions getManualRedactions(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestParam(value = "unprocessed", required = false, defaultValue = FALSE) boolean unprocessed) {
|
||||
|
||||
return manualRedactionService.getManualRedactions(fileId, unprocessed);
|
||||
@ -115,12 +117,13 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + READ_MANUAL_REDACTIONS + "')")
|
||||
public Comments getComments(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId) {
|
||||
public AnnotationComments getComments(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @PathVariable(ANNOTATION_ID) String annotationId) {
|
||||
|
||||
dossierManagementService.getDossierById(dossierId, false, false);
|
||||
fileStatusManagementService.getFileStatus(fileId, false);
|
||||
|
||||
return commentService.getComments(fileId);
|
||||
List<Comment> comments = commentService.getComments(fileId, annotationId);
|
||||
return new AnnotationComments(comments);
|
||||
}
|
||||
|
||||
|
||||
@ -134,10 +137,7 @@ public class ManualRedactionController implements ManualRedactionResource {
|
||||
accessControlService.verifyFileIsNotApproved(dossierId, fileId);
|
||||
accessControlService.verifyUserIsReviewerOrApprover(dossierId, fileId);
|
||||
|
||||
var response = commentService.addComment(dossierId,
|
||||
fileId,
|
||||
annotationId,
|
||||
CommentRequest.builder().user(KeycloakSecurity.getUserId()).text(addCommentRequest.getText()).build());
|
||||
var response = commentService.addComment(fileId, annotationId, CommentRequest.builder().user(KeycloakSecurity.getUserId()).text(addCommentRequest.getText()).build());
|
||||
|
||||
auditPersistenceService.audit(AuditRequest.builder()
|
||||
.userId(KeycloakSecurity.getUserId())
|
||||
|
||||
@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.CommentResponse;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comments;
|
||||
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.ManualAddResponse;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddCommentRequestModel;
|
||||
@ -131,16 +131,17 @@ public interface ManualRedactionResource {
|
||||
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@GetMapping(value = MANUAL_REDACTION_REST_PATH + DOSSIER_ID_PATH_PARAM + FILE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Returns the manual redactions", description = "If the unprocessed flag is true then only the unprocessed manual redactions are returned. If the flag is false" +
|
||||
"all manual redactions are returned. Default value for the flag is false.")
|
||||
@Operation(summary = "Returns the manual redactions", description = "If the unprocessed flag is true then only the unprocessed manual redactions are returned. If the flag is false" + "all manual redactions are returned. Default value for the flag is false.")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
ManualRedactions getManualRedactions(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @RequestParam(value = "unprocessed", required = false, defaultValue = FALSE) boolean unprocessed);
|
||||
ManualRedactions getManualRedactions(@PathVariable(DOSSIER_ID) String dossierId,
|
||||
@PathVariable(FILE_ID) String fileId,
|
||||
@RequestParam(value = "unprocessed", required = false, defaultValue = FALSE) boolean unprocessed);
|
||||
|
||||
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@GetMapping(value = MANUAL_REDACTION_REST_PATH + "/comments" + DOSSIER_ID_PATH_PARAM + FILE_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Returns the comments for a specific file", description = "None")
|
||||
@GetMapping(value = MANUAL_REDACTION_REST_PATH + "/comments" + DOSSIER_ID_PATH_PARAM + FILE_ID_PATH_VARIABLE + ANNOTATION_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Returns the comments for a specific annotation in a specific file", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
Comments getComments(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId);
|
||||
AnnotationComments getComments(@PathVariable(DOSSIER_ID) String dossierId, @PathVariable(FILE_ID) String fileId, @PathVariable(ANNOTATION_ID) String annotationId);
|
||||
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist
|
||||
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.CommentPersistenceService;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comment;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.CommentRequest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comments;
|
||||
import com.knecon.fforesight.databasetenantcommons.providers.utils.MagicConverter;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
@ -35,69 +34,34 @@ public class CommentService {
|
||||
|
||||
|
||||
@Transactional
|
||||
public void deleteComment(String dossierId, String fileId, List<Long> commentIds) {
|
||||
public void deleteComment(String fileId, List<Long> commentIds) {
|
||||
|
||||
for (var commentId : commentIds) {
|
||||
commentPersistenceService.softDelete(commentId, OffsetDateTime.now());
|
||||
}
|
||||
// update indicator
|
||||
fileStatusPersistenceService.updateHasComments(fileId, commentPersistenceService.fileHasComments(fileId));
|
||||
|
||||
// Since entityLog does not have comments, no need to trigger reprocess or to store them
|
||||
// // This is an ugly workaround, don't even look at it!
|
||||
// // Basically we should change how comments work and not merge them into the redaction log.
|
||||
// // if file is currently not analyzing, we can quickly change the redaction log, else we must wait for the analysis to finish.
|
||||
// if (!fileStatusService.getStatus(fileId).getProcessingStatus().equals(ProcessingStatus.PROCESSED)) {
|
||||
// reprocess(dossierId, fileId);
|
||||
// return;
|
||||
// }
|
||||
// fileStatusService.setStatusProcessing(fileId);
|
||||
// RedactionLog redactionLog = redactionLogService.getRedactionLog(dossierId, fileId);
|
||||
// redactionLog.getRedactionLogEntry().forEach(entry -> entry.getComments().removeIf(comment -> commentIds.contains(comment.getId())));
|
||||
// fileManagementStorageService.storeRedactionLog(dossierId, fileId, redactionLog);
|
||||
// fileStatusService.setStatusProcessed(fileId);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public Comments getComments(String fileId) {
|
||||
public Map<String, List<Comment>> getComments(String fileId) {
|
||||
|
||||
return new Comments(commentPersistenceService.findCommentsByFileID(fileId, false)
|
||||
return commentPersistenceService.findCommentsByFileID(fileId, false)
|
||||
.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, entry -> MagicConverter.convert(entry.getValue(), Comment.class, getDeltaMapper()))));
|
||||
}
|
||||
|
||||
|
||||
private static BiConsumer<CommentEntity, Comment> getDeltaMapper() {
|
||||
|
||||
return (c1, c2) -> c2.setUserId(c1.getUser());
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, entry -> toCommentList(entry.getValue())));
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public CommentEntity addComment(String dossierId, String fileId, String annotationId, CommentRequest commentRequest) {
|
||||
public CommentEntity addComment(String fileId, String annotationId, CommentRequest commentRequest) {
|
||||
|
||||
checkComment(commentRequest.getText());
|
||||
CommentEntity createdComment = addComment(fileId, annotationId, commentRequest.getText(), commentRequest.getUser());
|
||||
|
||||
fileStatusPersistenceService.updateHasComments(fileId, true);
|
||||
|
||||
// Since entityLog does not have comments, no need to trigger reprocess or to store them
|
||||
// // This is an ugly workaround, don't even look at it!
|
||||
// // Basically we should change how comments work and not merge them into the redaction log.
|
||||
// if (!fileStatusService.getStatus(fileId).getProcessingStatus().equals(ProcessingStatus.PROCESSED)) {
|
||||
// reprocess(dossierId, fileId);
|
||||
// return createdComment;
|
||||
// }
|
||||
// fileStatusService.setStatusProcessing(fileId);
|
||||
// RedactionLog redactionLog = redactionLogService.getRedactionLog(dossierId, fileId);
|
||||
// redactionLog.getRedactionLogEntry()
|
||||
// .stream()
|
||||
// .filter(entry -> entry.getId().equals(annotationId))
|
||||
// .forEach(entry -> entry.getComments().add(MagicConverter.convert(createdComment, RedactionLogComment.class)));
|
||||
// fileManagementStorageService.storeRedactionLog(dossierId, fileId, redactionLog);
|
||||
// fileStatusService.setStatusProcessed(fileId);
|
||||
return createdComment;
|
||||
}
|
||||
|
||||
@ -141,10 +105,34 @@ public class CommentService {
|
||||
commentPersistenceService.hardDelete(fileId, annotationId);
|
||||
}
|
||||
|
||||
//
|
||||
// private void reprocess(String dossierId, String fileId) {
|
||||
//
|
||||
// fileStatusService.setStatusReprocessForManual(dossierId, fileId, true);
|
||||
// }
|
||||
|
||||
public List<Comment> getComments(String fileId, String annotationId) {
|
||||
|
||||
return toCommentList(commentPersistenceService.findCommentsByAnnotationId(fileId, annotationId, false));
|
||||
}
|
||||
|
||||
|
||||
private static List<Comment> toCommentList(List<CommentEntity> entity) {
|
||||
|
||||
return entity.stream().map(CommentService::toComment).toList();
|
||||
}
|
||||
|
||||
|
||||
private static Comment toComment(CommentEntity entity) {
|
||||
|
||||
return MagicConverter.convert(entity, Comment.class, getDeltaMapper());
|
||||
}
|
||||
|
||||
|
||||
private static BiConsumer<CommentEntity, Comment> getDeltaMapper() {
|
||||
|
||||
return (c1, c2) -> c2.setUserId(c1.getUser());
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Integer> getCommentCounts(String fileId) {
|
||||
|
||||
return commentPersistenceService.findCommentsByFileID(fileId, false).entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().size()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -12,14 +13,18 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog
|
||||
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.FilteredEntityLogRequest;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||
public class EntityLogService {
|
||||
|
||||
private final FileManagementStorageService fileManagementStorageService;
|
||||
private final FileStatusService fileStatusService;
|
||||
FileManagementStorageService fileManagementStorageService;
|
||||
FileStatusService fileStatusService;
|
||||
CommentService commentService;
|
||||
|
||||
|
||||
public EntityLog getEntityLog(String dossierId, String fileId) {
|
||||
@ -32,19 +37,22 @@ public class EntityLogService {
|
||||
|
||||
var fileStatus = fileStatusService.getStatus(fileId);
|
||||
|
||||
EntityLog redactionLog;
|
||||
EntityLog entityLog;
|
||||
|
||||
redactionLog = fileManagementStorageService.getEntityLog(dossierId, fileId);
|
||||
entityLog = fileManagementStorageService.getEntityLog(dossierId, fileId);
|
||||
|
||||
if (fileStatus.isExcluded()) {
|
||||
redactionLog.setEntityLogEntry(new ArrayList<>());
|
||||
entityLog.setEntityLogEntry(new ArrayList<>());
|
||||
}
|
||||
|
||||
if (excludedTypes != null) {
|
||||
redactionLog.getEntityLogEntry().removeIf(entry -> excludedTypes.contains(entry.getType()));
|
||||
entityLog.getEntityLogEntry().removeIf(entry -> excludedTypes.contains(entry.getType()));
|
||||
}
|
||||
|
||||
return redactionLog;
|
||||
Map<String, Integer> commentCountPerAnnotationId = commentService.getCommentCounts(fileId);
|
||||
entityLog.getEntityLogEntry().forEach(entityLogEntry -> entityLogEntry.setNumberOfComments(commentCountPerAnnotationId.getOrDefault(entityLogEntry.getId(), 0)));
|
||||
|
||||
return entityLog;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -23,7 +23,6 @@ import com.iqser.red.service.persistence.management.v1.processor.service.persist
|
||||
import com.iqser.red.service.persistence.management.v1.processor.utils.ManualImageRecategorizationMapper;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.utils.ManualRedactionMapper;
|
||||
import com.iqser.red.service.persistence.management.v1.processor.utils.ManualResizeRedactionMapper;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comments;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.IdRemoval;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualForceRedaction;
|
||||
|
||||
@ -11,7 +11,7 @@ import com.iqser.red.service.persistence.management.v1.processor.entity.annotati
|
||||
|
||||
public interface CommentRepository extends JpaRepository<CommentEntity, Long> {
|
||||
|
||||
@Query("select e from CommentEntity e where e.fileId = :fileId and e.annotationId = :annotationId " + "and (:includeDeletions = true or e.softDeletedTime is null)")
|
||||
@Query("select e from CommentEntity e where e.fileId = :fileId and e.annotationId = :annotationId and (:includeDeletions = true or e.softDeletedTime is null)")
|
||||
List<CommentEntity> findByFileIdAndAnnotationId(String fileId, String annotationId, boolean includeDeletions);
|
||||
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ public class EntityLogEntry {
|
||||
List<Integer> containingNodeId;
|
||||
String closestHeadline;
|
||||
String section;
|
||||
|
||||
|
||||
float[] color;
|
||||
|
||||
@Builder.Default
|
||||
@ -71,4 +71,6 @@ public class EntityLogEntry {
|
||||
@Builder.Default
|
||||
Set<String> importedRedactionIntersections = new HashSet<>();
|
||||
|
||||
int numberOfComments;
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package com.iqser.red.service.persistence.service.v1.api.shared.model.annotations;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@ -12,8 +11,8 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Comments {
|
||||
public class AnnotationComments {
|
||||
|
||||
Map<String, List<Comment>> comments;
|
||||
List<Comment> comments;
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user