Skip to content
A tiny java rule engine
Java
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
gradle/wrapper
src
.gitignore
LICENSE
README.md
build.gradle
gradle.properties
gradlew
gradlew.bat
proguard-rules.pro

README.md

ruli Download

A tiny rule engine.

Ruli is the tiny rule engine behind the Android library Integrated Rating Request - a polite way to ask for ratings.

Get it

Ruli is available on Maven jCenter.

MAVEN

If you are using Maven for compilation you can declare the library as a dependency.

<dependency>
  <groupId>net.mediavrog</groupId>
  <artifactId>ruli</artifactId>
  <version>1.1.0</version>
</dependency>
GRADLE
compile 'net.mediavrog:ruli:1.1.0'

What is ruli?

Ruli is a tiny rule engine for the evaluation of simple rules. If consists of a couple of classes to describe and evaluate rules and sets of rules:

  • Rule: Abstract rule with evaluate interface to provide arbitrary results.
  • RuleSet: Evaluate groups of rules with logical AND or OR. Implements the Rule interface to allow nesting.
  • RuleEngine: A slightly enhanced RuleSet, which saves the last result and can notify a listener upon result availability.
  • Value: Boxed value to support dynamic generation e.g. by querying a persistence layer. Use Value.as shorthand to box a simple variable.
  • SimpleRule: A simple left-right hand comparison. Takes Values as arguments and a SimpleRule.Comparator.
  • SimpleRule.Comparator: An enum for common comparison types:
    • EQ - equal
    • NEQ - not equal
    • GT - greater than
    • GT_EQ - greater than or equal
    • LT - lesser than
    • LT_EQ - lesser than or equal

Ruli promotes immutability to support thread-safety. It doesn't make assumptions about your system, so use Threads when necessary if you expect your custom rules to take long time to evaluate.

Ruli is open to PR's. Please add tests for any code provided. Thanks!

Examples

OR RuleSet

SimpleRule trueRule1 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, true);
SimpleRule trueRule2 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, true);
SimpleRule falseRule1 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, false);

RuleSet set = new RuleSet.Builder(RuleSet.Mode.OR)
        .addRule(falseRule1)
        .addRule(trueRule1)
        .addRule(trueRule2)
        .build();

assertTrue(set.evaluate());

AND RuleSet

SimpleRule trueRule1 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, true);
SimpleRule trueRule2 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, true);
SimpleRule falseRule1 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, false);

RuleSet set = new RuleSet.Builder(RuleSet.Mode.AND)
        .addRule(trueRule1)
        .addRule(falseRule1)
        .addRule(trueRule2)
        .build();

assertFalse(set.evaluate());

RuleSet nesting

SimpleRule trueRule1 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, true);
SimpleRule trueRule2 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, true);
SimpleRule falseRule1 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, false);

RuleSet trueSet = new RuleSet.Builder(RuleSet.Mode.OR)
        .addRule(falseRule1)
        .addRule(trueRule1)
        .addRule(trueRule2)
        .build();

SimpleRule falseRule2 = new SimpleRule<Boolean>(true, SimpleRule.Comparator.EQ, false);

RuleSet set = new RuleSet.Builder(RuleSet.Mode.AND)
        .addRule(trueSet)
        .addRule(falseRule2)
        .build();

assertFalse(set.evaluate());

Custom rules

// fake data setup
class WeatherApi {
    public float getTemp() {
        return 30.4f;
    }
}

Integer iceEatenToday = 2;

final Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);

// the rules
RuleSet eatingIceTime = new RuleSet.Builder()
        // simple int comparison
        .addRule(new SimpleRule<Integer>(iceEatenToday, SimpleRule.Comparator.LT, 5))
        // float compared with return value of other object
        .addRule(new SimpleRule<Float>(new Value<Float>() {
            @Override
            public Float get() {
                return new WeatherApi().getTemp();
            }
        }, SimpleRule.Comparator.GT_EQ, 30f))
        // custom evaluation logic
        .addRule(new Rule() {
            @Override
            public boolean evaluate() {
                int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
                return dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY;
            }
        })
        .build();

assertTrue("Eh? But I'm still hungry!", eatingIceTime.evaluate()); // *yum* moar!
You can’t perform that action at this time.