Made EvalError serializable because errors can be cell values and need to be saved.
Turned is* functions into controls, since they have to be able to test errors, and only controls can do that, not functions. Polished display of errors in cells and in expression preview dialog. git-svn-id: http://google-refine.googlecode.com/svn/trunk@155 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
parent
0c6590fe2c
commit
983be19e14
@ -73,14 +73,16 @@ public class PreviewExpressionCommand extends Command {
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
if (result instanceof EvalError) {
|
||||
result = "[Error: " + ((EvalError) result).message + "]";
|
||||
} else if (result instanceof HasFields) {
|
||||
if (ExpressionUtils.isError(result)) {
|
||||
writer.object();
|
||||
writer.key("message"); writer.value(((EvalError) result).message);
|
||||
writer.endObject();
|
||||
} else {
|
||||
if (result != null && result instanceof HasFields) {
|
||||
result = "[object " + result.getClass().getSimpleName() + "]";
|
||||
}
|
||||
}
|
||||
writer.value(result);
|
||||
}
|
||||
writer.value(result);
|
||||
}
|
||||
writer.endArray();
|
||||
} catch (ParserException e) {
|
||||
|
@ -8,6 +8,11 @@ import java.util.Map.Entry;
|
||||
import com.metaweb.gridworks.expr.controls.ForEach;
|
||||
import com.metaweb.gridworks.expr.controls.ForNonBlank;
|
||||
import com.metaweb.gridworks.expr.controls.If;
|
||||
import com.metaweb.gridworks.expr.controls.IsBlank;
|
||||
import com.metaweb.gridworks.expr.controls.IsNonBlank;
|
||||
import com.metaweb.gridworks.expr.controls.IsNotNull;
|
||||
import com.metaweb.gridworks.expr.controls.IsNull;
|
||||
import com.metaweb.gridworks.expr.controls.IsNumeric;
|
||||
import com.metaweb.gridworks.expr.controls.With;
|
||||
import com.metaweb.gridworks.expr.functions.Get;
|
||||
import com.metaweb.gridworks.expr.functions.Length;
|
||||
@ -56,11 +61,6 @@ import com.metaweb.gridworks.expr.functions.strings.Trim;
|
||||
import com.metaweb.gridworks.expr.functions.strings.Unescape;
|
||||
import com.metaweb.gridworks.expr.functions.strings.Unicode;
|
||||
import com.metaweb.gridworks.expr.functions.strings.UnicodeType;
|
||||
import com.metaweb.gridworks.expr.functions.tests.IsBlank;
|
||||
import com.metaweb.gridworks.expr.functions.tests.IsNotBlank;
|
||||
import com.metaweb.gridworks.expr.functions.tests.IsNotNull;
|
||||
import com.metaweb.gridworks.expr.functions.tests.IsNull;
|
||||
import com.metaweb.gridworks.expr.functions.tests.IsNumeric;
|
||||
|
||||
public class ControlFunctionRegistry {
|
||||
|
||||
@ -83,7 +83,7 @@ public class ControlFunctionRegistry {
|
||||
static public Control getControl(String name) {
|
||||
return s_nameToControl.get(name);
|
||||
}
|
||||
static public String getControlName(Function f) {
|
||||
static public String getControlName(Control f) {
|
||||
return s_controlToName.get(f);
|
||||
}
|
||||
static public Set<Entry<String, Control>> getControlMapping() {
|
||||
@ -156,15 +156,16 @@ public class ControlFunctionRegistry {
|
||||
registerFunction("and", new And());
|
||||
registerFunction("or", new Or());
|
||||
registerFunction("not", new Not());
|
||||
registerFunction("isNull", new IsNull());
|
||||
registerFunction("isNotNull", new IsNotNull());
|
||||
registerFunction("isBlank", new IsBlank());
|
||||
registerFunction("isNotBlank", new IsNotBlank());
|
||||
registerFunction("isNumeric", new IsNumeric());
|
||||
|
||||
registerControl("if", new If());
|
||||
registerControl("with", new With());
|
||||
registerControl("forEach", new ForEach());
|
||||
registerControl("forNonBlank", new ForNonBlank());
|
||||
|
||||
registerControl("isNull", new IsNull());
|
||||
registerControl("isNotNull", new IsNotNull());
|
||||
registerControl("isBlank", new IsBlank());
|
||||
registerControl("isNonBlank", new IsNonBlank());
|
||||
registerControl("isNumeric", new IsNumeric());
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.metaweb.gridworks.expr;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.json.JSONException;
|
||||
@ -7,7 +8,9 @@ import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.Jsonizable;
|
||||
|
||||
public class EvalError implements Jsonizable {
|
||||
public class EvalError implements Serializable, Jsonizable {
|
||||
private static final long serialVersionUID = -102681220092874080L;
|
||||
|
||||
final public String message;
|
||||
|
||||
public EvalError(String message) {
|
||||
|
@ -8,6 +8,7 @@ import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.Control;
|
||||
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
|
||||
import com.metaweb.gridworks.expr.EvalError;
|
||||
import com.metaweb.gridworks.expr.Evaluable;
|
||||
import com.metaweb.gridworks.expr.ExpressionUtils;
|
||||
@ -16,9 +17,9 @@ import com.metaweb.gridworks.expr.VariableExpr;
|
||||
public class ForEach implements Control {
|
||||
public String checkArguments(Evaluable[] args) {
|
||||
if (args.length != 3) {
|
||||
return "forEach expects 3 arguments";
|
||||
return ControlFunctionRegistry.getControlName(this) + " expects 3 arguments";
|
||||
} else if (!(args[1] instanceof VariableExpr)) {
|
||||
return "forEach expects second argument to be a variable name";
|
||||
return ControlFunctionRegistry.getControlName(this) + " expects second argument to be a variable name";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.Control;
|
||||
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
|
||||
import com.metaweb.gridworks.expr.Evaluable;
|
||||
import com.metaweb.gridworks.expr.ExpressionUtils;
|
||||
import com.metaweb.gridworks.expr.VariableExpr;
|
||||
@ -13,9 +14,9 @@ import com.metaweb.gridworks.expr.VariableExpr;
|
||||
public class ForNonBlank implements Control {
|
||||
public String checkArguments(Evaluable[] args) {
|
||||
if (args.length != 4) {
|
||||
return "forNonBlank expects 4 arguments";
|
||||
return ControlFunctionRegistry.getControlName(this) + " expects 4 arguments";
|
||||
} else if (!(args[1] instanceof VariableExpr)) {
|
||||
return "forNonBlank expects second argument to be a variable name";
|
||||
return ControlFunctionRegistry.getControlName(this) + " expects second argument to be a variable name";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -6,13 +6,14 @@ import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.Control;
|
||||
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
|
||||
import com.metaweb.gridworks.expr.Evaluable;
|
||||
import com.metaweb.gridworks.expr.ExpressionUtils;
|
||||
|
||||
public class If implements Control {
|
||||
public String checkArguments(Evaluable[] args) {
|
||||
if (args.length != 3) {
|
||||
return "if expects 3 arguments";
|
||||
return ControlFunctionRegistry.getControlName(this) + " expects 3 arguments";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package com.metaweb.gridworks.expr.controls;
|
||||
|
||||
import com.metaweb.gridworks.expr.ExpressionUtils;
|
||||
|
||||
public class IsBlank extends IsTest {
|
||||
@Override
|
||||
protected String getDescription() {
|
||||
return "Returns whether o is null or an empty string";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean test(Object o) {
|
||||
return !ExpressionUtils.isNonBlankData(o);
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.metaweb.gridworks.expr.controls;
|
||||
|
||||
import com.metaweb.gridworks.expr.ExpressionUtils;
|
||||
|
||||
public class IsNonBlank extends IsTest {
|
||||
@Override
|
||||
protected String getDescription() {
|
||||
return "Returns whether o is not null and not an empty string";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean test(Object o) {
|
||||
return ExpressionUtils.isNonBlankData(o);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.metaweb.gridworks.expr.controls;
|
||||
|
||||
public class IsNotNull extends IsTest {
|
||||
@Override
|
||||
protected String getDescription() {
|
||||
return "Returns whether o is not null";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean test(Object o) {
|
||||
return o != null;
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.metaweb.gridworks.expr.controls;
|
||||
|
||||
public class IsNull extends IsTest {
|
||||
@Override
|
||||
protected String getDescription() {
|
||||
return "Returns whether o is null";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean test(Object o) {
|
||||
return o == null;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.metaweb.gridworks.expr.controls;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
public class IsNumeric extends IsTest {
|
||||
@Override
|
||||
protected String getDescription() {
|
||||
return "Returns whether o can represent a number";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean test(Object o) {
|
||||
if (o instanceof Number) return true;
|
||||
|
||||
String s = (o instanceof String) ? (String) o : o.toString();
|
||||
|
||||
return StringUtils.isNumeric(s);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.metaweb.gridworks.expr.controls;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.Control;
|
||||
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
|
||||
import com.metaweb.gridworks.expr.Evaluable;
|
||||
|
||||
abstract class IsTest implements Control {
|
||||
public String checkArguments(Evaluable[] args) {
|
||||
if (args.length != 1) {
|
||||
return ControlFunctionRegistry.getControlName(this) + " expects one argument";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object call(Properties bindings, Evaluable[] args) {
|
||||
Object o = args[0].evaluate(bindings);
|
||||
|
||||
return test(o);
|
||||
}
|
||||
|
||||
public void write(JSONWriter writer, Properties options)
|
||||
throws JSONException {
|
||||
|
||||
writer.object();
|
||||
writer.key("description"); writer.value(
|
||||
"Evaluates expression o. If it is true, evaluates expression eTrue and returns the result. " +
|
||||
"Otherwise, evaluates expression eFalse and returns that result instead."
|
||||
);
|
||||
writer.key("params"); writer.value("expression o");
|
||||
writer.key("returns"); writer.value("boolean");
|
||||
writer.endObject();
|
||||
}
|
||||
|
||||
abstract protected boolean test(Object v);
|
||||
|
||||
abstract protected String getDescription();
|
||||
}
|
@ -6,26 +6,22 @@ import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.Control;
|
||||
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
|
||||
import com.metaweb.gridworks.expr.Evaluable;
|
||||
import com.metaweb.gridworks.expr.ExpressionUtils;
|
||||
import com.metaweb.gridworks.expr.VariableExpr;
|
||||
|
||||
public class With implements Control {
|
||||
public String checkArguments(Evaluable[] args) {
|
||||
if (args.length != 3) {
|
||||
return "with expects 3 arguments";
|
||||
return ControlFunctionRegistry.getControlName(this) + " expects 3 arguments";
|
||||
} else if (!(args[1] instanceof VariableExpr)) {
|
||||
return "with expects second argument to be a variable name";
|
||||
return ControlFunctionRegistry.getControlName(this) + " expects second argument to be a variable name";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object call(Properties bindings, Evaluable[] args) {
|
||||
Object o = args[0].evaluate(bindings);
|
||||
if (ExpressionUtils.isError(o)) {
|
||||
return o;
|
||||
}
|
||||
|
||||
String name = ((VariableExpr) args[1]).getName();
|
||||
|
||||
Object oldValue = bindings.get(name);
|
||||
|
@ -1,26 +0,0 @@
|
||||
package com.metaweb.gridworks.expr.functions.tests;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.ExpressionUtils;
|
||||
import com.metaweb.gridworks.expr.Function;
|
||||
|
||||
public class IsBlank implements Function {
|
||||
|
||||
public Object call(Properties bindings, Object[] args) {
|
||||
return args.length == 0 || !ExpressionUtils.isNonBlankData(args[0]);
|
||||
}
|
||||
|
||||
public void write(JSONWriter writer, Properties options)
|
||||
throws JSONException {
|
||||
|
||||
writer.object();
|
||||
writer.key("description"); writer.value("Returns whether o is null or an empty string");
|
||||
writer.key("params"); writer.value("o");
|
||||
writer.key("returns"); writer.value("boolean");
|
||||
writer.endObject();
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package com.metaweb.gridworks.expr.functions.tests;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.ExpressionUtils;
|
||||
import com.metaweb.gridworks.expr.Function;
|
||||
|
||||
public class IsNotBlank implements Function {
|
||||
|
||||
public Object call(Properties bindings, Object[] args) {
|
||||
return args.length > 0 && ExpressionUtils.isNonBlankData(args[0]);
|
||||
}
|
||||
|
||||
public void write(JSONWriter writer, Properties options)
|
||||
throws JSONException {
|
||||
|
||||
writer.object();
|
||||
writer.key("description"); writer.value("Returns whether o is not null, not an error, and not an empty string");
|
||||
writer.key("params"); writer.value("o");
|
||||
writer.key("returns"); writer.value("boolean");
|
||||
writer.endObject();
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package com.metaweb.gridworks.expr.functions.tests;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.Function;
|
||||
|
||||
public class IsNotNull implements Function {
|
||||
|
||||
public Object call(Properties bindings, Object[] args) {
|
||||
return args.length > 0 && args[0] != null;
|
||||
}
|
||||
|
||||
public void write(JSONWriter writer, Properties options)
|
||||
throws JSONException {
|
||||
|
||||
writer.object();
|
||||
writer.key("description"); writer.value("Returns whether o is not null");
|
||||
writer.key("params"); writer.value("o");
|
||||
writer.key("returns"); writer.value("boolean");
|
||||
writer.endObject();
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package com.metaweb.gridworks.expr.functions.tests;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.Function;
|
||||
|
||||
public class IsNull implements Function {
|
||||
|
||||
public Object call(Properties bindings, Object[] args) {
|
||||
return args.length == 0 || args[0] == null;
|
||||
}
|
||||
|
||||
public void write(JSONWriter writer, Properties options)
|
||||
throws JSONException {
|
||||
|
||||
writer.object();
|
||||
writer.key("description"); writer.value("Returns whether o is null");
|
||||
writer.key("params"); writer.value("o");
|
||||
writer.key("returns"); writer.value("boolean");
|
||||
writer.endObject();
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package com.metaweb.gridworks.expr.functions.tests;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
|
||||
import com.metaweb.gridworks.expr.EvalError;
|
||||
import com.metaweb.gridworks.expr.Function;
|
||||
|
||||
public class IsNumeric implements Function {
|
||||
|
||||
public Object call(Properties bindings, Object[] args) {
|
||||
if (args.length == 1 && args[0] != null) {
|
||||
Object o = args[0];
|
||||
if (o instanceof Number) return true;
|
||||
String s = (o instanceof String) ? (String) o : o.toString();
|
||||
return StringUtils.isNumeric(s);
|
||||
}
|
||||
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects an argument");
|
||||
}
|
||||
|
||||
public void write(JSONWriter writer, Properties options)
|
||||
throws JSONException {
|
||||
|
||||
writer.object();
|
||||
writer.key("description"); writer.value("Returns whether o can represent a number");
|
||||
writer.key("params"); writer.value("o");
|
||||
writer.key("returns"); writer.value("boolean");
|
||||
writer.endObject();
|
||||
}
|
||||
}
|
@ -7,6 +7,8 @@ import org.json.JSONException;
|
||||
import org.json.JSONWriter;
|
||||
|
||||
import com.metaweb.gridworks.Jsonizable;
|
||||
import com.metaweb.gridworks.expr.EvalError;
|
||||
import com.metaweb.gridworks.expr.ExpressionUtils;
|
||||
import com.metaweb.gridworks.expr.HasFields;
|
||||
|
||||
public class Cell implements Serializable, HasFields, Jsonizable {
|
||||
@ -31,8 +33,13 @@ public class Cell implements Serializable, HasFields, Jsonizable {
|
||||
|
||||
public void write(JSONWriter writer, Properties options) throws JSONException {
|
||||
writer.object();
|
||||
writer.key("v");
|
||||
writer.value(value);
|
||||
if (ExpressionUtils.isError(value)) {
|
||||
writer.key("e");
|
||||
writer.value(((EvalError) value).message);
|
||||
} else {
|
||||
writer.key("v");
|
||||
writer.value(value);
|
||||
}
|
||||
|
||||
if (recon != null) {
|
||||
writer.key("r");
|
||||
|
@ -189,13 +189,15 @@ ExpressionPreviewDialog.prototype._renderPreview = function(expression, data) {
|
||||
if (v !== null && v !== undefined) {
|
||||
if ($.isArray(v)) {
|
||||
td.html(JSON.stringify(v));
|
||||
} else if ($.isPlainObject(v)) {
|
||||
$('<span></span>').addClass("expression-preview-special-value").text("Error: " + v.message).appendTo(td);
|
||||
} else if (typeof v === "string" && v.length == 0) {
|
||||
$('<span>empty string</span>').addClass("expression-preview-empty").appendTo(td);
|
||||
$('<span>empty string</span>').addClass("expression-preview-special-value").appendTo(td);
|
||||
} else {
|
||||
td.html(v.toString());
|
||||
}
|
||||
} else {
|
||||
$('<span>null</span>').addClass("expression-preview-empty").appendTo(td);
|
||||
$('<span>null</span>').addClass("expression-preview-special-value").appendTo(td);
|
||||
}
|
||||
};
|
||||
|
||||
@ -214,7 +216,7 @@ ExpressionPreviewDialog.prototype._renderPreview = function(expression, data) {
|
||||
// error
|
||||
|
||||
var message = (data.type == "parser") ? data.message : "internal error";
|
||||
$('<span></span>').text(message).addClass("expression-preview-empty").appendTo(tdValue);
|
||||
$('<span></span>').text(message).addClass("expression-preview-special-value").appendTo(tdValue);
|
||||
}
|
||||
}
|
||||
};
|
@ -15,13 +15,11 @@ DataTableCellUI.prototype._render = function() {
|
||||
$(this._td).empty();
|
||||
var divContent = $('<div></div>').appendTo(this._td);
|
||||
|
||||
if (cell == null || cell.v == null) {
|
||||
if (cell == null || ("v" in cell && cell.v == null)) {
|
||||
$(divContent).html(" ");
|
||||
// TODO: content editing UI
|
||||
return;
|
||||
}
|
||||
|
||||
if (!("r" in cell) || cell.r == null) {
|
||||
} else if ("e" in cell) {
|
||||
$('<span>').addClass("data-table-error").text(cell.e).appendTo(divContent);
|
||||
} else if (!("r" in cell) || cell.r == null) {
|
||||
$(divContent).html(cell.v);
|
||||
} else {
|
||||
var r = cell.r;
|
||||
|
@ -60,6 +60,9 @@ img.column-header-menu {
|
||||
}
|
||||
|
||||
|
||||
.data-table-error {
|
||||
color: red;
|
||||
}
|
||||
div.data-table-recon-candidates {
|
||||
margin: 0.5em 0;
|
||||
min-width: 15em;
|
||||
|
@ -19,7 +19,7 @@ td.expression-preview-heading {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.expression-preview-empty {
|
||||
.expression-preview-special-value {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user