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

org.qbicc.facts.Condition Maven / Gradle / Ivy

There is a newer version: 0.77.0
Show newest version
package org.qbicc.facts;

import java.util.function.ObjLongConsumer;

/**
 * A condition that, when met, triggers the execution of an action.
 *
 * @param  the fact type
 */
public abstract class Condition> {
    Condition() {}

    /**
     * A condition which is true when the given fact is present.
     *
     * @param fact the fact
     * @param  the fact type
     * @return the condition
     */
    public static > Condition when(F fact) {
        return new Of<>(fact);
    }


    /**
     * A condition which is true when all of the given facts are present.
     *
     * @param fact1 the first fact
     * @param fact2 the second fact
     * @param  the fact type
     * @return the condition
     */
    public static > Condition whenAll(F fact1, F fact2) {
        return new All2<>(fact1, fact2);
    }

    /**
     * A condition which is true when all of the given facts are present.
     *
     * @param fact1 the first fact
     * @param fact2 the second fact
     * @param fact3 the second fact
     * @param  the fact type
     * @return the condition
     */
    public static > Condition whenAll(F fact1, F fact2, F fact3) {
        return new All3<>(fact1, fact2, fact3);
    }

    /**
     * A condition which is true when all of the given facts are present.
     *
     * @param facts the facts
     * @param  the fact type
     * @return the condition
     */
    @SafeVarargs
    public static > Condition whenAll(F... facts) {
        return new AllMany<>(facts);
    }


    /**
     * A condition which is true when any of the given facts are present.
     *
     * @param fact1 the first fact
     * @param fact2 the second fact
     * @param  the fact type
     * @return the condition
     */
    public static > Condition whenAny(F fact1, F fact2) {
        return new Any2<>(fact1, fact2);
    }

    /**
     * A condition which is true when any of the given facts are present.
     *
     * @param fact1 the first fact
     * @param fact2 the second fact
     * @param fact3 the third fact
     * @param  the fact type
     * @return the condition
     */
    public static > Condition whenAny(F fact1, F fact2, F fact3) {
        return new Any3<>(fact1, fact2, fact3);
    }

    /**
     * A condition which is true when any of the given facts are present.
     *
     * @param facts the facts
     * @param  the fact type
     * @return the condition
     */
    @SafeVarargs
    public static > Condition whenAny(F... facts) {
        return new AnyMany<>(facts);
    }


    /**
     * Get a condition which is true when both this condition and the given condition are true.
     *
     * @param other the other condition
     * @return the new condition
     */
    public Condition and(Condition other) {
        return new And(this, other);
    }


    /**
     * Get a condition which is true when either this condition or the given condition are true.
     *
     * @param other the other condition
     * @return the new condition
     */
    public Condition or(Condition other) {
        return new Or(this, other);
    }


    abstract ObjLongConsumer getRegisterFunction(ObjLongConsumer next);

    static class Of> extends Condition {
        final F fact1;

        Of(F fact1) {
            this.fact1 = fact1;
        }

        @Override
        ObjLongConsumer getRegisterFunction(ObjLongConsumer next) {
            return (holder, bits) -> next.accept(holder, bits | 1L << holder.getFactIndex(fact1));
        }
    }

    static class Any2> extends Of {
        final F fact2;

        Any2(F fact1, F fact2) {
            super(fact1);
            this.fact2 = fact2;
        }

        @Override
        ObjLongConsumer getRegisterFunction(ObjLongConsumer next) {
            return (holder, bits) -> {
                next.accept(holder, bits | 1L << holder.getFactIndex(fact1));
                next.accept(holder, bits | 1L << holder.getFactIndex(fact2));
            };
        }
    }

    static class Any3> extends Any2 {
        final F fact3;

        Any3(F fact1, F fact2, F fact3) {
            super(fact1, fact2);
            this.fact3 = fact3;
        }

        @Override
        ObjLongConsumer getRegisterFunction(ObjLongConsumer next) {
            return (holder, bits) -> {
                next.accept(holder, bits | 1L << holder.getFactIndex(fact1));
                next.accept(holder, bits | 1L << holder.getFactIndex(fact2));
                next.accept(holder, bits | 1L << holder.getFactIndex(fact3));
            };
        }
    }

    static class AnyMany> extends Condition {
        final F[] facts;

        AnyMany(F[] facts) {
            this.facts = facts;
        }

        @Override
        ObjLongConsumer getRegisterFunction(ObjLongConsumer next) {
            return (holder, bits) -> {
                for (F fact : facts) {
                    next.accept(holder, bits | 1L << holder.getFactIndex(fact));
                }
            };
        }
    }

    static class All2> extends Of {
        final F fact2;

        All2(F fact1, F fact2) {
            super(fact1);
            this.fact2 = fact2;
        }

        @Override
        ObjLongConsumer getRegisterFunction(ObjLongConsumer next) {
            return (holder, bits) -> next.accept(holder, bits | 1L << holder.getFactIndex(fact1) | 1L << holder.getFactIndex(fact2));
        }
    }

    static class All3> extends All2 {
        final F fact3;

        All3(F fact1, F fact2, F fact3) {
            super(fact1, fact2);
            this.fact3 = fact3;
        }

        @Override
        ObjLongConsumer getRegisterFunction(ObjLongConsumer next) {
            return (holder, bits) -> next.accept(holder, bits | 1L << holder.getFactIndex(fact1) | 1L << holder.getFactIndex(fact2) | 1L << holder.getFactIndex(fact3));
        }
    }

    static class AllMany> extends Condition {
        final F[] facts;

        AllMany(F[] facts) {
            this.facts = facts;
        }

        @Override
        ObjLongConsumer getRegisterFunction(ObjLongConsumer next) {
            return (holder, bits) -> {
                for (F fact : facts) {
                    bits |= 1L << holder.getFactIndex(fact);
                }
                next.accept(holder, bits);
            };
        }
    }

    static class Or> extends Condition {
        private final Condition cond1;
        private final Condition cond2;

        Or(Condition cond1, Condition cond2) {
            this.cond1 = cond1;
            this.cond2 = cond2;
        }

        @Override
        ObjLongConsumer getRegisterFunction(ObjLongConsumer next) {
            var f1 = cond1.getRegisterFunction(next);
            var f2 = cond2.getRegisterFunction(next);
            return (holder, bits) -> {
                f1.accept(holder, bits);
                f2.accept(holder, bits);
            };
        }
    }

    static class And> extends Condition {
        private final Condition cond1;
        private final Condition cond2;

        And(Condition cond1, Condition cond2) {
            this.cond1 = cond1;
            this.cond2 = cond2;
        }

        @Override
        ObjLongConsumer getRegisterFunction(ObjLongConsumer next) {
            return cond1.getRegisterFunction(cond2.getRegisterFunction(next));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy