Add u, p, s, j, f, F flags
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1736024 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expander.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expander.java
index c66edd2..b20284d 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expander.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/Expander.java
@@ -32,6 +32,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
@@ -636,6 +637,8 @@
{
getch();
+ // unique flag
+ boolean flagu = false;
// sort flags
boolean flago = false;
boolean flagO = false;
@@ -662,11 +665,62 @@
// quoting
int flagq = 0;
boolean flagQ = false;
+ // split / join
+ String flags = null;
+ String flagj = null;
+ // length
+ boolean computeLength = false;
// Parse flags
if (ch == '(') {
getch();
+ boolean flagp = false;
while (ch != EOT && ch != ')') {
switch (ch) {
+ case 'u':
+ flagu = true;
+ break;
+ case 'p':
+ flagp = true;
+ break;
+ case 'f':
+ flags = "\n";
+ break;
+ case 'F':
+ flagj = "\n";
+ break;
+ case 's':
+ case 'j': {
+ char opt = ch;
+ char c = getch();
+ if (c == EOT) {
+ throw new IllegalArgumentException("error in flags");
+ }
+ int start = index;
+ while (true) {
+ char n = getch();
+ if (n == EOT) {
+ throw new IllegalArgumentException("error in flags");
+ }
+ else if (n == c) {
+ break;
+ }
+ }
+ String s = text.subSequence(start, index - 1).toString();
+ if (flagp) {
+ s = ansiEscape(s).toString();
+ }
+ if (opt == 's') {
+ flags = s;
+ }
+ else if (opt == 'j') {
+ flagj = s;
+ }
+ else {
+ throw new IllegalArgumentException("error in flags");
+ }
+ flagp = false;
+ break;
+ }
case 'q':
if (flagq != 0) {
throw new IllegalArgumentException("error in flags");
@@ -775,14 +829,14 @@
val = getAndEvaluateName();
}
else {
- boolean computeLength = false;
- boolean wordSplit = false;
if (ch == '#') {
computeLength = true;
getch();
}
if (ch == '=') {
- wordSplit = true;
+ if (flags == null) {
+ flags = "\\s";
+ }
getch();
}
@@ -874,32 +928,6 @@
}
}
}
- if (computeLength) {
- if (val instanceof Collection) {
- val = ((Collection) val).size();
- }
- else if (val instanceof Map) {
- val = ((Map) val).size();
- }
- else if (val != null) {
- val = val.toString().length();
- }
- else {
- val = 0;
- }
- }
- if (wordSplit) {
- val = mapToList.apply(val);
- if (val instanceof Collection) {
- val = asCollection(val).stream()
- .map(String::valueOf)
- .flatMap(s -> Arrays.stream(s.split("\\s+")))
- .collect(Collectors.toList());
- }
- else if (val != null) {
- val = Arrays.asList(val.toString().split("\\s"));
- }
- }
}
//
@@ -1021,6 +1049,53 @@
val = val != null ? evaluate.get(val.toString()) : null;
}
+
+ // Character evaluation
+ if (flagSharp) {
+ val = stringApplyer.apply(this::sharp, val);
+ }
+
+ // Length
+ if (computeLength) {
+ if (val instanceof Collection) {
+ val = ((Collection) val).size();
+ }
+ else if (val instanceof Map) {
+ val = ((Map) val).size();
+ }
+ else if (val != null) {
+ val = val.toString().length();
+ }
+ else {
+ val = 0;
+ }
+ }
+
+ // Joining
+ if (flagj != null) {
+ val = mapToList.apply(val);
+ if (val instanceof Collection) {
+ val = asCollection(val).stream()
+ .map(String::valueOf)
+ .collect(Collectors.joining(flagj));
+ }
+ }
+
+ // Splitting
+ if (flags != null) {
+ String _flags = flags;
+ val = mapToList.apply(val);
+ if (!(val instanceof Collection)) {
+ val = Collections.singletonList(val);
+ }
+ val = asCollection(val).stream()
+ .map(String::valueOf)
+ .flatMap(s -> Arrays.stream(s.split(_flags)))
+ .filter(s -> !s.isEmpty())
+ .collect(Collectors.toList());
+ }
+
+ // Case modification
if (flagC) {
val = stringApplyer.apply(this::toCamelCase, val);
}
@@ -1031,6 +1106,30 @@
val = stringApplyer.apply(String::toUpperCase, val);
}
+ // Visibility enhancement
+ if (flagV) {
+ val = stringApplyer.apply(this::visible, val);
+ }
+
+ // Quote
+ if (flagq != 0) {
+ int _flagq = flagq;
+ val = stringApplyer.apply(s -> quote(s, _flagq), val);
+ inQuote = true;
+ }
+ else if (flagQ) {
+ val = stringApplyer.apply(this::unquote, val);
+ }
+
+ // Uniqueness
+ if (flagu) {
+ val = mapToList.apply(val);
+ if (val instanceof Collection) {
+ val = new ArrayList<>(new HashSet<>(asCollection(val)));
+ }
+ }
+
+ // Ordering
if (flaga || flagi || flagn || flago || flagO) {
val = mapToList.apply(val);
if (val instanceof Collection) {
@@ -1057,25 +1156,6 @@
}
}
- if (flagSharp) {
- val = stringApplyer.apply(this::sharp, val);
- }
-
- if (flagV) {
- val = stringApplyer.apply(this::visible, val);
- }
-
- // Quote
- if (flagq != 0) {
- int _flagq = flagq;
- val = stringApplyer.apply(s -> quote(s, _flagq), val);
- inQuote = true;
- }
- // Unquote
- else if (flagQ) {
- val = stringApplyer.apply(this::unquote, val);
- }
-
if (inQuote) {
val = mapToList.apply(val);
if (val instanceof Collection) {
diff --git a/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestTokenizer.java b/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestTokenizer.java
index 3664413..b56940f 100644
--- a/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestTokenizer.java
+++ b/gogo/runtime/src/test/java/org/apache/felix/gogo/runtime/TestTokenizer.java
@@ -200,6 +200,25 @@
}
@Test
+ public void testJoinSplit() throws Exception {
+ vars.clear();
+ vars.put("array", Arrays.asList("a", "b", "c"));
+ vars.put("string", "a\n\nb\nc");
+ vars.put("str", "such a bad bad trip");
+
+ assertEquals("a:b:c", expand("${(j.:.)array}"));
+ assertEquals("a\nb\nc", expand("${(pj.\\n.)array}"));
+ assertEquals("a\nb\nc", expand("${(F)array}"));
+
+ assertEquals(Arrays.asList("a", "b", "c"), expand("${(f)string}"));
+ assertEquals(Arrays.asList("a\n\n", "\nc"), expand("${(s:b:)string}"));
+
+ assertEquals("a:b:c", expand("${(Fj':')array}"));
+
+ assertEquals("a bad such trip", expand("${(j' ')${(s' 'uo)str}}"));
+ }
+
+ @Test
public void testParamFlag() throws Exception {
vars.clear();
vars.put("foo", "bar");