diff --git a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java index 1c1ef7bc4..18385f579 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionHistoryCommand.java @@ -37,19 +37,71 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Properties; import java.util.Set; +import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; public class GetExpressionHistoryCommand extends Command { + + public static class ExpressionState implements Jsonizable { + @JsonProperty("code") + protected String code; + @JsonProperty("global") + protected boolean global = false; + @JsonProperty("starred") + protected boolean starred; + + protected ExpressionState(String code, boolean starred) { + this.code = code; + this.starred = starred; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("code"); writer.value(code); + writer.key("global"); writer.value(false); + writer.key("starred"); writer.value(starred); + writer.endObject(); + } + } + + public static class ExpressionsList implements Jsonizable { + @JsonProperty("expressions") + List expressions; + + protected ExpressionsList(List states) { + this.expressions = states; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("expressions"); + writer.array(); + for (ExpressionState e : expressions) { + e.write(writer, options); + } + writer.endArray(); + writer.endObject(); + } + } static protected List toExpressionList(Object o) { return o == null ? new ArrayList() : ((TopList) o).getList(); @@ -60,40 +112,14 @@ public class GetExpressionHistoryCommand extends Command { throws ServletException, IOException { try { - List localExpressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); - localExpressions = localExpressions.size() > 20 ? localExpressions.subList(0, 20) : localExpressions; - List globalExpressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); + List expressions = toExpressionList(ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")); Set starredExpressions = new HashSet(((TopList)ProjectManager.singleton.getPreferenceStore().get("scripting.starred-expressions")).getList()); - - Set done = new HashSet(); - - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - writer.key("expressions"); - writer.array(); - for (String s : localExpressions) { - writer.object(); - writer.key("code"); writer.value(s); - writer.key("global"); writer.value(false); - writer.key("starred"); writer.value(starredExpressions.contains(s)); - writer.endObject(); - done.add(s); - } - for (String s : globalExpressions) { - if (!done.contains(s)) { - writer.object(); - writer.key("code"); writer.value(s); - writer.key("global"); writer.value(true); - writer.key("starred"); writer.value(starredExpressions.contains(s)); - writer.endObject(); - } - } - writer.endArray(); - writer.endObject(); + ExpressionsList expressionsList = new ExpressionsList(expressions.stream() + .map(s -> new ExpressionState(s, starredExpressions.contains(s))) + .collect(Collectors.toList())); + + respondJSON(response, expressionsList); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java b/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java index 13023b561..b5400d909 100644 --- a/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java +++ b/main/src/com/google/refine/commands/expr/GetExpressionLanguageInfoCommand.java @@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.commands.expr; import java.io.IOException; +import java.util.Map; import java.util.Map.Entry; import java.util.Properties; @@ -41,8 +42,12 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.commands.Command; import com.google.refine.grel.Control; import com.google.refine.grel.ControlFunctionRegistry; @@ -50,23 +55,27 @@ import com.google.refine.grel.Function; public class GetExpressionLanguageInfoCommand extends Command { - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { + public static class LanguageInfo implements Jsonizable { - try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - Properties options = new Properties(); - + @JsonProperty("functions") + Map functions; + @JsonProperty("controls") + Map controls; + + public LanguageInfo() { + functions = ControlFunctionRegistry.getFunctionMap(); + controls = ControlFunctionRegistry.getControlMap(); + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { writer.object(); writer.key("functions"); writer.object(); { - for (Entry entry : ControlFunctionRegistry.getFunctionMapping()) { + for (Entry entry : functions.entrySet()) { writer.key(entry.getKey()); entry.getValue().write(writer, options); } @@ -76,7 +85,7 @@ public class GetExpressionLanguageInfoCommand extends Command { writer.key("controls"); writer.object(); { - for (Entry entry : ControlFunctionRegistry.getControlMapping()) { + for (Entry entry : controls.entrySet()) { writer.key(entry.getKey()); entry.getValue().write(writer, options); } @@ -84,6 +93,16 @@ public class GetExpressionLanguageInfoCommand extends Command { writer.endObject(); writer.endObject(); + } + + } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + try { + respondJSON(response, new LanguageInfo()); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java b/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java index b489d248b..acad51a5c 100644 --- a/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java +++ b/main/src/com/google/refine/commands/expr/GetStarredExpressionsCommand.java @@ -2,13 +2,19 @@ package com.google.refine.commands.expr; import java.io.IOException; import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.json.JSONException; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import com.google.refine.Jsonizable; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; @@ -16,27 +22,52 @@ import com.google.refine.preference.TopList; public class GetStarredExpressionsCommand extends Command { + protected static class Expression implements Jsonizable { + @JsonProperty("code") + protected String code; + protected Expression(String c) { + code = c; + } + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("code"); writer.value(code); + writer.endObject(); + } + } + + protected static class ExpressionList implements Jsonizable { + @JsonProperty("expressions") + protected List expressions; + protected ExpressionList(List e) { + expressions = e; + } + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("expressions"); + writer.array(); + for (Expression s : expressions) { + s.write(writer, options); + } + writer.endArray(); + writer.endObject(); + } + } + + public static ExpressionList getExpressionsList() { + List starredExpressions = ((TopList)ProjectManager.singleton.getPreferenceStore().get("scripting.starred-expressions")).getList(); + return new ExpressionList(starredExpressions.stream().map(e -> new Expression(e)).collect(Collectors.toList())); + } + @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { - List starredExpressions = ((TopList)ProjectManager.singleton.getPreferenceStore().get("scripting.starred-expressions")).getList(); - - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - writer.key("expressions"); - writer.array(); - for (String s : starredExpressions) { - writer.object(); - writer.key("code"); writer.value(s); - writer.endObject(); - } - writer.endArray(); - writer.endObject(); + respondJSON(response, getExpressionsList()); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/expr/LogExpressionCommand.java b/main/src/com/google/refine/commands/expr/LogExpressionCommand.java index 3723869d8..b5bc0bde1 100644 --- a/main/src/com/google/refine/commands/expr/LogExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/LogExpressionCommand.java @@ -41,7 +41,6 @@ import javax.servlet.http.HttpServletResponse; import com.google.refine.ProjectManager; import com.google.refine.commands.Command; -import com.google.refine.model.Project; import com.google.refine.preference.TopList; public class LogExpressionCommand extends Command { @@ -51,7 +50,6 @@ public class LogExpressionCommand extends Command { throws ServletException, IOException { try { - Project project = getProject(request); String expression = request.getParameter("expression"); ((TopList) ProjectManager.singleton.getPreferenceStore().get("scripting.expressions")) diff --git a/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java b/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java index 000f33acd..2f5941a6f 100644 --- a/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/PreviewExpressionCommand.java @@ -36,6 +36,7 @@ package com.google.refine.commands.expr; import java.io.IOException; import java.io.Serializable; import java.time.OffsetDateTime; +import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -48,6 +49,12 @@ import org.json.JSONException; import org.json.JSONObject; import org.json.JSONWriter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; + +import com.google.refine.Jsonizable; import com.google.refine.commands.Command; import com.google.refine.expr.EvalError; import com.google.refine.expr.Evaluable; @@ -64,6 +71,85 @@ import com.google.refine.util.ParsingUtilities; public class PreviewExpressionCommand extends Command { + protected static interface ExpressionValue extends Jsonizable { } + protected static class ErrorMessage implements ExpressionValue { + @JsonProperty("message") + protected String message; + public ErrorMessage(String m) { + message = m; + } + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("message"); writer.value(message); + writer.endObject(); + } + + } + protected static class SuccessfulEvaluation implements ExpressionValue { + @JsonValue + protected String value; + protected SuccessfulEvaluation(String value) { + this.value = value; + } + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.value(value); + } + + } + + protected static class PreviewResult implements Jsonizable { + @JsonProperty("code") + protected String code; + @JsonProperty("message") + @JsonInclude(Include.NON_NULL) + protected String message; + @JsonProperty("type") + @JsonInclude(Include.NON_NULL) + protected String type; + @JsonProperty("results") + List results; + + public PreviewResult(String code, String message, String type) { + this.code = code; + this.message = message; + this.type = type; + this.results = null; + } + + public PreviewResult(List evaluated) { + this.code = "ok"; + this.message = null; + this.type = null; + this.results = evaluated; + } + + @Override + public void write(JSONWriter writer, Properties options) + throws JSONException { + writer.object(); + writer.key("code"); writer.value(code); + if(message != null) { + writer.key("message"); writer.value(message); + } + if(type != null) { + writer.key("type"); writer.value(type); + } + if(results != null) { + writer.key("results"); + writer.array(); + for(ExpressionValue v : results) { + v.write(writer, options); + } + writer.endArray(); + } + writer.endObject(); + } + } + @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -77,7 +163,7 @@ public class PreviewExpressionCommand extends Command { String expression = request.getParameter("expression"); String rowIndicesString = request.getParameter("rowIndices"); if (rowIndicesString == null) { - respond(response, "{ \"code\" : \"error\", \"message\" : \"No row indices specified\" }"); + respondJSON(response, new PreviewResult("error", "No row indices specified", null)); return; } @@ -91,21 +177,13 @@ public class PreviewExpressionCommand extends Command { } } - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - JSONArray rowIndices = ParsingUtilities.evaluateJsonStringToArray(rowIndicesString); int length = rowIndices.length(); - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - try { Evaluable eval = MetaParser.parse(expression); - writer.key("code"); writer.value("ok"); - writer.key("results"); writer.array(); - + List evaluated = new ArrayList<>(); Properties bindings = ExpressionUtils.createBindings(project); for (int i = 0; i < length; i++) { Object result = null; @@ -140,31 +218,23 @@ public class PreviewExpressionCommand extends Command { } if (result == null) { - writer.value(null); + evaluated.add(null); } else if (ExpressionUtils.isError(result)) { - writer.object(); - writer.key("message"); writer.value(((EvalError) result).message); - writer.endObject(); + evaluated.add(new ErrorMessage(((EvalError) result).message)); } else { StringBuffer sb = new StringBuffer(); writeValue(sb, result, false); - writer.value(sb.toString()); + evaluated.add(new SuccessfulEvaluation(sb.toString())); } } - writer.endArray(); + respondJSON(response, new PreviewResult(evaluated)); } catch (ParsingException e) { - writer.key("code"); writer.value("error"); - writer.key("type"); writer.value("parser"); - writer.key("message"); writer.value(e.getMessage()); + respondJSON(response, new PreviewResult("error", e.getMessage(), "parser")); } catch (Exception e) { - writer.key("code"); writer.value("error"); - writer.key("type"); writer.value("other"); - writer.key("message"); writer.value(e.getMessage()); + respondJSON(response, new PreviewResult("error", e.getMessage(), "other")); } - - writer.endObject(); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/commands/expr/ToggleStarredExpressionCommand.java b/main/src/com/google/refine/commands/expr/ToggleStarredExpressionCommand.java index e61faf11d..65558ccc4 100644 --- a/main/src/com/google/refine/commands/expr/ToggleStarredExpressionCommand.java +++ b/main/src/com/google/refine/commands/expr/ToggleStarredExpressionCommand.java @@ -7,8 +7,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.json.JSONWriter; - import com.google.refine.ProjectManager; import com.google.refine.commands.Command; import com.google.refine.preference.TopList; @@ -30,21 +28,7 @@ public class ToggleStarredExpressionCommand extends Command { if(request.getParameter("returnList") != null) { try { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Type", "application/json"); - - JSONWriter writer = new JSONWriter(response.getWriter()); - writer.object(); - writer.key("expressions"); - writer.array(); - for (String s : starredExpressions) { - writer.object(); - writer.key("code"); - writer.value(s); - writer.endObject(); - } - writer.endArray(); - writer.endObject(); + respondJSON(response, GetStarredExpressionsCommand.getExpressionsList()); } catch (Exception e) { respondException(response, e); } diff --git a/main/src/com/google/refine/grel/ControlFunctionRegistry.java b/main/src/com/google/refine/grel/ControlFunctionRegistry.java index 397bb193d..8745832b9 100644 --- a/main/src/com/google/refine/grel/ControlFunctionRegistry.java +++ b/main/src/com/google/refine/grel/ControlFunctionRegistry.java @@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.grel; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -168,6 +169,9 @@ public class ControlFunctionRegistry { static public Set> getFunctionMapping() { return s_nameToFunction.entrySet(); } + static public Map getFunctionMap() { + return Collections.unmodifiableMap(s_nameToFunction); + } static public Control getControl(String name) { return s_nameToControl.get(name); @@ -178,6 +182,9 @@ public class ControlFunctionRegistry { static public Set> getControlMapping() { return s_nameToControl.entrySet(); } + static public Map getControlMap() { + return Collections.unmodifiableMap(s_nameToControl); + } static public void registerFunction(String name, Function f) { s_nameToFunction.put(name, f);