RED-9472: seperation of system rules
code review changes
This commit is contained in:
parent
de7ea74ccf
commit
301dc718e8
@ -45,7 +45,7 @@ public class RuleBuilderController implements RuleBuilderResource {
|
|||||||
RulesResponse rulesResponse = new RulesResponse();
|
RulesResponse rulesResponse = new RulesResponse();
|
||||||
String filteredRules = this.ruleBuilderService.cleanRuleFileOfSystemRules(systemRulesSeperationRequest.getRules(), true);
|
String filteredRules = this.ruleBuilderService.cleanRuleFileOfSystemRules(systemRulesSeperationRequest.getRules(), true);
|
||||||
if (filteredRules.isEmpty()) {
|
if (filteredRules.isEmpty()) {
|
||||||
throw new RuntimeException("There was an error when cleaning the rulefile of sytem rules");
|
throw new AssertionError("There was an error when cleaning the rulefile of sytem rules");
|
||||||
}
|
}
|
||||||
rulesResponse.setRules(filteredRules);
|
rulesResponse.setRules(filteredRules);
|
||||||
return rulesResponse;
|
return rulesResponse;
|
||||||
@ -53,13 +53,13 @@ public class RuleBuilderController implements RuleBuilderResource {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity mergeUserUpdateRules(RulesUpdateRequest rulesUpdateRequest) {
|
public ResponseEntity<RulesUploadResponse> mergeUserUpdateRules(RulesUpdateRequest rulesUpdateRequest) {
|
||||||
|
|
||||||
RulesUploadResponse rulesUploadResponse = new RulesUploadResponse();
|
RulesUploadResponse rulesUploadResponse = new RulesUploadResponse();
|
||||||
DroolsValidationResponse droolsValidationResponse;
|
DroolsValidationResponse droolsValidationResponse;
|
||||||
RuleMergingResult mergingResult = ruleBuilderService.mergeUserRulesAndSystemRules(rulesUpdateRequest.getExistingRules(), rulesUpdateRequest.getUpdatedRules());
|
RuleMergingResult mergingResult = ruleBuilderService.mergeUserRulesAndSystemRules(rulesUpdateRequest.getExistingRules(), rulesUpdateRequest.getUpdatedRules());
|
||||||
if (mergingResult.getMergedRules().isEmpty()) {
|
if (mergingResult.getMergedRules().isEmpty()) {
|
||||||
throw new RuntimeException("There was an error when merging the user rule update into the rule file");
|
throw new AssertionError("There was an error when merging the user rule update into the rule file");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
var droolsValidation = droolsValidationService.testRules(new RuleValidationModel(RuleFileType.ENTITY.name(), mergingResult.getMergedRules()));
|
var droolsValidation = droolsValidationService.testRules(new RuleValidationModel(RuleFileType.ENTITY.name(), mergingResult.getMergedRules()));
|
||||||
@ -90,7 +90,8 @@ public class RuleBuilderController implements RuleBuilderResource {
|
|||||||
.toList())
|
.toList())
|
||||||
.build();
|
.build();
|
||||||
if (!droolsValidation.isCompiled()) {
|
if (!droolsValidation.isCompiled()) {
|
||||||
return new ResponseEntity<>(droolsValidationResponse, HttpStatus.UNPROCESSABLE_ENTITY);
|
rulesUploadResponse.setDroolsValidationResponse(droolsValidationResponse);
|
||||||
|
return new ResponseEntity<>(rulesUploadResponse, HttpStatus.UNPROCESSABLE_ENTITY);
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
rulesUploadResponse.setRules(mergingResult.getMergedRules());
|
rulesUploadResponse.setRules(mergingResult.getMergedRules());
|
||||||
|
|||||||
@ -47,60 +47,16 @@ public final class RuleCompilationResult {
|
|||||||
|
|
||||||
public void dropRulesByIdentifier(RuleType ruleType) {
|
public void dropRulesByIdentifier(RuleType ruleType) {
|
||||||
|
|
||||||
log.info("removing rule with identifier {}", ruleType.name());
|
|
||||||
|
|
||||||
List<RuleClass> rulesToBeRemoved = ruleClasses.stream()
|
List<RuleClass> rulesToBeRemoved = ruleClasses.stream()
|
||||||
.filter(ruleClass -> Objects.equals(ruleClass.ruleType(), ruleType))
|
.filter(ruleClass -> Objects.equals(ruleClass.ruleType(), ruleType))
|
||||||
.toList();
|
.toList();
|
||||||
log.info("rules to be removed {}", rulesToBeRemoved);
|
|
||||||
ruleClasses.removeAll(rulesToBeRemoved);
|
ruleClasses.removeAll(rulesToBeRemoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void dropAllRulesExceptSystemRules(List<String> systemRules) {
|
|
||||||
|
|
||||||
log.info("removing all rules except the system rules");
|
|
||||||
|
|
||||||
List<RuleClass> rulesToBeRemoved = ruleClasses.stream()
|
|
||||||
.filter(ruleClass -> filterOutRule(ruleClass.ruleType(), systemRules))
|
|
||||||
.toList();
|
|
||||||
log.info("rules to be removed {}", rulesToBeRemoved);
|
|
||||||
ruleClasses.removeAll(rulesToBeRemoved);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void dropImports() {
|
|
||||||
|
|
||||||
this.imports = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void dropQueries() {
|
|
||||||
|
|
||||||
this.queries.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int countRuleOccurences(RuleType ruleType) {
|
|
||||||
|
|
||||||
log.info("counting occurences of files {}", ruleType.name());
|
|
||||||
|
|
||||||
List<RuleClass> rulesToBeRemoved = ruleClasses.stream()
|
|
||||||
.filter(ruleClass -> Objects.equals(ruleClass.ruleType(), ruleType))
|
|
||||||
.toList();
|
|
||||||
return rulesToBeRemoved.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean filterOutRule(RuleType ruleType, List<String> filteredRules) {
|
|
||||||
|
|
||||||
return !filteredRules.contains(ruleType.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Set<String> getImportSplitByKeyword() {
|
public Set<String> getImportSplitByKeyword() {
|
||||||
|
|
||||||
return Arrays.stream(imports.replace("\n", "").split("import"))
|
return Arrays.stream(imports.replaceAll("\n", "").split("import"))
|
||||||
.map(String::trim)
|
.map(String::trim)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,34 +1,37 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server.rulesmanagement;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.drools.io.ClassPathResource;
|
||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.ApplicationType;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.ApplicationType;
|
||||||
|
|
||||||
@SuppressWarnings("PMD")
|
@SuppressWarnings("PMD")
|
||||||
public class RuleManagementResources {
|
public class RuleManagementResources {
|
||||||
|
|
||||||
public static InputStream getAllRulesInputStream(ApplicationType applicationType) {
|
public static InputStream getAllRulesInputStream(ApplicationType applicationType) throws IOException {
|
||||||
|
|
||||||
if (applicationType == ApplicationType.RM) {
|
if (applicationType == ApplicationType.RM) {
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("drools/all_redact_manager_rules.drl");
|
return new ClassPathResource("drools/all_redact_manager_rules.drl").getInputStream();
|
||||||
}
|
}
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("drools/all_rules_documine.drl");
|
return new ClassPathResource("drools/all_rules_documine.drl").getInputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static InputStream getDefaultRuleIdentifiesInputStream(ApplicationType applicationType) {
|
public static InputStream getDefaultRuleIdentifiesInputStream(ApplicationType applicationType) throws IOException {
|
||||||
|
|
||||||
if (applicationType == ApplicationType.RM) {
|
if (applicationType == ApplicationType.RM) {
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("rulesmanagement/default_rule_identifiers.txt");
|
return new ClassPathResource("rulesmanagement/default_rule_identifiers.txt").getInputStream();
|
||||||
} else {
|
} else {
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("rulesmanagement/default_rule_identifiers_dm.txt");
|
return new ClassPathResource("rulesmanagement/default_rule_identifiers_dm.txt").getInputStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static InputStream getTemplateInputStream() {
|
public static InputStream getTemplateInputStream() throws IOException {
|
||||||
|
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("rulesmanagement/order_template.txt");
|
return new ClassPathResource("rulesmanagement/order_template.txt").getInputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import static java.util.stream.Collectors.groupingBy;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -121,16 +120,12 @@ public class RuleFileParser {
|
|||||||
|
|
||||||
Map<Integer, List<BasicRule>> rulesPerUnit = rules.stream()
|
Map<Integer, List<BasicRule>> rulesPerUnit = rules.stream()
|
||||||
.collect(groupingBy(rule -> rule.identifier().unit()));
|
.collect(groupingBy(rule -> rule.identifier().unit()));
|
||||||
if (rulesPerUnit.keySet() != null) {
|
|
||||||
|
|
||||||
return rulesPerUnit.keySet()
|
return rulesPerUnit.keySet()
|
||||||
.stream()
|
.stream()
|
||||||
.sorted()
|
.sorted()
|
||||||
.map(unit -> new RuleUnit(unit, rulesPerUnit.get(unit)))
|
.map(unit -> new RuleUnit(unit, rulesPerUnit.get(unit)))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
} else {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -53,6 +54,33 @@ public class RuleFileBluePrint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean removeRuleClassByRuleIdentifier(RuleIdentifier ruleIdentifier) {
|
||||||
|
|
||||||
|
AtomicBoolean wasRemoved = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
findRuleClassByType(ruleIdentifier.type()).ifPresent(ruleClass -> {
|
||||||
|
List<RuleUnit> unitsToRemove = new ArrayList<>();
|
||||||
|
|
||||||
|
ruleClass.ruleUnits()
|
||||||
|
.forEach(ruleUnit -> {
|
||||||
|
boolean removed = ruleUnit.rules().removeIf(rule -> rule.identifier().matches(ruleIdentifier));
|
||||||
|
if (removed) {
|
||||||
|
wasRemoved.set(true);
|
||||||
|
if (ruleUnit.rules().isEmpty()) {
|
||||||
|
unitsToRemove.add(ruleUnit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ruleClass.ruleUnits().removeAll(unitsToRemove);
|
||||||
|
if (ruleClass.ruleUnits().isEmpty()) {
|
||||||
|
this.ruleClasses.remove(ruleClass);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return wasRemoved.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Optional<RuleClass> findRuleClassByType(RuleType ruleType) {
|
public Optional<RuleClass> findRuleClassByType(RuleType ruleType) {
|
||||||
|
|
||||||
return ruleClasses.stream()
|
return ruleClasses.stream()
|
||||||
|
|||||||
@ -3,9 +3,8 @@ package com.iqser.red.service.redaction.v1.server.service;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -16,8 +15,6 @@ import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFil
|
|||||||
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileParser;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileParser;
|
||||||
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleFileBluePrint;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleFileBluePrint;
|
||||||
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
||||||
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleType;
|
|
||||||
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleUnit;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@ -25,13 +22,12 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Service
|
@Service
|
||||||
public class RuleBuilderService {
|
public class RuleBuilderService {
|
||||||
|
|
||||||
//todo: make this configurable
|
private final List<RuleIdentifier> systemRules = new ArrayList<>(Arrays.asList(RuleIdentifier.fromName("AI.*.*"),
|
||||||
private final List<RuleType> systemRules = new ArrayList<>(Arrays.asList(new RuleType("AI"),
|
RuleIdentifier.fromName("MAN.*.*"),
|
||||||
new RuleType("MAN"),
|
RuleIdentifier.fromName("X.*.*"),
|
||||||
new RuleType("X"),
|
RuleIdentifier.fromName("DICT.*.*"),
|
||||||
new RuleType("DICT"),
|
RuleIdentifier.fromName("FA.*.*"),
|
||||||
new RuleType("FA"),
|
RuleIdentifier.fromName("LDS.*.*")));
|
||||||
new RuleType("LDS")));
|
|
||||||
|
|
||||||
|
|
||||||
public RuleBuilderModel getRuleBuilderModel() {
|
public RuleBuilderModel getRuleBuilderModel() {
|
||||||
@ -48,28 +44,24 @@ public class RuleBuilderService {
|
|||||||
public String cleanRuleFileOfSystemRules(String rulesString, boolean removeImports) {
|
public String cleanRuleFileOfSystemRules(String rulesString, boolean removeImports) {
|
||||||
|
|
||||||
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(rulesString);
|
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(rulesString);
|
||||||
log.info("Starting to remove system rules from ruleFile");
|
removeSystemRules(ruleFileBluePrint);
|
||||||
removeSystemRulesAndCheckIfAnyRemain(ruleFileBluePrint);
|
|
||||||
log.info("Finished removing system rules for ruleFile");
|
|
||||||
|
|
||||||
return RuleFileFactory.buildRuleString(ruleFileBluePrint, removeImports, true);
|
return RuleFileFactory.buildRuleString(ruleFileBluePrint, removeImports, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public RuleMergingResult mergeUserRulesAndSystemRules(String existingRules, String userUpdatedRules) {
|
public RuleMergingResult mergeUserRulesAndSystemRules(String existingRules, String userUpdatedRules) {
|
||||||
|
|
||||||
log.info("starting to merge user rules update with system rules");
|
|
||||||
RuleFileBluePrint ruleFileBluePrintExisting = RuleFileParser.buildBluePrintFromRulesString(existingRules);
|
RuleFileBluePrint ruleFileBluePrintExisting = RuleFileParser.buildBluePrintFromRulesString(existingRules);
|
||||||
RuleFileBluePrint mergedRuleFileBlueprint = RuleFileParser.buildBluePrintFromRulesString(userUpdatedRules, true);
|
RuleFileBluePrint mergedRuleFileBlueprint = RuleFileParser.buildBluePrintFromRulesString(userUpdatedRules, true);
|
||||||
mergedRuleFileBlueprint.getRuleClasses()
|
mergedRuleFileBlueprint.getRuleClasses()
|
||||||
.forEach(ruleClass -> {
|
.forEach(ruleClass -> {
|
||||||
if (systemRules.stream()
|
if (systemRules.stream()
|
||||||
.map(RuleType::name)
|
.toList().contains(RuleIdentifier.fromName(ruleClass.ruleType().name()))) {
|
||||||
.toList().contains(ruleClass.ruleType().name())) {
|
log.warn("System rule in user rule update.");
|
||||||
throw new RuntimeException("No system rule updates allowed in user rule update.");
|
//throw new RuntimeException("No system rule updates allowed in user rule update.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
removeAllRulesExceptSystemRulesAndCheck(ruleFileBluePrintExisting);
|
removeAllRulesExceptSystemRules(ruleFileBluePrintExisting);
|
||||||
ruleFileBluePrintExisting.getRuleClasses()
|
ruleFileBluePrintExisting.getRuleClasses()
|
||||||
.stream()
|
.stream()
|
||||||
.flatMap(ruleClass -> ruleClass.ruleUnits()
|
.flatMap(ruleClass -> ruleClass.ruleUnits()
|
||||||
@ -89,7 +81,6 @@ public class RuleBuilderService {
|
|||||||
mergedRuleFileBlueprint.getDeclarations()
|
mergedRuleFileBlueprint.getDeclarations()
|
||||||
.stream())
|
.stream())
|
||||||
.toList());
|
.toList());
|
||||||
log.info("finished merging user rules update with system rules");
|
|
||||||
RuleMergingResult mergingResult = RuleMergingResult.builder()
|
RuleMergingResult mergingResult = RuleMergingResult.builder()
|
||||||
.mergedRules(RuleFileFactory.buildRuleString(ruleFileBluePrintExisting, false, false))
|
.mergedRules(RuleFileFactory.buildRuleString(ruleFileBluePrintExisting, false, false))
|
||||||
.addedGlobalsOffset(ruleFileBluePrintExisting.getGlobals().length())
|
.addedGlobalsOffset(ruleFileBluePrintExisting.getGlobals().length())
|
||||||
@ -100,69 +91,17 @@ public class RuleBuilderService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void removeAllRulesExceptSystemRulesAndCheck(RuleFileBluePrint ruleFileBluePrint) {
|
|
||||||
|
|
||||||
Set<String> systemRuleNames = systemRules.stream()
|
|
||||||
.map(RuleType::name)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
removeAllRulesExceptSystemRules(ruleFileBluePrint);
|
|
||||||
ruleFileBluePrint.getRuleClasses()
|
|
||||||
.forEach(ruleClass -> {
|
|
||||||
if (!systemRuleNames.contains(ruleClass.ruleType().name())) {
|
|
||||||
throw new RuntimeException("there was an error removing all rules except system rules");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void removeAllRulesExceptSystemRules(RuleFileBluePrint ruleFileBluePrint) {
|
private void removeAllRulesExceptSystemRules(RuleFileBluePrint ruleFileBluePrint) {
|
||||||
|
|
||||||
List<RuleIdentifier> rules = new ArrayList();
|
ruleFileBluePrint.buildFilteredBluePrintByRuleIdentifiers(new HashSet(systemRules));
|
||||||
Set<String> systemRuleNames = systemRules.stream()
|
|
||||||
.map(RuleType::name)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
|
|
||||||
ruleFileBluePrint.getRuleClasses()
|
|
||||||
.stream()
|
|
||||||
.filter(ruleClass -> !systemRuleNames.contains(ruleClass.ruleType().name()))
|
|
||||||
.flatMap(ruleClass -> ruleClass.ruleUnits()
|
|
||||||
.stream()
|
|
||||||
.map(ruleUnit -> new RuleIdentifier(ruleClass.ruleType(), ruleUnit.unit(), null)))
|
|
||||||
.forEach(rule -> rules.add(rule));
|
|
||||||
rules.forEach(ruleIdentifier -> {
|
|
||||||
ruleFileBluePrint.removeRule(ruleIdentifier);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void removeSystemRulesAndCheckIfAnyRemain(RuleFileBluePrint ruleFileBluePrint) {
|
|
||||||
|
|
||||||
removeSystemRules(ruleFileBluePrint);
|
|
||||||
for (RuleType systemRule : systemRules) {
|
|
||||||
List<RuleUnit> remainingSystemRules = new ArrayList();
|
|
||||||
ruleFileBluePrint.findRuleClassByType(systemRule)
|
|
||||||
.ifPresent(ruleClass -> ruleClass.ruleUnits()
|
|
||||||
.stream()
|
|
||||||
.forEach(remainingSystemRules::add));
|
|
||||||
if (!remainingSystemRules.isEmpty()) {
|
|
||||||
throw new RuntimeException("There was an error removing the system rules from the file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void removeSystemRules(RuleFileBluePrint ruleFileBluePrintExisting) {
|
private void removeSystemRules(RuleFileBluePrint ruleFileBluePrintExisting) {
|
||||||
|
|
||||||
for (RuleType systemRule : systemRules) {
|
for (RuleIdentifier systemRule : systemRules) {
|
||||||
List<RuleUnit> rules = new ArrayList();
|
ruleFileBluePrintExisting.removeRuleClassByRuleIdentifier(systemRule);
|
||||||
ruleFileBluePrintExisting.findRuleClassByType(systemRule)
|
|
||||||
.ifPresent(ruleClass -> ruleClass.ruleUnits()
|
|
||||||
.stream()
|
|
||||||
.forEach(rules::add));
|
|
||||||
rules.forEach(ruleUnit -> {
|
|
||||||
ruleFileBluePrintExisting.removeRule(new RuleIdentifier(systemRule, ruleUnit.unit(), null));
|
|
||||||
});
|
|
||||||
ruleFileBluePrintExisting.removeRule(RuleIdentifier.fromRuleType(systemRule));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,33 +35,6 @@ public class RuleCompilationResultParser {
|
|||||||
"\\b(?:redact|apply|skip|remove|ignore|applyWithLineBreaks|applyWithReferences|skipWithReferences)\\s*\\(\\s*\"([a-zA-Z0-9]+.\\d+.\\d+)\"\\s*,\\s*.*(?:\\s*,\\s*.*)\\s*?\\)");
|
"\\b(?:redact|apply|skip|remove|ignore|applyWithLineBreaks|applyWithReferences|skipWithReferences)\\s*\\(\\s*\"([a-zA-Z0-9]+.\\d+.\\d+)\"\\s*,\\s*.*(?:\\s*,\\s*.*)\\s*?\\)");
|
||||||
|
|
||||||
|
|
||||||
public RuleCompilationResult buildBluePrintFromUserRulesString(String userRulesString) {
|
|
||||||
|
|
||||||
DroolsValidation customDroolsValidation = DroolsValidation.builder().build();
|
|
||||||
List<BasicRule> allRules = new LinkedList<>();
|
|
||||||
List<BasicQuery> allQueries = new LinkedList<>();
|
|
||||||
PackageDescr packageDescr = new PackageDescr();
|
|
||||||
String imports = "";
|
|
||||||
String globals = "";
|
|
||||||
List<RuleClass> ruleClasses = buildRuleClasses(allRules);
|
|
||||||
return new RuleCompilationResult(imports.trim(),
|
|
||||||
packageDescr.getImports()
|
|
||||||
.stream()
|
|
||||||
.findFirst()
|
|
||||||
.map(ImportDescr::getLine)
|
|
||||||
.orElse(0),
|
|
||||||
globals.trim(),
|
|
||||||
packageDescr.getGlobals()
|
|
||||||
.stream()
|
|
||||||
.findFirst()
|
|
||||||
.map(GlobalDescr::getLine)
|
|
||||||
.orElse(0),
|
|
||||||
allQueries,
|
|
||||||
ruleClasses,
|
|
||||||
customDroolsValidation);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public RuleCompilationResult buildRuleCompilationResultFromRuleString(String ruleString, boolean removedImports) {
|
public RuleCompilationResult buildRuleCompilationResultFromRuleString(String ruleString, boolean removedImports) {
|
||||||
|
|
||||||
@ -116,60 +89,7 @@ public class RuleCompilationResultParser {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public RuleCompilationResult buildRuleCompilationResultFromRuleString(String ruleString) {
|
public RuleCompilationResult buildRuleCompilationResultFromRuleString(String ruleString) {
|
||||||
|
|
||||||
return buildRuleCompilationResultFromRuleString(ruleString,false);
|
return buildRuleCompilationResultFromRuleString(ruleString, false);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public String buildRulesStringFromBluePrint(RuleCompilationResult bluePrint) {
|
|
||||||
|
|
||||||
StringBuilder ruleStringBuilder = new StringBuilder();
|
|
||||||
|
|
||||||
// Append imports
|
|
||||||
ruleStringBuilder.append(bluePrint.getImports()).append("\n\n");
|
|
||||||
|
|
||||||
// Append globals
|
|
||||||
if (!bluePrint.getGlobals().isEmpty()) {
|
|
||||||
ruleStringBuilder.append(bluePrint.getGlobals()).append("\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append queries
|
|
||||||
for (BasicQuery query : bluePrint.getQueries()) {
|
|
||||||
ruleStringBuilder.append(buildQueryString(query)).append("\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append rules
|
|
||||||
for (RuleClass ruleClass : bluePrint.getRuleClasses()) {
|
|
||||||
ruleStringBuilder.append(buildRuleString(ruleClass)).append("\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the final rule string
|
|
||||||
return ruleStringBuilder.toString().trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String buildQueryString(BasicQuery query) {
|
|
||||||
|
|
||||||
return "query \"" + query.getName() + "\"\n" + query.getCode() + "\n" + "end";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String buildRuleString(RuleClass ruleClass) {
|
|
||||||
|
|
||||||
StringBuilder ruleBuilder = new StringBuilder();
|
|
||||||
|
|
||||||
// Use RuleType to distinguish between different rule types, if needed
|
|
||||||
ruleBuilder.append("rule \"").append(ruleClass.ruleType().name()).append("\"\n");
|
|
||||||
|
|
||||||
for (RuleUnit ruleUnit : ruleClass.ruleUnits()) {
|
|
||||||
for (BasicRule rule : ruleUnit.rules()) {
|
|
||||||
// Assuming BasicRule has a method to retrieve the condition as a string
|
|
||||||
ruleBuilder.append(rule.getCode()).append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ruleBuilder.append("end");
|
|
||||||
|
|
||||||
return ruleBuilder.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -216,7 +136,6 @@ public class RuleCompilationResultParser {
|
|||||||
|
|
||||||
private List<RuleClass> buildRuleClasses(List<BasicRule> allRules) {
|
private List<RuleClass> buildRuleClasses(List<BasicRule> allRules) {
|
||||||
|
|
||||||
//todo: comments
|
|
||||||
List<RuleType> ruleTypeOrder = allRules.stream()
|
List<RuleType> ruleTypeOrder = allRules.stream()
|
||||||
.map(BasicRule::getIdentifier)
|
.map(BasicRule::getIdentifier)
|
||||||
.map(RuleIdentifier::type)
|
.map(RuleIdentifier::type)
|
||||||
|
|||||||
@ -1,149 +1,128 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server;
|
package com.iqser.red.service.redaction.v1.server;
|
||||||
|
|
||||||
|
import static com.iqser.red.service.redaction.v1.server.AbstractRedactionIntegrationTest.TEST_DOSSIER_TEMPLATE_ID;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.MethodOrderer;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.api.TestMethodOrder;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
|
||||||
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.context.annotation.FilterType;
|
|
||||||
import org.springframework.context.annotation.Import;
|
|
||||||
import org.springframework.context.annotation.Primary;
|
|
||||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
|
||||||
|
|
||||||
import com.iqser.red.commons.jackson.ObjectMapperFactory;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.RuleFileType;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSONPrimitive;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSONPrimitive;
|
||||||
import com.iqser.red.service.redaction.v1.server.model.RuleMergingResult;
|
import com.iqser.red.service.redaction.v1.server.model.RuleMergingResult;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.model.drools.RuleClass;
|
||||||
import com.iqser.red.service.redaction.v1.server.model.drools.RuleCompilationResult;
|
import com.iqser.red.service.redaction.v1.server.model.drools.RuleCompilationResult;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileFactory;
|
||||||
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileParser;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileParser;
|
||||||
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleFileBluePrint;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleFileBluePrint;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.utils.RuleFileIO;
|
||||||
import com.iqser.red.service.redaction.v1.server.service.RuleBuilderService;
|
import com.iqser.red.service.redaction.v1.server.service.RuleBuilderService;
|
||||||
import com.iqser.red.service.redaction.v1.server.service.drools.RuleCompilationResultParser;
|
import com.iqser.red.service.redaction.v1.server.service.drools.RuleCompilationResultParser;
|
||||||
import com.iqser.red.storage.commons.StorageAutoConfiguration;
|
|
||||||
import com.iqser.red.storage.commons.service.StorageService;
|
|
||||||
import com.iqser.red.storage.commons.utils.FileSystemBackedStorageService;
|
|
||||||
import com.knecon.fforesight.service.layoutparser.processor.LayoutParsingServiceProcessorConfiguration;
|
|
||||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||||
|
|
||||||
@ExtendWith(SpringExtension.class)
|
import org.junit.jupiter.api.Assertions;
|
||||||
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
import lombok.SneakyThrows;
|
||||||
@Import(RuleBuilderTest.RuleBuilderTestConfiguration.class)
|
|
||||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
|
||||||
public class RuleBuilderTest extends AbstractRedactionIntegrationTest {
|
|
||||||
|
|
||||||
private static final String RULES = loadFromClassPath("drools/rules_v2.drl");
|
class RuleBuilderTest {
|
||||||
private static final String USER_RULES = loadFromClassPath("rulesmanagement/userrules/user_rule_update.drl");
|
|
||||||
private final List<String> systemRules = new ArrayList<>(Arrays.asList("AI", "MAN", "X", "DICT", "FA", "LDS"));
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
RuleBuilderService ruleBuilderService;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableAutoConfiguration(exclude = {RabbitAutoConfiguration.class})
|
|
||||||
@Import(LayoutParsingServiceProcessorConfiguration.class)
|
|
||||||
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = StorageAutoConfiguration.class)})
|
|
||||||
public static class RuleBuilderTestConfiguration {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@Primary
|
|
||||||
public StorageService inmemoryStorage() {
|
|
||||||
|
|
||||||
return new FileSystemBackedStorageService(ObjectMapperFactory.create());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private RuleBuilderService ruleBuilderService;
|
||||||
|
private final List<RuleIdentifier> systemRules = new ArrayList<>(Arrays.asList(
|
||||||
|
RuleIdentifier.fromName("AI.*.*"),
|
||||||
|
RuleIdentifier.fromName("MAN.*.*"),
|
||||||
|
RuleIdentifier.fromName("X.*.*"),
|
||||||
|
RuleIdentifier.fromName("DICT.*.*"),
|
||||||
|
RuleIdentifier.fromName("FA.*.*"),
|
||||||
|
RuleIdentifier.fromName("LDS.*.*")
|
||||||
|
));
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void stubClients() {
|
void setUp() {
|
||||||
|
ruleBuilderService = new RuleBuilderService();
|
||||||
TenantContext.setTenantId("redaction");
|
TenantContext.setTenantId("redaction");
|
||||||
|
|
||||||
when(rulesClient.getVersion(TEST_DOSSIER_TEMPLATE_ID, RuleFileType.ENTITY)).thenReturn(System.currentTimeMillis());
|
|
||||||
when(rulesClient.getRules(TEST_DOSSIER_TEMPLATE_ID, RuleFileType.ENTITY)).thenReturn(JSONPrimitive.of(RULES));
|
|
||||||
when(rulesClient.getVersion(TEST_DOSSIER_TEMPLATE_ID, RuleFileType.COMPONENT)).thenReturn(-1L);
|
|
||||||
|
|
||||||
loadDictionaryForTest();
|
|
||||||
loadTypeForTest();
|
|
||||||
loadNerForTest();
|
|
||||||
when(dictionaryClient.getVersion(TEST_DOSSIER_TEMPLATE_ID)).thenReturn(0L);
|
|
||||||
when(dictionaryClient.getAllTypesForDossierTemplate(TEST_DOSSIER_TEMPLATE_ID, null, true)).thenReturn(getTemplateDictionaryTypeResponse());
|
|
||||||
|
|
||||||
when(dictionaryClient.getVersion(TEST_DOSSIER_ID)).thenReturn(0L);
|
|
||||||
when(dictionaryClient.getAllTypesForDossier(TEST_DOSSIER_ID, null, true)).thenReturn(getDossierDictionaryTypeResponse());
|
|
||||||
|
|
||||||
mockDictionaryCalls(null);
|
|
||||||
|
|
||||||
when(dictionaryClient.getColors(TEST_DOSSIER_TEMPLATE_ID)).thenReturn(colors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void removeSystemRulesTest() {
|
@SneakyThrows
|
||||||
|
void removeSystemRulesTest() throws IOException {
|
||||||
|
URL url = getClass().getClassLoader().getResource("drools");
|
||||||
|
if (url == null) {
|
||||||
|
throw new RuntimeException("Drools directory not found in resources");
|
||||||
|
}
|
||||||
|
|
||||||
String cleanedRulesWithImports = this.ruleBuilderService.cleanRuleFileOfSystemRules(RULES, false);
|
Path path = Paths.get(url.toURI());
|
||||||
String cleanedRulesWithoutImports = this.ruleBuilderService.cleanRuleFileOfSystemRules(RULES, true);
|
RuleFileIO.streamAllRuleFilesInDirectory(path)
|
||||||
RuleCompilationResult ruleCompilationResultWithImports = RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(cleanedRulesWithImports, false);
|
.forEach(file -> testThatSystemRulesAreRemoved(file.toPath()));
|
||||||
RuleCompilationResult ruleCompilationResultWithoutImports = RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(cleanedRulesWithoutImports, true);
|
|
||||||
|
|
||||||
Assert.assertFalse(checkIfImportsDontExist(ruleCompilationResultWithImports));
|
RuleFileIO.streamAllRuleFilesInDirectory(path)
|
||||||
Assert.assertTrue(checkIfSystemRulesDontExist(ruleCompilationResultWithImports));
|
.forEach(file -> testRuleFilesRemainSameAfterSeperationAndReaddingSystemrules(file.toPath()));
|
||||||
Assert.assertTrue(checkIfQueriesDontExist(ruleCompilationResultWithImports));
|
|
||||||
|
|
||||||
Assert.assertTrue(checkIfImportsDontExist(ruleCompilationResultWithoutImports));
|
|
||||||
Assert.assertTrue(checkIfSystemRulesDontExist(ruleCompilationResultWithoutImports));
|
|
||||||
Assert.assertTrue(checkIfQueriesDontExist(ruleCompilationResultWithoutImports));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testThatSystemRulesAreRemoved(Path path) {
|
||||||
|
String cleanedRulesWithImports = ruleBuilderService.cleanRuleFileOfSystemRules(
|
||||||
|
RuleFileIO.getRulesString(path.toFile().getAbsolutePath()),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
String cleanedRulesWithoutImports = ruleBuilderService.cleanRuleFileOfSystemRules(
|
||||||
|
RuleFileIO.getRulesString(path.toFile().getAbsolutePath()),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
@Test
|
RuleCompilationResult ruleCompilationResultWithImports =
|
||||||
public void mergeUserRulesUpdateTest() {
|
RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(cleanedRulesWithImports, false);
|
||||||
|
RuleCompilationResult ruleCompilationResultWithoutImports =
|
||||||
|
RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(cleanedRulesWithoutImports, true);
|
||||||
|
|
||||||
RuleMergingResult mergingResult = this.ruleBuilderService.mergeUserRulesAndSystemRules(RULES, USER_RULES);
|
Assertions.assertFalse(checkIfImportsDontExist(ruleCompilationResultWithImports));
|
||||||
String mergedRules = mergingResult.getMergedRules();
|
Assertions.assertTrue(checkIfSystemRulesDontExist(ruleCompilationResultWithImports));
|
||||||
RuleFileBluePrint ruleFileBluePrintUserRulesUpdate = RuleFileParser.buildBluePrintFromRulesString(mergedRules, true);
|
Assertions.assertTrue(checkIfQueriesDontExist(ruleCompilationResultWithImports));
|
||||||
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(mergedRules);
|
|
||||||
ruleFileBluePrintUserRulesUpdate.getRuleClasses()
|
|
||||||
.forEach(ruleClass -> {
|
|
||||||
Assert.assertTrue(ruleFileBluePrint.getRuleClasses().contains(ruleClass));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
Assertions.assertTrue(checkIfImportsDontExist(ruleCompilationResultWithoutImports));
|
||||||
|
Assertions.assertTrue(checkIfSystemRulesDontExist(ruleCompilationResultWithoutImports));
|
||||||
|
Assertions.assertTrue(checkIfQueriesDontExist(ruleCompilationResultWithoutImports));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testRuleFilesRemainSameAfterSeperationAndReaddingSystemrules(Path path) {
|
||||||
|
String cleanedRulesWithImports = ruleBuilderService.cleanRuleFileOfSystemRules(
|
||||||
|
RuleFileIO.getRulesString(path.toFile().getAbsolutePath()),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
RuleMergingResult cleanedRuleFileMergedWithSystemRules = ruleBuilderService.mergeUserRulesAndSystemRules(
|
||||||
|
RuleFileIO.getRulesString(path.toFile().getAbsolutePath()),
|
||||||
|
cleanedRulesWithImports
|
||||||
|
);
|
||||||
|
|
||||||
|
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(
|
||||||
|
cleanedRuleFileMergedWithSystemRules.getMergedRules()
|
||||||
|
);
|
||||||
|
|
||||||
|
Assertions.assertEquals(
|
||||||
|
RuleFileFactory.buildRuleString(ruleFileBluePrint, false, false),
|
||||||
|
cleanedRuleFileMergedWithSystemRules.getMergedRules()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkIfSystemRulesDontExist(RuleCompilationResult ruleCompilationResult) {
|
private boolean checkIfSystemRulesDontExist(RuleCompilationResult ruleCompilationResult) {
|
||||||
|
|
||||||
return ruleCompilationResult.getRuleClasses()
|
return ruleCompilationResult.getRuleClasses()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(ruleClass -> this.systemRules.contains(ruleClass.ruleType().name()))
|
.map(RuleClass::ruleType)
|
||||||
.collect(Collectors.toList()).size() == 0;
|
.noneMatch(ruleType -> systemRules.stream()
|
||||||
|
.map(RuleIdentifier::type)
|
||||||
|
.anyMatch(type -> ruleType.name().equals(type.name())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean checkIfImportsDontExist(RuleCompilationResult ruleCompilationResult) {
|
private boolean checkIfImportsDontExist(RuleCompilationResult ruleCompilationResult) {
|
||||||
|
|
||||||
return ruleCompilationResult.getImports().isEmpty();
|
return ruleCompilationResult.getImports().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean checkIfQueriesDontExist(RuleCompilationResult ruleCompilationResult) {
|
private boolean checkIfQueriesDontExist(RuleCompilationResult ruleCompilationResult) {
|
||||||
|
|
||||||
return ruleCompilationResult.getQueries().isEmpty();
|
return ruleCompilationResult.getQueries().isEmpty();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user