Merge branch 'RED-8586' into 'master'
RED-8586 - Fix confidentiality rules Closes RED-8586 See merge request redactmanager/redaction-service!294
This commit is contained in:
commit
89dea4138a
@ -26,10 +26,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@FieldDefaults(makeFinal=true, level= AccessLevel.PRIVATE)
|
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||||
public class EntityChangeLogService {
|
public class EntityChangeLogService {
|
||||||
|
|
||||||
|
|
||||||
@Timed("redactmanager_computeChanges")
|
@Timed("redactmanager_computeChanges")
|
||||||
public boolean computeChanges(List<EntityLogEntry> previousEntityLogEntries, List<EntityLogEntry> newEntityLogEntries, ManualRedactions manualRedactions, int analysisNumber) {
|
public boolean computeChanges(List<EntityLogEntry> previousEntityLogEntries, List<EntityLogEntry> newEntityLogEntries, ManualRedactions manualRedactions, int analysisNumber) {
|
||||||
|
|
||||||
@ -42,7 +41,9 @@ public class EntityChangeLogService {
|
|||||||
boolean hasChanges = false;
|
boolean hasChanges = false;
|
||||||
|
|
||||||
for (EntityLogEntry entityLogEntry : newEntityLogEntries) {
|
for (EntityLogEntry entityLogEntry : newEntityLogEntries) {
|
||||||
Optional<EntityLogEntry> optionalPreviousEntity = previousEntityLogEntries.stream().filter(entry -> entry.getId().equals(entityLogEntry.getId())).findAny();
|
Optional<EntityLogEntry> optionalPreviousEntity = previousEntityLogEntries.stream()
|
||||||
|
.filter(entry -> entry.getId().equals(entityLogEntry.getId()))
|
||||||
|
.findAny();
|
||||||
if (optionalPreviousEntity.isEmpty()) {
|
if (optionalPreviousEntity.isEmpty()) {
|
||||||
hasChanges = true;
|
hasChanges = true;
|
||||||
entityLogEntry.getChanges().add(new Change(analysisNumber, ChangeType.ADDED, now));
|
entityLogEntry.getChanges().add(new Change(analysisNumber, ChangeType.ADDED, now));
|
||||||
@ -63,15 +64,22 @@ public class EntityChangeLogService {
|
|||||||
|
|
||||||
|
|
||||||
private void addRemovedEntriesAsRemoved(List<EntityLogEntry> previousEntityLogEntries,
|
private void addRemovedEntriesAsRemoved(List<EntityLogEntry> previousEntityLogEntries,
|
||||||
List<EntityLogEntry> newEntityLogEntries,
|
List<EntityLogEntry> newEntityLogEntries,
|
||||||
ManualRedactions manualRedactions,
|
ManualRedactions manualRedactions,
|
||||||
int analysisNumber,
|
int analysisNumber,
|
||||||
OffsetDateTime now) {
|
OffsetDateTime now) {
|
||||||
|
|
||||||
Set<String> existingIds = newEntityLogEntries.stream().map(EntityLogEntry::getId).collect(Collectors.toSet());
|
Set<String> existingIds = newEntityLogEntries.stream()
|
||||||
|
.map(EntityLogEntry::getId)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
List<EntityLogEntry> removedEntries = previousEntityLogEntries.stream()
|
List<EntityLogEntry> removedEntries = previousEntityLogEntries.stream()
|
||||||
.filter(entry -> !existingIds.contains(entry.getId()))
|
.filter(entry -> !existingIds.contains(entry.getId()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<EntityLogEntry> removedDossierRedaction = removedEntries.stream()
|
||||||
|
.filter(e -> e.getState() == EntryState.REMOVED && e.getType().equals("dossier_redaction"))
|
||||||
.toList();
|
.toList();
|
||||||
|
previousEntityLogEntries.removeAll(removedDossierRedaction);
|
||||||
|
removedEntries.removeAll(removedDossierRedaction);
|
||||||
removedEntries.forEach(entry -> entry.getChanges().add(new Change(analysisNumber, ChangeType.REMOVED, now)));
|
removedEntries.forEach(entry -> entry.getChanges().add(new Change(analysisNumber, ChangeType.REMOVED, now)));
|
||||||
removedEntries.forEach(entry -> entry.setState(EntryState.REMOVED));
|
removedEntries.forEach(entry -> entry.setState(EntryState.REMOVED));
|
||||||
removedEntries.forEach(entry -> addManualChangeForDictionaryRemovals(entry, manualRedactions));
|
removedEntries.forEach(entry -> addManualChangeForDictionaryRemovals(entry, manualRedactions));
|
||||||
@ -85,13 +93,15 @@ public class EntityChangeLogService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
manualRedactions.getIdsToRemove().stream()
|
manualRedactions.getIdsToRemove()
|
||||||
|
.stream()
|
||||||
.filter(IdRemoval::isRemoveFromDictionary)//
|
.filter(IdRemoval::isRemoveFromDictionary)//
|
||||||
.filter(removed -> removed.getAnnotationId().equals(entry.getId()))//
|
.filter(removed -> removed.getAnnotationId().equals(entry.getId()))//
|
||||||
.findFirst()//
|
.findFirst()//
|
||||||
.ifPresent(idRemove -> entry.getManualChanges().add(ManualChangeFactory.toManualChange(idRemove, false)));
|
.ifPresent(idRemove -> entry.getManualChanges().add(ManualChangeFactory.toManualChange(idRemove, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private ChangeType calculateChangeType(EntryState state, EntryState previousState) {
|
private ChangeType calculateChangeType(EntryState state, EntryState previousState) {
|
||||||
|
|
||||||
if (state.equals(previousState)) {
|
if (state.equals(previousState)) {
|
||||||
|
|||||||
@ -125,7 +125,7 @@ public class EntityLogCreatorService {
|
|||||||
.stream()
|
.stream()
|
||||||
.filter(entry -> (newEntityIds.contains(entry.getId()) || entry.getContainingNodeId().isEmpty() || sectionsToReanalyseIds.contains(entry.getContainingNodeId()
|
.filter(entry -> (newEntityIds.contains(entry.getId()) || entry.getContainingNodeId().isEmpty() || sectionsToReanalyseIds.contains(entry.getContainingNodeId()
|
||||||
.get(0))))
|
.get(0))))
|
||||||
.toList();
|
.collect(Collectors.toList());
|
||||||
previousEntityLog.getEntityLogEntry().removeAll(previousEntriesFromReAnalyzedSections);
|
previousEntityLog.getEntityLogEntry().removeAll(previousEntriesFromReAnalyzedSections);
|
||||||
|
|
||||||
boolean hasChanges = entityChangeLogService.computeChanges(previousEntriesFromReAnalyzedSections,
|
boolean hasChanges = entityChangeLogService.computeChanges(previousEntriesFromReAnalyzedSections,
|
||||||
|
|||||||
@ -692,13 +692,22 @@ rule "ETC.3.1: Redact logos (vertebrate study)"
|
|||||||
|
|
||||||
|
|
||||||
// Rule unit: ETC.5
|
// Rule unit: ETC.5
|
||||||
rule "ETC.5.0: Ignore dossier_redaction entries if confidentiality is not 'confidential'"
|
rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidential'"
|
||||||
|
when
|
||||||
|
FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
|
then
|
||||||
|
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
|
||||||
|
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Confidentiality", value == "confidential")
|
not FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
then
|
then
|
||||||
$dossierRedaction.ignore("ETC.5.0", "Ignore dossier redactions, when not confidential");
|
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
|
||||||
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
retract($dossierRedaction);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1150,13 +1150,22 @@ rule "ETC.4.2: Redact dossier dictionary entries"
|
|||||||
|
|
||||||
|
|
||||||
// Rule unit: ETC.5
|
// Rule unit: ETC.5
|
||||||
rule "ETC.5.0: Ignore dossier_redaction entries if confidentiality is not 'confidential'"
|
rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidential'"
|
||||||
|
when
|
||||||
|
FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
|
then
|
||||||
|
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
|
||||||
|
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Confidentiality", value == "confidential")
|
not FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
then
|
then
|
||||||
$dossierRedaction.ignore("ETC.5.0", "Ignore dossier redactions, when not confidential");
|
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
|
||||||
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
retract($dossierRedaction);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -802,13 +802,22 @@ rule "ETC.4.0: Redact dossier dictionary entries"
|
|||||||
|
|
||||||
|
|
||||||
// Rule unit: ETC.5
|
// Rule unit: ETC.5
|
||||||
rule "ETC.5.0: Ignore dossier_redaction entries if confidentiality is not 'confidential'"
|
rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidential'"
|
||||||
|
when
|
||||||
|
FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
|
then
|
||||||
|
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
|
||||||
|
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Confidentiality", value == "confidential")
|
not FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
then
|
then
|
||||||
$dossierRedaction.ignore("ETC.5.0", "Ignore dossier redactions, when not confidential");
|
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
|
||||||
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
retract($dossierRedaction);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -449,14 +449,22 @@ rule "ETC.3.1: Redact logos (non vertebrate study)"
|
|||||||
|
|
||||||
|
|
||||||
// Rule unit: ETC.5
|
// Rule unit: ETC.5
|
||||||
rule "ETC.5.0: Ignore dossier_redaction entries if confidentiality is not 'confidential'"
|
rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidential'"
|
||||||
|
when
|
||||||
|
FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
|
then
|
||||||
|
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
|
||||||
|
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Confidentiality", value == "confidential")
|
not FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
then
|
then
|
||||||
$dossierRedaction.ignore("ETC.5.0", "Ignore dossier redactions, when not confidential");
|
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
|
||||||
update($dossierRedaction);
|
retract($dossierRedaction);
|
||||||
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1159,13 +1159,22 @@ rule "ETC.4.2: Redact dossier dictionary entries"
|
|||||||
|
|
||||||
|
|
||||||
// Rule unit: ETC.5
|
// Rule unit: ETC.5
|
||||||
rule "ETC.5.0: Ignore dossier_redaction entries if confidentiality is not 'confidential'"
|
rule "ETC.5.0: Skip dossier_redaction entries if confidentiality is 'confidential'"
|
||||||
|
when
|
||||||
|
FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
|
then
|
||||||
|
$dossierRedaction.skip("ETC.5.0", "Ignore dossier_redaction when confidential");
|
||||||
|
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "ETC.5.1: Remove dossier_redaction entries if confidentiality is not 'confidential'"
|
||||||
when
|
when
|
||||||
not FileAttribute(label == "Confidentiality", value == "confidential")
|
not FileAttribute(label == "Confidentiality", value == "confidential")
|
||||||
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
$dossierRedaction: TextEntity(type() == "dossier_redaction")
|
||||||
then
|
then
|
||||||
$dossierRedaction.ignore("ETC.5.0", "Ignore dossier redactions, when not confidential");
|
$dossierRedaction.remove("ETC.5.1", "Remove dossier_redaction when not confidential");
|
||||||
$dossierRedaction.getIntersectingNodes().forEach(node -> update(node));
|
retract($dossierRedaction);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user