DEFENSIVE PROGRAMMING WITH KLOJANG CHECK

Composing Tests

Klojang Check allows you to combine two or more checks into a single new check that expresses the logical conjunction (AND) or disjunction (OR) of the individual checks. Generally the latter will be of more use since the chain of checks following Check.that(...) already constitutes a logical conjunction. For example, this statement:

    this.numChairs = Check.that(numChairs).is(positive()).is(lt(), 5).is(even()).ok();

requires the number of chairs to be positive and less than five and even. If the number of chairs needs to pass just one of these tests, write:

    this.numChairs = Check.that(numChairs).is(positive().orElse(lt(), 5).orElse(even());

Notice that the entire check now takes place within a single call to the is() method.

Nevertheless, you might still want to use the and() method for conciseness:

    Check.that(text).is(notNull().and(hasSubstring(), allOf(), "to", "be", "or", "not");

which is equivalent to, but quite a bit more economical than:

    Check.that(text).is(notNull())
        .is(hasSubstring(), "to")
        .is(hasSubstring(), "be")
        .is(hasSubstring(), "or")
        .is(hasSubstring(), "not");

On the downside: even though both notNull() and hasSubstring() have an error message associated with them, their combination (not-null-and-has-substring) does not. It is a completely new predicate that has no special meaning for Klojang Check. So you would probably want to provide our own error message when opting for the first variant.

orElse what?

You may not recall  orElse() being a method of Predicate or IntPredicate, and it isn't. While the is(), isNot(), has() and notHas() methods accept ordinary Predicate and IntPredicate arguments, the type of the predicates in the CommonChecks class is either ComposablePredicate or ComposableIntPredicate. These are extensions of Predicate and IntPredicate, respectively. It is through these interfaces that you can freely combine predicates and relations. Every composition must start either with a ComposablePredicate or a ComposableIntPredicate. Also, validating a value against a set of other values, as well as validating two interrelated values always happens through either a ComposablePredicate or a ComposableIntPredicate. (See Value Domain Tests and Interrelated Values.)