+ private static List<RangeConstraint> ensureResolvedRanges(final List<RangeConstraint> unresolved,
+ final List<RangeConstraint> baseRangeConstraints) {
+ // First check if we need to resolve anything at all
+ for (RangeConstraint c : unresolved) {
+ if (c.getMax() instanceof UnresolvedNumber || c.getMin() instanceof UnresolvedNumber) {
+ return resolveRanges(unresolved, baseRangeConstraints);
+ }
+ }
+
+ // No need, just return the same list
+ return unresolved;
+ }
+
+ private static List<RangeConstraint> resolveRanges(final List<RangeConstraint> unresolved,
+ final List<RangeConstraint> baseRangeConstraints) {
+ final Builder<RangeConstraint> builder = ImmutableList.builder();
+
+ for (RangeConstraint c : unresolved) {
+ final Number max = c.getMax();
+ final Number min = c.getMin();
+
+ if (max instanceof UnresolvedNumber || min instanceof UnresolvedNumber) {
+ final Number rMax = max instanceof UnresolvedNumber ?
+ ((UnresolvedNumber)max).resolve(baseRangeConstraints) : max;
+ final Number rMin = min instanceof UnresolvedNumber ?
+ ((UnresolvedNumber)min).resolve(baseRangeConstraints) : min;
+
+ builder.add(BaseConstraints.newRangeConstraint(rMin, rMax, Optional.fromNullable(c.getDescription()),
+ Optional.fromNullable(c.getReference())));
+ } else {
+ builder.add(c);
+ }
+
+ }
+
+ return builder.build();
+ }
+
+ private static List<RangeConstraint> ensureTypedRanges(final List<RangeConstraint> ranges,
+ final Class<? extends Number> clazz) {
+ for (RangeConstraint c : ranges) {
+ if (!clazz.isInstance(c.getMin()) || !clazz.isInstance(c.getMax())) {
+ return typedRanges(ranges, clazz);
+ }
+ }
+
+ return ranges;
+ }
+
+ private static List<RangeConstraint> typedRanges(final List<RangeConstraint> ranges, final Class<? extends Number> clazz) {
+ final Function<Number, Number> function = NumberUtil.converterTo(clazz);
+ Preconditions.checkArgument(function != null, "Unsupported range class %s", clazz);
+
+ final Builder<RangeConstraint> builder = ImmutableList.builder();
+
+ for (RangeConstraint c : ranges) {
+ if (!clazz.isInstance(c.getMin()) || !clazz.isInstance(c.getMax())) {
+ final Number min, max;
+
+ try {
+ min = function.apply(c.getMin());
+ max = function.apply(c.getMax());
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(String.format("Constraint %s does not fit into range of %s",
+ c, clazz.getSimpleName()), e);
+ }
+ builder.add(BaseConstraints.newRangeConstraint(min, max, Optional.fromNullable(c.getDescription()),
+ Optional.fromNullable(c.getReference())));
+ } else {
+ builder.add(c);
+ }
+ }
+
+ return builder.build();
+ }
+
+ private static boolean rangeCovered(final List<RangeConstraint> where,
+ final RangeConstraint what) {
+ // We have ensured the types match, and we are sure each of those types implements comparable
+ @SuppressWarnings("unchecked")
+ final Comparable<Object> min = (Comparable<Object>) what.getMin();
+ @SuppressWarnings("unchecked")
+ final Comparable<Object> max = (Comparable<Object>) what.getMax();
+
+ for (RangeConstraint c : where) {
+ if (min.compareTo(c.getMin()) >= 0 && max.compareTo(c.getMax()) <= 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+