com.gs.dmn.signavio.transformation.AbstractMergeInputDataTransformer Maven / Gradle / Ivy
/*
* Copyright 2016 Goldman Sachs.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.gs.dmn.signavio.transformation;
import com.gs.dmn.DMNModelRepository;
import com.gs.dmn.log.BuildLogger;
import com.gs.dmn.log.Slf4jBuildLogger;
import com.gs.dmn.runtime.DMNRuntimeException;
import com.gs.dmn.runtime.Pair;
import com.gs.dmn.signavio.SignavioDMNModelRepository;
import com.gs.dmn.signavio.testlab.InputParameterDefinition;
import com.gs.dmn.signavio.testlab.TestCase;
import com.gs.dmn.signavio.testlab.TestLab;
import com.gs.dmn.signavio.testlab.expression.Expression;
import com.gs.dmn.transformation.SimpleDMNTransformer;
import org.omg.spec.dmn._20180521.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.bind.JAXBElement;
import java.util.*;
public abstract class AbstractMergeInputDataTransformer extends SimpleDMNTransformer {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMergeInputDataTransformer.class);
private static final String FORCE_MERGE = "forceMerge";
private final BuildLogger logger;
private Map>> inputDataClasses;
private boolean forceMerge = true;
protected AbstractMergeInputDataTransformer() {
this(new Slf4jBuildLogger(LOGGER));
}
public AbstractMergeInputDataTransformer(BuildLogger logger) {
this.logger = logger;
}
@Override
public void configure(Map configuration) {
if (!(configuration == null || configuration.isEmpty())) {
Object forceMergeStr = configuration.get(FORCE_MERGE);
if (forceMergeStr instanceof String && configuration.size() == 1) {
this.forceMerge = Boolean.parseBoolean((String) forceMergeStr);
} else {
throw new DMNRuntimeException(String.format("Invalid transformer configuration: %s. Configuration does not have expected structure (expecting \"%s\" node)", configuration, FORCE_MERGE));
}
}
}
@Override
public DMNModelRepository transform(DMNModelRepository repository) {
if (isEmpty(repository)) {
logger.warn("DMN repository is empty; transformer will not run");
return repository;
}
this.inputDataClasses = new LinkedHashMap<>();
return mergeInputData(repository, logger);
}
@Override
public Pair> transform(DMNModelRepository repository, List testCasesList) {
if (isEmpty(repository, testCasesList)) {
logger.warn("DMN repository or test cases list is empty; transformer will not run");
return new Pair<>(repository, testCasesList);
}
// Transform model
if (inputDataClasses == null) {
transform(repository);
}
// Transform test cases
for (TestLab testLab: testCasesList) {
transform(testLab, (SignavioDMNModelRepository) repository);
}
return new Pair<>(repository.copy(), testCasesList);
}
private void transform(TestLab testLab, SignavioDMNModelRepository repository) {
// Check for conflicts between the values of the InputData in the same equivalence class
if (!forceMerge) {
List testCases = testLab.getTestCases();
for(TestCase testCase: testCases) {
List inputValues = testCase.getInputValues();
for(int i=0; i toRemove = new ArrayList<>();
List indexToRemove = new ArrayList<>();
List labels = new ArrayList<>();
for(int i=0; i> pair = this.inputDataClasses.get(requirementName);
if (pair == null) {
throw new DMNRuntimeException(String.format("Cannot find InputData for input parameter with requirementName='%s'", requirementName));
}
TInputData representative = pair.getLeft();
String representativeDiagramId = repository.getDiagramId(representative);
String representativeShapeId = repository.getShapeId(representative);
ipd.setDiagramId(representativeDiagramId);
ipd.setShapeId(representativeShapeId);
}
}
// Remove InputParameterDefinition
testLab.getInputParameterDefinitions().removeAll(toRemove);
// Remove corresponding Input Values
List testCases = testLab.getTestCases();
for(TestCase testCase: testCases) {
List inputValues = testCase.getInputValues();
List newList = new ArrayList<>();
for (int i=0; i> pair : inputDataClasses.values()) {
TInputData representative = pair.getLeft();
List inputDataInClass = pair.getRight();
if (inputDataInClass.size() >= 2) {
// For each decision
List decisions = repository.findDecisions(definitions);
for(TDecision decision: decisions) {
// Replace InputData in InformationRequirements with representative
List informationRequirementList = decision.getInformationRequirement();
for(TInformationRequirement ir: informationRequirementList) {
if (ir.getRequiredInput() != null) {
String href = ir.getRequiredInput().getHref();
TInputData referencedInputData = repository.findInputDataByRef(decision, href);
if (inputDataInClass.contains(referencedInputData) && referencedInputData != representative) {
String oldInputDataName = referencedInputData.getName();
String newInputDataName = representative.getName();
logger.info(String.format("Replacing input '%s' with '%s' in decision '%s'", oldInputDataName, newInputDataName, decision.getName()));
ir.getRequiredInput().setHref("#" + representative.getId());
// Replace in body
TExpression expression = decision.getExpression().getValue();
if (expression instanceof TDecisionTable) {
// For each InputClause
TDecisionTable decisionTable = (TDecisionTable) expression;
List inputClauselist = decisionTable.getInput();
for(TInputClause ic: inputClauselist) {
replace(oldInputDataName, newInputDataName, ic.getInputExpression());
}
// For each OutputClause
for(TOutputClause oc: decisionTable.getOutput()) {
replace(oldInputDataName, newInputDataName, oc.getDefaultOutputEntry());
}
// For each rule
for(TDecisionRule rule: decisionTable.getRule()) {
// Replace in description
String description = rule.getDescription();
rule.setDescription(replace(oldInputDataName, newInputDataName, description));
// Replace in InputEntry
for(TUnaryTests unaryTests : rule.getInputEntry()) {
unaryTests.setText(replace(oldInputDataName, newInputDataName, unaryTests.getText()));
}
// Replace in OutputEntry
for(TLiteralExpression literalExpression : rule.getOutputEntry()) {
replace(oldInputDataName, newInputDataName, literalExpression);
}
}
} else if (expression instanceof TLiteralExpression) {
replace(oldInputDataName, newInputDataName, (TLiteralExpression) expression);
}
}
}
}
}
}
}
// Remove all but the representative
for(Pair> pair : inputDataClasses.values()) {
TInputData representative = pair.getLeft();
List inputDataClass = pair.getRight();
for (TInputData inputData : inputDataClass) {
if (inputData != representative) {
removeDRGElement(definitions, inputData);
}
}
}
return repository.copy();
}
private Map>> inputDataEquivalenceClasses(DMNModelRepository repository) {
Map>> inputDataClasses = new LinkedHashMap<>();
TDefinitions definitions = repository.getRootDefinitions();
List inputDataList = repository.findInputDatas(definitions);
for(TInputData inputData: inputDataList) {
String key = equivalenceKey(inputData, repository);
Pair> inputDataClass = inputDataClasses.computeIfAbsent(key, k -> new Pair<>(null, new ArrayList<>()));
inputDataClass.getRight().add(inputData);
}
for(Map.Entry>> entry: inputDataClasses.entrySet()) {
Pair> inputDataClass = entry.getValue();
TInputData representative = shortestName(inputDataClass.getRight());
inputDataClasses.put(entry.getKey(), new Pair<>(representative, inputDataClass.getRight()));
}
return inputDataClasses;
}
private void replace(String oldName, String newName, TLiteralExpression expression) {
if (expression != null) {
String text = expression.getText();
String newText = replace(oldName, newName, text);
expression.setText(newText);
}
}
protected String replace(String oldName, String newName, String text) {
return text == null ? null : text.replaceAll("\\b"+oldName+"\\b", newName);
}
private void removeDRGElement(TDefinitions definitions, TDRGElement drgElement) {
JAXBElement> elementToRemove = null;
for(JAXBElement> element: definitions.getDrgElement()) {
if (element.getValue() == drgElement) {
elementToRemove = element;
}
}
definitions.getDrgElement().remove(elementToRemove);
}
private TInputData shortestName(List inputDataClass) {
int minLength = Integer.MAX_VALUE;
TInputData representative = null;
for(TInputData inputData: inputDataClass) {
String name = inputData.getName();
if (name.length() < minLength) {
minLength = name.length();
representative = inputData;
}
}
return representative;
}
protected boolean isIterator(TInputData inputData, DMNModelRepository repository) {
return repository instanceof SignavioDMNModelRepository && ((SignavioDMNModelRepository) repository).isIterator(inputData);
}
protected abstract String equivalenceKey(TInputData inputData, DMNModelRepository repository);
protected abstract String equivalenceKey(InputParameterDefinition parameter);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy