[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[GitHub] brooklyn-server pull request #982: Improve coercions esp with generics
Github user aledsage commented on a diff in the pull request:
https://github.com/apache/brooklyn-server/pull/982#discussion_r214611925
--- Diff: utils/common/src/main/java/org/apache/brooklyn/util/text/StringEscapes.java ---
@@ -315,12 +320,121 @@ else if (c=='\"') {
throw new IllegalArgumentException("String '"+s+"' is not a valid Java string (unterminated string)");
}
+ /** @deprecated since 1.0.0, use {@link #unwrapJsonishListStringIfPossible(String)} (old semantics)
+ * or {@link #unwrapJsonishListStringIfPossible(String)} (improved) */
+ public static List<String> unwrapJsonishListIfPossible(String input) {
+ return unwrapJsonishListStringIfPossible(input);
+ }
+
+ /** converts a comma separated list in a single string to a list of json primitives or maps,
+ * falling back to returning the input.
+ * <p>
+ * specifically:
+ * <li> 1) if of form <code>[ X ]</code> (in brackets after trim), parse as YAML;
+ * if parse succeeds return the result, or if parse fails, return {@link Maybe#absent()}.
+ * <ll> 2) if not of form <code>[ X ]</code>, wrap in brackets and parse as YAML,
+ * and if that succeeds and is a list, return the result.
+ * <li> 3) otherwise, expect comma-separated tokens which after trimming are of the form "A" or B,
+ * where "A" is a valid Java string or C is any string not starting with '
+ * and not containing " or ,. return the list of those tokens, where A and B
+ * are their string value, and C as a primitive if it is a number or boolean or null,
+ * or else a string, including the empty string if empty.
+ * <li> 4) if such tokens are not found, return {@link Maybe#absent()}.
+ * <p>
+ * @see #unwrapOptionallyQuotedJavaStringList(String)
+ **/
+ public static Maybe<List<Object>> tryUnwrapJsonishList(String input) {
+ if (input==null) return Maybe.absent("null input cannot unwrap to a list");
+ String inputT = input.trim();
+
+ String inputYaml = null;
+ if (!inputT.startsWith("[") && !inputT.endsWith("]")) {
+ inputYaml = "[" + inputT + "]";
+ }
+ if (inputT.startsWith("[") && inputT.endsWith("]")) {
+ inputYaml = inputT;
+ }
+ if (inputYaml!=null) {
+ try {
+ Object r = Iterables.getOnlyElement( Yamls.parseAll(inputYaml) );
+ if (r instanceof List) {
+ @SuppressWarnings("unchecked")
+ List<Object> result = (List<Object>)r;
+ return Maybe.of(result);
+ }
+ } catch (Exception e) {}
+ if (inputT.startsWith("[")) {
+ // if supplied as yaml, don't allow failures
+ return Maybe.absent("Supplied format looked like YAML but could not parse as YAML");
+ }
+ }
+
+ List<Object> result = MutableList.of();
+
+ // double quote: ^ \s* " ([not quote or backslash] or [backslash any-char])* " \s* (, or $)
+ Pattern dq = Pattern.compile("^\\s*(\"([^\"\\\\]|[\\\\.])*\")\\s*(,|$)");
+ // could also support this, but we need new unescape routines
+// // single quote: ^ \s* ' ([not quote or backslash] or [backslash any-char])* ' \s* (, or $)
+// Pattern sq = Pattern.compile("^\\s*'([^\'\\\\]|[\\\\.])'*\\s*(,|$)");
+ // no quote: ^ \s* (empty, or [not ' or " or space] ([not , or "]* [not , or " or space])?) \s* (, or $)
+ Pattern nq = Pattern.compile("^\\s*(|[^,\"\\s]([^,\"]*[^,\"\\s])?)\\s*(,|$)");
+
+ int removedChars = 0;
+ while (true) {
+ Object ri;
+ Matcher m = dq.matcher(input);
+ if (m.find()) {
+ try {
+ ri = unwrapJavaString(m.group(1));
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ return Maybe.absent("Could not match valid quote pattern" +
+ (removedChars>0 ? " at position "+removedChars : "")
+ + ": "+ Exceptions.collapseText(e));
+ }
+ } else {
+ m = nq.matcher(input);
+ if (m.find()) {
+ String w = m.group(1);
+
+ ri = w;
+ if (w.matches("[0-9]*.[0-9]+")) {
--- End diff --
Should this not be an escaped decimal place rather than any char (`.`)? Are you meaning to deal with `e` as well? Is `.4` a valid double in yaml (rather than having to write `0.4`)?
---