/** Returns a new Range object with the {@code max} value replaced by the specified value. * The {@code min} of the returned Range is guaranteed not to be greater than the new {@code max} value. * @param newMax the {@code max} value of the returned Range object * @return a new Range object with the specified {@code max} value */ public Range max(int newMax) { return new Range(Math.min(min, newMax), newMax, isVariable, isUnspecified, originalValue); }
/** Returns a new Range object with the {@code min} value replaced by the specified value. * The {@code max} of the returned Range is guaranteed not to be less than the new {@code min} value. * @param newMin the {@code min} value of the returned Range object * @return a new Range object with the specified {@code min} value */ public Range min(int newMin) { return new Range(newMin, Math.max(newMin, max), isVariable, isUnspecified, originalValue); }
/** Leniently parses the specified String as an {@code Range} value and return the result. A range string can * be a fixed integer value or a range of the form {@code MIN_VALUE + ".." + MAX_VALUE}. If the * {@code MIN_VALUE} string is not numeric, the minimum is zero. If the {@code MAX_VALUE} is not numeric, the * range is taken to be variable and the maximum is {@code Integer.MAX_VALUE}. * @param range the value range string to parse * @return a new {@code Range} value */ public static Range valueOf(String range) { range = range.trim(); boolean unspecified = range.length() == 0 || range.startsWith(".."); // || range.endsWith(".."); int min = -1, max = -1; boolean variable = false; int dots = -1; if ((dots = range.indexOf("..")) >= 0) { min = parseInt(range.substring(0, dots), 0); max = parseInt(range.substring(dots + 2), Integer.MAX_VALUE); variable = max == Integer.MAX_VALUE; } else { max = parseInt(range, Integer.MAX_VALUE); variable = max == Integer.MAX_VALUE; min = variable ? 0 : max; } Range result = new Range(min, max, variable, unspecified, range); return result; } private static int parseInt(String str, int defaultValue) {
private static Range parameterArity(TypedMember member) { if (member.isAnnotationPresent(Parameters.class)) { return adjustForType(Range.valueOf(member.getAnnotation(Parameters.class).arity()), member); } else { return member.isMethodParameter() ? adjustForType(Range.valueOf(""), member) : new Range(0, 0, false, true, "0"); } } /** Returns a new {@code Range} based on the {@link Parameters#index()} annotation on the specified field.
private static Range optionArity(TypedMember member) { return member.isAnnotationPresent(Option.class) ? adjustForType(Range.valueOf(member.getAnnotation(Option.class).arity()), member) : new Range(0, 0, false, true, "0"); } /** Returns a new {@code Range} based on the {@link Parameters#arity()} annotation on the specified field,
/** Returns a new Range object with the {@code min} value replaced by the specified value. * The {@code max} of the returned Range is guaranteed not to be less than the new {@code min} value. * @param newMin the {@code min} value of the returned Range object * @return a new Range object with the specified {@code min} value */ public Range min(int newMin) { return new Range(newMin, Math.max(newMin, max), isVariable, isUnspecified, originalValue); }
@Test(expected = InitializationException.class) public void testRangeConstructorDisallowsNegativeMin() { new Range(-1, 2, false, false, ""); }
@Test public void testArityConstructor_variableRange() { Range arity = new Range(1, Integer.MAX_VALUE, true, false, null); assertEquals("min", 1, arity.min); assertEquals("max", Integer.MAX_VALUE, arity.max); assertEquals("1..*", arity.toString()); assertEquals(Range.valueOf("1..*"), arity); }
private static Range parameterIndex(TypedMember member) { if (member.isAnnotationPresent(Parameters.class)) { Range result = Range.valueOf(member.getAnnotation(Parameters.class).index()); if (!result.isUnspecified) { return result; } } if (member.isMethodParameter()) { int min = ((MethodParam) member.accessible).position; int max = member.isMultiValue() ? Integer.MAX_VALUE : min; return new Range(min, max, member.isMultiValue(), false, ""); } return Range.valueOf("*"); // the default } static Range adjustForType(Range result, TypedMember member) {
/** Returns a new Range object with the {@code max} value replaced by the specified value. * The {@code min} of the returned Range is guaranteed not to be greater than the new {@code max} value. * @param newMax the {@code max} value of the returned Range object * @return a new Range object with the specified {@code max} value */ public Range max(int newMax) { return new Range(Math.min(min, newMax), newMax, isVariable, isUnspecified, originalValue); }
@Test public void testConstructorDisallowsInvalidRange() { try { new Range(1, 0, true, true, ""); fail("Expected exception"); } catch (InitializationException ex) { assertEquals("Invalid range (min=1, max=0)", ex.getMessage()); } try { new Range(3, 1, true, true, ""); fail("Expected exception"); } catch (InitializationException ex) { assertEquals("Invalid range (min=3, max=1)", ex.getMessage()); } }
@Test public void testConstructorDisallowsNegativeRange() { try { new Range(-1, 0, true, true, ""); fail("Expected exception"); } catch (InitializationException ex) { assertEquals("Invalid negative range (min=-1, max=0)", ex.getMessage()); } try { new Range(-3, -1, true, true, ""); fail("Expected exception"); } catch (InitializationException ex) { assertEquals("Invalid negative range (min=-3, max=-1)", ex.getMessage()); } }
@Test(expected = InitializationException.class) public void testRangeConstructorDisallowsNegativeMax() { new Range(0, -2, false, false, ""); }
@Test(expected = InitializationException.class) public void testRangeConstructorDisallowsNegativeMin() { new Range(-1, 2, false, false, ""); }
private static Range parameterIndex(IAnnotatedElement member) { if (member.isAnnotationPresent(Parameters.class)) { Range result = Range.valueOf(member.getAnnotation(Parameters.class).index()); if (!result.isUnspecified) { return result; } } if (member.isMethodParameter()) { int min = member.getMethodParamPosition(); int max = member.isMultiValue() ? Integer.MAX_VALUE : min; return new Range(min, max, member.isMultiValue(), false, ""); } return Range.valueOf("*"); // the default } static Range adjustForType(Range result, IAnnotatedElement member) {
private static Range parameterArity(IAnnotatedElement member) { if (member.isAnnotationPresent(Parameters.class)) { return adjustForType(Range.valueOf(member.getAnnotation(Parameters.class).arity()), member); } else { return member.isMethodParameter() ? adjustForType(Range.valueOf(""), member) : new Range(0, 0, false, true, "0"); } } /** Returns a new {@code Range} based on the {@link Parameters#index()} annotation on the specified field.
@Test public void testArityConstructor_variableRange() { Range arity = new Range(1, Integer.MAX_VALUE, true, false, null); assertEquals("min", 1, arity.min); assertEquals("max", Integer.MAX_VALUE, arity.max); assertEquals("1..*", arity.toString()); assertEquals(Range.valueOf("1..*"), arity); }
/** Returns a new Range object with the {@code isUnspecified} value replaced by the specified value. * @param unspecified the {@code unspecified} value of the returned Range object * @return a new Range object with the specified {@code unspecified} value */ public Range unspecified(boolean unspecified) { return new Range(min, max, isVariable, unspecified, originalValue); } /** Returns {@code true} if this Range is a default value, {@code false} if the user specified this value.
@Test public void testArityConstructor_fixedRange() { Range arity = new Range(1, 23, false, false, null); assertEquals("min", 1, arity.min); assertEquals("max", 23, arity.max); assertEquals("1..23", arity.toString()); assertEquals(Range.valueOf("1..23"), arity); } @Test
private static Range optionArity(IAnnotatedElement member) { return member.isAnnotationPresent(Option.class) ? adjustForType(Range.valueOf(member.getAnnotation(Option.class).arity()), member) : new Range(0, 0, false, true, "0"); } /** Returns a new {@code Range} based on the {@link Parameters#arity()} annotation on the specified field,