com.gs.dmn.validation.SweepMissingIntervalValidator 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.validation;
import com.gs.dmn.DMNModelRepository;
import com.gs.dmn.ast.TDRGElement;
import com.gs.dmn.ast.TDecisionTable;
import com.gs.dmn.ast.TDefinitions;
import com.gs.dmn.context.DMNContext;
import com.gs.dmn.dialect.DMNDialectDefinition;
import com.gs.dmn.el.analysis.semantics.type.Type;
import com.gs.dmn.el.synthesis.ELTranslator;
import com.gs.dmn.log.BuildLogger;
import com.gs.dmn.log.Slf4jBuildLogger;
import com.gs.dmn.validation.table.Bound;
import com.gs.dmn.validation.table.Interval;
import com.gs.dmn.validation.table.MissingIntervals;
import com.gs.dmn.validation.table.Table;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class SweepMissingIntervalValidator extends SweepValidator {
public SweepMissingIntervalValidator() {
this(new Slf4jBuildLogger(LOGGER));
}
public SweepMissingIntervalValidator(BuildLogger logger) {
super(logger);
}
public SweepMissingIntervalValidator(DMNDialectDefinition, ?, ?, ?, ?, ?> dmnDialectDefinition) {
super(dmnDialectDefinition);
}
@Override
protected void validate(TDRGElement element, TDecisionTable decisionTable, SweepValidationContext context) {
if (element != null) {
DMNModelRepository repository = context.getRepository();
ELTranslator elTranslator = context.getElTranslator();
logger.debug(String.format("Validating element '%s'", element.getName()));
List ruleIndex = new ArrayList<>();
int totalNumberOfRules = decisionTable.getRule().size();
for (int i = 0; i< totalNumberOfRules; i++) {
ruleIndex.add(i);
}
MissingIntervals missingIntervals = new MissingIntervals();
int totalNumberOfColumns = decisionTable.getInput().size();
Table table = this.factory.makeTable(totalNumberOfRules, totalNumberOfColumns, repository, element, decisionTable, elTranslator);
if (!table.isEmpty()) {
findMissingIntervals(ruleIndex, totalNumberOfColumns, missingIntervals, table);
logger.debug(String.format("Found missing intervals '%s'", missingIntervals));
for (int i=0; i intervals = missingIntervals.getIntervals(i);
if (intervals != null && !intervals.isEmpty()) {
context.addError(makeError(element, i, intervals, repository));
}
}
}
}
}
private String makeError(TDRGElement element, int columnIndex, List intervals, DMNModelRepository repository) {
TDefinitions model = repository.getModel(element);
String intervalsString = intervals.stream().map(Interval::serialize).collect(Collectors.joining(", "));
String message;
if (intervals.size() == 1) {
message = String.format("Interval '%s' is not covered for column %d in '%s' table", intervalsString, columnIndex + 1, repository.displayName(element));
} else {
message = String.format("Intervals '%s' are not covered for column %d in '%s' table", intervalsString, columnIndex + 1, repository.displayName(element));
}
return makeError(repository, model, element, message);
}
// Algorithm: findMissingRules.
// Input: ruleList; missingIntervals; i; N; missingRuleList.
// - ruleList, containing all rules of the input DMN table;
// - missingIntervals, storing the current missing intervals;
// - i, containing the index of the column under scrutiny;
// - N, representing the total number of columns;
// - missingRuleList, storing the missing rules.
// if i < N then
// Lxi = [] // initializes the current list of bounds
// sortedListAllBounds = ruleList.sort(i)
// lastBound = 0
// foreach currentBound ∈ sortedListAllBounds do
// if !areAdjacent( lastBound, currentBound) then
// missingIntervals[i] = constructInterval(lastBound, currentBound)
// if missingRuleList.canBeMerged(missingIntervals) then
// missingRuleList.merge(missingIntervals)
// else
// missingRuleList.add(missingIntervals)
// if !Lxi.isEmpty() then
// missingIntervals[i] = constructInterval(lastBound, currentBound)
// findMissingRules(Lxi, missingIntervals, i+1, N, missingRuleList) /* recursive invocation */
// if currentBound.isLower() then
// Lxi.put(currentBound)
// else
// Lxi.delete( currentBound);
// lastBound = currentBound
// return missingRuleList;
private void findMissingIntervals(List ruleList, int totalNumberOfColumns, MissingIntervals missingIntervals, Table table) {
for (int columnIndex=0; columnIndex sortedListAllBounds = makeBoundList(ruleList, columnIndex, table);
Bound lowerBound = table.getLowerBoundForColumn(columnIndex);
Bound upperBound = table.getUpperBoundForColumn(columnIndex);
Bound lastBound = lowerBound;
int boundCount = sortedListAllBounds.size();
List lxi = new ArrayList<>();
logger.debug(String.format("%sColumn = %s Sorted bounds = '%s'", indent, columnIndex, sortedListAllBounds));
for (int i = 0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy