diff --git a/src/main/java/net/rptools/maptool/client/MapTool.java b/src/main/java/net/rptools/maptool/client/MapTool.java index 98471b7a86..8e292e879b 100644 --- a/src/main/java/net/rptools/maptool/client/MapTool.java +++ b/src/main/java/net/rptools/maptool/client/MapTool.java @@ -876,23 +876,6 @@ public static void addGlobalMessage(String message) { addMessage(TextMessage.say(null, message)); } - /** - * Add a message all specified clients will see. This is a shortcut for addMessage(WHISPER, ...) - * and addMessage(GM, ...). The targets is expected do be in a string list built with - * separator. - * - * @param message message to be sent - * @param targets string specifying clients to send the message to (spaces are trimmed) - * @param separator the separator between entries in targets - */ - public static void addGlobalMessage(String message, String targets, String separator) { - List list = new LinkedList(); - for (String target : targets.split(separator)) { - list.add(target.trim()); - } - addGlobalMessage(message, list); - } - /** * Add a message all specified clients will see. This is a shortcut for addMessage(WHISPER, ...) * and addMessage(GM, ...). diff --git a/src/main/java/net/rptools/maptool/client/functions/ChatFunction.java b/src/main/java/net/rptools/maptool/client/functions/ChatFunction.java index b352c5b360..c2b4344bf0 100644 --- a/src/main/java/net/rptools/maptool/client/functions/ChatFunction.java +++ b/src/main/java/net/rptools/maptool/client/functions/ChatFunction.java @@ -23,6 +23,7 @@ import net.rptools.maptool.client.ui.commandpanel.CommandPanel; import net.rptools.maptool.language.I18N; import net.rptools.maptool.model.TextMessage; +import net.rptools.maptool.util.StringUtil; import net.rptools.parser.Parser; import net.rptools.parser.ParserException; import net.rptools.parser.VariableResolver; @@ -93,7 +94,9 @@ private Object broadcast(VariableResolver resolver, List param) throws P jarray = JsonParser.parseString(temp).getAsJsonArray(); else { jarray = new JsonArray(); - for (String t : temp.split(delim)) jarray.add(t.trim()); + for (String t : StringUtil.split(temp, delim)) { + jarray.add(t.trim()); + } } if (jarray.size() == 0) { return ""; // dont send to empty lists diff --git a/src/main/java/net/rptools/maptool/client/functions/ExecFunction.java b/src/main/java/net/rptools/maptool/client/functions/ExecFunction.java index 7da7a211bb..b0a7b9ab32 100644 --- a/src/main/java/net/rptools/maptool/client/functions/ExecFunction.java +++ b/src/main/java/net/rptools/maptool/client/functions/ExecFunction.java @@ -25,6 +25,7 @@ import net.rptools.maptool.client.functions.json.JsonArrayFunctions; import net.rptools.maptool.language.I18N; import net.rptools.maptool.util.FunctionUtil; +import net.rptools.maptool.util.StringUtil; import net.rptools.parser.Parser; import net.rptools.parser.ParserException; import net.rptools.parser.VariableResolver; @@ -88,7 +89,7 @@ public Object childEvaluate( jsonTargets = jsonArrayFunctions.parseJsonArray(strTargets); } else { jsonTargets = new JsonArray(); - for (String t : strTargets.split(delim)) { + for (String t : StringUtil.split(strTargets, delim)) { jsonTargets.add(t.trim()); } } diff --git a/src/main/java/net/rptools/maptool/client/functions/FogOfWarFunctions.java b/src/main/java/net/rptools/maptool/client/functions/FogOfWarFunctions.java index d0fd07e70a..47e89c09bf 100644 --- a/src/main/java/net/rptools/maptool/client/functions/FogOfWarFunctions.java +++ b/src/main/java/net/rptools/maptool/client/functions/FogOfWarFunctions.java @@ -29,6 +29,7 @@ import net.rptools.maptool.model.Token; import net.rptools.maptool.model.Zone; import net.rptools.maptool.util.FunctionUtil; +import net.rptools.maptool.util.StringUtil; import net.rptools.parser.Parser; import net.rptools.parser.ParserException; import net.rptools.parser.VariableResolver; @@ -172,7 +173,7 @@ private Set getTokenSetFromList(final Zone zone, final String paramStr, fi } } else { // String List - String[] strList = paramStr.split(delim); + String[] strList = StringUtil.split(paramStr, delim); for (String s : strList) { Token t = zone.resolveToken(s.trim()); if (t != null) { diff --git a/src/main/java/net/rptools/maptool/client/functions/InputFunction.java b/src/main/java/net/rptools/maptool/client/functions/InputFunction.java index 560be3ce4a..1fcc6e9b18 100644 --- a/src/main/java/net/rptools/maptool/client/functions/InputFunction.java +++ b/src/main/java/net/rptools/maptool/client/functions/InputFunction.java @@ -75,6 +75,7 @@ import net.rptools.maptool.language.I18N; import net.rptools.maptool.model.Token; import net.rptools.maptool.util.ImageManager; +import net.rptools.maptool.util.StringUtil; import net.rptools.parser.Parser; import net.rptools.parser.ParserException; import net.rptools.parser.VariableResolver; @@ -394,7 +395,7 @@ public List parseStringList(String valueString, String delim) { } } } else { - String[] values = valueString.split(delim); + String[] values = StringUtil.split(valueString, delim); for (String s : values) { ret.add(s.trim()); } diff --git a/src/main/java/net/rptools/maptool/client/functions/JSONMacroFunctionsOld.java b/src/main/java/net/rptools/maptool/client/functions/JSONMacroFunctionsOld.java deleted file mode 100644 index ef6ca66351..0000000000 --- a/src/main/java/net/rptools/maptool/client/functions/JSONMacroFunctionsOld.java +++ /dev/null @@ -1,1964 +0,0 @@ -/* - * This software Copyright by the RPTools.net development team, and - * licensed under the Affero GPL Version 3 or, at your option, any later - * version. - * - * MapTool Source Code is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public - * License * along with this source Code. If not, please visit - * and specifically the Affero license - * text at . - */ -package net.rptools.maptool.client.functions; - -import com.google.gson.JsonElement; -import com.jayway.jsonpath.*; -import com.jayway.jsonpath.spi.json.GsonJsonProvider; -import java.math.BigDecimal; -import java.util.*; -import net.rptools.dicelib.expression.ExpressionParser; -import net.rptools.maptool.client.MapTool; -import net.rptools.maptool.client.MapToolVariableResolver; -import net.rptools.maptool.language.I18N; -import net.rptools.maptool.util.FunctionUtil; -import net.rptools.parser.*; -import net.rptools.parser.function.AbstractFunction; -import net.sf.json.JSONArray; -import net.sf.json.JSONNull; -import net.sf.json.JSONObject; - -@SuppressWarnings("unchecked") -public class JSONMacroFunctionsOld extends AbstractFunction { - public enum JSONObjectType { - OBJECT, - ARRAY, - UNKNOWN - } - - private static final JSONMacroFunctionsOld instance = new JSONMacroFunctionsOld(); - - private static final Configuration jaywayConfig = - Configuration.builder().jsonProvider(new GsonJsonProvider()).build(); - - private JSONMacroFunctionsOld() { - super( - 1, - UNLIMITED_PARAMETERS, - "json.get", - "json.path.read", - "json.path.add", - "json.path.put", - "json.path.set", - "json.path.delete", - "json.type", - "json.fields", - "json.length", - "json.fromList", - "json.set", - "json.fromStrProp", - "json.toStrProp", - "json.toList", - "json.toVars", - "json.append", - "json.remove", - "json.indent", - "json.contains", - "json.sort", - "json.shuffle", - "json.reverse", - "json.evaluate", - "json.isEmpty", - "json.equals", - "json.count", - "json.indexOf", - "json.merge", - "json.unique", - "json.removeAll", - "json.union", - "json.intersection", - "json.difference", - "json.isSubset", - "json.removeFirst", - "json.rolls", - "json.objrolls"); - } - - public static JSONMacroFunctionsOld getInstance() { - return instance; - } - - @Override - public Object childEvaluate( - Parser parser, VariableResolver resolver, String functionName, List parameters) - throws ParserException { - - if (functionName.equalsIgnoreCase("json.fromList")) { - String delim = ","; - if (parameters.size() > 1) { - delim = parameters.get(1).toString(); - } - return fromStrList(parameters.get(0).toString(), delim); - } - - if (functionName.equalsIgnoreCase("json.path.read")) { - FunctionUtil.checkNumberParam(functionName, parameters, 2, 2); - String jsonStr = parameters.get(0).toString(); - String path = parameters.get(1).toString(); - - try { - JsonElement obj = JsonPath.using(jaywayConfig).parse(jsonStr).read(path); - if (obj.isJsonPrimitive()) { - try { - // Maybe it's a number. - BigDecimal bd = obj.getAsBigDecimal(); - return bd; - } catch (NumberFormatException e) { - // So, not a number. - // Doing a toString() was wrapping the returned string in quotes. - return obj.getAsString(); - } - } else { - // Curiously using getAsString() on JsonObjects threw an exception but using - // toString() works fine for objects and arrays. - return obj.toString(); - } - } catch (Exception e) { - throw new ParserException( - I18N.getText("macro.function.json.path", functionName, e.getLocalizedMessage())); - } - } - - if (functionName.equalsIgnoreCase("json.path.add")) { - FunctionUtil.checkNumberParam(functionName, parameters, 3, 3); - String jsonStr = parameters.get(0).toString(); - String path = parameters.get(1).toString(); - Object value = parameters.get(2); - Object json = convertToJSON(value.toString()); - if (json != null) value = json; // to prevent quotes getting turned into \" and \" - - try { - return JsonPath.parse(jsonStr).add(path, value).jsonString(); // add element to array - } catch (Exception e) { - throw new ParserException( - I18N.getText("macro.function.json.path", functionName, e.getLocalizedMessage())); - } - } - - if (functionName.equalsIgnoreCase("json.path.set")) { - FunctionUtil.checkNumberParam(functionName, parameters, 3, 3); - String jsonStr = parameters.get(0).toString(); - String path = parameters.get(1).toString(); - Object value = parameters.get(2); - Object json = convertToJSON(value.toString()); - if (json != null) value = json; - - try { - return JsonPath.parse(jsonStr).set(path, value).jsonString(); // set element in array/object - } catch (Exception e) { - throw new ParserException( - I18N.getText("macro.function.json.path", functionName, e.getLocalizedMessage())); - } - } - - if (functionName.equalsIgnoreCase("json.path.put")) { - FunctionUtil.checkNumberParam(functionName, parameters, 4, 4); - String jsonStr = parameters.get(0).toString(); - String path = parameters.get(1).toString(); - String key = parameters.get(2).toString(); - Object value = parameters.get(3); - Object json = convertToJSON(value.toString()); - if (json != null) value = json; - - try { - return JsonPath.parse(jsonStr).put(path, key, value).jsonString(); // add value in object - } catch (Exception e) { - throw new ParserException( - I18N.getText("macro.function.json.path", functionName, e.getLocalizedMessage())); - } - } - - if (functionName.equalsIgnoreCase("json.path.delete")) { - FunctionUtil.checkNumberParam(functionName, parameters, 2, 2); - String jsonStr = parameters.get(0).toString(); - String path = parameters.get(1).toString(); - - try { - return JsonPath.parse(jsonStr).delete(path).jsonString(); // delete path - } catch (Exception e) { - throw new ParserException( - I18N.getText("macro.function.json.path", functionName, e.getLocalizedMessage())); - } - } - - if (functionName.equalsIgnoreCase("json.fromStrProp")) { - String delim = ";"; - if (parameters.size() > 1) { - delim = parameters.get(1).toString(); - } - return fromStrProp(parameters.get(0).toString(), delim); - } - - if (functionName.equalsIgnoreCase("json.toVars")) { - FunctionUtil.checkNumberParam(functionName, parameters, 1, 3); - Object json = FunctionUtil.paramAsJson(functionName, parameters, 0); - JSONArray jsonNames = new JSONArray(); - if (json instanceof JSONObject) { - JSONObject jsonObject = (JSONObject) json; - String prefix = parameters.size() > 1 ? parameters.get(1).toString() : ""; - String suffix = parameters.size() > 2 ? parameters.get(2).toString() : ""; - - for (Object keyStr : jsonObject.keySet()) { - // add prefix and suffix - String varName = prefix + keyStr.toString().trim() + suffix; - // replace spaces by underscores - varName = varName.replaceAll("\\s", "_"); - // delete special characters other than "." & "_" in var name - varName = varName.replaceAll("[^a-zA-Z0-9._]", ""); - - if (!varName.equals("")) { - resolver.setVariable(varName, jsonObject.get(keyStr)); - jsonNames.add(varName); - } - } - } else { - FunctionUtil.checkNumberParam(functionName, parameters, 2, 2); - JSONArray jsonArray = (JSONArray) json; - - String varName = parameters.get(1).toString(); - // replace spaces by underscores - varName = varName.replaceAll("\\s", "_"); - // delete special characters other than "." & "_" in var name - varName = varName.replaceAll("[^a-zA-Z0-9._]", ""); - - if (!varName.equals("")) { - for (int i = 0; i < jsonArray.size(); i++) { - resolver.setVariable(varName + i, jsonArray.get(i)); - jsonNames.add(varName + i); - } - } - } - return jsonNames; - } - - if (functionName.equalsIgnoreCase("json.set")) { - if (parameters.size() < 3) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 3, parameters.size())); - } - return JSONSet(asJSON(parameters.get(0)), parameters); - } - - if (functionName.equalsIgnoreCase("json.length")) { - return JSONLength(asJSON(parameters.get(0))); - } - - if (functionName.equalsIgnoreCase("json.fields")) { - String delim = ","; - if (parameters.size() > 1) { - delim = parameters.get(1).toString(); - } - return JSONFields(asJSON(parameters.get(0)), delim); - } - - if (functionName.equalsIgnoreCase("json.type")) { - return getJSONObjectType(parameters.get(0)).toString(); - } - - if (functionName.equalsIgnoreCase("json.toList")) { - String delim = ","; - if (parameters.size() > 1) { - delim = parameters.get(1).toString(); - } - return JSONToList(asJSON(parameters.get(0)), delim); - } - - if (functionName.equalsIgnoreCase("json.toStrProp")) { - String delim = ";"; - if (parameters.size() > 1) { - delim = parameters.get(1).toString(); - } - return JSONToStrProp(asJSON(parameters.get(0)), delim); - } - - if (functionName.equalsIgnoreCase("json.get")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - return JSONGet(asJSON(parameters.get(0)), parameters.subList(1, parameters.size())); - } - - if (functionName.equalsIgnoreCase("json.append")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - return JSONAppend(asJSON(parameters.get(0)), parameters); - } - - if (functionName.equalsIgnoreCase("json.remove")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - return JSONDelete(asJSON(parameters.get(0)), parameters.get(1).toString()); - } - - if (functionName.equalsIgnoreCase("json.indent")) { - int indent = 4; - if (parameters.size() > 1) { - try { - indent = Integer.parseInt(parameters.get(1).toString()); - } catch (Exception e) { - // Do nothing as we will just use the default. - } - } - return JSONIndent(asJSON(parameters.get(0)), indent); - } - - if (functionName.equalsIgnoreCase("json.contains")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - return JSONContains(asJSON(parameters.get(0)), parameters.get(1).toString()) - ? BigDecimal.ONE - : BigDecimal.ZERO; - } - - if (functionName.equalsIgnoreCase("json.sort")) { - if (parameters.size() > 2) { - List fields = new ArrayList(parameters.size() - 2); - for (Object o : parameters.subList(2, parameters.size())) { - if (o instanceof String) fields.add((String) o); - else - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - o == null ? "NULL" : o.toString(), - functionName)); - } - return JSONSort(asJSON(parameters.get(0)), parameters.get(1).toString(), fields); - } else { - return JSONSort( - asJSON(parameters.get(0)), - parameters.size() > 1 ? parameters.get(1).toString() : "ascending", - null); - } - } - - if (functionName.equalsIgnoreCase("json.shuffle")) { - return JSONShuffle(asJSON(parameters.get(0))); - } - - if (functionName.equalsIgnoreCase("json.reverse")) { - return JSONReverse(asJSON(parameters.get(0))); - } - - if (functionName.equalsIgnoreCase("json.evaluate")) { - if (!MapTool.getParser().isMacroTrusted()) { - throw new ParserException(I18N.getText("macro.function.general.noPerm", functionName)); - } - Object j = asJSON(parameters.get(0)); - if (!(j instanceof JSONObject) && !(j instanceof JSONArray)) { - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - j == null ? "NULL" : j.toString(), - "json.evaluate")); - } - // Create a new object or array so that we preserve immutability for macros. - Object json; - if (j instanceof JSONObject) { - json = JSONObject.fromObject(j); - } else { - json = JSONArray.fromObject(j); - } - return JSONEvaluate((MapToolVariableResolver) resolver, json); - } - - if (functionName.equalsIgnoreCase("json.isEmpty")) { - Object j = asJSON(parameters.get(0)); - if (j instanceof JSONObject) { - return ((JSONObject) j).isEmpty() ? BigDecimal.ONE : BigDecimal.ZERO; - } - if (j instanceof JSONArray) { - return ((JSONArray) j).isEmpty() ? BigDecimal.ONE : BigDecimal.ZERO; - } - if (j instanceof String) { - return j.toString().length() == 0 ? BigDecimal.ONE : BigDecimal.ZERO; - } - return BigDecimal.ZERO; - } - - if (functionName.equalsIgnoreCase("json.equals")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - Object left = asJSON(parameters.get(0)); - Object right = asJSON(parameters.get(1)); - - if (left instanceof JSONArray) { - if (right instanceof JSONArray) { - JSONArray la = (JSONArray) left; - JSONArray ra = (JSONArray) right; - if (la.size() != ra.size()) { - return BigDecimal.ZERO; - } - for (int i = 0; i < la.size(); i++) { - if (!la.get(i).equals(ra.get(i))) { - return BigDecimal.ZERO; - } - } - return BigDecimal.ONE; - } - return BigDecimal.ZERO; - } - - if (left instanceof JSONObject && right instanceof JSONObject) { - JSONObject lo = (JSONObject) left; - JSONObject ro = (JSONObject) right; - - if (lo.size() != ro.size()) { - return BigDecimal.ZERO; - } - - for (Object key : lo.keySet()) { - if (!lo.get(key).equals(ro.get(key))) { - return BigDecimal.ZERO; - } - } - return BigDecimal.ONE; - } - - if (left instanceof String) { - if (right instanceof String) { - if (left.toString().length() == 0 || right.toString().length() == 0) { - return BigDecimal.ONE; - } - } - return BigDecimal.ZERO; - } - return BigDecimal.ZERO; - } - - if (functionName.equalsIgnoreCase("json.count")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - int start = 0; - if (parameters.size() > 2) { - if (!(parameters.get(2) instanceof BigDecimal)) { - throw new ParserException( - I18N.getText( - "macro.function.general.argumentTypeN", - functionName, - 3, - parameters.get(2).toString())); - } - start = ((BigDecimal) parameters.get(2)).intValue(); - } - return JSONCount(asJSON(parameters.get(0).toString()), parameters.get(1), start); - } - - if (functionName.equalsIgnoreCase("json.indexOf")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - int start = 0; - if (parameters.size() > 2) { - if (!(parameters.get(2) instanceof BigDecimal)) { - throw new ParserException( - I18N.getText( - "macro.function.general.argumentTypeN", - functionName, - 3, - parameters.get(2).toString())); - } - start = ((BigDecimal) parameters.get(2)).intValue(); - } - return JSONIndexOf(asJSON(parameters.get(0).toString()), parameters.get(1), start); - } - - if (functionName.equalsIgnoreCase("json.merge")) { - return JSONMerge(parameters); - } - - if (functionName.equalsIgnoreCase("json.unique")) { - return JSONUnique(asJSON(parameters.get(0).toString())); - } - - if (functionName.equalsIgnoreCase("json.removeAll")) { - return JSONRemoveAll(parameters); - } - - if (functionName.equalsIgnoreCase("json.removeFirst")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - return JSONRemoveFirst(parameters); - } - - if (functionName.equalsIgnoreCase("json.union")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - return JSONUnion(parameters); - } - - if (functionName.equalsIgnoreCase("json.difference")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - return JSONDifference(parameters); - } - - if (functionName.equalsIgnoreCase("json.intersection")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - return JSONIntersection(parameters); - } - - if (functionName.equalsIgnoreCase("json.isSubset")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } - return JSONIsSubset(parameters); - } - - if (functionName.equalsIgnoreCase("json.rolls")) { - if (parameters.size() < 2) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 2, parameters.size())); - } else if (parameters.size() > 3) { - throw new ParserException( - I18N.getText( - "macro.function.general.tooManyParam", functionName, 3, parameters.size())); - } - return JSONRolls(parameters); - } - - if (functionName.equalsIgnoreCase("json.objrolls")) { - if (parameters.size() != 3) { - throw new ParserException( - I18N.getText( - "macro.function.general.notEnoughParam", functionName, 3, parameters.size())); - } - - return JSONObjRolls(parameters); - } - throw new ParserException(functionName + "(): Unknown function"); - } - - /** - * Determines if JSON arrays are a subset of another array. - * - * @param parameters The arguments to the function. - * @return 1 if all the sets are a subset of the first set, otherwise 0. - * @throws ParserException If an error occurs. - */ - private BigDecimal JSONIsSubset(List parameters) throws ParserException { - Set set = new HashSet(); - Set subset = new HashSet(); - - Object o1 = asJSON(parameters.get(0)); - if (o1 instanceof JSONArray) { - set.addAll((JSONArray) o1); - } else if (o1 instanceof JSONObject) { - set.addAll(((JSONObject) o1).keySet()); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - o1 == null ? "NULL" : o1.toString(), - "json.isSubset")); - } - - for (int i = 1; i < parameters.size(); i++) { - Object o2 = asJSON(parameters.get(i)); - if (o2 instanceof JSONArray) { - subset.addAll((JSONArray) o2); - } else if (o2 instanceof JSONObject) { - subset.addAll(((JSONObject) o2).keySet()); - } else { - throw new ParserException( - I18N.getText("macro.function.json.onlyJSON", o1.toString(), "json.isSubset")); - } - - if (!set.containsAll(subset)) { - return BigDecimal.ZERO; - } - } - - return BigDecimal.ONE; - } - - /** - * Remove the first occurrence of each element in the second array from the first array. - * - * @param parameters The arguments to the function. - * @return a JSON array containing the difference of all the arguments. - * @throws ParserException - */ - private Object JSONRemoveFirst(List parameters) throws ParserException { - - List result; - - Object o = asJSON(parameters.get(0).toString()); - if (o instanceof JSONArray) { - result = new LinkedList<>((JSONArray) o); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyArray", - o == null ? "NULL" : o.toString(), - "json.removeFirst")); - } - - o = asJSON(parameters.get(1).toString()); - List toRemove; - if (o instanceof JSONArray) { - toRemove = new ArrayList<>((JSONArray) o); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyArray", - o == null ? "NULL" : o.toString(), - "json.removeFirst")); - } - - for (Object val : toRemove) { - Iterator iter = result.iterator(); - while (iter.hasNext()) { - Object obj = iter.next(); - if (obj.equals(val)) { - iter.remove(); - break; - } - } - } - - return JSONArray.fromObject(result); - } - - /** - * Perform a difference of all of the JSON objects or arrays. - * - * @param parameters The arguments to the function. - * @return a JSON array containing the difference of all the arguments. - * @throws ParserException - */ - private Object JSONDifference(List parameters) throws ParserException { - Set s = new HashSet(); - - Object o = asJSON(parameters.get(0).toString()); - if (o instanceof JSONArray) { - s.addAll((JSONArray) o); - } else if (o instanceof JSONObject) { - s.addAll(((JSONObject) o).keySet()); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - o == null ? "NULL" : o.toString(), - "json.difference")); - } - - for (int i = 1; i < parameters.size(); i++) { - o = asJSON(parameters.get(i).toString()); - if (o instanceof JSONArray) { - s.removeAll((JSONArray) o); - } else if (o instanceof JSONObject) { - s.removeAll(((JSONObject) o).keySet()); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - o == null ? "NULL" : o.toString(), - "json.difference")); - } - } - - return JSONArray.fromObject(s); - } - - /** - * Perform a union of all of the JSON objects or arrays. - * - * @param parameters The arguments to the function. - * @return a JSON array containing the union of all the arguments. - * @throws ParserException - */ - private Object JSONUnion(List parameters) throws ParserException { - Set s = new HashSet(); - - Object o = asJSON(parameters.get(0).toString()); - if (o instanceof JSONArray) { - s.addAll((JSONArray) o); - } else if (o instanceof JSONObject) { - s.addAll(((JSONObject) o).keySet()); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", o == null ? "NULL" : o.toString(), "json.union")); - } - - for (int i = 1; i < parameters.size(); i++) { - o = asJSON(parameters.get(i).toString()); - if (o instanceof JSONArray) { - s.addAll((JSONArray) o); - } else if (o instanceof JSONObject) { - s.addAll(((JSONObject) o).keySet()); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", o == null ? "NULL" : o.toString(), "json.union")); - } - } - - return JSONArray.fromObject(s); - } - - /** - * Perform a intersection of all of the JSON objects or arrays. - * - * @param parameters The arguments to the function. - * @return a JSON array containing the intersection of all the arguments. - * @throws ParserException - */ - private Object JSONIntersection(List parameters) throws ParserException { - Set s = new HashSet(); - - Object o = asJSON(parameters.get(0).toString()); - if (o instanceof JSONArray) { - s.addAll((JSONArray) o); - } else if (o instanceof JSONObject) { - s.addAll(((JSONObject) o).keySet()); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - o == null ? "NULL" : o.toString(), - "json.intersection")); - } - - for (int i = 1; i < parameters.size(); i++) { - o = asJSON(parameters.get(i).toString()); - if (o instanceof JSONArray) { - s.retainAll((JSONArray) o); - } else if (o instanceof JSONObject) { - s.retainAll(((JSONObject) o).keySet()); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - o == null ? "NULL" : o.toString(), - "json.intersection")); - } - } - - return JSONArray.fromObject(s); - } - - /** - * Removes all the values in the second and any subsequent objects/arrays from the first JSON - * object or array. - * - * @param parameters The parameters to the function. - * @return the new object or array. - * @throws ParserException if an error occurs. - */ - private Object JSONRemoveAll(List parameters) throws ParserException { - Object json = asJSON(parameters.get(0).toString()); - - if (json instanceof JSONArray) { - // Create a new JSON Array to preserve immutability for the macro script. - JSONArray jarr = JSONArray.fromObject(json); - - for (int i = 1; i < parameters.size(); i++) { - Object o2 = asJSON(parameters.get(i).toString()); - if (o2 instanceof JSONArray) { - jarr.removeAll((JSONArray) o2); - } else if (o2 instanceof JSONObject) { - jarr.removeAll(((JSONObject) o2).keySet()); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - o2 == null ? "NULL" : o2.toString(), - "json.removeAll")); - } - } - return jarr; - } else if (json instanceof JSONObject) { - // Create a new JSON Array to preserve immutability for the macro script. - JSONObject jobj = JSONObject.fromObject(json); - - for (int i = 1; i < parameters.size(); i++) { - Object o2 = asJSON(parameters.get(i).toString()); - if (o2 instanceof JSONArray) { - for (Object o3 : (JSONArray) o2) { - jobj.remove(o3); - } - } else if (o2 instanceof JSONObject) { - for (Object o3 : ((JSONObject) o2).keySet()) { - jobj.remove(o3); - } - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - o2 == null ? "NULL" : o2.toString(), - "json.removeAll")); - } - } - return jobj; - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - json == null ? "NULL" : json.toString(), - "json.removeAll")); - } - } - - /** - * Returns a JSON array with no duplicates. There is order of elements may not be preserved. - * - * @param obj The JSON array to remove the duplicates from. - * @return a JSON array. - * @throws ParserException if an exception occurs. - */ - private JSONArray JSONUnique(Object obj) throws ParserException { - if (!(obj instanceof JSONArray)) { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyArray", - obj == null ? "NULL" : obj.toString(), - "json.unique")); - } - JSONArray jarr = (JSONArray) obj; - Set s = new HashSet(jarr); - return JSONArray.fromObject(s); - } - - /** - * Merges multiple JSON objects or arrays. - * - * @param parameters The parameters to the function. - * @return the merged object or array. - * @throws ParserException if an error occurs. - */ - private Object JSONMerge(List parameters) throws ParserException { - Object json = asJSON(parameters.get(0).toString()); - - if (json instanceof JSONArray) { - // Create a new JSON Array to preserve immutability for the macro script. - JSONArray jarr = JSONArray.fromObject(json); - - for (int i = 1; i < parameters.size(); i++) { - Object o2 = asJSON(parameters.get(i).toString()); - if (!(o2 instanceof JSONArray)) { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - o2 == null ? "NULL" : o2.toString(), - "json.merge")); - } - jarr.addAll((JSONArray) o2); - } - return jarr; - } else if (json instanceof JSONObject) { - // Create a new JSON Array to preserve immutability for the macro script. - JSONObject jobj = JSONObject.fromObject(json); - - for (int i = 1; i < parameters.size(); i++) { - Object o2 = asJSON(parameters.get(i).toString()); - if (!(o2 instanceof JSONObject)) { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - o2 == null ? "NULL" : o2.toString(), - "json.merge")); - } - jobj.putAll((JSONObject) o2); - } - return jobj; - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyJSON", - json == null ? "NULL" : json.toString(), - "json.merge")); - } - } - - /** - * Gets the number of times a value appears in the array. - * - * @param json The JSON array to check. - * @param searchFor the value to search for. - * @param start the index to start searching at. - * @return the number of times the value occurs. - * @throws ParserException - */ - private BigDecimal JSONCount(Object json, Object searchFor, int start) throws ParserException { - if (!(json instanceof JSONArray)) { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyArray", - json == null ? "NULL" : json.toString(), - "json.count")); - } - JSONArray jarr = (JSONArray) json; - - if (searchFor instanceof String && convertToJSON((String) searchFor) != null) { - searchFor = convertToJSON((String) searchFor); - } - - int count = 0; - for (int i = start, max = jarr.size(); i < max; i++) { - Object ob = jarr.get(i); - if (ob instanceof Float) { - if (searchFor.equals(BigDecimal.valueOf((Float) ob))) { - count++; - } - } else if (ob instanceof Integer) { - if (searchFor.equals(BigDecimal.valueOf((Integer) ob))) { - count++; - } - } else if (ob instanceof Double) { - if (searchFor.equals(BigDecimal.valueOf((Double) ob))) { - count++; - } - } else if (ob instanceof Long) { - if (searchFor.equals(BigDecimal.valueOf((Long) ob))) { - count++; - } - } else { - if (searchFor.equals(ob)) { - count++; - } - } - } - - return BigDecimal.valueOf(count); - } - - /** - * Gets the index of a value in a JSON array. - * - * @param json The JSON array to check. - * @param searchFor The value to search for. - * @param start The index to start from. - * @return The index of the first occurance of the value in the array or -1 if it does not occur. - * @throws ParserException - */ - private BigDecimal JSONIndexOf(Object json, Object searchFor, int start) throws ParserException { - if (!(json instanceof JSONArray)) { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyArray", - json == null ? "NULL" : json.toString(), - "json.indexOf")); - } - JSONArray jarr = (JSONArray) json; - - if (searchFor instanceof String && convertToJSON((String) searchFor) != null) { - searchFor = convertToJSON((String) searchFor); - } - - for (int i = start, max = jarr.size(); i < max; i++) { - Object ob = jarr.get(i); - if (ob instanceof Float) { - if (searchFor.equals(BigDecimal.valueOf((Float) ob))) { - return BigDecimal.valueOf(i); - } - } else if (ob instanceof Integer) { - if (searchFor.equals(BigDecimal.valueOf((Integer) ob))) { - return BigDecimal.valueOf(i); - } - } else if (ob instanceof Double) { - if (searchFor.equals(BigDecimal.valueOf((Double) ob))) { - return BigDecimal.valueOf(i); - } - } else if (ob instanceof Long) { - if (searchFor.equals(BigDecimal.valueOf((Long) ob))) { - return BigDecimal.valueOf(i); - } - } else { - if (searchFor.equals(ob)) { - return BigDecimal.valueOf(i); - } - } - } - - return BigDecimal.valueOf(-1); - } - - /** - * Evaluates each of the strings in the JSON object or array. - * - * @param res The variable resolver. - * @param json the JSON object. - * @return the json object with the strings evaluated. - * @throws ParserException if there is an error. - */ - public Object JSONEvaluate(MapToolVariableResolver res, Object json) throws ParserException { - if (json instanceof JSONObject) { - JSONObject jobj = (JSONObject) json; - for (Object key : jobj.keySet()) { - Object o = jobj.get(key); - if (o instanceof JSONObject || o instanceof JSONArray) { - jobj.put(key, JSONEvaluate(res, o)); - } else if (o instanceof String) { - jobj.put(key, EvalMacroFunctions.evalMacro(res, res.getTokenInContext(), o.toString())); - } - } - } else { - JSONArray jarr = (JSONArray) json; - for (int i = 0; i < jarr.size(); i++) { - Object o = jarr.get(i); - if (o instanceof JSONObject || o instanceof JSONArray) { - jarr.set(i, JSONEvaluate(res, o)); - } else if (o instanceof String) { - // For arrays we may have an extra "" so it can be stored in the array - String line = o.toString(); - line = line.replaceFirst("^\"", "").replaceFirst("\"$", ""); - jarr.set(i, EvalMacroFunctions.evalMacro(res, res.getTokenInContext(), line)); - } - } - } - return json; - } - - /** - * Shuffles the values in a json array. - * - * @param jsonArray the array to shuffle. - * @return the shuffled array. - * @throws ParserException if the object is not a JSON Array. - */ - private JSONArray JSONShuffle(Object jsonArray) throws ParserException { - if (!(jsonArray instanceof JSONArray)) { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyArray", - jsonArray == null ? "NULL" : jsonArray.toString(), - "json.shuffle")); - } - // Create a new JSON Array to support immutable types in macros. - JSONArray jarr = JSONArray.fromObject(jsonArray); - Collections.shuffle(jarr); - return jarr; - } - - /** - * Sorts a json array. If all values in the array are numbers then the values are sorted in - * numeric order, otherwise values are sorted in string order. - * - * @param jsonArray The json array to sort. - * @param direction The direction "ascending" or "descending" to sort the array. - * @param fields A list of Strings defining which fields with the JSON objects to use for sorting - * and the precedence of those fields. - * @return The sorted array. - * @throws ParserException if the object is not a JSON array. - */ - @SuppressWarnings("unchecked") - private JSONArray JSONSort(Object jsonArray, String direction, List fields) - throws ParserException { - if (!(jsonArray instanceof JSONArray)) { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyArray", - jsonArray == null ? "NULL" : jsonArray.toString(), - "json.sort")); - } - - // Create a new JSON Array to support immutable types in macros. - JSONArray jarr = JSONArray.fromObject(jsonArray); - if (fields != null) { - return JSONSortObjects(jarr, direction, fields); - } - - // Check to see if we are all numbers - boolean sortAsNumber = true; - for (Object o : jarr) { - if (!(o instanceof Double) && !(o instanceof Integer)) { - sortAsNumber = false; - break; - } - } - - boolean ascending = true; - if (direction.toLowerCase().startsWith("d")) { - ascending = false; - } - - if (sortAsNumber) { - jarr.sort(new JSONNumberComparator(ascending)); - } else { - jarr.sort(new JSONStringComparator(ascending)); - } - return jarr; - } - - /** - * Sorts the JSON objects in a JSON array - * - * @param jsonArray the array to sort. - * @param direction the direction, ascending or descending to sort the array. - * @param fields the fields to base the sort on. - * @return The sorted array. - * @throws ParserException when an error occurs. - */ - private JSONArray JSONSortObjects(JSONArray jsonArray, String direction, List fields) - throws ParserException { - for (Object o : jsonArray) { - if (!(o instanceof JSONObject)) { - throw new ParserException( - I18N.getText("macro.function.json.arrayMustContainObjects", o.toString())); - } - } - boolean ascending = true; - if (direction.toLowerCase().startsWith("d")) { - ascending = false; - } - - JSONNumberComparator numberCompare = new JSONNumberComparator(ascending); - JSONStringComparator stringCompare = new JSONStringComparator(ascending); - - List> comparatorList = new ArrayList>(); - // Generate the comparator we will use for each fld - // Check to see if we are all numbers for each field - for (Object fld : fields) { - boolean sortAsNumber = true; - for (Object jo : jsonArray) { - Object o = ((JSONObject) jo).get(fld.toString()); - if (o == null) { - throw new ParserException( - I18N.getText("macro.function.json.notAllContainKey", fld.toString())); - } - if (!(o instanceof Integer) && !(o instanceof Double)) { - sortAsNumber = false; - break; - } - } - if (sortAsNumber) { - comparatorList.add(numberCompare); - } else { - comparatorList.add(stringCompare); - } - } - - jsonArray.sort(new JSONObjectComparator(ascending, fields, comparatorList)); - - return jsonArray; - } - - /** - * Attempts to convert a string to a JSON object. - * - * @param obj The string to attempt to convert. - * @return Either a JSONObject, JSONArray, or null. - */ - public static Object convertToJSON(String obj) { - if (obj.trim().startsWith("[")) { - try { - return JSONArray.fromObject(obj); - } catch (Exception e) { - return null; - } - } - - if (obj.trim().startsWith("{")) { - try { - return JSONObject.fromObject(obj); - } catch (Exception e) { - return null; - } - } - - return null; - } - - /** - * JSONify the given value, inducing JSON type from the Maptool string value. Because Maptool - * arbitrarily convert null, true, and false from incoming json data into "null", "true" and - * "false", this function does the opposite to allow Maptool to send json data - * - * @param value A Maptool value. - * @return null, true or false instead of "null", "true, or "false", or the value unchanged - */ - public static Object jsonify(Object value) { - // the json library does not use the java null object, but one singleton of its own - if ("null".equals(value)) { - return JSONNull.getInstance(); - } else if ("true".equals(value)) { - return true; - } else if ("false".equals(value)) { - return false; - } - return value; - } - - /** - * Append a value to a JSON array. - * - * @param obj The JSON object. - * @param values The values to append to the array. - * @return the JSON array. - * @throws ParserException - */ - private JSONArray JSONAppend(Object obj, List values) throws ParserException { - if (obj == null || obj.toString().length() == 0) { - obj = new JSONArray(); - } - - if (obj instanceof JSONArray) { - // Create a new JSON Array to support immutable types in macros. - JSONArray jarr = JSONArray.fromObject(obj); - for (Object val : values.subList(1, values.size())) { - jarr.add(jsonify(val)); - } - return jarr; - } else { - throw new ParserException( - I18N.getText("macro.function.json.append.onlyArray", obj.toString(), "json.append")); - } - } - - /** - * Gets a value from the JSON Object or Array. - * - * @param obj The JSON Object or Array. - * @param keys The key for the object or index for the array. - * @return the value. - * @throws ParserException - */ - private Object JSONGet(Object obj, List keys) throws ParserException { - Object val = null; - if (obj instanceof JSONObject) { - JSONObject jobj = (JSONObject) obj; - if (keys.size() == 1) { - Object oval = jobj.get(keys.get(0).toString()); - if (oval == null) { - val = ""; - } else { - val = oval.toString(); - } - } else { - Map values = new HashMap(); - for (Object key : keys) { - Object oval = jobj.get(key.toString()); - values.put(key.toString(), oval != null ? oval : ""); - } - val = JSONObject.fromObject(values); - } - } else if (obj instanceof JSONArray) { - JSONArray jarr = (JSONArray) obj; - if (keys.size() == 1) { - val = jarr.get(Integer.parseInt(keys.get(0).toString())).toString(); - } else { - int start = Integer.parseInt(keys.get(0).toString()); - // Wrap around - if (start < 0) { - start = jarr.size() + start; - } - if (start >= jarr.size() || start < 0) { - throw new ParserException( - I18N.getText( - "macro.function.json.getInvalidStartIndex", "json.get", start, jarr.size())); - } - int end = Integer.parseInt(keys.get(1).toString()); - if (end < 0) { - end = jarr.size() + end; - } - if (end >= jarr.size() || end < 0) { - throw new ParserException( - I18N.getText( - "macro.function.json.getInvalidEndIndex", "json.end", start, jarr.size())); - } - - List values = new ArrayList(); - if (start > end) { - for (int i = start; i >= end; i--) { - values.add(jarr.get(i)); - } - } else { - for (int i = start; i <= end; i++) { - values.add(jarr.get(i)); - } - } - val = JSONArray.fromObject(values); - } - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - obj == null ? "NULL" : obj.toString(), - "json.get")); - } - - if (keys.size() == 1) { - // Attempt to convert to a number ... - try { - return new BigDecimal((String) val); - } catch (Exception e) { - // Ignore - } - } - return val == null ? "" : val; - } - - /** - * Converts a JSON object to a string property. - * - * @param obj The object to convert. - * @param delim The delimiter used in the string property. - * @return The string property of the object. - * @throws ParserException If the object is not a JSON object. - */ - private String JSONToStrProp(Object obj, String delim) throws ParserException { - - StringBuilder sb = new StringBuilder(); - if (obj instanceof JSONObject) { - JSONObject jobj = (JSONObject) obj; - for (Object ob : jobj.keySet()) { - if (sb.length() > 0) { - sb.append(delim); - } - sb.append(ob).append("=").append(jobj.get(ob)); - } - return sb.toString(); - } else if (obj instanceof JSONArray) { - JSONArray jarr = (JSONArray) obj; - for (int i = 0; i < jarr.size(); i++) { - if (sb.length() > 0) { - sb.append(delim); - } - sb.append(i).append("=").append(jarr.get(i)); - } - return sb.toString(); - } else if (obj instanceof String && ((String) obj).trim().length() == 0) { - return obj.toString(); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - obj == null ? "NULL" : obj.toString(), - "json.toStrProp")); - } - } - - /** - * Converts a JSON object to a string list. - * - * @param obj The object to convert. - * @param delim The delimiter used in the string list. - * @return The string list of the object. - * @throws ParserException If the object is not a JSON object. - */ - private Object JSONToList(Object obj, String delim) throws ParserException { - - StringBuilder sb = new StringBuilder(); - if (obj instanceof JSONObject) { - JSONObject jobj = (JSONObject) obj; - for (Object ob : jobj.keySet()) { - if (sb.length() > 0) { - sb.append(delim); - } - sb.append(ob); - } - return sb.toString(); - } else if (obj instanceof JSONArray) { - JSONArray jarr = (JSONArray) obj; - for (Object o : jarr) { - if (sb.length() > 0) { - sb.append(delim); - } - sb.append(o); - } - return sb.toString(); - } else if (obj instanceof String && ((String) obj).trim().length() == 0) { - return obj.toString(); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - obj == null ? "NULL" : obj.toString(), - "json.toStrList")); - } - } - - /** - * Gets a list of the JSON objects fields. - * - * @param obj The object to get the fields of. - * @param delim The delimiter used in the string list. - * @return The string property of the object. - * @throws ParserException If the object is not a JSON object. - */ - private Object JSONFields(Object obj, String delim) throws ParserException { - - StringBuilder sb = new StringBuilder(); - if (obj instanceof JSONObject) { - JSONObject jobj = JSONObject.fromObject(obj); - if ("json".equals(delim)) { - return JSONArray.fromObject(jobj.keySet()); - } else { - for (Object ob : jobj.keySet()) { - if (sb.length() > 0) { - sb.append(delim); - } - sb.append(ob.toString()); - } - return sb.toString(); - } - } else if (obj instanceof JSONArray) { - JSONArray jarr = (JSONArray) obj; - for (int i = 0; i < jarr.size(); i++) { - if (sb.length() > 0) { - sb.append(delim); - } - sb.append(i); - } - return sb.toString(); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - obj == null ? "NULL" : obj.toString(), - "json.fields")); - } - } - - /** - * Gets the length of a JSON object. If the object is an array then the number of elements is - * returned, if it is an object then the number of fields is returned. - * - * @param obj The JSON object. - * @return the number of elements or fields. - * @throws ParserException if obj is not a JSON object. - */ - private BigDecimal JSONLength(Object obj) throws ParserException { - - if (obj instanceof JSONObject) { - JSONObject jobj = (JSONObject) obj; - return BigDecimal.valueOf(jobj.keySet().size()); - } else if (obj instanceof JSONArray) { - JSONArray jarr = (JSONArray) obj; - return BigDecimal.valueOf(jarr.size()); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - obj == null ? "NULL" : obj.toString(), - "json.length")); - } - } - - /** - * Sets the value of an element in a JSON Array or a Field in a JSON Object. - * - * @param obj The JSON object. - * @param param The key/value pairs to set. - * @return new JSON object. - * @throws ParserException if the obj is not a JSON object. - */ - private Object JSONSet(Object obj, List param) throws ParserException { - - if (obj == null || obj.toString().length() == 0) { - obj = new JSONObject(); - } - - if (param.size() % 2 != 1) { - throw new ParserException(I18N.getText("macro.function.json.setNoMatchingValue", "json.set")); - } - - if (obj instanceof JSONObject) { - // Create a new JSON object to preserve macro object immutable types. - JSONObject jobj = JSONObject.fromObject(obj); - for (int i = 1; i < param.size(); i += 2) { - jobj.put(param.get(i).toString(), jsonify(param.get(i + 1))); - } - return jobj; - } else if (obj instanceof JSONArray) { - // Create a new JSON array to preserve macro object immutable types. - JSONArray jarr = JSONArray.fromObject(obj); - for (int i = 1; i < param.size(); i += 2) { - jarr.set(Integer.parseInt(param.get(i).toString()), jsonify(param.get(i + 1))); - } - return jarr; - } else { - throw new ParserException( - I18N.getText("macro.function.json.unknownType", obj.toString(), "json.set")); - } - } - - /** - * Creates a JSON Array from a String list. - * - * @param list The string list. - * @param delim The delimiter used to separate items in the string list. - * @return The JSON Array. - */ - public JSONArray fromStrList(String list, String delim) { - delim = delim != null ? delim : ","; - String[] stringArray = list.split(delim); - - // Empty list should generate empty JSON array - if (stringArray.length == 1 && stringArray[0].length() == 0) return new JSONArray(); - - Object[] array = new Object[stringArray.length]; - // Try to convert it to a number and if that works we store it that way - for (int i = 0; i < stringArray.length; i++) { - String value = stringArray[i].trim(); - // Empty list element generates an empty string in the JSON array - if (value.length() == 0) array[i] = ""; - else { - try { - BigDecimal bd = new BigDecimal(value); - array[i] = bd; - } catch (NumberFormatException nfe) { - array[i] = value; - } - } - } - return JSONArray.fromObject(array); - } - - /** - * Creates a JSON object from a String property list. - * - * @param prop The String Property list. - * @param delim The delimiter used to separate items in the list. - * @return The JSON Object. - */ - public JSONObject fromStrProp(String prop, String delim) { - delim = delim != null ? delim : ";"; - String[] props = prop.split(delim); - HashMap obmap = new HashMap(); - for (String s : props) { - String[] vals = s.split("=", 2); - String key = vals[0].trim(); - if (vals.length > 1) { - // Try to convert it to a number and if that works we store it that way - String value = vals[1].trim(); - try { - obmap.put(key, new BigDecimal(value)); - } catch (Exception e) { - obmap.put(key, value); - } - } else { - obmap.put(key, ""); - } - } - return JSONObject.fromObject(obmap); - } - - /** - * Gets the type of the JSON object. - * - * @param obj The json object. - * @return the type of object. - */ - private JSONObjectType getJSONObjectType(Object obj) { - if (obj instanceof JSONObject) { - return JSONObjectType.OBJECT; - } else if (obj instanceof JSONArray) { - return JSONObjectType.ARRAY; - } else { - String str = obj.toString().trim(); - if (str.startsWith("{") || str.startsWith("[")) { - Object converted = asJSON(str); - if (converted != null) { - return getJSONObjectType(converted); - } - } - return JSONObjectType.UNKNOWN; - } - } - - /** - * Deletes a field from a JSON object or element from a JSON array. - * - * @param obj The JSON object. - * @param key - * @return The new JSON object. - * @throws ParserException if obj can not be converted to a JSON object. - */ - private Object JSONDelete(Object obj, String key) throws ParserException { - - if (obj instanceof JSONObject) { - // Create a new JSON object so that old one remains immutable to macro - JSONObject jobj = JSONObject.fromObject(obj); - jobj.remove(key); - return jobj; - } else if (obj instanceof JSONArray) { - // Create a new JSON array so that old one remains immutable to macro - JSONArray jarr = JSONArray.fromObject(obj); - jarr.remove(Integer.parseInt(key)); - return jarr; - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - obj == null ? "NULL" : obj.toString(), - "json.delete")); - } - } - - /** - * Returns and indented version of a JSON string. - * - * @param obj The JSON string to ident. - * @param indent The indention factor. - * @return The indented string. - * @throws ParserException If an error occurs parsing the JSON String. - */ - private String JSONIndent(Object obj, int indent) throws ParserException { - if (obj instanceof JSONObject) { - return ((JSONObject) obj).toString(indent); - } else if (obj instanceof JSONArray) { - return ((JSONArray) obj).toString(indent); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - obj == null ? "NULL" : obj.toString(), - "json.indent")); - } - } - - /** - * Checks to see if a JSON object contains the specified key. - * - * @param obj The JSON Object. - * @param key The key to check for. - * @return true if the JSON object contains the key. - * @throws ParserException - */ - private boolean JSONContains(Object obj, String key) throws ParserException { - - if (obj instanceof JSONObject) { - return ((JSONObject) obj).containsKey(key); - } - - if (obj instanceof JSONArray) { - try { - return ((JSONArray) obj).contains(Integer.parseInt(key)); - } catch (Exception e) { - // Do nothing as we will try another conversion - } - - try { - return ((JSONArray) obj).contains(Double.parseDouble(key)); - } catch (Exception e) { - // Do nothing as we will try it as a string - } - return ((JSONArray) obj).contains(key); - } - - throw new ParserException( - I18N.getText( - "macro.function.json.unknownType", - obj == null ? "NULL" : obj.toString(), - "json.contains")); - } - - /** - * Reverses a json array. - * - * @param jsonArray The json array to reverse. - * @return the reversed json array. - * @throws ParserException if jsonArray is not a json array. - */ - private JSONArray JSONReverse(Object jsonArray) throws ParserException { - if (!(jsonArray instanceof JSONArray)) { - throw new ParserException(I18N.getText("macro.function.json.onlyArray", "json.reverse")); - } - - // Create a new JSON Array to preserve immutable state for macros. - JSONArray jarr = JSONArray.fromObject(jsonArray); - List arr = new LinkedList(); - for (int i = jarr.size() - 1; i >= 0; i--) { - arr.add(jarr.get(i)); - } - - return JSONArray.fromObject(arr); - } - - /** Compares two numbers from a json array. */ - private static class JSONNumberComparator implements Comparator { - private final boolean ascending; - - public JSONNumberComparator(boolean ascending) { - this.ascending = ascending; - } - - public int compare(Object o1, Object o2) { - BigDecimal v1; - BigDecimal v2; - - if (o1 instanceof Integer) { - v1 = BigDecimal.valueOf((Integer) o1); - } else { - v1 = BigDecimal.valueOf((Double) o1); - } - - if (o2 instanceof Integer) { - v2 = BigDecimal.valueOf((Integer) o2); - } else { - v2 = BigDecimal.valueOf((Double) o2); - } - return ascending ? v1.compareTo(v2) : v2.compareTo(v1); - } - } - - /** Compares two strings from a json array. */ - private static class JSONStringComparator implements Comparator { - private final boolean ascending; - - public JSONStringComparator(boolean ascending) { - this.ascending = ascending; - } - - public int compare(Object o1, Object o2) { - String s1 = o1.toString(); - String s2 = o2.toString(); - return ascending ? s1.compareTo(s2) : s2.compareTo(s1); - } - } - - /** Compares two objects from a json array. */ - private static class JSONObjectComparator implements Comparator { - private final boolean ascending; - private final List fields; - private final List> comparators; - - public JSONObjectComparator( - boolean ascending, List fields, List> comparators) { - this.ascending = ascending; - this.fields = fields; - this.comparators = comparators; - } - - public int compare(Object o1, Object o2) { - JSONObject jo1 = (JSONObject) o1; - JSONObject jo2 = (JSONObject) o2; - - for (int i = 0; i < fields.size(); i++) { - Object f = fields.get(i); - int c = comparators.get(i).compare(jo1.get(f), jo2.get(f)); - if (c != 0) { - return c; - } - } - return 0; - } - } - - /** - * Returns a JSON object from the parameter. - * - * @param o The parameter. - * @return a JSON object. - */ - @SuppressWarnings("unused") - private static JSONObject asJSONObject(Object o) { - if (o instanceof JSONObject) { - return (JSONObject) o; - } - - return JSONObject.fromObject(o.toString()); - } - - /** - * Returns a JSON Array from the parameter. - * - * @param o The parameter. - * @return a JSON array. - */ - @SuppressWarnings("unused") - private static JSONArray asJSONArray(Object o) { - if (o instanceof JSONArray) { - return (JSONArray) o; - } - // Special cases we have to deal with cases where the parser - // has already had a go at single index arrays. - if (o instanceof BigDecimal) { - JSONArray jarr = new JSONArray(); - jarr.add(o); - return jarr; - } else if (o instanceof String) { - String s = ((String) o).trim(); - if (!s.startsWith("[") && !s.startsWith("{")) { - JSONArray jarr = new JSONArray(); - if (o.toString().length() > 0) { - jarr.add(o); - } - return jarr; - } - } - - return JSONArray.fromObject(o.toString()); - } - - /** - * Returns a JSONObject or JSONArray from the parameter. - * - * @param o The parameter to convert. - * @return The JSONObject or JSONArray. - */ - public static Object asJSON(Object o) { - if (o instanceof JSONArray) { - return o; - } else if (o instanceof JSONObject) { - return o; - } - // Special cases we have to deal with cases where the parser - // has already had a go at single index arrays. - if (o instanceof BigDecimal) { - JSONArray jarr = new JSONArray(); - jarr.add(o); - return jarr; - } else if (o instanceof String) { - String s = ((String) o).trim(); - if (!s.startsWith("[") && !s.startsWith("{")) { - if (o.toString().length() == 0) { - return o.toString(); - } - JSONArray jarr = new JSONArray(); - if (o.toString().length() > 0) { - jarr.add(o); - } - return jarr; - } - } - return convertToJSON(o.toString()); - } - - public JSONArray JSONRolls(List param) throws ParserException { - String roll = param.get(0).toString(); - if (!(param.get(1) instanceof BigDecimal)) { - throw new ParserException( - I18N.getText( - "macro.function.general.argumentTypeN", "json.rolls", 1, param.get(1).toString())); - } - int dim1 = ((BigDecimal) param.get(1)).intValue(); - - int dim2; - if (param.size() == 2) { - dim2 = 1; - } else if (!(param.get(2) instanceof BigDecimal)) { - throw new ParserException( - I18N.getText( - "macro.function.general.argumentTypeN", "json.rolls", 2, param.get(2).toString())); - } else { - dim2 = ((BigDecimal) param.get(2)).intValue(); - } - - ExpressionParser parser = new ExpressionParser(); - - if (dim2 == 1) { - Object[] rollArr = new Object[dim1]; - for (int i = 0; i < dim1; i++) { - rollArr[i] = parser.evaluate(roll).getValue(); - } - - return JSONArray.fromObject(rollArr); - } else { - Object[][] rollArr = new Object[dim1][dim2]; - for (int i2 = 0; i2 < dim2; i2++) { - for (int i = 0; i < dim1; i++) { - rollArr[i][i2] = parser.evaluate(roll).getValue(); - } - } - return JSONArray.fromObject(rollArr); - } - } - - public JSONObject JSONObjRolls(List param) throws ParserException { - JSONArray names; - Object[] stats; - Object[] rolls; - - Object o; - o = asJSON(param.get(0)); - if (o instanceof JSONArray) { - names = (JSONArray) o; - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyArray", o == null ? "NULL" : o.toString(), "json.objrolls")); - } - - o = asJSON(param.get(1)); - if (o instanceof JSONArray) { - stats = ((JSONArray) o).toArray(); - } else { - throw new ParserException( - I18N.getText( - "macro.function.json.onlyArray", o == null ? "NULL" : o.toString(), "json.objrolls")); - } - - if (param.get(2).toString().trim().startsWith("[")) { - o = asJSON(param.get(2)); - if (o instanceof JSONArray) { - rolls = ((JSONArray) o).toArray(); - if (rolls.length != stats.length) { - throw new ParserException(I18N.getText("macro.function.json.matchingArrayOrRoll")); - } - } else { - throw new ParserException(I18N.getText("macro.function.json.matchingArrayOrRoll")); - } - } else if (param.get(2) instanceof String) { - String roll = (String) param.get(2); - rolls = new String[stats.length]; - for (int i = 0; i < rolls.length; i++) { - rolls[i] = roll; - } - } else { - throw new ParserException(I18N.getText("macro.function.json.matchingArrayOrRoll")); - } - - ExpressionParser parser = new ExpressionParser(); - JSONObject jobj = new JSONObject(); - for (Object name : names) { - JSONObject jstatObj = new JSONObject(); - for (int i = 0; i < stats.length; i++) { - jstatObj.put(stats[i], parser.evaluate(rolls[i].toString()).getValue()); - } - jobj.put(name, jstatObj); - } - - return jobj; - } -} diff --git a/src/main/java/net/rptools/maptool/client/functions/MacroLinkFunction.java b/src/main/java/net/rptools/maptool/client/functions/MacroLinkFunction.java index 49b34a0157..d4da5a2c76 100644 --- a/src/main/java/net/rptools/maptool/client/functions/MacroLinkFunction.java +++ b/src/main/java/net/rptools/maptool/client/functions/MacroLinkFunction.java @@ -144,7 +144,9 @@ public Object childEvaluate( jsonTargets = JSONMacroFunctions.getInstance().asJsonElement(strTargets).getAsJsonArray(); else { jsonTargets = new JsonArray(); - for (String t : strTargets.split(delim)) jsonTargets.add(t.trim()); + for (String t : StringUtil.split(strTargets, delim)) { + jsonTargets.add(t.trim()); + } } if (jsonTargets.size() == 0) { return ""; // dont send to empty lists diff --git a/src/main/java/net/rptools/maptool/client/functions/TokenSelectionFunctions.java b/src/main/java/net/rptools/maptool/client/functions/TokenSelectionFunctions.java index e535a61b5d..5c8f371dbb 100644 --- a/src/main/java/net/rptools/maptool/client/functions/TokenSelectionFunctions.java +++ b/src/main/java/net/rptools/maptool/client/functions/TokenSelectionFunctions.java @@ -28,6 +28,7 @@ import net.rptools.maptool.model.Token; import net.rptools.maptool.model.Zone; import net.rptools.maptool.util.FunctionUtil; +import net.rptools.maptool.util.StringUtil; import net.rptools.parser.Parser; import net.rptools.parser.ParserException; import net.rptools.parser.VariableResolver; @@ -107,7 +108,7 @@ private void deselectTokens(List parameters) throws ParserException { } } else { // String List - String[] strList = paramStr.split(delim); + String[] strList = StringUtil.split(paramStr, delim); for (String s : strList) { Token t = zone.resolveToken(s.trim()); if (t != null) { @@ -185,7 +186,7 @@ private void selectTokens(List parameters) throws ParserException { } } else { // String List - String[] strList = paramStr.split(delim); + String[] strList = StringUtil.split(paramStr, delim); for (String s : strList) { Token t = zone.resolveToken(s.trim()); if (t != null) { diff --git a/src/main/java/net/rptools/maptool/client/functions/json/JsonArrayFunctions.java b/src/main/java/net/rptools/maptool/client/functions/json/JsonArrayFunctions.java index be2c724a17..60373589e5 100644 --- a/src/main/java/net/rptools/maptool/client/functions/json/JsonArrayFunctions.java +++ b/src/main/java/net/rptools/maptool/client/functions/json/JsonArrayFunctions.java @@ -27,6 +27,7 @@ import java.util.Set; import java.util.stream.Collectors; import net.rptools.maptool.language.I18N; +import net.rptools.maptool.util.StringUtil; import net.rptools.parser.ParserException; import net.rptools.parser.VariableResolver; @@ -104,7 +105,7 @@ public int compare(JsonObject jo1, JsonObject jo2) { * @return the string list as a json array. */ public JsonArray fromStringList(String strList, String delim) { - String[] list = strList.split(delim); + String[] list = StringUtil.split(strList, delim); // An Empty list should generate an empty JSON array. if (list.length == 1 && list[0].length() == 0) { diff --git a/src/main/java/net/rptools/maptool/client/functions/json/JsonObjectFunctions.java b/src/main/java/net/rptools/maptool/client/functions/json/JsonObjectFunctions.java index 87a5229d76..6447c77d0c 100644 --- a/src/main/java/net/rptools/maptool/client/functions/json/JsonObjectFunctions.java +++ b/src/main/java/net/rptools/maptool/client/functions/json/JsonObjectFunctions.java @@ -21,6 +21,7 @@ import java.math.BigDecimal; import java.util.List; import net.rptools.maptool.language.I18N; +import net.rptools.maptool.util.StringUtil; import net.rptools.parser.ParserException; import net.rptools.parser.VariableResolver; @@ -48,7 +49,7 @@ public JsonObjectFunctions(JsonMTSTypeConversion converter) { * @return a {@link JsonObject} convert4d from the string properties. */ public JsonObject fromStrProp(String prop, String delim) { - String[] propsArray = prop.split(delim); + String[] propsArray = StringUtil.split(prop, delim); JsonObject jsonObject = new JsonObject(); for (String s : propsArray) { diff --git a/src/main/java/net/rptools/maptool/util/StringUtil.java b/src/main/java/net/rptools/maptool/util/StringUtil.java index 7d331ae011..333ccf223b 100644 --- a/src/main/java/net/rptools/maptool/util/StringUtil.java +++ b/src/main/java/net/rptools/maptool/util/StringUtil.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; @@ -319,4 +320,16 @@ public static String htmlize(String input, String type) { default -> input; }; } + + /** + * Splits a string using a literal delimiter. + * + *

Unlike {@link String#split(String)}, {@code delim} is not a regular expression. + * + * @return + */ + public static String[] split(String string, String delim) { + var pattern = Pattern.quote(delim); + return string.split(pattern); + } } diff --git a/src/test/java/net/rptools/maptool/client/functions/json/JSONMacroFunctions.java b/src/test/java/net/rptools/maptool/client/functions/json/JSONMacroFunctions.java deleted file mode 100644 index 405ac1772c..0000000000 --- a/src/test/java/net/rptools/maptool/client/functions/json/JSONMacroFunctions.java +++ /dev/null @@ -1,321 +0,0 @@ -/* - * This software Copyright by the RPTools.net development team, and - * licensed under the Affero GPL Version 3 or, at your option, any later - * version. - * - * MapTool Source Code is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public - * License * along with this source Code. If not, please visit - * and specifically the Affero license - * text at . - */ -package net.rptools.maptool.client.functions.json; - -import static org.junit.jupiter.api.Assertions.*; - -import com.jayway.jsonpath.JsonPath; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.stream.Collectors; -import net.rptools.maptool.client.functions.JSONMacroFunctionsOld; -import net.rptools.parser.MapVariableResolver; -import net.rptools.parser.Parser; -import net.rptools.parser.ParserException; -import net.sf.json.JSONArray; -import net.sf.json.JSONObject; -import org.junit.jupiter.api.Test; -import org.locationtech.jts.util.Assert; - -class TestJSONMacroFunctions { - // a list of json objects ready to be used in tests - public static final HashMap o_samples = new HashMap(); - public static final HashMap a_samples = new HashMap(); - // MT uses bigdecimal 0 and 1 as value for boolean operations - public static final BigDecimal _true = BigDecimal.ONE; - public static final BigDecimal _false = BigDecimal.ZERO; - private static final Parser parser = new Parser(); - - /** An alias to childEvaluate. */ - Object run(String function_name, Object json, List keys) throws ParserException { - List fparams = new ArrayList(); - fparams.add(json); - fparams.addAll(keys); - return JSONMacroFunctionsOld.getInstance() - .childEvaluate(parser, new MapVariableResolver(), function_name, fparams); - } - - /** - * An alias to childEvaluate. - * - * @param functionName the name of the function - * @param objs the arguments of the function - * @return the output of the function - * @throws ParserException if the macro function throws a parser exception - */ - Object run(String functionName, Object... objs) throws ParserException { - List params = new ArrayList<>(Arrays.asList(objs)); - return JSONMacroFunctionsOld.getInstance().childEvaluate(parser, null, functionName, params); - } - - // @BeforeAll - static void setUpOnce() { - InputStream is = TestJSONMacroFunctions.class.getResourceAsStream("json_macro.json"); - JSONObject json_from_file = null; - if (is != null) { - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - json_from_file = - JSONObject.fromObject(reader.lines().collect(Collectors.joining(System.lineSeparator()))); - } - - if (json_from_file != null) { - for (Object k : json_from_file.keySet()) { - Object value = json_from_file.get(k); - if (value instanceof JSONObject) { - o_samples.put((String) k, (JSONObject) value); - } - if (value instanceof JSONArray) { - a_samples.put((String) k, (JSONArray) value); - } - } - } - } - - private static Object sanitize(Object obj) { - // MT always use BigDecimal for the json type "Number" - // the Java lib may use Integer or Double, sanitize the java data9 - // to be ready for comparisons - if (obj instanceof Integer) { - return new BigDecimal((Integer) obj); - } - if (obj instanceof Double) { - // what a drag, round up double and strip trailing zeros to avoid test failing - // like "12.15000" does not equal "12.15", there may be a better solution - return (new BigDecimal((Double) obj)).setScale(5, RoundingMode.HALF_UP).stripTrailingZeros(); - } - return obj; - } - - // java to mt json object - // take a json java object and use MT fonctions to build an identical json object (hopefully) - private static JSONObject j2m(JSONObject o) { - return o; // TODO - } - - // asJSON works on complex json type (objects and arrays) - // jsonify works on simple types (number, strings, booleans) - // this function merges the 2 functionality in one. - private static Object jsonify(Object mt_value) { - if (mt_value instanceof String) { - String trimmed = ((String) mt_value).trim(); - // complex json data types - if (trimmed.startsWith("[") || trimmed.startsWith("{")) { - return JSONMacroFunctionsOld.asJSON(mt_value); - } - // simple json data types - return JSONMacroFunctionsOld.jsonify(mt_value); - } - return mt_value; - } - - // @Test - // @DisplayName("JSONGet testing.") - void testJSONGet() throws ParserException { - // test the Maptool json.get impl. against the Java JSON library get implementation - for (String k : o_samples.keySet()) { - JSONObject jobj = o_samples.get(k); - for (Object field : jobj.keySet()) { - Object java_value = jobj.get(field); - Object mt_value = run("json.get", jobj, field); - // while both may use different data types, their string representation must match - assertEquals(java_value.toString(), mt_value.toString()); - // however calling jsonify on MT values should make it match the internal java type - // there's a limitation of MT not able to encode properly "true", "false", and "null" - String[] blacklist = {"true", "false", "null"}; - if (!Arrays.stream(blacklist).anyMatch(java_value::equals)) { - assertEquals(sanitize(java_value), jsonify(mt_value)); - } - } - } - } - - // @Test - // @DisplayName("JSONSet testing.") - void testJSONSet() throws ParserException { - // test the Maptool json.get impl. against the Java JSON library set implementation - for (String k : o_samples.keySet()) { - JSONObject src = o_samples.get(k); - JSONObject dst = new JSONObject(); - // iterate over all src pairs k,v and use MT json.set to build a new, yet identical object - for (Object field : src.keySet()) { - Object java_value = src.get(field); - dst = (JSONObject) run("json.set", dst, field, java_value); - } - // eventually they have to match - assertEquals(src, dst); - } - } - - // @Test - // @DisplayName("JSONEmpty testing.") - void testJSONEmpty() throws ParserException { - BigDecimal _true = BigDecimal.ONE; - BigDecimal _false = BigDecimal.ZERO; - // explicit use of test fixtures - assertEquals(_true, (BigDecimal) run("json.isEmpty", o_samples.get("o_empty"))); - assertEquals(_false, (BigDecimal) run("json.isEmpty", o_samples.get("o_nested"))); - assertEquals(_true, (BigDecimal) run("json.isEmpty", a_samples.get("a_empty"))); - assertEquals(_false, (BigDecimal) run("json.isEmpty", a_samples.get("a_nested"))); - - // using json.set("", "key", "v") should not yield an empty object - assertEquals(_false, (BigDecimal) run("json.isEmpty", run("json.set", "", "a_key", "a_value"))); - // adding and removing a key from an already empty json object should yield an empty object - assertEquals( - _true, - (BigDecimal) - run( - "json.isEmpty", - run("json.remove", run("json.set", "", "a_key", "a_value"), "a_key"))); - // iterate over all fixtures objects and test the MT impl. against the java impl. - for (String k : o_samples.keySet()) { - JSONObject jobj = o_samples.get(k); - // match MT impl. against java library - assertEquals(jobj.isEmpty() ? _true : _false, (BigDecimal) run("json.isEmpty", jobj)); - } - } - - // @DisplayName("JSONLength testing.") - void testJSONLength() throws ParserException { - for (JSONArray java_array : a_samples.values()) { - JSONArray mt_array = JSONArray.fromObject("[]"); - for (Object elem : java_array) { - mt_array = (JSONArray) run("json.append", mt_array, elem); - } - assertEquals(sanitize(java_array.size()), run("json.length", mt_array)); - } - } - - /** JSON example from https://github.com/json-path/JsonPath/ */ - private static final String JSON = - "{ \"store\": {" - + " \"book\": [ " - + " { \"category\": \"reference\"," - + " \"author\": \"Nigel Rees\"," - + " \"title\": \"Sayings of the Century\"," - + " \"price\": 8.95" - + " },\n" - + " { \"category\": \"fiction\"," - + " \"author\": \"Evelyn Waugh\"," - + " \"title\": \"Sword of Honour\"," - + " \"price\": 12.99" - + " }," - + " { \"category\": \"fiction\"," - + " \"author\": \"Herman Melville\"," - + " \"title\": \"Moby Dick\"," - + " \"isbn\": \"0-553-21311-3\"," - + " \"price\": 8.99" - + " },\n" - + " { \"category\": \"fiction\"," - + " \"author\": \"J. R. R. Tolkien\"," - + " \"title\": \"The Lord of the Rings\"," - + " \"isbn\": \"0-395-19395-8\"," - + " \"price\": 22.99" - + " }\n" - + " ],\n" - + " \"bicycle\": {" - + " \"color\": \"red\"," - + " \"price\": 19.95" - + " }\n" - + " }, \"expensive\": 10" - + "}"; - - /** Path examples from https://github.com/json-path/JsonPath. */ - private static final String[] PATHS = { - "$.store.book[*].author", - "$..author", - "$.store.*", - "$.store..price", - "$..book[2]", - "$..book[-2]", - "$..book[0,1]", - "$..book[:2]", - "$..book[1:2]", - "$..book[-2:]", - "$..book[2:]", - "$..book[?(@.isbn)]", - "$.store.book[?(@.price < 10)]", - "$..*", - "$..book[?(@.author =~ /.*REES/i)]", - // "$..book.length()", // The length() operation appears to be broken in general with json-path - // see the many issues open on it at - // https://github.com/json-path/JsonPath/issues?q=is%3Aissue+is%3Aopen+length - "$..book[?(@.price <= $['expensive'])]" - }; - - /** Tests the JSON and paths from https://github.com/json-path/JsonPath. */ - @Test - void testJsonPathRead() { - String fName = "json.path.read"; - String msg = "Incorrect output for path %s"; - String excMsg = "Parser exception '%s' for path %s."; - for (String path : PATHS) { - try { - String mtOutput = run(fName, JSON, path).toString(); - String jwOutput = JsonPath.read(JSON, path).toString(); - Assert.equals(jwOutput, mtOutput, String.format(msg, path)); - } catch (ParserException e) { - fail(String.format(excMsg, e.getLocalizedMessage(), path)); - } - } - } - - /** Test json.difference() when Strings are used as arguments (fixed bug #1177). */ - @Test - void testJsonDifferenceWithStrings() throws ParserException { - Assert.equals("[]", run("json.difference", "test", "test").toString()); - } - /** Test json.isEmpty() when String is used as argument (fixed bug #1167). */ - @Test - void testJsonIsEmptyWithString() throws ParserException { - Assert.equals(BigDecimal.ZERO, run("json.isEmpty", "a")); - } - /** Test json.set() when empty String is used as argument (fixed bug #1151). */ - @Test - void testJsonSetWithEmptyString() throws ParserException { - Assert.equals("{\"field\":\"\"}", run("json.set", "{}", "field", "").toString()); - } - /** Test json.get() returning empty string if field doesn't exist (fixed bug #1121). */ - @Test - void testJsonGetMissingField() throws ParserException { - Assert.equals("", run("json.get", "{}", "field")); - } - /** Test json.get() when String is used as argument (fixed bug #1144). */ - @Test - void testJsonGetWithString() throws ParserException { - Assert.equals("test", run("json.get", "test", 0)); - } - /** Test json.append() when number is surrounded by white spaces (fixed bug #1139). */ - @Test - void testJsonAppendWhiteSpaces() throws ParserException { - Assert.equals("[\" 0 \"]", run("json.append", "[]", " 0 ").toString()); - } - /** Test json.toList() when quotes are in the json used as argument (fixed bug #1143). */ - @Test - void testJsonToListWithQuotes() throws ParserException { - Assert.equals("\"", run("json.toList", "[\"\\\"\"]").toString()); - } - /** Test json.type() with a json array (fixed bug #1125). */ - @Test - void testJsonTypeArray() throws ParserException { - Assert.equals("ARRAY", run("json.type", "[]")); - } -}