RED-6369: Rules Refactor

* marked entities as resized if a resizeRedaction with same id exists
This commit is contained in:
Kilian Schuettler 2023-04-17 13:25:45 +02:00
parent 2278195318
commit 86b5059d77
5 changed files with 64 additions and 72 deletions

View File

@ -139,6 +139,12 @@ public class EntityNode {
} }
public boolean matchesResizedAnnotationId(String resizedAnnotationId) {
return getEntityPositionsPerPage().stream().anyMatch(entityPosition -> entityPosition.getId().equals(resizedAnnotationId));
}
@Override @Override
public String toString() { public String toString() {

View File

@ -8,12 +8,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.kie.api.KieServices; import org.kie.api.KieServices;
@ -27,6 +21,7 @@ import org.kie.api.runtime.rule.QueryResultsRow;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttribute; import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttribute;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction;
import com.iqser.red.service.redaction.v1.server.client.RulesClient; import com.iqser.red.service.redaction.v1.server.client.RulesClient;
import com.iqser.red.service.redaction.v1.server.document.graph.DocumentGraph; import com.iqser.red.service.redaction.v1.server.document.graph.DocumentGraph;
import com.iqser.red.service.redaction.v1.server.document.graph.nodes.SectionNode; import com.iqser.red.service.redaction.v1.server.document.graph.nodes.SectionNode;
@ -39,20 +34,6 @@ import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.Dict
import io.micrometer.core.annotation.Timed; import io.micrometer.core.annotation.Timed;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.iqser.red.service.redaction.v1.server.client.RulesClient;
import com.iqser.red.service.redaction.v1.server.exception.RulesValidationException;
import com.iqser.red.service.redaction.v1.server.multitenancy.TenantContext;
import com.iqser.red.service.redaction.v1.server.redaction.model.Section;
import com.iqser.red.service.redaction.v1.server.redaction.model.TenantRules;
import com.iqser.red.service.redaction.v1.server.settings.RedactionServiceSettings;
import io.micrometer.core.annotation.Timed;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@ -62,24 +43,7 @@ public class DroolsExecutionService {
private final Map<String, KieContainer> kieContainers = new HashMap<>(); private final Map<String, KieContainer> kieContainers = new HashMap<>();
private final RedactionServiceSettings settings; private final Map<String, Long> rulesVersionPerDossierTemplateId = new HashMap<>();
private LoadingCache<String, TenantRules> tenantRulesCache;
@PostConstruct
protected void createCache() {
tenantRulesCache = CacheBuilder.newBuilder()
.maximumSize(settings.getDictionaryCacheMaximumSize())
.expireAfterAccess(settings.getDictionaryCacheExpireAfterAccessDays(), TimeUnit.DAYS)
.build(new CacheLoader<>() {
public TenantRules load(String key) {
return new TenantRules();
}
});
}
private final EntityCreationService entityCreationService; private final EntityCreationService entityCreationService;
@ -96,7 +60,11 @@ public class DroolsExecutionService {
@Timed("redactmanager_executeRules") @Timed("redactmanager_executeRules")
public List<FileAttribute> executeRules(KieContainer kieContainer, DocumentGraph document, Dictionary dictionary, List<FileAttribute> fileAttributes) { public List<FileAttribute> executeRules(KieContainer kieContainer,
DocumentGraph document,
Dictionary dictionary,
List<FileAttribute> fileAttributes,
Set<ManualResizeRedaction> resizeRedactions) {
KieSession kieSession = kieContainer.newKieSession(); KieSession kieSession = kieContainer.newKieSession();
kieSession.setGlobal("document", document); kieSession.setGlobal("document", document);
@ -107,6 +75,7 @@ public class DroolsExecutionService {
document.getTableOfContents().streamAllEntriesInOrder().forEach(entry -> kieSession.insert(entry.getNode())); document.getTableOfContents().streamAllEntriesInOrder().forEach(entry -> kieSession.insert(entry.getNode()));
document.getPages().forEach(kieSession::insert); document.getPages().forEach(kieSession::insert);
fileAttributes.forEach(kieSession::insert); fileAttributes.forEach(kieSession::insert);
resizeRedactions.forEach(kieSession::insert);
kieSession.getAgenda().getAgendaGroup("LOCAL_DICTIONARY_ADDS").setFocus(); kieSession.getAgenda().getAgendaGroup("LOCAL_DICTIONARY_ADDS").setFocus();
kieSession.fireAllRules(); kieSession.fireAllRules();
@ -120,7 +89,8 @@ public class DroolsExecutionService {
DocumentGraph document, DocumentGraph document,
List<SectionNode> sectionsToReanalyze, List<SectionNode> sectionsToReanalyze,
Dictionary dictionary, Dictionary dictionary,
List<FileAttribute> fileAttributes) { List<FileAttribute> fileAttributes,
Set<ManualResizeRedaction> resizeRedactions) {
KieSession kieSession = kieContainer.newKieSession(); KieSession kieSession = kieContainer.newKieSession();
kieSession.setGlobal("document", document); kieSession.setGlobal("document", document);
@ -128,9 +98,11 @@ public class DroolsExecutionService {
kieSession.setGlobal("dictionary", dictionary); kieSession.setGlobal("dictionary", dictionary);
document.getEntities().forEach(kieSession::insert); document.getEntities().forEach(kieSession::insert);
sectionsToReanalyze.forEach(kieSession::insert);
sectionsToReanalyze.stream().flatMap(SemanticNode::streamAllSubNodes).forEach(kieSession::insert); sectionsToReanalyze.stream().flatMap(SemanticNode::streamAllSubNodes).forEach(kieSession::insert);
document.getPages().forEach(kieSession::insert); document.getPages().forEach(kieSession::insert);
fileAttributes.forEach(kieSession::insert); fileAttributes.forEach(kieSession::insert);
resizeRedactions.forEach(kieSession::insert);
kieSession.getAgenda().getAgendaGroup("LOCAL_DICTIONARY_ADDS").setFocus(); kieSession.getAgenda().getAgendaGroup("LOCAL_DICTIONARY_ADDS").setFocus();
kieSession.fireAllRules(); kieSession.fireAllRules();
@ -178,13 +150,13 @@ public class DroolsExecutionService {
public KieContainer updateRules(String dossierTemplateId) { public KieContainer updateRules(String dossierTemplateId) {
long version = rulesClient.getVersion(dossierTemplateId); long version = rulesClient.getVersion(dossierTemplateId);
Long rulesVersion = getVersionForDossierTemplate(dossierTemplateId); Long rulesVersion = rulesVersionPerDossierTemplateId.get(dossierTemplateId);
if (rulesVersion == null) { if (rulesVersion == null) {
rulesVersion = -1L; rulesVersion = -1L;
} }
if (version > rulesVersion) { if (version > rulesVersion) {
setRulesVersionForDossierTemplate(dossierTemplateId, version); rulesVersionPerDossierTemplateId.put(dossierTemplateId, version);
return createOrUpdateKieContainer(dossierTemplateId); return createOrUpdateKieContainer(dossierTemplateId);
} }
return getKieContainer(dossierTemplateId); return getKieContainer(dossierTemplateId);
@ -243,25 +215,11 @@ public class DroolsExecutionService {
public long getRulesVersion(String dossierTemplateId) { public long getRulesVersion(String dossierTemplateId) {
Long rulesVersion = getVersionForDossierTemplate(dossierTemplateId); Long rulesVersion = rulesVersionPerDossierTemplateId.get(dossierTemplateId);
if (rulesVersion == null) { if (rulesVersion == null) {
return -1; return -1;
} }
return rulesVersion; return rulesVersion;
} }
@SneakyThrows
private Long getVersionForDossierTemplate(String dossierTemplateId) {
return tenantRulesCache.get(TenantContext.getTenantId()).getRulesVersionPerDossierTemplateId().get(dossierTemplateId);
}
@SneakyThrows
private void setRulesVersionForDossierTemplate(String dossierTemplateId, long version) {
tenantRulesCache.get(TenantContext.getTenantId()).getRulesVersionPerDossierTemplateId().put(dossierTemplateId, version);
}
} }

View File

@ -185,7 +185,12 @@ public class AnalyzeService {
KieContainer kieContainer = droolsExecutionService.updateRules(analyzeRequest.getDossierTemplateId()); KieContainer kieContainer = droolsExecutionService.updateRules(analyzeRequest.getDossierTemplateId());
Set<FileAttribute> addedFileAttributes = entityRedactionService.addRuleEntities(dictionary, documentGraph, sectionsToReAnalyse, kieContainer, analyzeRequest, nerEntities); Set<FileAttribute> addedFileAttributes = entityRedactionService.addRuleEntitiesToGraphAndReturnAddedFileAttributes(dictionary,
documentGraph,
sectionsToReAnalyse,
kieContainer,
analyzeRequest,
nerEntities);
List<RedactionLogEntry> newRedactionLogEntries = redactionLogCreatorService.createRedactionLog(documentGraph.getEntities(), analyzeRequest.getDossierTemplateId()); List<RedactionLogEntry> newRedactionLogEntries = redactionLogCreatorService.createRedactionLog(documentGraph.getEntities(), analyzeRequest.getDossierTemplateId());
@ -220,7 +225,11 @@ public class AnalyzeService {
Dictionary dictionary = dictionaryService.getDeepCopyDictionary(analyzeRequest.getDossierTemplateId(), analyzeRequest.getDossierId()); Dictionary dictionary = dictionaryService.getDeepCopyDictionary(analyzeRequest.getDossierTemplateId(), analyzeRequest.getDossierId());
entityRedactionService.addDictionaryEntities(dictionary, documentGraph); entityRedactionService.addDictionaryEntities(dictionary, documentGraph);
Set<FileAttribute> addedFileAttributes = entityRedactionService.addRuleEntities(dictionary, documentGraph, kieContainer, analyzeRequest, nerEntities); Set<FileAttribute> addedFileAttributes = entityRedactionService.addRuleEntitiesToGraphAndReturnAddedFileAttributes(dictionary,
documentGraph,
kieContainer,
analyzeRequest,
nerEntities);
List<RedactionLogEntry> redactionLogEntries = redactionLogCreatorService.createRedactionLog(documentGraph.getEntities(), analyzeRequest.getDossierTemplateId()); List<RedactionLogEntry> redactionLogEntries = redactionLogCreatorService.createRedactionLog(documentGraph.getEntities(), analyzeRequest.getDossierTemplateId());

View File

@ -33,18 +33,22 @@ public class EntityRedactionService {
EntityCreationService entityCreationService; EntityCreationService entityCreationService;
public Set<FileAttribute> addRuleEntities(Dictionary dictionary, public Set<FileAttribute> addRuleEntitiesToGraphAndReturnAddedFileAttributes(Dictionary dictionary,
DocumentGraph documentGraph, DocumentGraph documentGraph,
KieContainer kieContainer, KieContainer kieContainer,
AnalyzeRequest analyzeRequest, AnalyzeRequest analyzeRequest,
NerEntities nerEntities) { NerEntities nerEntities) {
List<FileAttribute> allFileAttributes = droolsExecutionService.executeRules(kieContainer, documentGraph, dictionary, analyzeRequest.getFileAttributes()); List<FileAttribute> allFileAttributes = droolsExecutionService.executeRules(kieContainer,
documentGraph,
dictionary,
analyzeRequest.getFileAttributes(),
analyzeRequest.getManualRedactions().getResizeRedactions());
return allFileAttributes.stream().filter(fileAttribute -> !analyzeRequest.getFileAttributes().contains(fileAttribute)).collect(Collectors.toUnmodifiableSet()); return allFileAttributes.stream().filter(fileAttribute -> !analyzeRequest.getFileAttributes().contains(fileAttribute)).collect(Collectors.toUnmodifiableSet());
} }
public Set<FileAttribute> addRuleEntities(Dictionary dictionary, public Set<FileAttribute> addRuleEntitiesToGraphAndReturnAddedFileAttributes(Dictionary dictionary,
DocumentGraph documentGraph, DocumentGraph documentGraph,
List<SectionNode> sectionsToReanalyze, List<SectionNode> sectionsToReanalyze,
KieContainer kieContainer, KieContainer kieContainer,
@ -55,7 +59,8 @@ public class EntityRedactionService {
documentGraph, documentGraph,
sectionsToReanalyze, sectionsToReanalyze,
dictionary, dictionary,
analyzeRequest.getFileAttributes()); analyzeRequest.getFileAttributes(),
analyzeRequest.getManualRedactions().getResizeRedactions());
return allFileAttributes.stream().filter(fileAttribute -> !analyzeRequest.getFileAttributes().contains(fileAttribute)).collect(Collectors.toUnmodifiableSet()); return allFileAttributes.stream().filter(fileAttribute -> !analyzeRequest.getFileAttributes().contains(fileAttribute)).collect(Collectors.toUnmodifiableSet());
} }

View File

@ -20,6 +20,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlo
import com.iqser.red.service.redaction.v1.server.document.services.EntityCreationService; import com.iqser.red.service.redaction.v1.server.document.services.EntityCreationService;
import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.Dictionary; import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.Dictionary;
import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.DictionaryModel; import com.iqser.red.service.redaction.v1.server.redaction.model.dictionary.DictionaryModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction;
global DocumentGraph document global DocumentGraph document
global EntityCreationService entityCreationService global EntityCreationService entityCreationService
@ -31,6 +32,19 @@ query "getFileAttributes"
$fileAttribute: FileAttribute() $fileAttribute: FileAttribute()
end end
// --------------------------------------- apply resize redactions -------------------------------------------------------------------
rule "apply resize redactions"
salience 200
no-loop true
when
$resizeRedaction: ManualResizeRedaction($id: annotationId)
$resizedEntity: EntityNode(matchesResizedAnnotationId($id))
then
$resizedEntity.setResized(true);
update($resizedEntity);
end
// --------------------------------------- merging rules ------------------------------------------------------------------- // --------------------------------------- merging rules -------------------------------------------------------------------
rule "merge intersecting Entities of same type" rule "merge intersecting Entities of same type"