09 — Core

RuleSets

A RuleSet groups multiple rules into an ordered collection and runs them in sequence against the same bindings.

Creating a RuleSet

RuleSet<?> ruleSet = RuleSet.builder()
    .with("EligibilityRules", "Checks if user is eligible")
    .rule(Rule.builder()
        .name("AgeRule")
        .given(condition((Integer age) -> age >= 18))
        .then(action((Binding<Boolean> eligible) -> eligible.setValue(true)))
        .build())
    .rule(Rule.builder()
        .name("ScoreRule")
        .given(condition((Integer score) -> score >= 50))
        .then(action((Binding<Integer> bonus) -> bonus.setValue(10)))
        .build())
    .build();

Running a RuleSet

Bindings bindings = Bindings.builder().standard();
bindings.bind("age", 25);
bindings.bind("score", 75);
bindings.bind("eligible", false);
bindings.bind("bonus", 0);

ruleSet.run(bindings);

// After execution:
// eligible = true   (AgeRule passed)
// bonus = 10        (ScoreRule passed)

Lifecycle Hooks

A RuleSet supports optional lifecycle hooks that run at specific points:

1 PreCondition — Should the set run at all?
2 Initializer — Setup action before any rules
3 Rules — Execute rules one by one
4 StopCondition — Stop early if condition is met
5 Finalizer — Cleanup action after all rules
6 ResultExtractor — Extract a return value
RuleSet<String> ruleSet = RuleSet.builder()
    .with("MyRuleSet")
    .preCondition(condition(() -> true))
    .initializer(action(() -> { /* setup */ }))
    .rule(/* ... rules ... */)
    .stopCondition(condition(() -> false))
    .finalizer(action(() -> { /* cleanup */ }))
    .resultExtractor(function(() -> "done"))
    .build();

String result = ruleSet.run(bindings);
// result == "done"

Accessing Rules in a RuleSet

Rule ageRule  = ruleSet.getRule("AgeRule");   // by name
Rule first    = ruleSet.getRule(0);              // by index
List<Rule> all = ruleSet.getRules();             // all rules
int count     = ruleSet.size();                   // count
boolean empty = ruleSet.isEmpty();                // is empty?

Combining Validation Rules

RuleSets are perfect for grouping validation rules:

RuleSet<?> validationSet = RuleSet.builder()
    .with("UserValidation")
    .rule(Rule.builder().build(new NotNullValidationRule("name")))
    .rule(Rule.builder().build(new NotEmptyValidationRule("name")))
    .rule(Rule.builder().build(new SizeValidationRule("name", 2, 50)))
    .rule(Rule.builder().build(new EmailValidationRule("email")))
    .build();

validationSet.run(
    name -> "Alice",
    email -> "alice@example.com",
    ruleViolations -> new RuleViolations()
);