RED-9472: seperation of system rules
added endpoints for seperating and readding system rules working on service RED-9472: seperation of system rules refactored endpoints. now removing system rules on download merging user rules with systemrules on upload RED-9472: seperation of system rules RED-9472: seperation of system rules 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 RED-9472: seperation of system rules RED-9472: seperation of system rules introduced tests working on fixing bug with merging rules RED-9472: seperation of system rules introduced tests RED-9472: seperation of system rules fixed circular depdency RED-9472: seperation of system rules updated persistence service version RED-9472: seperation of system rules refactored rules refactored pcackages RED-9472: seperation of system rules fixed failing tests RED-9472: seperation of system rules fixed failing tests RED-9472: seperation of system rules fixed some sonarqube errors RED-9472: seperation of system rules fixed pmd error RED-9472: seperation of system rules added deploy stage to gitlab pipeline RED-9472: seperation of system rules RED-9472: seperation of system rules fixed a mistake RED-9472: seperation of system rules updated controller to return RulesUploadResponse including the droolsvalidationresponse RED-9472: seperation of system rules updated controller to return RulesUploadResponse including the droolsvalidationresponse
This commit is contained in:
parent
0aea884da2
commit
de7ea74ccf
@ -7,6 +7,24 @@ include:
|
|||||||
ref: 'main'
|
ref: 'main'
|
||||||
file: 'ci-templates/gradle_java.yml'
|
file: 'ci-templates/gradle_java.yml'
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
stage: deploy
|
||||||
|
tags:
|
||||||
|
- dind
|
||||||
|
script:
|
||||||
|
- echo "Building with gradle version ${BUILDVERSION}"
|
||||||
|
- gradle -Pversion=${BUILDVERSION} publish
|
||||||
|
- gradle bootBuildImage --publishImage -PbuildbootDockerHostNetwork=true -Pversion=${BUILDVERSION}
|
||||||
|
- echo "BUILDVERSION=$BUILDVERSION" >> version.env
|
||||||
|
artifacts:
|
||||||
|
reports:
|
||||||
|
dotenv: version.env
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||||
|
- if: $CI_COMMIT_BRANCH =~ /^release/
|
||||||
|
- if: $CI_COMMIT_BRANCH =~ /^feature/
|
||||||
|
- if: $CI_COMMIT_TAG
|
||||||
|
|
||||||
deploy JavaDoc:
|
deploy JavaDoc:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
@ -4,11 +4,12 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
description = "redaction-service-api-v1"
|
description = "redaction-service-api-v1"
|
||||||
val persistenceServiceVersion = "2.581.0"
|
val persistenceServiceVersion = "2.585.0-RED9472.0"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.springframework:spring-web:6.0.12")
|
implementation("org.springframework:spring-web:6.0.12")
|
||||||
implementation("com.iqser.red.service:persistence-service-internal-api-v1:${persistenceServiceVersion}")
|
implementation("com.iqser.red.service:persistence-service-internal-api-v1:${persistenceServiceVersion}")
|
||||||
|
api("com.knecon.fforesight:swagger-commons:0.7.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
|
|||||||
@ -1,13 +1,26 @@
|
|||||||
package com.iqser.red.service.redaction.v1.resources;
|
package com.iqser.red.service.redaction.v1.resources;
|
||||||
|
|
||||||
import com.iqser.red.service.redaction.v1.model.RuleBuilderModel;
|
|
||||||
|
|
||||||
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 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.SystemRulesSeperationRequest;
|
||||||
|
import com.iqser.red.service.redaction.v1.model.RuleBuilderModel;
|
||||||
|
|
||||||
public interface RuleBuilderResource {
|
public interface RuleBuilderResource {
|
||||||
|
|
||||||
@PostMapping(value = "/rule-builder-model", produces = MediaType.APPLICATION_JSON_VALUE)
|
@PostMapping(value = "/rule-builder-model", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
RuleBuilderModel getRuleBuilderModel();
|
RuleBuilderModel getRuleBuilderModel();
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping(value = "/internal-api/rules/user-rules", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
RulesResponse getRuleFileWithoutSystemRules(@RequestBody SystemRulesSeperationRequest systemRulesSeperationRequest);
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping(value = "/internal-api/rules/system-rules", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
ResponseEntity mergeUserUpdateRules(@RequestBody RulesUpdateRequest rulesUpdateRequest);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ val layoutParserVersion = "0.181.0"
|
|||||||
val jacksonVersion = "2.15.2"
|
val jacksonVersion = "2.15.2"
|
||||||
val droolsVersion = "9.44.0.Final"
|
val droolsVersion = "9.44.0.Final"
|
||||||
val pdfBoxVersion = "3.0.0"
|
val pdfBoxVersion = "3.0.0"
|
||||||
val persistenceServiceVersion = "2.581.0"
|
val persistenceServiceVersion = "2.585.0-RED9472.1"
|
||||||
val llmServiceVersion = "1.11.0"
|
val llmServiceVersion = "1.11.0"
|
||||||
val springBootStarterVersion = "3.1.5"
|
val springBootStarterVersion = "3.1.5"
|
||||||
val springCloudVersion = "4.0.4"
|
val springCloudVersion = "4.0.4"
|
||||||
@ -83,6 +83,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation("net.logstash.logback:logstash-logback-encoder:7.4")
|
implementation("net.logstash.logback:logstash-logback-encoder:7.4")
|
||||||
api("ch.qos.logback:logback-classic")
|
api("ch.qos.logback:logback-classic")
|
||||||
|
api("com.knecon.fforesight:swagger-commons:0.7.0")
|
||||||
|
|
||||||
implementation("org.reflections:reflections:0.10.2")
|
implementation("org.reflections:reflections:0.10.2")
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,111 @@
|
|||||||
package com.iqser.red.service.redaction.v1.server.controller;
|
package com.iqser.red.service.redaction.v1.server.controller;
|
||||||
|
|
||||||
import java.util.Collections;
|
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.RulesUpdateRequest;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.rules.RulesUploadResponse;
|
||||||
|
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.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.drools.DroolsValidationService;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.utils.exception.RulesValidationException;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@Slf4j
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class RuleBuilderController implements RuleBuilderResource {
|
public class RuleBuilderController implements RuleBuilderResource {
|
||||||
|
|
||||||
|
private final RuleBuilderService ruleBuilderService;
|
||||||
|
private final DroolsValidationService droolsValidationService;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RuleBuilderModel getRuleBuilderModel() {
|
public RuleBuilderModel getRuleBuilderModel() {
|
||||||
|
|
||||||
RuleBuilderModel ruleBuilderModel = new RuleBuilderModel();
|
return this.ruleBuilderService.getRuleBuilderModel();
|
||||||
|
}
|
||||||
|
|
||||||
ruleBuilderModel.setWhenClauses(Collections.emptyList());
|
|
||||||
ruleBuilderModel.setThenConditions(Collections.emptyList());
|
|
||||||
|
|
||||||
return ruleBuilderModel;
|
@Override
|
||||||
|
public RulesResponse getRuleFileWithoutSystemRules(SystemRulesSeperationRequest systemRulesSeperationRequest) {
|
||||||
|
|
||||||
|
RulesResponse rulesResponse = new RulesResponse();
|
||||||
|
String filteredRules = this.ruleBuilderService.cleanRuleFileOfSystemRules(systemRulesSeperationRequest.getRules(), true);
|
||||||
|
if (filteredRules.isEmpty()) {
|
||||||
|
throw new RuntimeException("There was an error when cleaning the rulefile of sytem rules");
|
||||||
|
}
|
||||||
|
rulesResponse.setRules(filteredRules);
|
||||||
|
return rulesResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity mergeUserUpdateRules(RulesUpdateRequest rulesUpdateRequest) {
|
||||||
|
|
||||||
|
RulesUploadResponse rulesUploadResponse = new RulesUploadResponse();
|
||||||
|
DroolsValidationResponse droolsValidationResponse;
|
||||||
|
RuleMergingResult mergingResult = ruleBuilderService.mergeUserRulesAndSystemRules(rulesUpdateRequest.getExistingRules(), rulesUpdateRequest.getUpdatedRules());
|
||||||
|
if (mergingResult.getMergedRules().isEmpty()) {
|
||||||
|
throw new RuntimeException("There was an error when merging the user rule update into the rule file");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
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 {
|
||||||
|
//
|
||||||
|
rulesUploadResponse.setRules(mergingResult.getMergedRules());
|
||||||
|
rulesUploadResponse.setDroolsValidationResponse(droolsValidationResponse);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RulesValidationException("Could not test rules: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return new ResponseEntity<>(rulesUploadResponse, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private enum RuleFileType {
|
||||||
|
ENTITY,
|
||||||
|
COMPONENT
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@ package com.iqser.red.service.redaction.v1.server.model.document.nodes;
|
|||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.experimental.FieldDefaults;
|
import lombok.experimental.FieldDefaults;
|
||||||
@ -46,7 +45,6 @@ public class SuperSection extends AbstractSemanticNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
||||||
@ -86,5 +84,4 @@ public class SuperSection extends AbstractSemanticNode {
|
|||||||
return streamAllSubNodesOfType(NodeType.HEADLINE).anyMatch(h -> h.containsStringIgnoreCase(value));
|
return streamAllSubNodesOfType(NodeType.HEADLINE).anyMatch(h -> h.containsStringIgnoreCase(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,13 +18,15 @@ import lombok.Builder;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.experimental.FieldDefaults;
|
import lombok.experimental.FieldDefaults;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@Slf4j
|
||||||
@Builder
|
@Builder
|
||||||
@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;
|
||||||
@ -43,9 +45,62 @@ public final class RuleFileBluePrint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void dropRulesByIdentifier(RuleType ruleType) {
|
||||||
|
|
||||||
|
log.info("removing rule with identifier {}", ruleType.name());
|
||||||
|
|
||||||
|
List<RuleClass> rulesToBeRemoved = ruleClasses.stream()
|
||||||
|
.filter(ruleClass -> Objects.equals(ruleClass.ruleType(), ruleType))
|
||||||
|
.toList();
|
||||||
|
log.info("rules to be removed {}", 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.replaceAll("\n", "").split("import"))
|
return Arrays.stream(imports.replace("\n", "").split("import"))
|
||||||
.map(String::trim)
|
.map(String::trim)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
@ -74,7 +129,7 @@ public final class RuleFileBluePrint {
|
|||||||
public List<RuleIdentifier> getAllRuleIdentifiers() {
|
public List<RuleIdentifier> getAllRuleIdentifiers() {
|
||||||
|
|
||||||
return streamAllRules().map(BasicRule::getIdentifier)
|
return streamAllRules().map(BasicRule::getIdentifier)
|
||||||
.collect(Collectors.toList());
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -94,4 +149,10 @@ public final class RuleFileBluePrint {
|
|||||||
return "RuleFileBluePrint[imports=" + imports + ", globals=" + globals + ", queries=" + queries + ", ruleClasses=" + ruleClasses + ']';
|
return "RuleFileBluePrint[imports=" + imports + ", globals=" + globals + ", queries=" + queries + ", ruleClasses=" + ruleClasses + ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addRuleClass(RuleClass ruleClass) {
|
||||||
|
|
||||||
|
this.ruleClasses.add(ruleClass);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.ApplicationType;
|
||||||
|
|
||||||
|
@SuppressWarnings("PMD")
|
||||||
|
public class RuleManagementResources {
|
||||||
|
|
||||||
|
public static InputStream getAllRulesInputStream(ApplicationType applicationType) {
|
||||||
|
|
||||||
|
if (applicationType == ApplicationType.RM) {
|
||||||
|
return RuleManagementResources.class.getClassLoader().getResourceAsStream("drools/all_redact_manager_rules.drl");
|
||||||
|
}
|
||||||
|
return RuleManagementResources.class.getClassLoader().getResourceAsStream("drools/all_rules_documine.drl");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static InputStream getDefaultRuleIdentifiesInputStream(ApplicationType applicationType) {
|
||||||
|
|
||||||
|
if (applicationType == ApplicationType.RM) {
|
||||||
|
return RuleManagementResources.class.getClassLoader().getResourceAsStream("rulesmanagement/default_rule_identifiers.txt");
|
||||||
|
} else {
|
||||||
|
return RuleManagementResources.class.getClassLoader().getResourceAsStream("rulesmanagement/default_rule_identifiers_dm.txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static InputStream getTemplateInputStream() {
|
||||||
|
|
||||||
|
return RuleManagementResources.class.getClassLoader().getResourceAsStream("rulesmanagement/order_template.txt");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,12 +1,12 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.factory;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.factory;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.RuleManagementResources;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.RuleManagementResources;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.ApplicationType;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.factory;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.factory;
|
||||||
|
|
||||||
import static java.util.Collections.emptySet;
|
import static java.util.Collections.emptySet;
|
||||||
|
|
||||||
@ -9,13 +9,13 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.RuleManagementResources;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.RuleManagementResources;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.ApplicationType;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleClass;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleClass;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleFileBluePrint;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleType;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleType;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleUnit;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleUnit;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
@ -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,35 @@ 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");
|
||||||
|
} else {
|
||||||
|
//todo: this is hacked to enable compiling the rules without imports
|
||||||
|
sb.append("package drools");
|
||||||
|
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().isEmpty() ? "" : 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 +113,9 @@ public class RuleFileFactory {
|
|||||||
}
|
}
|
||||||
writeRuleClass(bluePrint, ruleBlockType, sb);
|
writeRuleClass(bluePrint, ruleBlockType, sb);
|
||||||
}
|
}
|
||||||
|
sb.append("//------------------------------------ functions ------------------------------------");
|
||||||
|
sb.append("\n\n");
|
||||||
|
sb.append(bluePrint.getFunctions().isEmpty() ? "" : bluePrint.getFunctions());
|
||||||
return sb.toString().trim() + "\n";
|
return sb.toString().trim() + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,30 +1,35 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.factory;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.factory;
|
||||||
|
|
||||||
import static java.util.stream.Collectors.groupingBy;
|
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;
|
||||||
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;
|
||||||
import org.drools.drl.parser.DrlParser;
|
import org.drools.drl.parser.DrlParser;
|
||||||
import org.kie.internal.builder.conf.LanguageLevelOption;
|
import org.kie.internal.builder.conf.LanguageLevelOption;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.RuleManagementResources;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.RuleManagementResources;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.ApplicationType;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.BasicRule;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.BasicDeclaration;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleClass;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.BasicFunction;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.BasicRule;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleClass;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleType;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleFileBluePrint;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleUnit;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
||||||
import com.knecon.fforesight.utility.rules.management.utils.RuleFileIO;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleType;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleUnit;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.utils.RuleFileIO;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
@ -45,10 +50,19 @@ public class RuleFileParser {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public RuleFileBluePrint buildBluePrintFromRulesString(String rulesString) {
|
public RuleFileBluePrint buildBluePrintFromRulesString(String rulesString) {
|
||||||
|
|
||||||
|
return buildBluePrintFromRulesString(rulesString, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public RuleFileBluePrint buildBluePrintFromRulesString(String rulesString, boolean removeImports) {
|
||||||
|
|
||||||
DrlParser parser = new DrlParser(LanguageLevelOption.DRL6);
|
DrlParser parser = new DrlParser(LanguageLevelOption.DRL6);
|
||||||
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,12 +71,30 @@ public class RuleFileParser {
|
|||||||
}
|
}
|
||||||
allRules.add(BasicRule.fromRuleDescr(rule, rulesString));
|
allRules.add(BasicRule.fromRuleDescr(rule, rulesString));
|
||||||
}
|
}
|
||||||
String imports = rulesString.substring(0,
|
for (FunctionDescr function : packageDescr.getFunctions()) {
|
||||||
packageDescr.getImports()
|
functions.add(BasicFunction.fromFunctionDescr(function, rulesString));
|
||||||
.stream()
|
}
|
||||||
.mapToInt(ImportDescr::getEndCharacter)
|
for (AbstractClassTypeDeclarationDescr declaration : packageDescr.getTypeDeclarations()) {
|
||||||
.max()
|
declarations.add(BasicDeclaration.fromDeclarationDescription(declaration, rulesString));
|
||||||
.orElseThrow() + 1);
|
}
|
||||||
|
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 = "";
|
||||||
|
if (!removeImports && !packageDescr.getImports().isEmpty()) {
|
||||||
|
imports = rulesString.substring(0,
|
||||||
|
packageDescr.getImports()
|
||||||
|
.stream()
|
||||||
|
.mapToInt(ImportDescr::getEndCharacter)
|
||||||
|
.max()
|
||||||
|
.orElseThrow() + 1);
|
||||||
|
}
|
||||||
String globals = packageDescr.getGlobals()
|
String globals = packageDescr.getGlobals()
|
||||||
.stream()
|
.stream()
|
||||||
.map(globalDescr -> rulesString.substring(globalDescr.getStartCharacter(), globalDescr.getEndCharacter()))
|
.map(globalDescr -> rulesString.substring(globalDescr.getStartCharacter(), globalDescr.getEndCharacter()))
|
||||||
@ -70,7 +102,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -89,11 +121,17 @@ 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()));
|
||||||
return rulesPerUnit.keySet()
|
if (rulesPerUnit.keySet() != null) {
|
||||||
.stream()
|
|
||||||
.sorted()
|
return rulesPerUnit.keySet()
|
||||||
.map(unit -> new RuleUnit(unit, rulesPerUnit.get(unit)))
|
.stream()
|
||||||
.collect(Collectors.toList());
|
.sorted()
|
||||||
|
.map(unit -> new RuleUnit(unit, rulesPerUnit.get(unit)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
} else {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.migration;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.migration;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -6,12 +6,12 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileFactory;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileFactory;
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileParser;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileParser;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.BasicRule;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.BasicRule;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleFileBluePrint;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
||||||
import com.knecon.fforesight.utility.rules.management.utils.RuleFileIO;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.utils.RuleFileIO;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
@ -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));
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.migration;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.migration;
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -9,16 +9,15 @@ import java.util.List;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.RuleManagementResources;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileFactory;
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileFactory;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileParser;
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileParser;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.ApplicationType;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.BasicRule;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.BasicRule;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleUnit;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleClass;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleClass;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleFileBluePrint;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleUnit;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.RuleManagementResources;
|
||||||
import com.knecon.fforesight.utility.rules.management.translation.OldRulesParser;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.experimental.UtilityClass;
|
import lombok.experimental.UtilityClass;
|
||||||
@ -35,7 +34,6 @@ public class RuleIdentifierMigrator {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void migrateAllRuleIdentifiers() {
|
public void migrateAllRuleIdentifiers() {
|
||||||
|
|
||||||
List<OldRulesParser.OldRulesCsvRecord> parsedRecords = OldRulesParser.getOldRulesCsvRecords(RuleManagementResources.getOldRulesCsvInputStream());
|
|
||||||
RuleFileBluePrint bluePrint = getBluePrint(ApplicationType.RM);
|
RuleFileBluePrint bluePrint = getBluePrint(ApplicationType.RM);
|
||||||
|
|
||||||
// migrateIdentifier(RuleIdentifier.fromString("PII.10.0"), RuleIdentifier.fromString("CBI.20.0"), bluePrint, parsedRecords);
|
// migrateIdentifier(RuleIdentifier.fromString("PII.10.0"), RuleIdentifier.fromString("CBI.20.0"), bluePrint, parsedRecords);
|
||||||
@ -46,20 +44,17 @@ 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));
|
||||||
}
|
}
|
||||||
String csvString = OldRulesParser.formatAsCsv(parsedRecords);
|
|
||||||
try (var out = new FileOutputStream("/tmp/old_rules_with_translations.csv")) {
|
|
||||||
out.write(csvString.getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//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 +62,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;
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ public class RuleIdentifierMigrator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void migrateIdentifier(RuleIdentifier oldIdentifier, RuleIdentifier newIdentifier, RuleFileBluePrint bluePrint, List<OldRulesParser.OldRulesCsvRecord> records) {
|
public void migrateIdentifier(RuleIdentifier oldIdentifier, RuleIdentifier newIdentifier, RuleFileBluePrint bluePrint) {
|
||||||
|
|
||||||
BasicRule oldRule = bluePrint.findRuleClassByType(oldIdentifier.type())
|
BasicRule oldRule = bluePrint.findRuleClassByType(oldIdentifier.type())
|
||||||
.orElseThrow().findRuleUnitByInteger(oldIdentifier.unit())
|
.orElseThrow().findRuleUnitByInteger(oldIdentifier.unit())
|
||||||
@ -132,9 +132,6 @@ public class RuleIdentifierMigrator {
|
|||||||
bluePrint.removeRule(oldIdentifier);
|
bluePrint.removeRule(oldIdentifier);
|
||||||
bluePrint.addRule(newRule);
|
bluePrint.addRule(newRule);
|
||||||
|
|
||||||
records.stream()
|
|
||||||
.filter(record -> record.translatesTo().contains(oldIdentifier))
|
|
||||||
.forEach(record -> replaceOldIdentifier(oldIdentifier, newIdentifier, record.translatesTo()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -152,7 +149,7 @@ public class RuleIdentifierMigrator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public record Context(RuleFileBluePrint bluePrint, List<OldRulesParser.OldRulesCsvRecord> records) {
|
public record Context(RuleFileBluePrint bluePrint) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.models;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,8 +1,8 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.models;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
||||||
|
|
||||||
import org.drools.drl.ast.descr.RuleDescr;
|
import org.drools.drl.ast.descr.RuleDescr;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.utils.RuleFileIO;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.utils.RuleFileIO;
|
||||||
|
|
||||||
public record BasicRule(RuleIdentifier identifier, String name, String code) {
|
public record BasicRule(RuleIdentifier identifier, String name, String code) {
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.models;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
||||||
|
|
||||||
import org.drools.drl.ast.descr.RuleDescr;
|
import org.drools.drl.ast.descr.RuleDescr;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.models;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.models;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -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()
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.models;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.models;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.models;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.models;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.utils;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.utils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@ -0,0 +1,169 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.iqser.red.service.redaction.v1.model.RuleBuilderModel;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.model.RuleMergingResult;
|
||||||
|
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.models.RuleFileBluePrint;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class RuleBuilderService {
|
||||||
|
|
||||||
|
//todo: make this configurable
|
||||||
|
private final List<RuleType> systemRules = new ArrayList<>(Arrays.asList(new RuleType("AI"),
|
||||||
|
new RuleType("MAN"),
|
||||||
|
new RuleType("X"),
|
||||||
|
new RuleType("DICT"),
|
||||||
|
new RuleType("FA"),
|
||||||
|
new RuleType("LDS")));
|
||||||
|
|
||||||
|
|
||||||
|
public RuleBuilderModel getRuleBuilderModel() {
|
||||||
|
|
||||||
|
RuleBuilderModel ruleBuilderModel = new RuleBuilderModel();
|
||||||
|
|
||||||
|
ruleBuilderModel.setWhenClauses(Collections.emptyList());
|
||||||
|
ruleBuilderModel.setThenConditions(Collections.emptyList());
|
||||||
|
|
||||||
|
return ruleBuilderModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String cleanRuleFileOfSystemRules(String rulesString, boolean removeImports) {
|
||||||
|
|
||||||
|
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(rulesString);
|
||||||
|
log.info("Starting to remove system rules from ruleFile");
|
||||||
|
removeSystemRulesAndCheckIfAnyRemain(ruleFileBluePrint);
|
||||||
|
log.info("Finished removing system rules for ruleFile");
|
||||||
|
|
||||||
|
return RuleFileFactory.buildRuleString(ruleFileBluePrint, removeImports, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public RuleMergingResult mergeUserRulesAndSystemRules(String existingRules, String userUpdatedRules) {
|
||||||
|
|
||||||
|
log.info("starting to merge user rules update with system rules");
|
||||||
|
RuleFileBluePrint ruleFileBluePrintExisting = RuleFileParser.buildBluePrintFromRulesString(existingRules);
|
||||||
|
RuleFileBluePrint mergedRuleFileBlueprint = RuleFileParser.buildBluePrintFromRulesString(userUpdatedRules, true);
|
||||||
|
mergedRuleFileBlueprint.getRuleClasses()
|
||||||
|
.forEach(ruleClass -> {
|
||||||
|
if (systemRules.stream()
|
||||||
|
.map(RuleType::name)
|
||||||
|
.toList().contains(ruleClass.ruleType().name())) {
|
||||||
|
throw new RuntimeException("No system rule updates allowed in user rule update.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
removeAllRulesExceptSystemRulesAndCheck(ruleFileBluePrintExisting);
|
||||||
|
ruleFileBluePrintExisting.getRuleClasses()
|
||||||
|
.stream()
|
||||||
|
.flatMap(ruleClass -> ruleClass.ruleUnits()
|
||||||
|
.stream()
|
||||||
|
.flatMap(ruleUnit -> ruleUnit.rules()
|
||||||
|
.stream()))
|
||||||
|
.forEach(mergedRuleFileBlueprint::addRule);
|
||||||
|
mergedRuleFileBlueprint.setImports(ruleFileBluePrintExisting.getImports() + mergedRuleFileBlueprint.getImports());
|
||||||
|
mergedRuleFileBlueprint.setGlobals(ruleFileBluePrintExisting.getGlobals() + mergedRuleFileBlueprint.getGlobals());
|
||||||
|
mergedRuleFileBlueprint.setFunctions(Stream.concat(ruleFileBluePrintExisting.getFunctions()
|
||||||
|
.stream(),
|
||||||
|
mergedRuleFileBlueprint.getFunctions()
|
||||||
|
.stream())
|
||||||
|
.toList());
|
||||||
|
mergedRuleFileBlueprint.setDeclarations(Stream.concat(ruleFileBluePrintExisting.getDeclarations()
|
||||||
|
.stream(),
|
||||||
|
mergedRuleFileBlueprint.getDeclarations()
|
||||||
|
.stream())
|
||||||
|
.toList());
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
List<RuleIdentifier> rules = new ArrayList();
|
||||||
|
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) {
|
||||||
|
|
||||||
|
for (RuleType systemRule : systemRules) {
|
||||||
|
List<RuleUnit> rules = new ArrayList();
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -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,
|
||||||
|
|||||||
@ -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,41 @@ 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, boolean removedImports) {
|
||||||
|
|
||||||
DroolsValidation customDroolsValidation = DroolsValidation.builder().build();
|
DroolsValidation customDroolsValidation = DroolsValidation.builder().build();
|
||||||
DrlParser parser = new DrlParser(LanguageLevelOption.DRL6);
|
DrlParser parser = new DrlParser(LanguageLevelOption.DRL6);
|
||||||
@ -52,12 +79,15 @@ public class RuleFileParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String imports = ruleString.substring(0,
|
String imports = "";
|
||||||
packageDescr.getImports()
|
if (!removedImports) {
|
||||||
.stream()
|
imports = ruleString.substring(0,
|
||||||
.mapToInt(ImportDescr::getEndCharacter)
|
packageDescr.getImports()
|
||||||
.max()
|
.stream()
|
||||||
.orElseThrow() + 1);
|
.mapToInt(ImportDescr::getEndCharacter)
|
||||||
|
.max()
|
||||||
|
.orElseThrow() + 1);
|
||||||
|
}
|
||||||
String globals = packageDescr.getGlobals()
|
String globals = packageDescr.getGlobals()
|
||||||
.stream()
|
.stream()
|
||||||
.map(globalDescr -> ruleString.substring(globalDescr.getStartCharacter(), globalDescr.getEndCharacter()))
|
.map(globalDescr -> ruleString.substring(globalDescr.getStartCharacter(), globalDescr.getEndCharacter()))
|
||||||
@ -65,21 +95,81 @@ 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
|
||||||
|
public RuleCompilationResult buildRuleCompilationResultFromRuleString(String ruleString) {
|
||||||
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -126,6 +216,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)
|
||||||
@ -0,0 +1,149 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
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.common.JSONPrimitive;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.model.RuleMergingResult;
|
||||||
|
import com.iqser.red.service.redaction.v1.server.model.drools.RuleCompilationResult;
|
||||||
|
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.service.RuleBuilderService;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
|
@Import(RuleBuilderTest.RuleBuilderTestConfiguration.class)
|
||||||
|
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||||
|
public class RuleBuilderTest extends AbstractRedactionIntegrationTest {
|
||||||
|
|
||||||
|
private static final String RULES = loadFromClassPath("drools/rules_v2.drl");
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void stubClients() {
|
||||||
|
|
||||||
|
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
|
||||||
|
public void removeSystemRulesTest() {
|
||||||
|
|
||||||
|
String cleanedRulesWithImports = this.ruleBuilderService.cleanRuleFileOfSystemRules(RULES, false);
|
||||||
|
String cleanedRulesWithoutImports = this.ruleBuilderService.cleanRuleFileOfSystemRules(RULES, true);
|
||||||
|
RuleCompilationResult ruleCompilationResultWithImports = RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(cleanedRulesWithImports, false);
|
||||||
|
RuleCompilationResult ruleCompilationResultWithoutImports = RuleCompilationResultParser.buildRuleCompilationResultFromRuleString(cleanedRulesWithoutImports, true);
|
||||||
|
|
||||||
|
Assert.assertFalse(checkIfImportsDontExist(ruleCompilationResultWithImports));
|
||||||
|
Assert.assertTrue(checkIfSystemRulesDontExist(ruleCompilationResultWithImports));
|
||||||
|
Assert.assertTrue(checkIfQueriesDontExist(ruleCompilationResultWithImports));
|
||||||
|
|
||||||
|
Assert.assertTrue(checkIfImportsDontExist(ruleCompilationResultWithoutImports));
|
||||||
|
Assert.assertTrue(checkIfSystemRulesDontExist(ruleCompilationResultWithoutImports));
|
||||||
|
Assert.assertTrue(checkIfQueriesDontExist(ruleCompilationResultWithoutImports));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mergeUserRulesUpdateTest() {
|
||||||
|
|
||||||
|
RuleMergingResult mergingResult = this.ruleBuilderService.mergeUserRulesAndSystemRules(RULES, USER_RULES);
|
||||||
|
String mergedRules = mergingResult.getMergedRules();
|
||||||
|
RuleFileBluePrint ruleFileBluePrintUserRulesUpdate = RuleFileParser.buildBluePrintFromRulesString(mergedRules, true);
|
||||||
|
RuleFileBluePrint ruleFileBluePrint = RuleFileParser.buildBluePrintFromRulesString(mergedRules);
|
||||||
|
ruleFileBluePrintUserRulesUpdate.getRuleClasses()
|
||||||
|
.forEach(ruleClass -> {
|
||||||
|
Assert.assertTrue(ruleFileBluePrint.getRuleClasses().contains(ruleClass));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean checkIfSystemRulesDontExist(RuleCompilationResult ruleCompilationResult) {
|
||||||
|
|
||||||
|
return ruleCompilationResult.getRuleClasses()
|
||||||
|
.stream()
|
||||||
|
.filter(ruleClass -> this.systemRules.contains(ruleClass.ruleType().name()))
|
||||||
|
.collect(Collectors.toList()).size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean checkIfImportsDontExist(RuleCompilationResult ruleCompilationResult) {
|
||||||
|
|
||||||
|
return ruleCompilationResult.getImports().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean checkIfQueriesDontExist(RuleCompilationResult ruleCompilationResult) {
|
||||||
|
|
||||||
|
return ruleCompilationResult.getQueries().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -11,10 +11,10 @@ import java.util.List;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileParser;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileParser;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.BasicRule;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.BasicRule;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleFileBluePrint;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleFileBluePrint;
|
||||||
import com.knecon.fforesight.utility.rules.management.utils.RuleFileIO;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.utils.RuleFileIO;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|||||||
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
@ -27,10 +27,10 @@ public class DroolsCompilationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testValidateRuleSyntax() throws IOException {
|
public void testValidateRuleSyntax() throws IOException {
|
||||||
|
|
||||||
URL rmURL = Resources.getResource("all_redact_manager_rules.drl");
|
URL rmURL = Resources.getResource("rulesmanagement/all_redact_manager_rules.drl");
|
||||||
String rmRule = Resources.toString(rmURL, StandardCharsets.UTF_8);
|
String rmRule = Resources.toString(rmURL, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
URL dmURL = Resources.getResource("all_rules_documine.drl");
|
URL dmURL = Resources.getResource("rulesmanagement/all_rules_documine.drl");
|
||||||
String dmRule = Resources.toString(dmURL, StandardCharsets.UTF_8);
|
String dmRule = Resources.toString(dmURL, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
assertTrue(validateRuleSyntax(rmRule).isValid());
|
assertTrue(validateRuleSyntax(rmRule).isValid());
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
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.RuleIdentifier;
|
||||||
|
|
||||||
|
public class RuleFileBluePrintMergingTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBothRuleFilesCanBeMerged() {
|
||||||
|
|
||||||
|
RuleFileBluePrint combined = RuleFileParser.buildBluePrintFromAllRuleFiles();
|
||||||
|
assertEquals(1, combined.findRuleByIdentifier(RuleIdentifier.fromString("X.0.0")).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -8,7 +8,7 @@ import java.util.List;
|
|||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.migration.RuleFileMigrator;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.migration.RuleFileMigrator;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.factory;
|
package com.iqser.red.service.redaction.v1.server.rulesmanagement.factory;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
@ -19,10 +19,10 @@ import java.util.stream.Stream;
|
|||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.RuleManagementResources;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.RuleManagementResources;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.ApplicationType;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
||||||
import com.knecon.fforesight.utility.rules.management.utils.RuleFileIO;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.utils.RuleFileIO;
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package drools
|
||||||
|
//------------------------------------ Table extraction rules ------------------------------------
|
||||||
|
|
||||||
|
// Rule unit: TAB.0
|
||||||
|
rule "TAB.0.0: Changed Study Type File Attribute"
|
||||||
|
when
|
||||||
|
not FileAttribute(label == "OECD Number", valueEqualsAnyOf("402","403","404","405","425","429","436","438","439","471","487"))
|
||||||
|
$section: Section(containsAnyString("DATA REQUIREMENT", "TEST GUIDELINE", "MÉTODO(S) DE REFERÊNCIA(S):")
|
||||||
|
&& containsAnyString("OECD", "EPA", "OPPTS"))
|
||||||
|
then
|
||||||
|
RedactionSearchUtility.findTextRangesByRegexIgnoreCase("(?<=OECD)(?:[\\w\\s,\\[\\]\\(\\)\\.]{1,10}|(?:.{5,40}(?:Number |Procedure |Guideline )))(4[\\d]{2})", 1 ,$section.getTextBlock()).stream()
|
||||||
|
.map(boundary -> $section.getTextBlock().subSequence(boundary).toString())
|
||||||
|
.map(value -> FileAttribute.builder().label("OECD Number").value(value).build())
|
||||||
|
.forEach(fileAttribute -> insert(fileAttribute));
|
||||||
|
RedactionSearchUtility.findTextRangesByRegexIgnoreCase("(?<=OECD).{5,40}Method (4[\\d]{2}).{1,65}(\\d{4})\\)", 1, $section.getTextBlock()).stream()
|
||||||
|
.map(boundary -> $section.getTextBlock().subSequence(boundary).toString())
|
||||||
|
.map(value -> FileAttribute.builder().label("OECD Number").value(value).build())
|
||||||
|
.forEach(fileAttribute -> insert(fileAttribute));
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "TAB.0.1: Changed Guidelines"
|
||||||
|
when
|
||||||
|
$section: Section(containsAnyString("DATA REQUIREMENT", "TEST GUIDELINE", "MÉTODO(S) DE REFERÊNCIA(S):") && containsAnyString("OECD", "EPA", "OPPTS"))
|
||||||
|
then
|
||||||
|
entityCreationService.byRegex("(?<=OECD)(?:[\\w\\s,\\[\\]\\(\\)\\.]{1,10}|.{5,40}(?:Number |Procedure |Guideline ))(4[\\d]{2})", "oecd_guideline_number", EntityType.ENTITY, 1, $section)
|
||||||
|
.forEach(guideline -> guideline.apply("TAB.0.1", "OECD Guideline no. found"));
|
||||||
|
entityCreationService.byRegex("(?<=OECD)(?:[\\w\\s,\\[\\]\\(\\)\\.]{1,10}|.{5,40}(?:Number |Procedure |Guideline ))(4[\\d]{2}),?\\s\\(?(\\d{4})\\)?", "oecd_guideline_year", EntityType.ENTITY, 2, $section)
|
||||||
|
.forEach(guideline -> guideline.apply("TAB.0.1", "OECD Guideline year found"));
|
||||||
|
entityCreationService.byRegex("(?<=OECD)[\\w\\s,\\[\\]]{1,10}\\((\\d{4})\\)\\s(4[\\d]{2})", "oecd_guideline_year", EntityType.ENTITY, 1, $section)
|
||||||
|
.forEach(guideline -> guideline.apply("TAB.0.1", "OECD Guideline year found"));
|
||||||
|
entityCreationService.byRegex("(?<=OECD).{5,40}Method (4[\\d]{2}).{1,65}(\\d{4})\\)", "oecd_guideline_number", EntityType.ENTITY, 1, $section)
|
||||||
|
.forEach(guideline -> guideline.apply("TAB.0.1", "OECD Guideline number found"));
|
||||||
|
entityCreationService.byRegex("(?<=OECD).{5,40}Method (4[\\d]{2}).{1,65}(\\d{4})\\)", "oecd_guideline_year", EntityType.ENTITY, 2, $section)
|
||||||
|
.forEach(guideline -> guideline.apply("TAB.0.1", "OECD Guideline year found"));
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
// Rule unit: TAB.6
|
||||||
|
rule "TAB.6.1: Changed Targeted cell extraction (Experimental Stop date)"
|
||||||
|
when
|
||||||
|
$section: Section(getHeadline().containsString("Advanced Table Extraction"), containsAllStrings("female", "Female", "Survived", "Group 2"))
|
||||||
|
$table: Table(hasHeader("Group 2")) from $section.streamChildren().toList()
|
||||||
|
TableCell(containsWordIgnoreCase("Female"), $row: row) from $table.streamTableCellsWithHeader("Group 2").toList()
|
||||||
|
TableCell($row == row, containsStringIgnoreCase("Survived")) from $table.streamTableCellsWithHeader("Group 2").toList()
|
||||||
|
$femaleSurvived: TableCell($row == row) from $table.streamTableCellsWithHeader("Group 2").toList()
|
||||||
|
then
|
||||||
|
entityCreationService.bySemanticNode($femaleSurvived, "experiment_female_survived", EntityType.ENTITY)
|
||||||
|
.ifPresent(entity -> entity.apply("TAB.6.0", "Female in group to experimental start date"));
|
||||||
|
end
|
||||||
|
|
||||||
@ -27,10 +27,10 @@ sourceSets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":redaction-service-server-v1"))
|
implementation(project(mapOf("path" to ":redaction-service-server-v1")))
|
||||||
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
|
implementation(project(":redaction-service-server-v1"))
|
||||||
implementation("com.github.javaparser:javaparser-core:3.25.3")
|
implementation("com.github.javaparser:javaparser-core:3.25.3")
|
||||||
implementation("org.drools:drools-drl-parser:8.41.0.Final")
|
implementation("org.drools:drools-drl-parser:8.41.0.Final")
|
||||||
implementation("org.apache.commons:commons-csv:1.10.0")
|
implementation("org.apache.commons:commons-csv:1.10.0")
|
||||||
|
|||||||
@ -17,12 +17,11 @@ import org.apache.commons.cli.Option;
|
|||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileFactory;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileFactory;
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileParser;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.factory.RuleFileParser;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.ApplicationType;
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.models.RuleIdentifier;
|
||||||
import com.knecon.fforesight.utility.rules.management.translation.OldRulesParser;
|
import com.iqser.red.service.redaction.v1.server.rulesmanagement.utils.RuleFileIO;
|
||||||
import com.knecon.fforesight.utility.rules.management.utils.RuleFileIO;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
@ -72,7 +71,6 @@ public class Main {
|
|||||||
Set<RuleIdentifier> identifiers = switch (type) {
|
Set<RuleIdentifier> identifiers = switch (type) {
|
||||||
case "list", "l" -> RuleIdentifier.fromListOfIdentifiersString(input);
|
case "list", "l" -> RuleIdentifier.fromListOfIdentifiersString(input);
|
||||||
case "file", "f" -> RuleFileParser.parseRuleIdentifiersFromFile(input);
|
case "file", "f" -> RuleFileParser.parseRuleIdentifiersFromFile(input);
|
||||||
case "old", "o" -> OldRulesParser.translateOldRulesStringToNewIdentifiers(RuleFileIO.getRulesString(input), applicationType);
|
|
||||||
default -> throw new IllegalArgumentException(String.format("type \"%s\" is not valid", cmd.getOptionValue("t")));
|
default -> throw new IllegalArgumentException(String.format("type \"%s\" is not valid", cmd.getOptionValue("t")));
|
||||||
};
|
};
|
||||||
ruleFileString = RuleFileFactory.createFileFromIdentifiers(identifiers, applicationType);
|
ruleFileString = RuleFileFactory.createFileFromIdentifiers(identifiers, applicationType);
|
||||||
@ -102,7 +100,6 @@ public class Main {
|
|||||||
String type = cmd.hasOption("t") ? cmd.getOptionValue("t") : "f";
|
String type = cmd.hasOption("t") ? cmd.getOptionValue("t") : "f";
|
||||||
Map<Path, Set<RuleIdentifier>> identifiersPerFile = switch (type) {
|
Map<Path, Set<RuleIdentifier>> identifiersPerFile = switch (type) {
|
||||||
case "file", "f" -> parseIdentifiersFromFiles(Path.of(cmd.getOptionValue("input")));
|
case "file", "f" -> parseIdentifiersFromFiles(Path.of(cmd.getOptionValue("input")));
|
||||||
case "old", "o" -> translateIdentifiersFromOldFiles(Path.of(cmd.getOptionValue("input")), applicationType);
|
|
||||||
default -> throw new IllegalArgumentException(String.format("type \"%s\" is not valid in combination with the \"recursive\" flag", cmd.getOptionValue("t")));
|
default -> throw new IllegalArgumentException(String.format("type \"%s\" is not valid in combination with the \"recursive\" flag", cmd.getOptionValue("t")));
|
||||||
};
|
};
|
||||||
identifiersPerFile.keySet()
|
identifiersPerFile.keySet()
|
||||||
@ -137,13 +134,6 @@ public class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private static Map<Path, Set<RuleIdentifier>> translateIdentifiersFromOldFiles(Path inputDirectory, ApplicationType applicationType) {
|
|
||||||
|
|
||||||
return RuleFileIO.streamAllRuleFilesInDirectory(inputDirectory)
|
|
||||||
.collect(Collectors.toMap(file -> getRelativizedPath(inputDirectory, file), e -> OldRulesParser.translateOldRulesFileToNewIdentifiers(e, applicationType)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private static Map<Path, Set<RuleIdentifier>> parseIdentifiersFromFiles(Path inputDirectory) {
|
private static Map<Path, Set<RuleIdentifier>> parseIdentifiersFromFiles(Path inputDirectory) {
|
||||||
|
|||||||
@ -1,56 +0,0 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
@SuppressWarnings("PMD")
|
|
||||||
public class RuleManagementResources {
|
|
||||||
|
|
||||||
public static InputStream getAllRulesInputStream(ApplicationType applicationType) {
|
|
||||||
|
|
||||||
if (applicationType == ApplicationType.RM) {
|
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("all_redact_manager_rules.drl");
|
|
||||||
}
|
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("all_rules_documine.drl");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static InputStream getDefaultRuleIdentifiesInputStream(ApplicationType applicationType) {
|
|
||||||
|
|
||||||
if (applicationType == ApplicationType.RM) {
|
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("default_rule_identifiers.txt");
|
|
||||||
} else {
|
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("default_rule_identifiers_dm.txt");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static InputStream getTemplateInputStream() {
|
|
||||||
|
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("order_template.txt");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static InputStream getOldRulesCsvInputStream() {
|
|
||||||
|
|
||||||
return RuleManagementResources.class.getClassLoader().getResourceAsStream("old_rules_with_translations.csv");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public static String createTempOldRulesCsv(String formattedAsCsv) {
|
|
||||||
|
|
||||||
File csvFile = File.createTempFile("old_rules_with_translations-", ".csv");
|
|
||||||
try (var out = new FileOutputStream(csvFile)) {
|
|
||||||
out.write(formattedAsCsv.getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
return csvFile.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,203 +0,0 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.translation;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.apache.commons.csv.CSVFormat;
|
|
||||||
import org.apache.commons.csv.CSVPrinter;
|
|
||||||
import org.apache.commons.csv.CSVRecord;
|
|
||||||
import org.drools.drl.ast.descr.PackageDescr;
|
|
||||||
import org.drools.drl.ast.descr.RuleDescr;
|
|
||||||
import org.drools.drl.parser.DrlParser;
|
|
||||||
import org.kie.internal.builder.conf.LanguageLevelOption;
|
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.RuleManagementResources;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileParser;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.models.BasicRule;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.models.OldRule;
|
|
||||||
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.utils.RuleFileIO;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class OldRulesParser {
|
|
||||||
|
|
||||||
static List<String> HEADERS = List.of("id", "old rule names", "old rule code", "translates to");
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public void createSetOfTranslatedRuleIdentifiersForEachFileInTheCsv() {
|
|
||||||
|
|
||||||
List<String> allHeaders = List.of();
|
|
||||||
List<OldRulesCsvRecord> records = getOldRulesCsvRecords(RuleManagementResources.getOldRulesCsvInputStream());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Set<RuleIdentifier> translateOldRulesFileToNewIdentifiers(File oldRulesFile, ApplicationType applicationType) {
|
|
||||||
|
|
||||||
return translateOldRulesFileToNewIdentifiers(oldRulesFile.toString(), applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Set<RuleIdentifier> translateOldRulesFileToNewIdentifiers(String oldRulesFile, ApplicationType applicationType) {
|
|
||||||
|
|
||||||
return translateOldRulesStringToNewIdentifiers(RuleFileIO.getRulesString(oldRulesFile), applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Set<RuleIdentifier> translateEscapedOldRulesStringToNewIdentifiers(String escapedOldRulesString, ApplicationType applicationType) {
|
|
||||||
|
|
||||||
return translateOldRulesStringToNewIdentifiers(RuleFileIO.unescapeAndUnWrap(escapedOldRulesString), applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Set<RuleIdentifier> translateOldRulesStringToNewIdentifiers(String oldRulesString, ApplicationType applicationType) {
|
|
||||||
|
|
||||||
List<OldRule> oldRules = parseOldRules(oldRulesString);
|
|
||||||
List<OldRulesCsvRecord> records = getOldRulesCsvRecords(RuleManagementResources.getOldRulesCsvInputStream());
|
|
||||||
Map<OldRule, List<RuleIdentifier>> translationPairs = new HashMap<>();
|
|
||||||
for (OldRule oldRule : oldRules) {
|
|
||||||
List<RuleIdentifier> translatedIdentifiers = records.stream()
|
|
||||||
.filter(oldRulesCsvRecord -> oldRulesCsvRecord.code().equals(oldRule.code()))
|
|
||||||
.map(OldRulesCsvRecord::translatesTo)
|
|
||||||
.findAny()
|
|
||||||
.orElse(Collections.emptyList());
|
|
||||||
translationPairs.put(oldRule, translatedIdentifiers);
|
|
||||||
}
|
|
||||||
boolean allTranslated = true;
|
|
||||||
for (OldRule oldRule : translationPairs.keySet()) {
|
|
||||||
if (translationPairs.get(oldRule).isEmpty()) {
|
|
||||||
allTranslated = false;
|
|
||||||
records.add(new OldRulesCsvRecord(records.size(), oldRule.code(), oldRule.name(), Collections.emptyList()));
|
|
||||||
System.out.printf(
|
|
||||||
"Rule %s has not been translated yet! %nIt has been added to the bottom of the old_rules_with_translations.csv file. To continue, translate the rule and enter its identifier in the csv, then try again!%n",
|
|
||||||
oldRule.name());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!allTranslated) {
|
|
||||||
String formattedAsCsv = formatAsCsv(records);
|
|
||||||
String fileLocation = RuleManagementResources.createTempOldRulesCsv(formattedAsCsv);
|
|
||||||
System.out.printf("CSV File with updated values is located at %s%n", fileLocation);
|
|
||||||
throw new IllegalArgumentException("Non translated Rule found!");
|
|
||||||
}
|
|
||||||
RuleFileBluePrint bluePrint = RuleFileParser.buildBluePrintFromAllRulesFile(applicationType);
|
|
||||||
|
|
||||||
translationPairs.forEach((key, value) -> System.out.printf("Rule %s will be translated to %s \n",
|
|
||||||
key.name(),
|
|
||||||
String.format("%s: %s",
|
|
||||||
value,
|
|
||||||
value.stream()
|
|
||||||
.map(bluePrint::findRuleByIdentifier)
|
|
||||||
.flatMap(Collection::stream)
|
|
||||||
.map(BasicRule::name)
|
|
||||||
.toList())));
|
|
||||||
|
|
||||||
return Stream.concat(//
|
|
||||||
Stream.of(RuleIdentifier.fromString("X"), RuleIdentifier.fromString("FA"), RuleIdentifier.fromString("LDS"), RuleIdentifier.fromString("MAN")),//
|
|
||||||
translationPairs.values()
|
|
||||||
.stream()
|
|
||||||
.flatMap(Collection::stream))
|
|
||||||
.map(ruleIdentifier -> new RuleIdentifier(ruleIdentifier.type(), ruleIdentifier.unit(), null))
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public String formatAsCsv(List<OldRulesCsvRecord> records) {
|
|
||||||
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setHeader(HEADERS.toArray(String[]::new)).build();
|
|
||||||
try (CSVPrinter printer = new CSVPrinter(sw, csvFormat)) {
|
|
||||||
for (OldRulesCsvRecord record : records) {
|
|
||||||
printer.printRecord(Stream.of(record.id, RuleFileIO.escapeAndWrap(record.names), RuleFileIO.escapeAndWrap(record.code), record.translatesTo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sw.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private List<OldRule> parseOldRules(String oldRuleString) {
|
|
||||||
|
|
||||||
DrlParser parser = new DrlParser(LanguageLevelOption.DRL6);
|
|
||||||
PackageDescr packageDescr = parser.parse(false, oldRuleString);
|
|
||||||
List<OldRule> oldRules = new LinkedList<>();
|
|
||||||
for (RuleDescr rule : packageDescr.getRules()) {
|
|
||||||
if (!rule.isRule()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
oldRules.add(OldRule.fromRuleDescr(rule, oldRuleString));
|
|
||||||
}
|
|
||||||
return oldRules;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public List<OldRulesCsvRecord> getOldRulesCsvRecords(InputStream allRulesCsvInputStream) {
|
|
||||||
|
|
||||||
List<OldRulesCsvRecord> parsedRecords = new LinkedList<>();
|
|
||||||
try (Reader reader = new InputStreamReader(allRulesCsvInputStream)) {
|
|
||||||
Iterable<CSVRecord> records = CSVFormat.DEFAULT.withHeader().withSkipHeaderRecord().parse(reader);
|
|
||||||
for (CSVRecord record : records) {
|
|
||||||
String[] values = record.values();
|
|
||||||
parsedRecords.add(new OldRulesCsvRecord(Long.parseLong(values[0]),
|
|
||||||
RuleFileIO.unescapeAndUnWrap(values[2]),
|
|
||||||
RuleFileIO.unescapeAndUnWrap(values[1]),
|
|
||||||
parseRuleIdentifiers(values[3])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parsedRecords;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private List<RuleIdentifier> parseRuleIdentifiers(String value) {
|
|
||||||
|
|
||||||
String cleanedValue = value;
|
|
||||||
if (cleanedValue.startsWith("[")) {
|
|
||||||
cleanedValue = cleanedValue.substring(1);
|
|
||||||
}
|
|
||||||
if (cleanedValue.endsWith("]")) {
|
|
||||||
cleanedValue = cleanedValue.substring(0, cleanedValue.length() - 1);
|
|
||||||
}
|
|
||||||
if (cleanedValue.isEmpty() || cleanedValue.isBlank()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
List<RuleIdentifier> ruleIdentifiers = new LinkedList<>();
|
|
||||||
for (String identifier : cleanedValue.split(", ")) {
|
|
||||||
ruleIdentifiers.add(RuleIdentifier.fromString(identifier));
|
|
||||||
}
|
|
||||||
return ruleIdentifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private List<Boolean> parseBooleanList(String[] values) {
|
|
||||||
|
|
||||||
return Arrays.stream(values)
|
|
||||||
.map(Boolean::parseBoolean)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public record OldRulesCsvRecord(long id, String code, String names, List<RuleIdentifier> translatesTo) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
public class RuleFileBluePrintMergingTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testBothRuleFilesCanBeMerged() {
|
|
||||||
|
|
||||||
RuleFileBluePrint combined = RuleFileParser.buildBluePrintFromAllRuleFiles();
|
|
||||||
assertEquals(1, combined.findRuleByIdentifier(RuleIdentifier.fromString("X.0.0")).size());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,176 +0,0 @@
|
|||||||
package com.knecon.fforesight.utility.rules.management.translation;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import com.knecon.fforesight.utility.rules.management.RuleManagementResources;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileFactory;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.factory.RuleFileParser;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.models.ApplicationType;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.models.BasicRule;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleIdentifier;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleType;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.models.RuleUnit;
|
|
||||||
import com.knecon.fforesight.utility.rules.management.utils.RuleFileIO;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
@SuppressWarnings("PMD")
|
|
||||||
class OldRulesParserTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SneakyThrows
|
|
||||||
@Disabled
|
|
||||||
public void translateOldRulesToNewIdentifiersTest() {
|
|
||||||
|
|
||||||
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("efsa_regulation_rules.txt")) {
|
|
||||||
String oldRulesString = new String(inputStream.readAllBytes());
|
|
||||||
Set<RuleIdentifier> identifiers = OldRulesParser.translateEscapedOldRulesStringToNewIdentifiers(oldRulesString, ApplicationType.RM);
|
|
||||||
System.out.println(identifiers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SneakyThrows
|
|
||||||
@Disabled
|
|
||||||
public void translateMoreOldRules() {
|
|
||||||
|
|
||||||
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("basf/demo/table_demo.drl")) {
|
|
||||||
String oldRulesString = new String(inputStream.readAllBytes());
|
|
||||||
Set<RuleIdentifier> identifiers = OldRulesParser.translateOldRulesStringToNewIdentifiers(oldRulesString, ApplicationType.RM);
|
|
||||||
System.out.println(identifiers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Disabled
|
|
||||||
public void printTranslationsTest() {
|
|
||||||
|
|
||||||
List<OldRulesParser.OldRulesCsvRecord> records = OldRulesParser.getOldRulesCsvRecords(RuleManagementResources.getOldRulesCsvInputStream());
|
|
||||||
List.of(RuleType.fromString("SYN"), RuleType.fromString("CBI"), RuleType.fromString("PII"), RuleType.fromString("ETC"), RuleType.fromString("AI"))
|
|
||||||
.forEach(type -> {
|
|
||||||
List<RuleUnit> rulesOfClass = RuleFileParser.buildBluePrintFromAllRulesFile(ApplicationType.RM).findRuleClassByType(type)
|
|
||||||
.orElseThrow().ruleUnits();
|
|
||||||
rulesOfClass.forEach(unit -> printOldRulesThatTranslatesToNewRule(unit, records));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void printOldRulesThatTranslatesToNewRule(RuleUnit ruleUnit, List<OldRulesParser.OldRulesCsvRecord> records) {
|
|
||||||
|
|
||||||
if (ruleUnit.rules().isEmpty()) {
|
|
||||||
System.out.println("Rule unit empty, skipping!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RuleIdentifier identifier = ruleUnit.rules()
|
|
||||||
.get(0).identifier();
|
|
||||||
RuleIdentifier unitIdentifier = new RuleIdentifier(identifier.type(), identifier.unit(), null);
|
|
||||||
String oldNames = records.stream()
|
|
||||||
.filter(r -> r.translatesTo()
|
|
||||||
.stream()
|
|
||||||
.anyMatch(i -> i.matches(unitIdentifier)))
|
|
||||||
.map(OldRulesParser.OldRulesCsvRecord::names)
|
|
||||||
.map(OldRulesParserTest::removeIdFromName)
|
|
||||||
.distinct()
|
|
||||||
.collect(Collectors.joining(", "));
|
|
||||||
System.out.println(unitIdentifier.toRuleUnitString() + " " + ruleUnit.rules()
|
|
||||||
.stream()
|
|
||||||
.map(BasicRule::name)
|
|
||||||
.collect(Collectors.joining(", ")));
|
|
||||||
System.out.println("translate from");
|
|
||||||
System.out.println(oldNames);
|
|
||||||
System.out.println();
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static String removeIdFromName(String name) {
|
|
||||||
|
|
||||||
String[] values = name.split(":");
|
|
||||||
return String.join(":", Arrays.copyOfRange(values, 1, values.length));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Disabled
|
|
||||||
@SneakyThrows
|
|
||||||
public void findAllCustomerRuleFilesInDossierTemplatesRepoAndTranslate() {
|
|
||||||
|
|
||||||
String dossierTemplatesRepo = getClass().getClassLoader().getResource("pilot/EFSA_sanitisation_GFL_v1").getFile();
|
|
||||||
RuleFileIO.streamAllRuleFilesInDirectory(Path.of(dossierTemplatesRepo))
|
|
||||||
.map(e -> OldRulesParser.translateOldRulesFileToNewIdentifiers(e, ApplicationType.RM))
|
|
||||||
.map(e -> RuleFileFactory.createFileFromIdentifiers(e, ApplicationType.RM))
|
|
||||||
.peek(System.out::println)
|
|
||||||
.map(RuleFileIO::escapeAndWrap)
|
|
||||||
.forEach(System.out::println);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Disabled
|
|
||||||
@SneakyThrows
|
|
||||||
public void findAllRuleFilesInDossierTemplatesRepoAndTranslate() {
|
|
||||||
|
|
||||||
String dossierTemplatesRepo = getClass().getClassLoader().getResource("business-logic/Syngenta_RSS").getFile();
|
|
||||||
RuleFileIO.streamAllRuleFilesInDirectory(Path.of(dossierTemplatesRepo))
|
|
||||||
.map(e -> OldRulesParser.translateOldRulesFileToNewIdentifiers(e, ApplicationType.DM))
|
|
||||||
.map(e -> RuleFileFactory.createFileFromIdentifiers(e, ApplicationType.DM))
|
|
||||||
.peek(System.out::println)
|
|
||||||
.map(RuleFileIO::escapeAndWrap)
|
|
||||||
.forEach(System.out::println);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Disabled
|
|
||||||
@SneakyThrows
|
|
||||||
public void translateDossierTemplatesV2() {
|
|
||||||
|
|
||||||
// String dossierTemplatesRepo = "/home/aoezyetimoglu/repositories/RED/dossier-templates-v2/";
|
|
||||||
// Stream.of(Files.walk(Path.of(dossierTemplatesRepo + "dev")), Files.walk(Path.of(dossierTemplatesRepo + "docu")), Files.walk(Path.of(dossierTemplatesRepo + "qa")))
|
|
||||||
String dossierTemplatesRepo = "/home/aoezyetimoglu/repositories/PROJECTMANAGEMENT/Syngenta/business-logic/";
|
|
||||||
Stream.of(Files.walk(Path.of(dossierTemplatesRepo + "dev")),
|
|
||||||
Files.walk(Path.of(dossierTemplatesRepo + "dev-v2")),
|
|
||||||
Files.walk(Path.of(dossierTemplatesRepo + "prod-cp-eu-reg")),
|
|
||||||
Files.walk(Path.of(dossierTemplatesRepo + "prod-cp-global-reg")),
|
|
||||||
Files.walk(Path.of(dossierTemplatesRepo + "prod-seeds-reg"))
|
|
||||||
//
|
|
||||||
)
|
|
||||||
.flatMap(Function.identity())//
|
|
||||||
.filter(path -> path.getFileName().toString().equals("rules.drl"))//
|
|
||||||
.map(Path::toFile)//
|
|
||||||
.forEach(this::translateOldRuleFile);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private void translateOldRuleFile(File oldRulesFile) {
|
|
||||||
|
|
||||||
Set<RuleIdentifier> identifiers = OldRulesParser.translateOldRulesFileToNewIdentifiers(oldRulesFile, ApplicationType.RM);
|
|
||||||
String newRulesString = RuleFileFactory.createFileFromIdentifiers(identifiers, ApplicationType.RM);
|
|
||||||
String result = RuleFileIO.escapeAndWrap(newRulesString);
|
|
||||||
|
|
||||||
try (var out = new FileOutputStream(oldRulesFile)) {
|
|
||||||
out.write(result.getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user