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

org.openremote.manager.rules.RulesBuilder Maven / Gradle / Ivy

/*
 * Copyright 2018, OpenRemote Inc.
 *
 * See the CONTRIBUTORS.txt file in the distribution for a
 * full listing of individual contributors.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see .
 */
package org.openremote.manager.rules;

import org.jeasy.rules.api.Rule;
import org.jeasy.rules.core.RuleBuilder;

import java.util.ArrayList;
import java.util.List;

/**
 * Call {@link #add()} to add rules.
 */
public class RulesBuilder {

    @FunctionalInterface
    public interface Condition {
        Object evaluate(RulesFacts facts);
    }

    public interface Action {
        void execute(RulesFacts facts);
    }

    public static class Builder {
        protected String name = org.jeasy.rules.api.Rule.DEFAULT_NAME;
        protected String description = org.jeasy.rules.api.Rule.DEFAULT_DESCRIPTION;
        protected int priority = org.jeasy.rules.api.Rule.DEFAULT_PRIORITY;
        protected Condition condition = facts -> false;
        protected Action action = facts -> {
        };

        /**
         * Required (short) rule name.
         */
        public Builder name(String name) {
            this.name = name;
            return this;
        }

        /**
         * Optional longer description.
         */
        public Builder description(String description) {
            this.description = description;
            return this;
        }

        /**
         * Lower priority rules execute before higher priority rules.
         * Default priority is Integer.MAX_VALUE - 1.
         */
        public Builder priority(int priority) {
            this.priority = priority;
            return this;
        }

        public Builder when(Condition condition) {
            this.condition = condition;
            return this;
        }

        public Builder then(Action action) {
            this.action = action;
            return this;
        }
    }

    final protected List builders = new ArrayList<>();

    public Builder add() {
        Builder builder = new Builder();
        builders.add(builder);
        return builder;
    }

    public Rule[] build() {
        List rules = new ArrayList<>();

        // Maintain rule order by adjusting priority for each rule within the ruleset
        int i = 1;
        for (Builder builder : builders) {

            int priority = (builder.priority < Integer.MAX_VALUE - 1) ? builder.priority : Integer.MAX_VALUE - 10000 + i;
            i++;

            Rule rule = new RuleBuilder()
                .name(builder.name)
                .description(builder.description)
                .priority(priority)
                .when(facts -> {
                    Object result;
                    try {
                        result = builder.condition.evaluate((RulesFacts) facts);
                    } catch (Exception ex) {
                        throw new RuntimeException("Error evaluating condition of rule '" + builder.name + "': " + ex.getMessage());
                    }
                    if (result instanceof Boolean) {
                        return (boolean)result;
                    } else {
                        throw new IllegalArgumentException("Error evaluating condition of rule '" + builder.name + "': result is not boolean but " + result);
                    }
                })
                .then(facts -> builder.action.execute((RulesFacts) facts))
                .build();

            rules.add(rule);
        }
        return rules.toArray(new Rule[rules.size()]);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy