All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gs.dmn.validation.SweepMissingRuleValidator Maven / Gradle / Ivy

The newest version!
/*
 * 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.*;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class SweepMissingRuleValidator extends SweepValidator {
    private final boolean merge;

    public SweepMissingRuleValidator() {
        this(new Slf4jBuildLogger(LOGGER), false);
    }

    public SweepMissingRuleValidator(BuildLogger logger, boolean merge) {
        super(logger);
        this.merge = merge;
    }

    public SweepMissingRuleValidator(DMNDialectDefinition dmnDialectDefinition) {
        super(dmnDialectDefinition);
        this.merge = false;
    }

    public SweepMissingRuleValidator(DMNDialectDefinition dmnDialectDefinition, boolean merge) {
        super(dmnDialectDefinition);
        this.merge = merge;
    }

    @Override
    protected void validate(TDRGElement element, TDecisionTable decisionTable, SweepValidationContext context) {
        if (element != null) {
            logger.debug(String.format("Validating element '%s'", element.getName()));

            DMNModelRepository repository = context.getRepository();
            ELTranslator feelTranslator = context.getElTranslator();
            List ruleIndex = new ArrayList<>();
            int totalNumberOfRules = decisionTable.getRule().size();
            for (int i = 0; i< totalNumberOfRules; i++) {
                ruleIndex.add(i);
            }
            MissingIntervals missingIntervals = new MissingIntervals();
            MissingRuleList missingRuleList = new MissingRuleList();
            int totalNumberOfColumns = decisionTable.getInput().size();
            Table table = this.factory.makeTable(totalNumberOfRules, totalNumberOfColumns, repository, element, decisionTable, feelTranslator);
            if (!table.isEmpty()) {
                findMissingRules(ruleIndex, 0, totalNumberOfColumns, missingIntervals, missingRuleList, table);

                logger.debug(String.format("Found missing rules %s", missingRuleList));

                for (Rule rule: missingRuleList.getRules()) {
                    context.addError(makeError(element, rule, repository));
                }
            }
        }
    }

    private String makeError(TDRGElement element, Rule rule, DMNModelRepository repository) {
        TDefinitions model = repository.getModel(element);
        String intervalsString = rule.getIntervals().stream().map(Interval::serialize).collect(Collectors.joining(", "));
        String message = String.format("Found missing rule '[%s]' in '%s' table", intervalsString, 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 findMissingRules(List ruleList, int columnIndex, int totalNumberOfColumns, MissingIntervals missingIntervals, MissingRuleList missingRuleList, Table table) {
        String indent = StringUtils.repeat("\t", columnIndex);
        logger.debug(String.format("%sColumn = '%s' Active rules = '%s' Missing intervals = '%s'", indent, columnIndex, ruleList, missingIntervals));

        if(columnIndex < totalNumberOfColumns) {
            List 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