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

com.contentgrid.thunx.predicates.model.FunctionExpression Maven / Gradle / Ivy

Go to download

Set of (vendor-neutral) data structures to model authorization policy expressions

There is a newer version: 0.11.0
Show newest version
package com.contentgrid.thunx.predicates.model;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

public interface FunctionExpression extends ThunkExpression {

    Operator getOperator();

    List> getTerms();

    default  R accept(ThunkExpressionVisitor visitor, C context) {
        return visitor.visit(this, context);
    }

    default String toDebugString() {
        return String.format("%s(%s)",
                this.getOperator().getKey().toUpperCase(Locale.ROOT),
                this.getTerms().stream().map(Object::toString).collect(Collectors.joining(", ")));
    }

    // TASK switch this to an interface Operator with sealed classes as subtypes
    // that would eliminate much of the casting
    @RequiredArgsConstructor
    enum Operator {
        // Comparison operators
        EQUALS("eq", Boolean.class, (FunctionExpressionFactory) Comparison::areEqual),
        NOT_EQUAL_TO("neq", Boolean.class, (FunctionExpressionFactory) Comparison::notEqual),
        GREATER_THAN("gt", Boolean.class, (FunctionExpressionFactory) Comparison::greater),
        GREATER_THAN_OR_EQUAL_TO("gte", Boolean.class, (FunctionExpressionFactory) Comparison::greaterOrEquals),
        LESS_THAN("lt", Boolean.class, (FunctionExpressionFactory) Comparison::less),
        LESS_THEN_OR_EQUAL_TO("lte", Boolean.class, (FunctionExpressionFactory) Comparison::lessOrEquals),

        // Logical operator
        AND("and", Boolean.class, (FunctionExpressionFactory) LogicalOperation::uncheckedConjunction),
        OR("or", Boolean.class, (FunctionExpressionFactory) LogicalOperation::uncheckedDisjunction),
        NOT("not", Boolean.class, (FunctionExpressionFactory) LogicalOperation::uncheckedNegation),

        // Numeric operators
        PLUS("plus", Number.class, (FunctionExpressionFactory) NumericFunction::plus),
        MINUS("minus", Number.class, (FunctionExpressionFactory) NumericFunction::minus),
        DIVIDE("div", Number.class, (FunctionExpressionFactory) NumericFunction::divide),
        MULTIPLY("mul", Number.class, (FunctionExpressionFactory) NumericFunction::multiply),
        MODULUS("mod", Number.class, (FunctionExpressionFactory) NumericFunction::modulus);

        @Getter
        @NonNull
        private final String key;

        @Getter
        @NonNull
        private final Class type;

        // TODO remove getter, expose create method directly and delegate to the factory instead
        @Getter
        @NonNull
        private final FunctionExpressionFactory factory;

        public static Operator resolve(@NonNull String key) {
            return Arrays.stream(Operator.values())
                    .filter(op -> Objects.equals(key, op.getKey()))
                    .findFirst()
                    .orElseThrow(() -> {
                        String message = String.format("Invalid %s key: '%s'", Operator.class.getSimpleName(), key);
                        return new IllegalArgumentException(message);
                    });
        }

        public FunctionExpression create(List> terms) {
            return this.factory.create(terms);
        }
    }

    @FunctionalInterface
    interface FunctionExpressionFactory {

        FunctionExpression create(List> terms);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy