diff --git a/ganttzk/src/main/java/org/zkoss/ganttz/data/constraint/Constraint.java b/ganttzk/src/main/java/org/zkoss/ganttz/data/constraint/Constraint.java index 1e72d939e..48d1b2425 100644 --- a/ganttzk/src/main/java/org/zkoss/ganttz/data/constraint/Constraint.java +++ b/ganttzk/src/main/java/org/zkoss/ganttz/data/constraint/Constraint.java @@ -19,8 +19,10 @@ */ package org.zkoss.ganttz.data.constraint; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.List; import org.zkoss.ganttz.util.WeakReferencedListeners; import org.zkoss.ganttz.util.WeakReferencedListeners.IListenerNotification; @@ -35,6 +37,37 @@ public abstract class Constraint { public void constraintViolated(Constraint constraint, T value); } + public static class ConstraintBuilder { + + private final T value; + + private final List> constraints = new ArrayList>(); + + public ConstraintBuilder(T value) { + this.value = value; + } + + public ConstraintBuilder withConstraints( + Constraint... constraints) { + return withConstraints(Arrays.asList(constraints)); + } + + public ConstraintBuilder withConstraints( + List> constraints) { + this.constraints.addAll(constraints); + return this; + } + + public T apply() { + return Constraint.apply(value, constraints); + } + + } + + public static ConstraintBuilder initialValue(T value) { + return new ConstraintBuilder(value); + } + public static T apply(T initialValue, Constraint... constraints) { return apply(initialValue, Arrays.asList(constraints)); } diff --git a/ganttzk/src/test/java/org/zkoss/ganttz/data/constraint/ConstraintTest.java b/ganttzk/src/test/java/org/zkoss/ganttz/data/constraint/ConstraintTest.java index de40d5578..1a064797f 100644 --- a/ganttzk/src/test/java/org/zkoss/ganttz/data/constraint/ConstraintTest.java +++ b/ganttzk/src/test/java/org/zkoss/ganttz/data/constraint/ConstraintTest.java @@ -39,23 +39,15 @@ import org.zkoss.ganttz.data.constraint.Constraint.IConstraintViolationListener; */ public class ConstraintTest { - private Constraint biggerThanFive = new Constraint() { + private Constraint biggerThanFive = biggerThan(5); - @Override - protected Integer applyConstraintTo(Integer currentValue) { - return Math.max(6, currentValue); - } + private Constraint biggerThanSeven = biggerThan(7); - @Override - public boolean isSatisfiedBy(Integer value) { - return value != null && value > 5; - } - }; private Constraint lessThanFive = new Constraint() { @Override public boolean isSatisfiedBy(Integer value) { - return value!=null && value <5; + return value != null && value < 5; } @Override @@ -64,6 +56,21 @@ public class ConstraintTest { } }; + private static Constraint biggerThan(final int limit) { + return new Constraint() { + + @Override + protected Integer applyConstraintTo(Integer currentValue) { + return Math.max(limit + 1, currentValue); + } + + @Override + public boolean isSatisfiedBy(Integer value) { + return value != null && value > limit; + } + }; + } + @Test public void ifThereIsNoConstraintsTheOriginalValueIsReturned() { assertThat(Constraint.apply(2), equalTo(2)); @@ -129,4 +136,39 @@ public class ConstraintTest { assertThat(constraintViolated[0], equalTo(biggerThanFive)); } + @SuppressWarnings("unchecked") + @Test + public void theApplicationCanBeDoneUsingAFluentInterface() { + assertThat(Constraint.initialValue(3) + .withConstraints(biggerThanFive) + .apply(), + equalTo(6)); + } + + @SuppressWarnings("unchecked") + @Test + public void severalConstraintsCanBeChained() { + assertThat(Constraint.initialValue(3) + .withConstraints(biggerThanFive) + .withConstraints(biggerThanSeven) + .apply(), + equalTo(8)); + } + + @SuppressWarnings("unchecked") + @Test + public void chainingSeveralConstrainsShowsThePriority() { + assertThat(Constraint.initialValue(5) + .withConstraints(biggerThanFive) + .withConstraints(lessThanFive) + .apply(), + equalTo(4)); + + assertThat(Constraint.initialValue(5) + .withConstraints(lessThanFive) + .withConstraints(biggerThanFive) + .apply(), + equalTo(6)); + } + }