TextUtils { public static Set<Integer> parseRange(String range) { if (range == null) { return Collections.emptySet(); } Set<Integer> ret = new LinkedHashSet<>(); StringTokenizer stringTokenizer = new StringTokenizer(range, String.format("%s%s", COMMA, DASH), true); Integer from = null; Integer to = null; boolean rangeStarted = false; while (stringTokenizer.hasMoreTokens()) { String token = stringTokenizer.nextToken(); if (isValueDelimiter(token)) { ret.addAll(fromToAsSet(from, to)); from = null; to = null; rangeStarted = false; } else if (isRangeDelimiter(token)) { rangeStarted = true; } else { String trimmedValue = token.trim(); if (!isPositiveInt(trimmedValue)) { throw new IllegalArgumentException("Range values should be positive numbers."); } Integer parsedInteger = Integer.parseUnsignedInt(trimmedValue); if (rangeStarted) { to = parsedInteger; } else { from = parsedInteger; } } if (from != null) { ret.addAll(fromToAsSet(from, to)); } } return ret; }  static String replacePlaceholders(final String template, Map<Placeholder, String> values); static String getPlaceholder(Placeholder placeholder); static String underscoreToUpperCamel(String input); static boolean containsPlaceholder(final String template, Placeholder placeholder); static String enumerateValues(Collection<String> values); static String enumerateValues(Collection<String> values, String delimiter); static String joinLines(Collection<String> values); static String humanizedDuration(ZonedDateTime zonedDateTime); static String createAssignment(Map<String, Set<String>> data); static Map<String, Set<String>> parseAssignment(String data); static Set<Integer> parseRange(String range); static boolean isRange(String value); static Set<String> parseEnumeration(String data); static Set<String> parseEnumeration(String data, String delimiter); static boolean isRangeDelimiter(String key); static boolean isFirstElementKey(String key); static boolean isLastElementKey(String key); static boolean isNextElementKey(String key); static boolean isPrevElementKey(String key); static boolean isExitKey(String key); static boolean isSkipKey(String key); static boolean isYesKey(String key); static boolean isNoKey(String key); static boolean isRepeatKey(String key); static boolean isNumericKey(String key); static boolean isPositiveInt(String key); static String quoteIfNeeded(String value); static String getAsExactMatch(String value); static Collection<String> removeSuffixes(Collection<String> input, Collection<String> suffixes); static Optional<T> routeByKey(Map<Predicate<String>, Function<String, T>> routes); static Optional<T> routeByKey(Map<Predicate<String>, Function<String, T>> routes, Consumer<String> onInvalidKey); static Optional<T> routeByKey(Map<Predicate<String>, Function<String, T>> routes, Consumer<String> onInvalidKey, Consumer<Exception> onException); static String getVersion(); static final String YES; static final String NO; static final String QUIT; static final String DASH; }
@Test public void testParseRange() { assertThat(parseRange(null), empty()); assertThat(parseRange(""), empty()); String range = "1,3- 5, 7 -9"; assertThat(parseRange(range), contains(1, 3, 4, 5, 7, 8, 9)); }
@Test(expected = IllegalArgumentException.class) public void testParseIllegalRange() throws Exception { parseRange("#$%-"); }