RED-9472: seperation of system rules

refactored two have a rulefileblueprint and a rulefileblueprint for validationresult

changed the flow of merging and seperating system and user rules

added functions and declarations to rule file parsing
This commit is contained in:
yhampe 2024-10-07 13:59:34 +02:00
parent 4978259fc6
commit ae38506809
17 changed files with 338 additions and 142 deletions

View File

@ -1,6 +1,7 @@
package com.iqser.red.service.redaction.v1.resources; package com.iqser.red.service.redaction.v1.resources;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@ -20,6 +21,6 @@ public interface RuleBuilderResource {
@PostMapping(value = "/internal-api/rules/system-rules", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value = "/internal-api/rules/system-rules", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
RulesResponse getRuleFileWithSeperatedSystemRules(@RequestBody RulesUpdateRequest rulesUpdateRequest); ResponseEntity mergeUserUpdateRules(@RequestBody RulesUpdateRequest rulesUpdateRequest);
} }

View File

@ -1,13 +1,20 @@
package com.iqser.red.service.redaction.v1.server.controller; package com.iqser.red.service.redaction.v1.server.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.DroolsValidationResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.RuleBlacklistErrorMessage;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.RuleSyntaxErrorMessage;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.RuleSyntaxWarningMessage;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.RulesResponse; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.RulesResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.RulesUpdateRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.RulesUpdateRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.SystemRulesSeperationRequest; import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.SystemRulesSeperationRequest;
import com.iqser.red.service.redaction.v1.model.RuleBuilderModel; import com.iqser.red.service.redaction.v1.model.RuleBuilderModel;
import com.iqser.red.service.redaction.v1.model.RuleValidationModel; import com.iqser.red.service.redaction.v1.model.RuleValidationModel;
import com.iqser.red.service.redaction.v1.resources.RuleBuilderResource; import com.iqser.red.service.redaction.v1.resources.RuleBuilderResource;
import com.iqser.red.service.redaction.v1.server.model.RuleMergingResult;
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.DroolsValidationService; import com.iqser.red.service.redaction.v1.server.service.drools.DroolsValidationService;
import com.iqser.red.service.redaction.v1.server.utils.exception.RulesValidationException; import com.iqser.red.service.redaction.v1.server.utils.exception.RulesValidationException;
@ -36,28 +43,54 @@ 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);
try {
droolsValidationService.testRules(new RuleValidationModel(RuleFileType.ENTITY.name(), filteredRules));
} catch (Exception e) {
throw new RulesValidationException("Error trying to compile the cleaned rule file: " + filteredRules + " with message: {} " + e.getMessage(), e);
}
rulesResponse.setRules(filteredRules); rulesResponse.setRules(filteredRules);
return rulesResponse; return rulesResponse;
} }
@Override @Override
public RulesResponse getRuleFileWithSeperatedSystemRules(RulesUpdateRequest rulesUpdateRequest) { public ResponseEntity mergeUserUpdateRules(RulesUpdateRequest rulesUpdateRequest) {
RulesResponse rulesResponse = new RulesResponse(); RulesResponse rulesResponse = new RulesResponse();
String mergedRules = ruleBuilderService.getRuleFileWithSeperatedSystemRules(rulesUpdateRequest.getExistingRules(), rulesUpdateRequest.getUpdatedRules()); DroolsValidationResponse droolsValidationResponse = new DroolsValidationResponse();
RuleMergingResult mergingResult = ruleBuilderService.mergeUserRulesAndSystemRules(rulesUpdateRequest.getExistingRules(), rulesUpdateRequest.getUpdatedRules());
try { try {
droolsValidationService.testRules(new RuleValidationModel(RuleFileType.ENTITY.name(), mergedRules)); var droolsValidation = droolsValidationService.testRules(new RuleValidationModel(RuleFileType.ENTITY.name(), mergingResult.getMergedRules()));
droolsValidationResponse = DroolsValidationResponse.builder()
.syntaxErrorMessages(droolsValidation.getSyntaxErrorMessages()
.stream()
.map(droolsSyntaxErrorMessage -> new RuleSyntaxErrorMessage(droolsSyntaxErrorMessage.getLine()
- (mergingResult.getAddedImportsOffset()
+ mergingResult.getAddedGlobalsOffset()),
droolsSyntaxErrorMessage.getColumn(),
droolsSyntaxErrorMessage.getMessage()))
.toList())
.deprecatedWarnings(droolsValidation.getDeprecatedWarnings()
.stream()
.map(droolsSyntaxDeprecatedWarnings -> new RuleSyntaxWarningMessage(droolsSyntaxDeprecatedWarnings.getLine()
- (mergingResult.getAddedImportsOffset()
+ mergingResult.getAddedGlobalsOffset()),
droolsSyntaxDeprecatedWarnings.getColumn(),
droolsSyntaxDeprecatedWarnings.getMessage()))
.toList())
.blacklistErrorMessages(droolsValidation.getBlacklistErrorMessages()
.stream()
.map(droolsBlacklistErrorMessage -> new RuleBlacklistErrorMessage(droolsBlacklistErrorMessage.getLine()
- (mergingResult.getAddedImportsOffset()
+ mergingResult.getAddedGlobalsOffset()),
droolsBlacklistErrorMessage.getColumn(),
droolsBlacklistErrorMessage.getMessage()))
.toList())
.build();
if (!droolsValidation.isCompiled()) {
return new ResponseEntity<>(droolsValidationResponse, HttpStatus.UNPROCESSABLE_ENTITY);
} else {
rulesResponse.setRules(mergingResult.getMergedRules());
}
} catch (Exception e) { } catch (Exception e) {
throw new RulesValidationException("Error trying to compile the cleaned rule file: " + mergedRules + " with message: {} " + e.getMessage(), e); throw new RulesValidationException("Could not test rules: " + e.getMessage(), e);
} }
rulesResponse.setRules(mergedRules); return new ResponseEntity<>(rulesResponse, HttpStatus.OK);
return rulesResponse;
} }

View File

@ -0,0 +1,24 @@
package com.iqser.red.service.redaction.v1.server.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(description = "Object containing a string of Drools rules.")
public class RuleMergingResult {
@Schema(description = "The merged rules.")
private String mergedRules;
@Schema(description = "the length of added imports from sytemRules")
private int addedImportsOffset;
@Schema(description = "the length of added globals from sytemRules")
private int addedGlobalsOffset;
}

View File

@ -1,23 +0,0 @@
package com.iqser.red.service.redaction.v1.server.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(description = "Object containing a string of Drools rules.")
public class RulesResponse {
@Schema(description = "The actual string of rules.")
private String rules;
@Schema(description = "The DossierTemplate Id for these rules")
private String dossierTemplateId;
@Schema(description = "Bad written rules can lead to timeouts or endless processing. This will be detected by the system and all analyse request for the rules will be rejected. This flag indicates that a timeout was detected and you need to fix the rules")
private boolean timeoutDetected;
}

View File

@ -26,7 +26,7 @@ import lombok.extern.slf4j.Slf4j;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE) @FieldDefaults(level = AccessLevel.PRIVATE)
public final class RuleFileBluePrint { public final class RuleCompilationResult {
String imports; String imports;
int importLine; int importLine;

View File

@ -8,9 +8,11 @@ import java.util.List;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.iqser.red.service.redaction.v1.model.RuleBuilderModel; import com.iqser.red.service.redaction.v1.model.RuleBuilderModel;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleFileBluePrint; import com.iqser.red.service.redaction.v1.server.model.RuleMergingResult;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleType; import com.knecon.fforesight.utility.rules.management.factory.RuleFileFactory;
import com.iqser.red.service.redaction.v1.server.service.drools.RuleFileParser; import com.knecon.fforesight.utility.rules.management.factory.RuleFileParser;
import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint;
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -37,34 +39,32 @@ public class RuleBuilderService {
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(rulesString); RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(rulesString);
log.info("Starting to remove system rules from ruleFile"); log.info("Starting to remove system rules from ruleFile");
for (String systemRule : systemRules) { for (String systemRule : systemRules) {
ruleFileBluePrint.dropRulesByIdentifier(RuleType.fromString(systemRule)); ruleFileBluePrint.removeRule(RuleIdentifier.fromName(systemRule));
}
ruleFileBluePrint.dropQueries();
if (removeImports) {
ruleFileBluePrint.dropImports();
} }
log.info("Finished removing system rules for ruleFile"); log.info("Finished removing system rules for ruleFile");
return RuleFileParser.buildRulesStringFromBluePrint(ruleFileBluePrint); // removing imports if flagged and dropping queries when building result string
return RuleFileFactory.buildRuleString(ruleFileBluePrint, removeImports, true);
} }
public String getRuleFileWithSeperatedSystemRules(String existingRules, String updatedRules) { public RuleMergingResult mergeUserRulesAndSystemRules(String existingRules, String updatedRules) {
//todo: when returning validation result to frotnend substract the length of imports/globals
log.info("starting to merge user rules update with system rules");
RuleFileBluePrint ruleFileBluePrintExisting = RuleFileParser.buildBluePrintFromRulesString(existingRules); RuleFileBluePrint ruleFileBluePrintExisting = RuleFileParser.buildBluePrintFromRulesString(existingRules);
ruleFileBluePrintExisting.dropAllRulesExceptSystemRules(systemRules); RuleFileBluePrint ruleFileBluePrintExistingMerged = RuleFileParser.buildBluePrintFromRulesString(updatedRules);
RuleFileBluePrint ruleFileBluePrintUpdate = RuleFileParser.buildBluePrintFromRulesString(updatedRules); // add imports from systemrules
for (String systemRule : systemRules) { ruleFileBluePrintExistingMerged.setImports(ruleFileBluePrintExisting.getImports() + ruleFileBluePrintExistingMerged.getImports());
if (ruleFileBluePrintUpdate.countRuleOccurences(RuleType.fromString(systemRule)) > 0) { //add globals from systemrules
throw new RuntimeException("System rules are not allowed in an update."); ruleFileBluePrintExistingMerged.setGlobals(ruleFileBluePrintExisting.getGlobals() + ruleFileBluePrintExistingMerged.getGlobals());
log.info("finished merging user rules update with system rules");
RuleMergingResult mergingResult = RuleMergingResult.builder()
.mergedRules(RuleFileFactory.buildRuleString(ruleFileBluePrintExisting, false, false))
.addedGlobalsOffset(ruleFileBluePrintExisting.getGlobals().length())
.addedImportsOffset(ruleFileBluePrintExisting.getImports().length())
.build();
} return mergingResult;
}
ruleFileBluePrintExisting.setImports(ruleFileBluePrintUpdate.getImports());
ruleFileBluePrintUpdate.getRuleClasses()
.forEach(ruleFileBluePrintExisting::addRuleClass);
return RuleFileParser.buildRulesStringFromBluePrint(ruleFileBluePrintExisting);
} }
} }

View File

@ -28,7 +28,7 @@ import com.iqser.red.service.redaction.v1.server.model.dictionary.SearchImplemen
import com.iqser.red.service.redaction.v1.server.model.drools.BasicQuery; import com.iqser.red.service.redaction.v1.server.model.drools.BasicQuery;
import com.iqser.red.service.redaction.v1.server.model.drools.BasicRule; import com.iqser.red.service.redaction.v1.server.model.drools.BasicRule;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleClass; import com.iqser.red.service.redaction.v1.server.model.drools.RuleClass;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleFileBluePrint; import com.iqser.red.service.redaction.v1.server.model.drools.RuleCompilationResult;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleUnit; import com.iqser.red.service.redaction.v1.server.model.drools.RuleUnit;
import com.iqser.red.service.redaction.v1.server.storage.RuleManagementResources; import com.iqser.red.service.redaction.v1.server.storage.RuleManagementResources;
@ -69,70 +69,70 @@ public class DroolsValidationService {
private DroolsValidation buildCustomDroolsValidation(String ruleString, RuleFileType ruleFileType) throws DroolsParserException { private DroolsValidation buildCustomDroolsValidation(String ruleString, RuleFileType ruleFileType) throws DroolsParserException {
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(ruleString); RuleCompilationResult ruleCompilationResult = RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(ruleString);
DroolsValidation customValidation = ruleFileBluePrint.getDroolsValidation(); DroolsValidation customValidation = ruleCompilationResult.getDroolsValidation();
addSyntaxDeprecatedWarnings(ruleFileType, ruleFileBluePrint, customValidation); addSyntaxDeprecatedWarnings(ruleFileType, ruleCompilationResult, customValidation);
addSyntaxErrorMessages(ruleFileType, ruleFileBluePrint, customValidation); addSyntaxErrorMessages(ruleFileType, ruleCompilationResult, customValidation);
if (redactionServiceSettings.isRuleExecutionSecured()) { if (redactionServiceSettings.isRuleExecutionSecured()) {
addBlacklistErrorMessages(ruleFileBluePrint, customValidation); addBlacklistErrorMessages(ruleCompilationResult, customValidation);
} }
return customValidation; return customValidation;
} }
private void addSyntaxDeprecatedWarnings(RuleFileType ruleFileType, RuleFileBluePrint ruleFileBluePrint, DroolsValidation customValidation) { private void addSyntaxDeprecatedWarnings(RuleFileType ruleFileType, RuleCompilationResult ruleCompilationResult, DroolsValidation customValidation) {
// find deprecated elements in the ruleFileBluePrint // find deprecated elements in the ruleFileBluePrint
DroolsSyntaxDeprecatedWarnings warningMessageForImports = getWarningsForDeprecatedImports(ruleFileBluePrint); DroolsSyntaxDeprecatedWarnings warningMessageForImports = getWarningsForDeprecatedImports(ruleCompilationResult);
if (warningMessageForImports != null) { if (warningMessageForImports != null) {
customValidation.getDeprecatedWarnings().add(warningMessageForImports); customValidation.getDeprecatedWarnings().add(warningMessageForImports);
} }
customValidation.getDeprecatedWarnings().addAll(getWarningsForDeprecatedRules(ruleFileBluePrint)); customValidation.getDeprecatedWarnings().addAll(getWarningsForDeprecatedRules(ruleCompilationResult));
if (ruleFileType.equals(RuleFileType.COMPONENT)) { if (ruleFileType.equals(RuleFileType.COMPONENT)) {
if (!ruleFileBluePrint.getGlobals().contains(ComponentDroolsExecutionService.COMPONENT_MAPPING_SERVICE_GLOBAL)) { if (!ruleCompilationResult.getGlobals().contains(ComponentDroolsExecutionService.COMPONENT_MAPPING_SERVICE_GLOBAL)) {
customValidation.getDeprecatedWarnings().add(buildComponentMappingServiceMissingMessage(ruleFileBluePrint)); customValidation.getDeprecatedWarnings().add(buildComponentMappingServiceMissingMessage(ruleCompilationResult));
} }
} }
} }
private static DroolsSyntaxDeprecatedWarnings buildComponentMappingServiceMissingMessage(RuleFileBluePrint ruleFileBluePrint) { private static DroolsSyntaxDeprecatedWarnings buildComponentMappingServiceMissingMessage(RuleCompilationResult ruleCompilationResult) {
return DroolsSyntaxDeprecatedWarnings.builder() return DroolsSyntaxDeprecatedWarnings.builder()
.message("global ComponentMappingService " .message("global ComponentMappingService "
+ ComponentDroolsExecutionService.COMPONENT_MAPPING_SERVICE_GLOBAL + ComponentDroolsExecutionService.COMPONENT_MAPPING_SERVICE_GLOBAL
+ "\n is missing from the rules, consider adding it, as it will be required in future versions!") + "\n is missing from the rules, consider adding it, as it will be required in future versions!")
.line(ruleFileBluePrint.getGlobalsLine()) .line(ruleCompilationResult.getGlobalsLine())
.column(0) .column(0)
.build(); .build();
} }
private DroolsSyntaxDeprecatedWarnings getWarningsForDeprecatedImports(RuleFileBluePrint ruleFileBluePrint) { private DroolsSyntaxDeprecatedWarnings getWarningsForDeprecatedImports(RuleCompilationResult ruleCompilationResult) {
if (!deprecatedElementsFinder.getDeprecatedClasses().isEmpty()) { if (!deprecatedElementsFinder.getDeprecatedClasses().isEmpty()) {
String imports = ruleFileBluePrint.getImports(); String imports = ruleCompilationResult.getImports();
SearchImplementation classesSearchImplementation = deprecatedElementsFinder.getClassesSearchImplementation(); SearchImplementation classesSearchImplementation = deprecatedElementsFinder.getClassesSearchImplementation();
List<SearchImplementation.MatchPosition> matches = classesSearchImplementation.getMatches(imports); List<SearchImplementation.MatchPosition> matches = classesSearchImplementation.getMatches(imports);
if (!matches.isEmpty()) { if (!matches.isEmpty()) {
String sb = "Following imports are deprecated: \n" + matches.stream() String sb = "Following imports are deprecated: \n" + matches.stream()
.map(m -> imports.substring(m.startIndex(), m.endIndex())) .map(m -> imports.substring(m.startIndex(), m.endIndex()))
.collect(Collectors.joining("\n")); .collect(Collectors.joining("\n"));
return DroolsSyntaxDeprecatedWarnings.builder().line(ruleFileBluePrint.getImportLine()).column(0).message(sb).build(); return DroolsSyntaxDeprecatedWarnings.builder().line(ruleCompilationResult.getImportLine()).column(0).message(sb).build();
} }
} }
return null; return null;
} }
private List<DroolsSyntaxDeprecatedWarnings> getWarningsForDeprecatedRules(RuleFileBluePrint ruleFileBluePrint) { private List<DroolsSyntaxDeprecatedWarnings> getWarningsForDeprecatedRules(RuleCompilationResult ruleCompilationResult) {
List<DroolsSyntaxDeprecatedWarnings> warningMessages = new ArrayList<>(); List<DroolsSyntaxDeprecatedWarnings> warningMessages = new ArrayList<>();
@ -141,7 +141,7 @@ public class DroolsValidationService {
SearchImplementation methodsSearchImplementation = deprecatedElementsFinder.getMethodsSearchImplementation(); SearchImplementation methodsSearchImplementation = deprecatedElementsFinder.getMethodsSearchImplementation();
Map<String, String> deprecatedMethodsSignatureMap = deprecatedElementsFinder.getDeprecatedMethodsSignaturesMap(); Map<String, String> deprecatedMethodsSignatureMap = deprecatedElementsFinder.getDeprecatedMethodsSignaturesMap();
for (RuleClass ruleClass : ruleFileBluePrint.getRuleClasses()) { for (RuleClass ruleClass : ruleCompilationResult.getRuleClasses()) {
for (RuleUnit ruleUnit : ruleClass.ruleUnits()) { for (RuleUnit ruleUnit : ruleClass.ruleUnits()) {
for (BasicRule basicRule : ruleUnit.rules()) { for (BasicRule basicRule : ruleUnit.rules()) {
List<SearchImplementation.MatchPosition> matches = methodsSearchImplementation.getMatches(basicRule.getCode()); List<SearchImplementation.MatchPosition> matches = methodsSearchImplementation.getMatches(basicRule.getCode());
@ -165,32 +165,32 @@ public class DroolsValidationService {
} }
private void addSyntaxErrorMessages(RuleFileType ruleFileType, RuleFileBluePrint ruleFileBluePrint, DroolsValidation customValidation) { private void addSyntaxErrorMessages(RuleFileType ruleFileType, RuleCompilationResult ruleCompilationResult, DroolsValidation customValidation) {
RuleFileBluePrint baseRuleFileBluePrint = switch (ruleFileType) { RuleCompilationResult baseRuleCompilationResult = switch (ruleFileType) {
case ENTITY -> RuleFileParser.buildBluePrintFromRulesString(RuleManagementResources.getBaseRuleFileString()); case ENTITY -> RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(RuleManagementResources.getBaseRuleFileString());
case COMPONENT -> RuleFileParser.buildBluePrintFromRulesString(RuleManagementResources.getBaseComponentRuleFileString()); case COMPONENT -> RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(RuleManagementResources.getBaseComponentRuleFileString());
}; };
if (!importsAreValid(baseRuleFileBluePrint, ruleFileBluePrint)) { if (!importsAreValid(baseRuleCompilationResult, ruleCompilationResult)) {
customValidation.getSyntaxErrorMessages() customValidation.getSyntaxErrorMessages()
.add(DroolsSyntaxErrorMessage.builder() .add(DroolsSyntaxErrorMessage.builder()
.line(ruleFileBluePrint.getImportLine()) .line(ruleCompilationResult.getImportLine())
.column(0) .column(0)
.message(String.format("Changing the imports is not allowed! Must be: %n%s", baseRuleFileBluePrint.getImports())) .message(String.format("Changing the imports is not allowed! Must be: %n%s", baseRuleCompilationResult.getImports()))
.build()); .build());
} }
if (!ruleFileBluePrint.getGlobals().contains(baseRuleFileBluePrint.getGlobals())) { if (!ruleCompilationResult.getGlobals().contains(baseRuleCompilationResult.getGlobals())) {
customValidation.getSyntaxErrorMessages() customValidation.getSyntaxErrorMessages()
.add(DroolsSyntaxErrorMessage.builder() .add(DroolsSyntaxErrorMessage.builder()
.line(ruleFileBluePrint.getGlobalsLine()) .line(ruleCompilationResult.getGlobalsLine())
.column(0) .column(0)
.message(String.format("Removing the globals is not allowed! Must be: %n%s", baseRuleFileBluePrint.getGlobals())) .message(String.format("Removing the globals is not allowed! Must be: %n%s", baseRuleCompilationResult.getGlobals()))
.build()); .build());
} }
baseRuleFileBluePrint.getQueries() baseRuleCompilationResult.getQueries()
.forEach(basicQuery -> { .forEach(basicQuery -> {
if (!validateQueryIsPresent(basicQuery, ruleFileBluePrint)) { if (!validateQueryIsPresent(basicQuery, ruleCompilationResult)) {
customValidation.getSyntaxErrorMessages() customValidation.getSyntaxErrorMessages()
.add(DroolsSyntaxErrorMessage.builder() .add(DroolsSyntaxErrorMessage.builder()
.line(basicQuery.getLine()) .line(basicQuery.getLine())
@ -201,7 +201,7 @@ public class DroolsValidationService {
}); });
if (ruleFileType.equals(RuleFileType.ENTITY)) { if (ruleFileType.equals(RuleFileType.ENTITY)) {
String requiredAgendaGroup = "LOCAL_DICTIONARY_ADDS"; String requiredAgendaGroup = "LOCAL_DICTIONARY_ADDS";
if (!validateAgendaGroupIsPresent(ruleFileBluePrint, requiredAgendaGroup)) { if (!validateAgendaGroupIsPresent(ruleCompilationResult, requiredAgendaGroup)) {
customValidation.getSyntaxErrorMessages() customValidation.getSyntaxErrorMessages()
.add(DroolsSyntaxErrorMessage.builder() .add(DroolsSyntaxErrorMessage.builder()
.line(0) .line(0)
@ -213,18 +213,18 @@ public class DroolsValidationService {
} }
private boolean validateAgendaGroupIsPresent(RuleFileBluePrint ruleFileBluePrint, String agendaGroupName) { private boolean validateAgendaGroupIsPresent(RuleCompilationResult ruleCompilationResult, String agendaGroupName) {
return ruleFileBluePrint.streamAllRules() return ruleCompilationResult.streamAllRules()
.anyMatch(basicRule -> basicRule.getAgendaGroup().equals(agendaGroupName)); .anyMatch(basicRule -> basicRule.getAgendaGroup().equals(agendaGroupName));
} }
private boolean importsAreValid(RuleFileBluePrint baseRuleFileBluePrint, RuleFileBluePrint ruleFileBluePrint) { private boolean importsAreValid(RuleCompilationResult baseRuleCompilationResult, RuleCompilationResult ruleCompilationResult) {
// imports may shrink, but not add anything new! // imports may shrink, but not add anything new!
Set<String> baseImports = baseRuleFileBluePrint.getImportSplitByKeyword(); Set<String> baseImports = baseRuleCompilationResult.getImportSplitByKeyword();
Set<String> imports = ruleFileBluePrint.getImportSplitByKeyword(); Set<String> imports = ruleCompilationResult.getImportSplitByKeyword();
Set<String> additionalImports = Sets.difference(imports, baseImports); Set<String> additionalImports = Sets.difference(imports, baseImports);
@ -233,15 +233,15 @@ public class DroolsValidationService {
} }
private static boolean validateQueryIsPresent(BasicQuery queryToCheckFor, RuleFileBluePrint ruleFileBluePrint) { private static boolean validateQueryIsPresent(BasicQuery queryToCheckFor, RuleCompilationResult ruleCompilationResult) {
return ruleFileBluePrint.getQueries() return ruleCompilationResult.getQueries()
.stream() .stream()
.anyMatch(query -> query.getName().equals(queryToCheckFor.getName()) && query.getCode().equals(queryToCheckFor.getCode())); .anyMatch(query -> query.getName().equals(queryToCheckFor.getName()) && query.getCode().equals(queryToCheckFor.getCode()));
} }
private void addBlacklistErrorMessages(RuleFileBluePrint ruleFileBluePrint, DroolsValidation customValidation) { private void addBlacklistErrorMessages(RuleCompilationResult ruleCompilationResult, DroolsValidation customValidation) {
List<DroolsBlacklistErrorMessage> blacklistErrorMessages = new ArrayList<>(); List<DroolsBlacklistErrorMessage> blacklistErrorMessages = new ArrayList<>();
@ -253,14 +253,14 @@ public class DroolsValidationService {
// check also the imports // check also the imports
DroolsBlacklistErrorMessage blacklistErrorMessage = checkAndGetBlackListedMessages(blacklistedKeywordSearchImplementation, DroolsBlacklistErrorMessage blacklistErrorMessage = checkAndGetBlackListedMessages(blacklistedKeywordSearchImplementation,
ruleFileBluePrint.getImports(), ruleCompilationResult.getImports(),
ruleFileBluePrint.getImportLine()); ruleCompilationResult.getImportLine());
if (blacklistErrorMessage != null) { if (blacklistErrorMessage != null) {
blacklistErrorMessages.add(blacklistErrorMessage); blacklistErrorMessages.add(blacklistErrorMessage);
} }
// check the rules // check the rules
for (RuleClass ruleClass : ruleFileBluePrint.getRuleClasses()) { for (RuleClass ruleClass : ruleCompilationResult.getRuleClasses()) {
for (RuleUnit ruleUnit : ruleClass.ruleUnits()) { for (RuleUnit ruleUnit : ruleClass.ruleUnits()) {
for (BasicRule basicRule : ruleUnit.rules()) { for (BasicRule basicRule : ruleUnit.rules()) {
DroolsBlacklistErrorMessage ruleBlacklistErrorMessage = checkAndGetBlackListedMessages(blacklistedKeywordSearchImplementation, DroolsBlacklistErrorMessage ruleBlacklistErrorMessage = checkAndGetBlackListedMessages(blacklistedKeywordSearchImplementation,

View File

@ -20,7 +20,7 @@ import com.iqser.red.service.redaction.v1.model.DroolsValidation;
import com.iqser.red.service.redaction.v1.server.model.drools.BasicQuery; import com.iqser.red.service.redaction.v1.server.model.drools.BasicQuery;
import com.iqser.red.service.redaction.v1.server.model.drools.BasicRule; import com.iqser.red.service.redaction.v1.server.model.drools.BasicRule;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleClass; import com.iqser.red.service.redaction.v1.server.model.drools.RuleClass;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleFileBluePrint; import com.iqser.red.service.redaction.v1.server.model.drools.RuleCompilationResult;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleIdentifier; import com.iqser.red.service.redaction.v1.server.model.drools.RuleIdentifier;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleType; import com.iqser.red.service.redaction.v1.server.model.drools.RuleType;
import com.iqser.red.service.redaction.v1.server.model.drools.RuleUnit; import com.iqser.red.service.redaction.v1.server.model.drools.RuleUnit;
@ -29,14 +29,38 @@ import lombok.SneakyThrows;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
@UtilityClass @UtilityClass
public class RuleFileParser { public class RuleCompilationResultParser {
private final static Pattern ruleIdentifierInCodeFinder = Pattern.compile( private final static Pattern ruleIdentifierInCodeFinder = Pattern.compile(
"\\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 RuleFileBluePrint buildBluePrintFromRulesString(String ruleString) { public RuleCompilationResult buildRuleCompilationResultFromRuleString(String ruleString) {
DroolsValidation customDroolsValidation = DroolsValidation.builder().build(); DroolsValidation customDroolsValidation = DroolsValidation.builder().build();
DrlParser parser = new DrlParser(LanguageLevelOption.DRL6); DrlParser parser = new DrlParser(LanguageLevelOption.DRL6);
@ -65,26 +89,26 @@ public class RuleFileParser {
List<RuleClass> ruleClasses = buildRuleClasses(allRules); List<RuleClass> ruleClasses = buildRuleClasses(allRules);
return new RuleFileBluePrint(imports.trim(), return new RuleCompilationResult(imports.trim(),
packageDescr.getImports() packageDescr.getImports()
.stream() .stream()
.findFirst() .findFirst()
.map(ImportDescr::getLine) .map(ImportDescr::getLine)
.orElse(0), .orElse(0),
globals.trim(), globals.trim(),
packageDescr.getGlobals() packageDescr.getGlobals()
.stream() .stream()
.findFirst() .findFirst()
.map(GlobalDescr::getLine) .map(GlobalDescr::getLine)
.orElse(0), .orElse(0),
allQueries, allQueries,
ruleClasses, ruleClasses,
customDroolsValidation); customDroolsValidation);
} }
@SneakyThrows @SneakyThrows
public String buildRulesStringFromBluePrint(RuleFileBluePrint bluePrint) { public String buildRulesStringFromBluePrint(RuleCompilationResult bluePrint) {
StringBuilder ruleStringBuilder = new StringBuilder(); StringBuilder ruleStringBuilder = new StringBuilder();
@ -179,6 +203,7 @@ public class RuleFileParser {
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)

View File

@ -22,11 +22,11 @@ import com.iqser.red.service.redaction.v1.model.RuleValidationModel;
import com.iqser.red.service.redaction.v1.server.DeprecatedElementsFinder; import com.iqser.red.service.redaction.v1.server.DeprecatedElementsFinder;
import com.iqser.red.service.redaction.v1.server.RedactionServiceSettings; import com.iqser.red.service.redaction.v1.server.RedactionServiceSettings;
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.model.drools.RuleFileBluePrint; import com.iqser.red.service.redaction.v1.server.model.drools.RuleCompilationResult;
import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService; import com.iqser.red.service.redaction.v1.server.service.document.EntityEnrichmentService;
import com.iqser.red.service.redaction.v1.server.service.drools.DroolsValidationService; import com.iqser.red.service.redaction.v1.server.service.drools.DroolsValidationService;
import com.iqser.red.service.redaction.v1.server.service.drools.KieContainerCreationService; import com.iqser.red.service.redaction.v1.server.service.drools.KieContainerCreationService;
import com.iqser.red.service.redaction.v1.server.service.drools.RuleFileParser; import com.iqser.red.service.redaction.v1.server.service.drools.RuleCompilationResultParser;
import com.iqser.red.service.redaction.v1.server.storage.RuleManagementResources; import com.iqser.red.service.redaction.v1.server.storage.RuleManagementResources;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@ -235,11 +235,11 @@ class DroolsValidationServiceTest {
if (droolsValidation.isCompiled()) { if (droolsValidation.isCompiled()) {
continue; continue;
} }
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(rulesString); RuleCompilationResult ruleCompilationResult = RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(rulesString);
RuleFileBluePrint baseRuleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(RuleManagementResources.getBaseRuleFileString()); RuleCompilationResult baseRuleCompilationResult = RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(RuleManagementResources.getBaseRuleFileString());
rulesString = rulesString.replace(ruleFileBluePrint.getImports(), baseRuleFileBluePrint.getImports()); rulesString = rulesString.replace(ruleCompilationResult.getImports(), baseRuleCompilationResult.getImports());
rulesString = rulesString.replace(ruleFileBluePrint.getGlobals(), baseRuleFileBluePrint.getGlobals()); rulesString = rulesString.replace(ruleCompilationResult.getGlobals(), baseRuleCompilationResult.getGlobals());
try (OutputStream outStream = new FileOutputStream(rulesFile.getFile().getAbsolutePath().replace("/test", "").replace("build", "src/test"))) { try (OutputStream outStream = new FileOutputStream(rulesFile.getFile().getAbsolutePath().replace("/test", "").replace("build", "src/test"))) {
outStream.write(rulesString.getBytes(StandardCharsets.UTF_8)); outStream.write(rulesString.getBytes(StandardCharsets.UTF_8));
@ -460,9 +460,9 @@ class DroolsValidationServiceTest {
end end
"""; """;
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(ruleString); RuleCompilationResult ruleCompilationResult = RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(ruleString);
assertFalse(ruleFileBluePrint.getDroolsValidation().isCompiled()); assertFalse(ruleCompilationResult.getDroolsValidation().isCompiled());
} }
} }

View File

@ -48,17 +48,17 @@ public class RuleFileFactory {
} }
RuleFileBluePrint bluePrint = RuleFileParser.buildBluePrintFromAllRulesFile(applicationType); RuleFileBluePrint bluePrint = RuleFileParser.buildBluePrintFromAllRulesFile(applicationType);
RuleFileBluePrint filteredBluePrint = bluePrint.buildFilteredBluePrintByRuleIdentifiers(identifiers); RuleFileBluePrint filteredBluePrint = bluePrint.buildFilteredBluePrintByRuleIdentifiers(identifiers);
return buildRuleString(filteredBluePrint); return buildRuleString(filteredBluePrint, false, false);
} }
@SneakyThrows @SneakyThrows
public String buildRuleString(RuleFileBluePrint bluePrint) { public String buildRuleString(RuleFileBluePrint bluePrint, boolean dropImports, boolean dropQueries) {
try (var templateInputStream = RuleManagementResources.getTemplateInputStream()) { try (var templateInputStream = RuleManagementResources.getTemplateInputStream()) {
String template = new String(templateInputStream.readAllBytes(), StandardCharsets.UTF_8); String template = new String(templateInputStream.readAllBytes(), StandardCharsets.UTF_8);
List<RuleType> templateRuleOrder = parseRuleOrder(template); List<RuleType> templateRuleOrder = parseRuleOrder(template);
return buildBluePrintWithTemplateRuleOrder(bluePrint, templateRuleOrder); return buildBluePrintWithTemplateRuleOrder(bluePrint, templateRuleOrder, dropImports, dropQueries);
} }
} }
@ -72,23 +72,31 @@ public class RuleFileFactory {
} }
private String buildBluePrintWithTemplateRuleOrder(RuleFileBluePrint bluePrint, List<RuleType> ruleOrder) { private String buildBluePrintWithTemplateRuleOrder(RuleFileBluePrint bluePrint, List<RuleType> ruleOrder, boolean dropImports, boolean dropQueries) {
Set<RuleType> additionalRuleTypes = bluePrint.ruleClasses() Set<RuleType> additionalRuleTypes = bluePrint.getRuleClasses()
.stream() .stream()
.map(RuleClass::ruleType) .map(RuleClass::ruleType)
.filter(ruleType -> !ruleOrder.contains(ruleType)) .filter(ruleType -> !ruleOrder.contains(ruleType))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(bluePrint.imports()); if (!dropImports) {
sb.append(bluePrint.getImports());
sb.append("\n\n");
}
sb.append(bluePrint.getGlobals());
sb.append("\n\n"); sb.append("\n\n");
sb.append(bluePrint.globals()); sb.append("//------------------------------------ declarations ------------------------------------");
sb.append("\n\n"); sb.append("\n\n");
sb.append("//------------------------------------ queries ------------------------------------"); sb.append(bluePrint.getDeclarations());
sb.append("\n\n");
sb.append(bluePrint.queries());
sb.append("\n\n"); sb.append("\n\n");
if (!dropQueries) {
sb.append("//------------------------------------ queries ------------------------------------");
sb.append("\n\n");
sb.append(bluePrint.getQueries());
sb.append("\n\n");
}
for (RuleType ruleBlockType : ruleOrder) { for (RuleType ruleBlockType : ruleOrder) {
if (ruleBlockType.isWildCard()) { if (ruleBlockType.isWildCard()) {
additionalRuleTypes.stream() additionalRuleTypes.stream()
@ -101,6 +109,9 @@ public class RuleFileFactory {
} }
writeRuleClass(bluePrint, ruleBlockType, sb); writeRuleClass(bluePrint, ruleBlockType, sb);
} }
sb.append("//------------------------------------ functions ------------------------------------");
sb.append("\n\n");
sb.append(bluePrint.getFunctions());
return sb.toString().trim() + "\n"; return sb.toString().trim() + "\n";
} }

View File

@ -10,6 +10,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.drools.drl.ast.descr.AbstractClassTypeDeclarationDescr;
import org.drools.drl.ast.descr.FunctionDescr;
import org.drools.drl.ast.descr.ImportDescr; import org.drools.drl.ast.descr.ImportDescr;
import org.drools.drl.ast.descr.PackageDescr; import org.drools.drl.ast.descr.PackageDescr;
import org.drools.drl.ast.descr.RuleDescr; import org.drools.drl.ast.descr.RuleDescr;
@ -18,6 +20,8 @@ import org.kie.internal.builder.conf.LanguageLevelOption;
import com.knecon.fforesight.utility.rules.management.RuleManagementResources; import com.knecon.fforesight.utility.rules.management.RuleManagementResources;
import com.knecon.fforesight.utility.rules.management.models.ApplicationType; import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
import com.knecon.fforesight.utility.rules.management.models.BasicDeclaration;
import com.knecon.fforesight.utility.rules.management.models.BasicFunction;
import com.knecon.fforesight.utility.rules.management.models.BasicRule; import com.knecon.fforesight.utility.rules.management.models.BasicRule;
import com.knecon.fforesight.utility.rules.management.models.RuleClass; import com.knecon.fforesight.utility.rules.management.models.RuleClass;
import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint; import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint;
@ -49,6 +53,8 @@ public class RuleFileParser {
PackageDescr packageDescr = parser.parse(false, rulesString); PackageDescr packageDescr = parser.parse(false, rulesString);
StringBuilder queryBuilder = new StringBuilder(); StringBuilder queryBuilder = new StringBuilder();
List<BasicRule> allRules = new LinkedList<>(); List<BasicRule> allRules = new LinkedList<>();
List<BasicFunction> functions = new LinkedList<>();
List<BasicDeclaration> declarations = new LinkedList<>();
for (RuleDescr rule : packageDescr.getRules()) { for (RuleDescr rule : packageDescr.getRules()) {
if (rule.isQuery()) { if (rule.isQuery()) {
queryBuilder.append(rulesString, rule.getStartCharacter(), rule.getEndCharacter()); queryBuilder.append(rulesString, rule.getStartCharacter(), rule.getEndCharacter());
@ -57,6 +63,21 @@ public class RuleFileParser {
} }
allRules.add(BasicRule.fromRuleDescr(rule, rulesString)); allRules.add(BasicRule.fromRuleDescr(rule, rulesString));
} }
for (FunctionDescr function : packageDescr.getFunctions()) {
functions.add(BasicFunction.fromFunctionDescr(function, rulesString));
}
for (AbstractClassTypeDeclarationDescr declaration : packageDescr.getTypeDeclarations()) {
declarations.add(BasicDeclaration.fromDeclarationDescription(declaration, rulesString));
}
for (AbstractClassTypeDeclarationDescr declaration : packageDescr.getEnumDeclarations()) {
declarations.add(BasicDeclaration.fromDeclarationDescription(declaration, rulesString));
}
for (AbstractClassTypeDeclarationDescr declaration : packageDescr.getClassAndEnumDeclarationDescrs()) {
declarations.add(BasicDeclaration.fromDeclarationDescription(declaration, rulesString));
}
for (AbstractClassTypeDeclarationDescr declaration : packageDescr.getTypeDeclarations()) {
declarations.add(BasicDeclaration.fromDeclarationDescription(declaration, rulesString));
}
String imports = rulesString.substring(0, String imports = rulesString.substring(0,
packageDescr.getImports() packageDescr.getImports()
.stream() .stream()
@ -70,7 +91,7 @@ public class RuleFileParser {
List<RuleClass> ruleClasses = buildRuleClasses(allRules); List<RuleClass> ruleClasses = buildRuleClasses(allRules);
return new RuleFileBluePrint(imports.trim(), globals.trim(), queryBuilder.toString().trim(), ruleClasses); return new RuleFileBluePrint(imports.trim(), globals.trim(), queryBuilder.toString().trim(), ruleClasses, declarations, functions);
} }

View File

@ -33,7 +33,7 @@ public class RuleFileMigrator {
//replaceRules(ruleFileBluePrint, combinedBluePrint); //replaceRules(ruleFileBluePrint, combinedBluePrint);
replaceRuleIdentifiers(combinedBluePrint, ruleFileBluePrint); replaceRuleIdentifiers(combinedBluePrint, ruleFileBluePrint);
String migratedRulesString = RuleFileFactory.buildRuleString(ruleFileBluePrint); String migratedRulesString = RuleFileFactory.buildRuleString(ruleFileBluePrint,false, false);
String migratedFilePath = ruleFile.getAbsolutePath(); String migratedFilePath = ruleFile.getAbsolutePath();
try (var out = new FileOutputStream(migratedFilePath)) { try (var out = new FileOutputStream(migratedFilePath)) {
out.write(migratedRulesString.getBytes(StandardCharsets.UTF_8)); out.write(migratedRulesString.getBytes(StandardCharsets.UTF_8));

View File

@ -46,7 +46,7 @@ public class RuleIdentifierMigrator {
bluePrint = migrateMatchedRuleForAllRules(bluePrint); bluePrint = migrateMatchedRuleForAllRules(bluePrint);
String ruleString = RuleFileFactory.buildRuleString(bluePrint); String ruleString = RuleFileFactory.buildRuleString(bluePrint, false, false);
try (var out = new FileOutputStream("/tmp/all_redact_manager_rules.drl")) { try (var out = new FileOutputStream("/tmp/all_redact_manager_rules.drl")) {
out.write(ruleString.getBytes(StandardCharsets.UTF_8)); out.write(ruleString.getBytes(StandardCharsets.UTF_8));
} }
@ -57,9 +57,10 @@ public class RuleIdentifierMigrator {
} }
//todo: introduce functions and declarations
private static RuleFileBluePrint migrateMatchedRuleForAllRules(RuleFileBluePrint bluePrint) { private static RuleFileBluePrint migrateMatchedRuleForAllRules(RuleFileBluePrint bluePrint) {
List<BasicRule> migratedRules = bluePrint.ruleClasses() List<BasicRule> migratedRules = bluePrint.getRuleClasses()
.stream() .stream()
.map(RuleClass::ruleUnits) .map(RuleClass::ruleUnits)
.flatMap(Collection::stream) .flatMap(Collection::stream)
@ -67,7 +68,12 @@ public class RuleIdentifierMigrator {
.flatMap(Collection::stream) .flatMap(Collection::stream)
.map(RuleIdentifierMigrator::migrateMatchedRule) .map(RuleIdentifierMigrator::migrateMatchedRule)
.toList(); .toList();
RuleFileBluePrint migratedBluePrint = new RuleFileBluePrint(bluePrint.imports(), bluePrint.globals(), bluePrint.queries(), new LinkedList<>()); RuleFileBluePrint migratedBluePrint = new RuleFileBluePrint(bluePrint.getImports(),
bluePrint.getGlobals(),
bluePrint.getQueries(),
new LinkedList<>(),
new LinkedList<>(),
new LinkedList<>());
migratedRules.forEach(migratedBluePrint::addRule); migratedRules.forEach(migratedBluePrint::addRule);
return migratedBluePrint; return migratedBluePrint;
} }

View File

@ -0,0 +1,34 @@
package com.knecon.fforesight.utility.rules.management.models;
import org.drools.drl.ast.descr.AbstractClassTypeDeclarationDescr;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.FieldDefaults;
@Getter
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class BasicDeclaration {
@EqualsAndHashCode.Include
String declarationFullTypeName;
String body;
int line;
public static BasicDeclaration fromDeclarationDescription(AbstractClassTypeDeclarationDescr declaration, String rulesString) {
String declarationFullTypeName = declaration.getFullTypeName();
String body = rulesString.substring(declaration.getStartCharacter(), declaration.getEndCharacter());
int line = declaration.getLine();
return new BasicDeclaration(declarationFullTypeName, body, line);
}
}

View File

@ -0,0 +1,36 @@
package com.knecon.fforesight.utility.rules.management.models;
import org.drools.drl.ast.descr.FunctionDescr;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.FieldDefaults;
@Getter
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class BasicFunction {
@EqualsAndHashCode.Include
String functionName;
String returnType;
String body;
int line;
public static BasicFunction fromFunctionDescr(FunctionDescr function, String rulesString) {
String functionName = function.getName();
String returnType = function.getReturnType();
String body = rulesString.substring(function.getStartCharacter(), function.getEndCharacter());
int line = function.getLine();
return new BasicFunction(functionName, returnType, body, line);
}
}

View File

@ -10,7 +10,29 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public record RuleFileBluePrint(String imports, String globals, String queries, List<RuleClass> ruleClasses) { import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
@Data
@Slf4j
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class RuleFileBluePrint {
String imports;
String globals;
String queries;
List<RuleClass> ruleClasses;
List<BasicDeclaration> declarations;
List<BasicFunction> functions;
public boolean removeRule(RuleIdentifier ruleIdentifier) { public boolean removeRule(RuleIdentifier ruleIdentifier) {
@ -24,7 +46,7 @@ public record RuleFileBluePrint(String imports, String globals, String queries,
ruleClass.ruleUnits().remove(ruleUnit); ruleClass.ruleUnits().remove(ruleUnit);
} }
if (ruleClass.ruleUnits().isEmpty()) { if (ruleClass.ruleUnits().isEmpty()) {
ruleClasses().remove(ruleClass); this.ruleClasses.remove(ruleClass);
} }
})); }));
return wasRemoved.get(); return wasRemoved.get();
@ -41,7 +63,7 @@ public record RuleFileBluePrint(String imports, String globals, String queries,
public Set<BasicRule> getAllRules() { public Set<BasicRule> getAllRules() {
return ruleClasses().stream() return this.ruleClasses.stream()
.map(RuleClass::ruleUnits) .map(RuleClass::ruleUnits)
.flatMap(Collection::stream) .flatMap(Collection::stream)
.map(RuleUnit::rules) .map(RuleUnit::rules)
@ -101,7 +123,7 @@ public record RuleFileBluePrint(String imports, String globals, String queries,
public Set<RuleIdentifier> getAllRuleIdentifiers() { public Set<RuleIdentifier> getAllRuleIdentifiers() {
return ruleClasses().stream() return ruleClasses.stream()
.map(RuleClass::ruleUnits) .map(RuleClass::ruleUnits)
.flatMap(Collection::stream) .flatMap(Collection::stream)
.map(RuleUnit::rules) .map(RuleUnit::rules)
@ -122,10 +144,16 @@ public record RuleFileBluePrint(String imports, String globals, String queries,
} }
public void setImports(String newImports) {
this.imports = newImports;
}
public RuleFileBluePrint buildFilteredBluePrintByRuleIdentifiers(Set<RuleIdentifier> identifiers) { public RuleFileBluePrint buildFilteredBluePrintByRuleIdentifiers(Set<RuleIdentifier> identifiers) {
RuleFileBluePrint filteredBluePrint = new RuleFileBluePrint(imports(), globals(), queries(), new LinkedList<>()); RuleFileBluePrint filteredBluePrint = new RuleFileBluePrint(imports, globals, queries, new LinkedList<>(), new LinkedList<>(), new LinkedList<>());
ruleClasses().stream() ruleClasses.stream()
.flatMap(ruleClass -> ruleClass.ruleUnits() .flatMap(ruleClass -> ruleClass.ruleUnits()
.stream()) .stream())
.flatMap(ruleUnit -> ruleUnit.rules() .flatMap(ruleUnit -> ruleUnit.rules()

View File

@ -8,7 +8,7 @@ import com.knecon.fforesight.utility.rules.management.factory.RuleFileParser;
import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint; import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint;
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier; import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
public class RuleFileBluePrintMergingTest { public class RuleCompilationResultMergingTest {
@Test @Test
public void testBothRuleFilesCanBeMerged() { public void testBothRuleFilesCanBeMerged() {