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

com.gs.dmn.feel.lib.BaseFEELLib Maven / Gradle / Ivy

There is a newer version: 8.7.3
Show 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.feel.lib;

import com.gs.dmn.feel.lib.type.*;
import com.gs.dmn.feel.lib.type.context.DefaultContextType;
import com.gs.dmn.runtime.Context;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

public abstract class BaseFEELLib implements FEELLib {
    protected final NumericType numericType;
    protected final BooleanType booleanType;
    protected final StringType stringType;
    protected final DateType dateType;
    protected final TimeType timeType;
    protected final DateTimeType dateTimeType;
    protected final DurationType durationType;
    protected final ListType listType;
    protected final ContextType contextType;

    @Deprecated
    // Backwards compatibility with 5.3.0
    public BaseFEELLib(NumericType numericType, BooleanType booleanType, StringType stringType, DateType dateType, TimeType timeType, DateTimeType dateTimeType, DurationType durationType, ListType listType) {
        this(numericType, booleanType, stringType, dateType, timeType, dateTimeType, durationType, listType, new DefaultContextType(LOGGER));
    }

    public BaseFEELLib(NumericType numericType, BooleanType booleanType, StringType stringType, DateType dateType, TimeType timeType, DateTimeType dateTimeType, DurationType durationType, ListType listType, ContextType contextType) {
        this.numericType = numericType;
        this.booleanType = booleanType;
        this.stringType = stringType;
        this.dateType = dateType;
        this.timeType = timeType;
        this.dateTimeType = dateTimeType;
        this.durationType = durationType;
        this.listType = listType;
        this.contextType = contextType;
    }

    //
    // Numeric operators
    //
    public NUMBER numericAdd(NUMBER first, NUMBER second) {
        return numericType.numericAdd(first, second);
    }

    public NUMBER numericSubtract(NUMBER first, NUMBER second) {
        return numericType.numericSubtract(first, second);
    }

    public NUMBER numericMultiply(NUMBER first, NUMBER second) {
        return numericType.numericMultiply(first, second);
    }

    public NUMBER numericDivide(NUMBER first, NUMBER second) {
        return numericType.numericDivide(first, second);
    }

    public NUMBER numericUnaryMinus(NUMBER first) {
        return numericType.numericUnaryMinus(first);
    }

    public NUMBER numericExponentiation(NUMBER first, NUMBER second) {
        return numericType.numericExponentiation(first, second);
    }

    public Boolean numericEqual(NUMBER first, NUMBER second) {
        return numericType.numericEqual(first, second);
    }

    public Boolean numericNotEqual(NUMBER first, NUMBER second) {
        return numericType.numericNotEqual(first, second);
    }

    public Boolean numericLessThan(NUMBER first, NUMBER second) {
        return numericType.numericLessThan(first, second);
    }

    public Boolean numericGreaterThan(NUMBER first, NUMBER second) {
        return numericType.numericGreaterThan(first, second);
    }

    public Boolean numericLessEqualThan(NUMBER first, NUMBER second) {
        return numericType.numericLessEqualThan(first, second);
    }

    public Boolean numericGreaterEqualThan(NUMBER first, NUMBER second) {
        return numericType.numericGreaterEqualThan(first, second);
    }

    //
    // Boolean operators
    //
    public Boolean booleanNot(Object operand) {
        return booleanType.booleanNot(operand);
    }

    public Boolean booleanOr(List operands) {
        return booleanType.booleanOr(operands);
    }

    public Boolean booleanOr(Object... operands) {
        return booleanType.booleanOr(operands);
    }

    public Boolean binaryBooleanOr(Object first, Object second) {
        return booleanType.binaryBooleanOr(first, second);
    }

    public Boolean booleanAnd(List operands) {
        return booleanType.booleanAnd(operands);
    }

    public Boolean booleanAnd(Object... operands) {
        return booleanType.booleanAnd(operands);
    }

    public Boolean binaryBooleanAnd(Object first, Object second) {
        return booleanType.binaryBooleanAnd(first, second);
    }

    public Boolean booleanEqual(Boolean first, Boolean second) {
        return booleanType.booleanEqual(first, second);
    }

    public Boolean booleanNotEqual(Boolean first, Boolean second) {
        return booleanType.booleanNotEqual(first, second);
    }

    @Deprecated
    public Boolean booleanNot(Boolean operand) {
        return booleanType.booleanNot(operand);
    }

    @Deprecated
    public Boolean booleanOr(Boolean... operands) {
        return booleanType.booleanOr(operands);
    }

    @Deprecated
    public Boolean binaryBooleanOr(Boolean first, Boolean second) {
        return booleanType.binaryBooleanOr(first, second);
    }

    @Deprecated
    public Boolean booleanAnd(Boolean... operands) {
        return booleanType.booleanAnd(operands);
    }

    @Deprecated
    public Boolean binaryBooleanAnd(Boolean first, Boolean second) {
        return booleanType.binaryBooleanAnd(first, second);
    }

    //
    // String operators
    //
    public Boolean stringEqual(String first, String second) {
        return stringType.stringEqual(first, second);
    }

    public Boolean stringNotEqual(String first, String second) {
        return stringType.stringNotEqual(first, second);
    }

    public String stringAdd(String first, String second) {
        return stringType.stringAdd(first, second);
    }

    public Boolean stringLessThan(String first, String second) {
        return stringType.stringLessThan(first, second);
    }

    public Boolean stringGreaterThan(String first, String second) {
        return stringType.stringGreaterThan(first, second);
    }

    public Boolean stringLessEqualThan(String first, String second) {
        return stringType.stringLessEqualThan(first, second);
    }

    public Boolean stringGreaterEqualThan(String first, String second) {
        return stringType.stringGreaterEqualThan(first, second);
    }

    //
    // Date operators
    //

    public Boolean dateEqual(DATE first, DATE second) {
        return dateType.dateEqual(first, second);
    }

    public Boolean dateNotEqual(DATE first, DATE second) {
        return dateType.dateNotEqual(first, second);
    }

    public Boolean dateLessThan(DATE first, DATE second) {
        return dateType.dateLessThan(first, second);
    }

    public Boolean dateGreaterThan(DATE first, DATE second) {
        return dateType.dateGreaterThan(first, second);
    }

    public Boolean dateLessEqualThan(DATE first, DATE second) {
        return dateType.dateLessEqualThan(first, second);
    }

    public Boolean dateGreaterEqualThan(DATE first, DATE second) {
        return dateType.dateGreaterEqualThan(first, second);
    }

    public DURATION dateSubtract(DATE first, DATE second) {
        return dateType.dateSubtract(first, second);
    }

    public DATE dateAddDuration(DATE date, DURATION duration) {
        return dateType.dateAddDuration(date, duration);
    }

    public DATE dateSubtractDuration(DATE date, DURATION duration) {
        return dateType.dateSubtractDuration(date, duration);
    }

    //
    // Time operators
    //
    public Boolean timeEqual(TIME first, TIME second) {
        return timeType.timeEqual(first, second);
    }

    public Boolean timeNotEqual(TIME first, TIME second) {
        return timeType.timeNotEqual(first, second);
    }

    public Boolean timeLessThan(TIME first, TIME second) {
        return timeType.timeLessThan(first, second);
    }

    public Boolean timeGreaterThan(TIME first, TIME second) {
        return timeType.timeGreaterThan(first, second);
    }

    public Boolean timeLessEqualThan(TIME first, TIME second) {
        return timeType.timeLessEqualThan(first, second);
    }

    public Boolean timeGreaterEqualThan(TIME first, TIME second) {
        return timeType.timeGreaterEqualThan(first, second);
    }

    public DURATION timeSubtract(TIME first, TIME second) {
        return timeType.timeSubtract(first, second);
    }

    public TIME timeAddDuration(TIME time, DURATION duration) {
        return timeType.timeAddDuration(time, duration);
    }

    public TIME timeSubtractDuration(TIME time, DURATION duration) {
        return timeType.timeSubtractDuration(time, duration);
    }

    //
    // Date and Time operators
    //
    public Boolean dateTimeEqual(DATE_TIME first, DATE_TIME second) {
        return dateTimeType.dateTimeEqual(first, second);
    }

    public Boolean dateTimeNotEqual(DATE_TIME first, DATE_TIME second) {
        return dateTimeType.dateTimeNotEqual(first, second);
    }

    public Boolean dateTimeLessThan(DATE_TIME first, DATE_TIME second) {
        return dateTimeType.dateTimeLessThan(first, second);
    }

    public Boolean dateTimeGreaterThan(DATE_TIME first, DATE_TIME second) {
        return dateTimeType.dateTimeGreaterThan(first, second);
    }

    public Boolean dateTimeLessEqualThan(DATE_TIME first, DATE_TIME second) {
        return dateTimeType.dateTimeLessEqualThan(first, second);
    }

    public Boolean dateTimeGreaterEqualThan(DATE_TIME first, DATE_TIME second) {
        return dateTimeType.dateTimeGreaterEqualThan(first, second);
    }

    public DURATION dateTimeSubtract(DATE_TIME first, DATE_TIME second) {
        return dateTimeType.dateTimeSubtract(first, second);
    }

    public DATE_TIME dateTimeAddDuration(DATE_TIME date_time, DURATION duration) {
        return dateTimeType.dateTimeAddDuration(date_time, duration);
    }

    public DATE_TIME dateTimeSubtractDuration(DATE_TIME date_time, DURATION duration) {
        return dateTimeType.dateTimeSubtractDuration(date_time, duration);
    }

    //
    // Duration operators
    //
    public Boolean durationEqual(DURATION first, DURATION second) {
        return durationType.durationEqual(first, second);
    }

    public Boolean durationNotEqual(DURATION first, DURATION second) {
        return durationType.durationNotEqual(first, second);
    }

    public Boolean durationLessThan(DURATION first, DURATION second) {
        return durationType.durationLessThan(first, second);
    }

    public Boolean durationGreaterThan(DURATION first, DURATION second) {
        return durationType.durationGreaterThan(first, second);
    }

    public Boolean durationLessEqualThan(DURATION first, DURATION second) {
        return durationType.durationLessEqualThan(first, second);
    }

    public Boolean durationGreaterEqualThan(DURATION first, DURATION second) {
        return durationType.durationGreaterEqualThan(first, second);
    }

    public DURATION durationAdd(DURATION first, DURATION second) {
        return durationType.durationAdd(first, second);
    }

    public DURATION durationSubtract(DURATION first, DURATION second) {
        return durationType.durationSubtract(first, second);
    }

    public DURATION durationMultiply(DURATION first, NUMBER second) {
        return durationType.durationMultiply(first, second);
    }

    public DURATION durationDivide(DURATION first, NUMBER second) {
        return durationType.durationDivide(first, second);
    }

    //
    // List operators
    //
    public Boolean listEqual(List list1, List list2) {
        return listType.listEqual(list1, list2);
    }

    public Boolean listNotEqual(List list1, List list2) {
        return listType.listNotEqual(list1, list2);
    }

    //
    // Context operators
    //
    public Boolean contextEqual(Object c1, Object c2) {
        return contextType.contextEqual(c1, c2);
    }

    public Boolean contextNotEqual(Object c1, Object c2) {
        return contextType.contextNotEqual(c1, c2);
    }

    //
    // Context functions
    //
    @Override
    public List getEntries(Object m) {
        if (m instanceof Context) {
            List result = new ArrayList<>();
            Context context = (Context) m;
            Set keys = context.getBindings().keySet();
            for (Object key: keys) {
                Context c = new Context().add("key", key).add("value", context.get(key));
                result.add(c);
            }
            return result;
        } else {
            return null;
        }
    }

    @Override
    public Object getValue(Object m, Object key) {
        if (m instanceof Context) {
            return ((Context) m).get(key);
        } else {
            return null;
        }
    }

    //
    // Extra functions
    //
    @Override
    public List asList(T ...objects) {
        if (objects == null) {
            List result = new ArrayList<>();
            result.add(null);
            return result;
        } else {
            return Arrays.asList(objects);
        }
    }

    @Override
    public T asElement(List list) {
        if (list == null) {
            return null;
        } else if (list.size() == 1) {
            return list.get(0);
        } else {
            return null;
        }
    }

    public List rangeToList(boolean isOpenStart, BigDecimal start, boolean isOpenEnd, BigDecimal end) {
        if (start == null || end == null) {
            return new ArrayList<>();
        }
        int startValue = isOpenStart ? start.intValue() + 1 : start.intValue();
        int endValue = isOpenEnd ? end.intValue() - 1 : end.intValue();
        return decimalRangeToList(startValue, endValue);
    }

    public List rangeToList(boolean isOpenStart, Double start, boolean isOpenEnd, Double end) {
        if (start == null || end == null) {
            return new ArrayList<>();
        }
        int startValue = isOpenStart ? start.intValue() + 1 : start.intValue();
        int endValue = isOpenEnd ? end.intValue() - 1 : end.intValue();
        return doubleRangeToList(startValue, endValue);
    }

    public List rangeToList(BigDecimal start, BigDecimal end) {
        if (start == null || end == null) {
            return new ArrayList<>();
        }
        int startValue = start.intValue();
        int endValue = end.intValue();
        return decimalRangeToList(startValue, endValue);
    }
    public List rangeToList(Double start, Double end) {
        if (start == null || end == null) {
            return new ArrayList<>();
        }
        int startValue = start.intValue();
        int endValue = end.intValue();
        return doubleRangeToList(startValue, endValue);
    }

    private List decimalRangeToList(int startValue, int endValue) {
        List result = new ArrayList<>();
        if (startValue <= endValue) {
            for (int i = startValue; i <= endValue; i++) {
                result.add(BigDecimal.valueOf(i));
            }
        } else {
            for (int i = startValue; i >= endValue; i--) {
                result.add(BigDecimal.valueOf(i));
            }
        }
        return result;
    }

    private List doubleRangeToList(int startValue, int endValue) {
        List result = new ArrayList<>();
        if (startValue <= endValue) {
            for (int i = startValue; i <= endValue; i++) {
                result.add(Double.valueOf(i));
            }
        } else {
            for (int i = startValue; i >= endValue; i--) {
                result.add(Double.valueOf(i));
            }
        }
        return result;
    }

    @Override
    public List flattenFirstLevel(List list) {
        if (list == null) {
            return null;
        }
        List result = new ArrayList<>();
        for (Object object : list) {
            if (object instanceof List) {
                result.addAll((List) object);
            } else {
                result.add(object);
            }
        }
        return result;
    }

    public Object elementAt(List list, BigDecimal index) {
        return elementAt(list, index.intValue());
    }

    public Object elementAt(List list, Double index) {
        return elementAt(list, index.intValue());
    }

    private Object elementAt(List list, int index) {
        if (list == null) {
            return null;
        }
        int listSize = list.size();
        if (1 <= index && index <= listSize) {
            return list.get(index - 1);
        } else if (-listSize <= index && index <= -1) {
            return list.get(listSize + index);
        } else {
            return null;
        }
    }
}