|
|
@@ -0,0 +1,64 @@
|
|
|
+package net.ranides.assira.collection.lists;
|
|
|
+
|
|
|
+import net.ranides.assira.text.StringTraits;
|
|
|
+
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+import java.util.stream.IntStream;
|
|
|
+
|
|
|
+public class IntListGenerator {
|
|
|
+
|
|
|
+ private static final Pattern IS_RANGE = Pattern.compile("([0-9]+)-([0-9]+)");
|
|
|
+
|
|
|
+ public static IntList parse(String selector) {
|
|
|
+ return parse(Collections.emptyList(), Integer.MAX_VALUE, selector);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static IntList parse(int size, String selector) {
|
|
|
+ return parse(Collections.emptyList(), size, selector);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static IntList parse(List<String> names, String selector) {
|
|
|
+ return parse(names, names.size(), selector);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static IntList parse(List<String> names, int size, String selector) {
|
|
|
+ IntList indexes = new IntArrayList();
|
|
|
+
|
|
|
+ Matcher hit;
|
|
|
+
|
|
|
+ for(String expr : selector.split(",")) {
|
|
|
+ int fieldIndex = names.indexOf(expr);
|
|
|
+ if(fieldIndex != -1) {
|
|
|
+ indexes.add(fieldIndex);
|
|
|
+ }
|
|
|
+ else if((hit = IS_RANGE.matcher(expr)).matches()) {
|
|
|
+ range(hit).filter(v -> v < size).forEach(indexes::add);
|
|
|
+ }
|
|
|
+ else if(StringTraits.isNumber(expr)) {
|
|
|
+ int i = Integer.parseInt(expr);
|
|
|
+ if(i > size) {
|
|
|
+ throw new IndexOutOfBoundsException(i + " out of range: [0-" + size + ")");
|
|
|
+ } else {
|
|
|
+ indexes.add(i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ throw new IllegalArgumentException("Invalid index name: " + expr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return indexes;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static IntStream range(Matcher range) {
|
|
|
+ int a = Integer.parseInt(range.group(1));
|
|
|
+ int b = Integer.parseInt(range.group(2));
|
|
|
+ if (a <= b) {
|
|
|
+ return IntStream.rangeClosed(a, b);
|
|
|
+ } else {
|
|
|
+ return IntStream.rangeClosed(b, a).map(v -> b + a - v);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|