RangeCondition implements Predicate<Wrapper<?>> { static <X extends Number & Comparable<X>> RangeCondition<X> exact(final Function<Wrapper<?>, X> value, final Domain<X> allowedValues, final X minimum, final X maximum) { if (!allowedValues.test(minimum)) { throw new IllegalArgumentException("Minimum " + minimum + " does not fit " + allowedValues); } else if (!allowedValues.test(maximum)) { throw new IllegalArgumentException("Maximum " + maximum + " does not fit " + allowedValues); } else if (minimum.compareTo(maximum) > 0) { throw new IllegalArgumentException("Minimum " + minimum + " is over maximum " + maximum); } return new RangeCondition<>(value, v -> v.compareTo(minimum) >= 0 && v.compareTo(maximum) <= 0, "Range: <" + minimum + "; " + maximum + ">"); } private  RangeCondition(final Function<Wrapper<?>, T> accessor, final Predicate<T> acceptor,
            final String toString); @Override boolean test(final Wrapper<?> wrapper); @Override String toString();  }
@Test void exact() { final RangeCondition<Integer> c = RangeCondition.exact(Wrapper::getOriginalTermInMonths, new Domain<>(Integer.class, 0, null), 5, 5); final Wrapper<?> w = mock(Wrapper.class); when(w.getOriginalTermInMonths()).thenReturn(5); assertThat(c).accepts(w); when(w.getOriginalTermInMonths()).thenReturn(4); assertThat(c).rejects(w); when(w.getOriginalTermInMonths()).thenReturn(6); assertThat(c).rejects(w); }