red6/dmn-check

View on GitHub
validators/src/main/java/de/redsix/dmncheck/feel/FeelExpression.java

Summary

Maintainability
A
0 mins
Test Coverage
package de.redsix.dmncheck.feel;

import java.time.LocalDateTime;
import java.util.Optional;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.derive4j.Data;
import org.derive4j.Derive;
import org.derive4j.Make;
import org.derive4j.Visibility;

@Data(
        value =
                @Derive(
                        withVisibility = Visibility.Package,
                        make = {Make.constructors, Make.caseOfMatching, Make.getters}))
public abstract class FeelExpression {

    public interface Cases<R> {
        R Empty();

        R Null();

        R BooleanLiteral(Boolean aBoolean);

        R DateLiteral(LocalDateTime dateTime);

        R DoubleLiteral(Double aDouble);

        R IntegerLiteral(Integer aInteger);

        R StringLiteral(String string);

        R VariableLiteral(String name);

        R RangeExpression(
                boolean isLeftInclusive,
                FeelExpression lowerBound,
                FeelExpression upperBound,
                boolean isRightInclusive);

        R UnaryExpression(Operator operator, FeelExpression expression);

        R BinaryExpression(FeelExpression left, Operator operator, FeelExpression right);

        R DisjunctionExpression(FeelExpression head, FeelExpression tail);
    }

    public abstract <R> R match(Cases<R> cases);

    public Optional<Boolean> subsumes(final FeelExpression expression) {
        return Subsumption.subsumes(this, expression, Subsumption.eq);
    }

    public boolean containsVariable(final String name) {
        return FeelExpressions.caseOf(this)
                .Empty_(false)
                .Null_(false)
                .BooleanLiteral_(false)
                .DateLiteral_(false)
                .DoubleLiteral_(false)
                .IntegerLiteral_(false)
                .StringLiteral_(false)
                .VariableLiteral(variableName -> variableName.equals(name))
                .RangeExpression((__, lowerBound, upperBound, ___) ->
                        lowerBound.containsVariable(name) || upperBound.containsVariable(name))
                .UnaryExpression((__, expression) -> expression.containsVariable(name))
                .BinaryExpression((left, __, right) -> left.containsVariable(name) || right.containsVariable(name))
                .DisjunctionExpression((head, tail) -> head.containsVariable(name) || tail.containsVariable(name));
    }

    public boolean isLiteral() {
        return FeelExpressions.caseOf(this)
                .BooleanLiteral_(true)
                .DateLiteral_(true)
                .DoubleLiteral_(true)
                .IntegerLiteral_(true)
                .StringLiteral_(true)
                .VariableLiteral_(true)
                .otherwise_(false);
    }

    public boolean containsNot() {
        return FeelExpressions.caseOf(this)
                .Empty_(false)
                .Null_(false)
                .BooleanLiteral_(false)
                .DateLiteral_(false)
                .DoubleLiteral_(false)
                .IntegerLiteral_(false)
                .StringLiteral_(false)
                .VariableLiteral_(false)
                .RangeExpression(
                        (__, lowerBound, upperBound, ___) -> lowerBound.containsNot() || upperBound.containsNot())
                .UnaryExpression((operator, expression) -> operator.equals(Operator.NOT))
                .BinaryExpression((left, __, right) -> left.containsNot() || right.containsNot())
                .DisjunctionExpression((head, tail) -> head.containsNot() || tail.containsNot());
    }

    @Override
    public abstract int hashCode();

    @Override
    public abstract boolean equals(@Nullable Object obj);

    @Override
    public abstract String toString();
}