Skip to content

Commit

Permalink
Merge pull request #1742 from The-Lum/Evol
Browse files Browse the repository at this point in the history
feat: add new JSON builtin functions (`%str2json`, `%json_add` and `%json_remove`)
  • Loading branch information
arnaudroques committed Apr 16, 2024
2 parents c7d43f3 + 24239ff commit 81e7e76
Show file tree
Hide file tree
Showing 8 changed files with 611 additions and 7 deletions.
6 changes: 6 additions & 0 deletions src/net/sourceforge/plantuml/tim/TContext.java
Expand Up @@ -110,7 +110,9 @@
import net.sourceforge.plantuml.tim.stdlib.InvokeProcedure;
import net.sourceforge.plantuml.tim.stdlib.IsDark;
import net.sourceforge.plantuml.tim.stdlib.IsLight;
import net.sourceforge.plantuml.tim.stdlib.JsonAdd;
import net.sourceforge.plantuml.tim.stdlib.JsonKeyExists;
import net.sourceforge.plantuml.tim.stdlib.JsonRemove;
import net.sourceforge.plantuml.tim.stdlib.Lighten;
import net.sourceforge.plantuml.tim.stdlib.LoadJson;
import net.sourceforge.plantuml.tim.stdlib.LogicalAnd;
Expand All @@ -132,6 +134,7 @@
import net.sourceforge.plantuml.tim.stdlib.Size;
import net.sourceforge.plantuml.tim.stdlib.SplitStr;
import net.sourceforge.plantuml.tim.stdlib.SplitStrRegex;
import net.sourceforge.plantuml.tim.stdlib.Str2Json;
import net.sourceforge.plantuml.tim.stdlib.StringFunction;
import net.sourceforge.plantuml.tim.stdlib.Strlen;
import net.sourceforge.plantuml.tim.stdlib.Strpos;
Expand Down Expand Up @@ -216,6 +219,9 @@ private void addStandardFunctions(Defines defines) {
functionsSet.addFunction(new GetAllTheme());
functionsSet.addFunction(new GetAllStdlib());
functionsSet.addFunction(new SplitStrRegex());
functionsSet.addFunction(new Str2Json());
functionsSet.addFunction(new JsonAdd());
functionsSet.addFunction(new JsonRemove());
// %standard_exists_function
// %str_replace
// !exit
Expand Down
89 changes: 89 additions & 0 deletions src/net/sourceforge/plantuml/tim/stdlib/JsonAdd.java
@@ -0,0 +1,89 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2021, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
* Contribution: The-Lum
*
*/
package net.sourceforge.plantuml.tim.stdlib;

import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sourceforge.plantuml.json.JsonArray;
import net.sourceforge.plantuml.json.JsonObject;
import net.sourceforge.plantuml.json.JsonValue;
import net.sourceforge.plantuml.text.StringLocated;
import net.sourceforge.plantuml.tim.EaterException;
import net.sourceforge.plantuml.tim.TContext;
import net.sourceforge.plantuml.tim.TFunctionSignature;
import net.sourceforge.plantuml.tim.TMemory;
import net.sourceforge.plantuml.tim.expression.TValue;

public class JsonAdd extends SimpleReturnFunction {

public TFunctionSignature getSignature() {
return new TFunctionSignature("%json_add", 3);
}

@Override
public boolean canCover(int nbArg, Set<String> namedArgument) {
return nbArg == 2 || nbArg == 3;
}

@Override
public TValue executeReturnFunction(TContext context, TMemory memory, StringLocated location, List<TValue> values,
Map<String, TValue> named) throws EaterException {
final TValue data = values.get(0);
if (data.isJson() == false)
throw new EaterException("Not JSON data", location);

final JsonValue json = data.toJson();

if (!json.isArray() && !json.isObject())
return data;
if (json.isArray()) {
final JsonValue value = values.get(1).toJson();
final JsonArray array = (JsonArray) json;
array.add(value);
return TValue.fromJson(array);
}
if (json.isObject()) {
final String name = values.get(1).toString();
final JsonValue value = values.get(2).toJson();
final JsonObject object = (JsonObject) json;
object.add(name, value);
return TValue.fromJson(object);
}
throw new EaterException("Bad JSON type", location);
}
}
91 changes: 91 additions & 0 deletions src/net/sourceforge/plantuml/tim/stdlib/JsonRemove.java
@@ -0,0 +1,91 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2021, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
* Contribution: The-Lum
*
*/
package net.sourceforge.plantuml.tim.stdlib;

import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sourceforge.plantuml.json.JsonArray;
import net.sourceforge.plantuml.json.JsonObject;
import net.sourceforge.plantuml.json.JsonValue;
import net.sourceforge.plantuml.text.StringLocated;
import net.sourceforge.plantuml.tim.EaterException;
import net.sourceforge.plantuml.tim.TContext;
import net.sourceforge.plantuml.tim.TFunctionSignature;
import net.sourceforge.plantuml.tim.TMemory;
import net.sourceforge.plantuml.tim.expression.TValue;

public class JsonRemove extends SimpleReturnFunction {

public TFunctionSignature getSignature() {
return new TFunctionSignature("%json_remove", 2);
}

@Override
public boolean canCover(int nbArg, Set<String> namedArgument) {
return nbArg == 2;
}

@Override
public TValue executeReturnFunction(TContext context, TMemory memory, StringLocated location, List<TValue> values,
Map<String, TValue> named) throws EaterException {
final TValue data = values.get(0);
if (data.isJson() == false)
throw new EaterException("Not JSON data", location);

final JsonValue json = data.toJson();

if (!json.isArray() && !json.isObject())
return data;
if (json.isArray()) {
final JsonArray array = (JsonArray) json;
if (values.get(1).isNumber()) {
final Integer index = values.get(1).toInt();
if (0 <= index && index < array.size())
array.remove(index);
}
return TValue.fromJson(array);
}
if (json.isObject()) {
final JsonObject object = (JsonObject) json;
final String name = values.get(1).toString();
object.remove(name);
return TValue.fromJson(object);
}
throw new EaterException("Bad JSON type", location);
}
}
75 changes: 75 additions & 0 deletions src/net/sourceforge/plantuml/tim/stdlib/Str2Json.java
@@ -0,0 +1,75 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2021, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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. See the GNU General Public
* License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
* Contribution: The-Lum
*
*/
package net.sourceforge.plantuml.tim.stdlib;

import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sourceforge.plantuml.json.Json;
import net.sourceforge.plantuml.json.JsonArray;
import net.sourceforge.plantuml.json.JsonObject;
import net.sourceforge.plantuml.json.JsonValue;
import net.sourceforge.plantuml.text.StringLocated;
import net.sourceforge.plantuml.tim.EaterException;
import net.sourceforge.plantuml.tim.TContext;
import net.sourceforge.plantuml.tim.TFunctionSignature;
import net.sourceforge.plantuml.tim.TMemory;
import net.sourceforge.plantuml.tim.expression.TValue;

public class Str2Json extends SimpleReturnFunction {

public TFunctionSignature getSignature() {
return new TFunctionSignature("%str2json", 1);
}

@Override
public boolean canCover(int nbArg, Set<String> namedArgument) {
return nbArg == 1;
}

@Override
public TValue executeReturnFunction(TContext context, TMemory memory, StringLocated location, List<TValue> values,
Map<String, TValue> named) throws EaterException {
try {
final String value = values.get(0).toString();
final JsonValue json = Json.parse(value);
return TValue.fromJson(json);
} catch (Throwable t) {
return TValue.fromString("");
}
}
}
49 changes: 42 additions & 7 deletions test/net/sourceforge/plantuml/tim/TimTestUtils.java
Expand Up @@ -16,21 +16,28 @@ public class TimTestUtils {

// Tfunc: () -> (String)
public static void assertTimExpectedOutput(TFunction func, String expected) throws EaterException {
TValue tValue = func.executeReturnFunction(null, null, null, null, null);
final TValue tValue = func.executeReturnFunction(null, null, null, Collections.emptyList(), null);
assertEquals(expected, tValue.toString());
}

// Tfunc: (Integer) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, Integer input, String expected) throws EaterException {
List<TValue> values = Collections.singletonList(TValue.fromInt(input));
TValue tValue = func.executeReturnFunction(null, null, null, values, null);
final List<TValue> values = Collections.singletonList(TValue.fromInt(input));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}

// Tfunc: (Integer, Integer) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, Integer input1, Integer input2, String expected) throws EaterException {
final List<TValue> values = Arrays.asList(TValue.fromInt(input1), TValue.fromInt(input2));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}

// Tfunc: (String) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, String input, String expected) throws EaterException {
List<TValue> values = Collections.singletonList(TValue.fromString(input));
TValue tValue = func.executeReturnFunction(null, null, null, values, null);
final List<TValue> values = Collections.singletonList(TValue.fromString(input));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}

Expand All @@ -43,8 +50,36 @@ public static void assertTimExpectedOutputFromInput(TFunction func, String input

// Tfunc: (JsonValue) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, JsonValue input, String expected) throws EaterException {
List<TValue> values = Collections.singletonList(TValue.fromJson(input));
TValue tValue = func.executeReturnFunction(null, null, null, values, null);
final List<TValue> values = Collections.singletonList(TValue.fromJson(input));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}

// Tfunc: (JsonValue, JsonValue) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, JsonValue input1, JsonValue input2, String expected) throws EaterException {
final List<TValue> values = Arrays.asList(TValue.fromJson(input1), TValue.fromJson(input2));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}

// Tfunc: (JsonValue, Int) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, JsonValue input1, Integer input2, String expected) throws EaterException {
final List<TValue> values = Arrays.asList(TValue.fromJson(input1), TValue.fromInt(input2));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}

// Tfunc: (JsonValue, String) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, JsonValue input1, String input2, String expected) throws EaterException {
final List<TValue> values = Arrays.asList(TValue.fromJson(input1), TValue.fromString(input2));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}

// Tfunc: (JsonValue, String, JsonValue) -> (String)
public static void assertTimExpectedOutputFromInput(TFunction func, JsonValue input1, String input2, JsonValue input3, String expected) throws EaterException {
final List<TValue> values = Arrays.asList(TValue.fromJson(input1), TValue.fromString(input2), TValue.fromJson(input3));
final TValue tValue = func.executeReturnFunction(null, null, null, values, null);
assertEquals(expected, tValue.toString());
}

Expand Down

0 comments on commit 81e7e76

Please sign in to comment.