Introduced EvalError objects as possible values returned by expressions.

Extracted function and control name mappings to ControlFunctionRegistry.


git-svn-id: http://google-refine.googlecode.com/svn/trunk@148 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-02-27 05:48:33 +00:00
parent f0b8268809
commit c914aa6c16
50 changed files with 456 additions and 261 deletions

View File

@ -100,8 +100,8 @@ public class ReconJudgeOneCellCommand extends Command {
protected HistoryEntry createHistoryEntry() throws Exception { protected HistoryEntry createHistoryEntry() throws Exception {
Cell cell = _project.rows.get(rowIndex).getCell(cellIndex); Cell cell = _project.rows.get(rowIndex).getCell(cellIndex);
if (cell == null || ExpressionUtils.isBlank(cell.value)) { if (cell == null || !ExpressionUtils.isNonBlankData(cell.value)) {
throw new Exception("Cell is blank"); throw new Exception("Cell is blank or error");
} }
Column column = _project.columnModel.getColumnByCellIndex(cellIndex); Column column = _project.columnModel.getColumnByCellIndex(cellIndex);

View File

@ -12,8 +12,8 @@ import org.json.JSONWriter;
import com.metaweb.gridworks.commands.Command; import com.metaweb.gridworks.commands.Command;
import com.metaweb.gridworks.expr.Control; import com.metaweb.gridworks.expr.Control;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.Parser;
public class GetExpressionLanguageInfoCommand extends Command { public class GetExpressionLanguageInfoCommand extends Command {
@ -30,7 +30,7 @@ public class GetExpressionLanguageInfoCommand extends Command {
writer.key("functions"); writer.key("functions");
writer.object(); writer.object();
{ {
for (Entry<String, Function> entry : Parser.functionTable.entrySet()) { for (Entry<String, Function> entry : ControlFunctionRegistry.getFunctionMapping()) {
writer.key(entry.getKey()); writer.key(entry.getKey());
entry.getValue().write(writer, options); entry.getValue().write(writer, options);
} }
@ -40,7 +40,7 @@ public class GetExpressionLanguageInfoCommand extends Command {
writer.key("controls"); writer.key("controls");
writer.object(); writer.object();
{ {
for (Entry<String, Control> entry : Parser.controlTable.entrySet()) { for (Entry<String, Control> entry : ControlFunctionRegistry.getControlMapping()) {
writer.key(entry.getKey()); writer.key(entry.getKey());
entry.getValue().write(writer, options); entry.getValue().write(writer, options);
} }

View File

@ -86,7 +86,7 @@ public class GuessTypesOfColumnCommand extends Command {
for (Row row : project.rows) { for (Row row : project.rows) {
Object value = row.getCellValue(cellIndex); Object value = row.getCellValue(cellIndex);
if (!ExpressionUtils.isBlank(value)) { if (ExpressionUtils.isNonBlankData(value)) {
String s = value.toString().trim(); String s = value.toString().trim();
if (!sampleSet.contains(s)) { if (!sampleSet.contains(s)) {
samples.add(s); samples.add(s);

View File

@ -12,10 +12,12 @@ import org.json.JSONWriter;
import com.metaweb.gridworks.commands.Command; import com.metaweb.gridworks.commands.Command;
import com.metaweb.gridworks.expr.EvalError;
import com.metaweb.gridworks.expr.Evaluable; import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.ExpressionUtils; import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.expr.HasFields; import com.metaweb.gridworks.expr.HasFields;
import com.metaweb.gridworks.expr.Parser; import com.metaweb.gridworks.expr.Parser;
import com.metaweb.gridworks.expr.Parser.ParserException;
import com.metaweb.gridworks.model.Cell; import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.model.Project; import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row; import com.metaweb.gridworks.model.Row;
@ -69,15 +71,23 @@ public class PreviewExpressionCommand extends Command {
} }
if (result != null) { if (result != null) {
if (result instanceof HasFields) { if (result instanceof EvalError) {
result = "[Error: " + ((EvalError) result).message + "]";
} else if (result instanceof HasFields) {
result = "[object " + result.getClass().getSimpleName() + "]"; result = "[object " + result.getClass().getSimpleName() + "]";
} }
} }
writer.value(result); writer.value(result);
} }
writer.endArray(); writer.endArray();
} catch (ParserException e) {
writer.key("code"); writer.value("error");
writer.key("type"); writer.value("parser");
writer.key("message"); writer.value(e.getMessage());
} catch (Exception e) { } catch (Exception e) {
writer.key("code"); writer.value("error"); writer.key("code"); writer.value("error");
writer.key("type"); writer.value("other");
writer.key("message"); writer.value(e.getMessage());
} }
writer.endObject(); writer.endObject();

View File

@ -6,4 +6,6 @@ import com.metaweb.gridworks.Jsonizable;
public interface Control extends Jsonizable { public interface Control extends Jsonizable {
public Object call(Properties bindings, Evaluable[] args); public Object call(Properties bindings, Evaluable[] args);
public String checkArguments(Evaluable[] args);
} }

View File

@ -0,0 +1,128 @@
package com.metaweb.gridworks.expr;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
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.With;
import com.metaweb.gridworks.expr.functions.And;
import com.metaweb.gridworks.expr.functions.Ceil;
import com.metaweb.gridworks.expr.functions.EndsWith;
import com.metaweb.gridworks.expr.functions.Floor;
import com.metaweb.gridworks.expr.functions.Get;
import com.metaweb.gridworks.expr.functions.IndexOf;
import com.metaweb.gridworks.expr.functions.IsBlank;
import com.metaweb.gridworks.expr.functions.IsNotBlank;
import com.metaweb.gridworks.expr.functions.IsNotNull;
import com.metaweb.gridworks.expr.functions.IsNull;
import com.metaweb.gridworks.expr.functions.Join;
import com.metaweb.gridworks.expr.functions.LastIndexOf;
import com.metaweb.gridworks.expr.functions.Length;
import com.metaweb.gridworks.expr.functions.Ln;
import com.metaweb.gridworks.expr.functions.Log;
import com.metaweb.gridworks.expr.functions.Max;
import com.metaweb.gridworks.expr.functions.Min;
import com.metaweb.gridworks.expr.functions.Mod;
import com.metaweb.gridworks.expr.functions.Not;
import com.metaweb.gridworks.expr.functions.Or;
import com.metaweb.gridworks.expr.functions.Replace;
import com.metaweb.gridworks.expr.functions.Reverse;
import com.metaweb.gridworks.expr.functions.Round;
import com.metaweb.gridworks.expr.functions.Slice;
import com.metaweb.gridworks.expr.functions.Sort;
import com.metaweb.gridworks.expr.functions.Split;
import com.metaweb.gridworks.expr.functions.StartsWith;
import com.metaweb.gridworks.expr.functions.ToLowercase;
import com.metaweb.gridworks.expr.functions.ToNumber;
import com.metaweb.gridworks.expr.functions.ToString;
import com.metaweb.gridworks.expr.functions.ToTitlecase;
import com.metaweb.gridworks.expr.functions.ToUppercase;
public class ControlFunctionRegistry {
static private Map<String, Function> s_nameToFunction = new HashMap<String, Function>();
static private Map<Function, String> s_functionToName = new HashMap<Function, String>();
static private Map<String, Control> s_nameToControl = new HashMap<String, Control>();
static private Map<Control, String> s_controlToName = new HashMap<Control, String>();
static public Function getFunction(String name) {
return s_nameToFunction.get(name);
}
static public String getFunctionName(Function f) {
return s_functionToName.get(f);
}
static public Set<Entry<String, Function>> getFunctionMapping() {
return s_nameToFunction.entrySet();
}
static public Control getControl(String name) {
return s_nameToControl.get(name);
}
static public String getControlName(Function f) {
return s_controlToName.get(f);
}
static public Set<Entry<String, Control>> getControlMapping() {
return s_nameToControl.entrySet();
}
static protected void registerFunction(String name, Function f) {
s_nameToFunction.put(name, f);
s_functionToName.put(f, name);
}
static protected void registerControl(String name, Control c) {
s_nameToControl.put(name, c);
s_controlToName.put(c, name);
}
static {
registerFunction("toString", new ToString());
registerFunction("toNumber", new ToNumber());
registerFunction("toUppercase", new ToUppercase());
registerFunction("toLowercase", new ToLowercase());
registerFunction("toTitlecase", new ToTitlecase());
registerFunction("get", new Get());
registerFunction("slice", new Slice());
registerFunction("substring", new Slice());
registerFunction("replace", new Replace());
registerFunction("split", new Split());
registerFunction("length", new Length());
registerFunction("indexOf", new IndexOf());
registerFunction("lastIndexOf", new LastIndexOf());
registerFunction("startsWith", new StartsWith());
registerFunction("endsWith", new EndsWith());
registerFunction("join", new Join());
registerFunction("reverse", new Reverse());
registerFunction("sort", new Sort());
registerFunction("round", new Round());
registerFunction("floor", new Floor());
registerFunction("ceil", new Ceil());
registerFunction("mod", new Mod());
registerFunction("max", new Max());
registerFunction("min", new Min());
registerFunction("log", new Log());
registerFunction("ln", new Ln());
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());
registerControl("if", new If());
registerControl("with", new With());
registerControl("forEach", new ForEach());
registerControl("forNonBlank", new ForNonBlank());
}
}

View File

@ -0,0 +1,26 @@
package com.metaweb.gridworks.expr;
import java.util.Properties;
import org.json.JSONException;
import org.json.JSONWriter;
import com.metaweb.gridworks.Jsonizable;
public class EvalError implements Jsonizable {
final public String message;
public EvalError(String message) {
this.message = message;
}
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("type"); writer.value("error");
writer.key("message"); writer.value(message);
writer.endObject();
}
}

View File

@ -32,9 +32,20 @@ public class ExpressionUtils {
} }
} }
static public boolean isError(Object o) {
return o != null && o instanceof EvalError;
}
/*
static public boolean isBlank(Object o) { static public boolean isBlank(Object o) {
return o == null || (o instanceof String && ((String) o).length() == 0); return o == null || (o instanceof String && ((String) o).length() == 0);
} }
*/
static public boolean isNonBlankData(Object o) {
return
o != null &&
!(o instanceof EvalError) &&
(!(o instanceof String) || ((String) o).length() > 0);
}
static public boolean isTrue(Object o) { static public boolean isTrue(Object o) {
return o != null && return o != null &&

View File

@ -13,10 +13,15 @@ public class FieldAccessorExpr implements Evaluable {
public Object evaluate(Properties bindings) { public Object evaluate(Properties bindings) {
Object o = _inner.evaluate(bindings); Object o = _inner.evaluate(bindings);
if (o != null && o instanceof HasFields) { if (ExpressionUtils.isError(o)) {
return o;
} else if (o == null) {
return new EvalError("Cannot retrieve field from null");
} else if (o instanceof HasFields) {
return ((HasFields) o).getField(_fieldName, bindings); return ((HasFields) o).getField(_fieldName, bindings);
} else {
return new EvalError("Object does not have any field, including " + _fieldName);
} }
return null;
} }
@Override @Override

View File

@ -14,7 +14,11 @@ public class FunctionCallExpr implements Evaluable {
public Object evaluate(Properties bindings) { public Object evaluate(Properties bindings) {
Object[] args = new Object[_args.length]; Object[] args = new Object[_args.length];
for (int i = 0; i < _args.length; i++) { for (int i = 0; i < _args.length; i++) {
args[i] = _args[i].evaluate(bindings); Object v = _args[i].evaluate(bindings);
if (ExpressionUtils.isError(v)) {
return v;
}
args[i] = v;
} }
return _function.call(bindings, args); return _function.call(bindings, args);
} }

View File

@ -14,7 +14,11 @@ public class OperatorCallExpr implements Evaluable {
public Object evaluate(Properties bindings) { public Object evaluate(Properties bindings) {
Object[] args = new Object[_args.length]; Object[] args = new Object[_args.length];
for (int i = 0; i < _args.length; i++) { for (int i = 0; i < _args.length; i++) {
args[i] = _args[i].evaluate(bindings); Object v = _args[i].evaluate(bindings);
if (ExpressionUtils.isError(v)) {
return v;
}
args[i] = v;
} }
if (args.length == 2) { if (args.length == 2) {

View File

@ -1,109 +1,30 @@
package com.metaweb.gridworks.expr; package com.metaweb.gridworks.expr;
import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
import com.metaweb.gridworks.expr.Scanner.NumberToken; import com.metaweb.gridworks.expr.Scanner.NumberToken;
import com.metaweb.gridworks.expr.Scanner.Token; import com.metaweb.gridworks.expr.Scanner.Token;
import com.metaweb.gridworks.expr.Scanner.TokenType; import com.metaweb.gridworks.expr.Scanner.TokenType;
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.With;
import com.metaweb.gridworks.expr.functions.And;
import com.metaweb.gridworks.expr.functions.Ceil;
import com.metaweb.gridworks.expr.functions.EndsWith;
import com.metaweb.gridworks.expr.functions.Floor;
import com.metaweb.gridworks.expr.functions.Get;
import com.metaweb.gridworks.expr.functions.IndexOf;
import com.metaweb.gridworks.expr.functions.IsBlank;
import com.metaweb.gridworks.expr.functions.IsNotBlank;
import com.metaweb.gridworks.expr.functions.IsNotNull;
import com.metaweb.gridworks.expr.functions.IsNull;
import com.metaweb.gridworks.expr.functions.Join;
import com.metaweb.gridworks.expr.functions.LastIndexOf;
import com.metaweb.gridworks.expr.functions.Length;
import com.metaweb.gridworks.expr.functions.Ln;
import com.metaweb.gridworks.expr.functions.Log;
import com.metaweb.gridworks.expr.functions.Max;
import com.metaweb.gridworks.expr.functions.Min;
import com.metaweb.gridworks.expr.functions.Mod;
import com.metaweb.gridworks.expr.functions.Not;
import com.metaweb.gridworks.expr.functions.Or;
import com.metaweb.gridworks.expr.functions.Replace;
import com.metaweb.gridworks.expr.functions.Reverse;
import com.metaweb.gridworks.expr.functions.Round;
import com.metaweb.gridworks.expr.functions.Slice;
import com.metaweb.gridworks.expr.functions.Sort;
import com.metaweb.gridworks.expr.functions.Split;
import com.metaweb.gridworks.expr.functions.StartsWith;
import com.metaweb.gridworks.expr.functions.ToLowercase;
import com.metaweb.gridworks.expr.functions.ToNumber;
import com.metaweb.gridworks.expr.functions.ToString;
import com.metaweb.gridworks.expr.functions.ToTitlecase;
import com.metaweb.gridworks.expr.functions.ToUppercase;
public class Parser { public class Parser {
protected Scanner _scanner; protected Scanner _scanner;
protected Token _token; protected Token _token;
protected Evaluable _root; protected Evaluable _root;
static public Map<String, Function> functionTable = new HashMap<String, Function>(); static public class ParserException extends Exception {
static public Map<String, Control> controlTable = new HashMap<String, Control>(); private static final long serialVersionUID = 155004505172098755L;
static { protected ParserException(String message) {
functionTable.put("toString", new ToString()); super(message);
functionTable.put("toNumber", new ToNumber()); }
functionTable.put("toUppercase", new ToUppercase());
functionTable.put("toLowercase", new ToLowercase());
functionTable.put("toTitlecase", new ToTitlecase());
functionTable.put("get", new Get());
functionTable.put("slice", new Slice());
functionTable.put("substring", new Slice());
functionTable.put("replace", new Replace());
functionTable.put("split", new Split());
functionTable.put("length", new Length());
functionTable.put("indexOf", new IndexOf());
functionTable.put("lastIndexOf", new LastIndexOf());
functionTable.put("startsWith", new StartsWith());
functionTable.put("endsWith", new EndsWith());
functionTable.put("join", new Join());
functionTable.put("reverse", new Reverse());
functionTable.put("sort", new Sort());
functionTable.put("round", new Round());
functionTable.put("floor", new Floor());
functionTable.put("ceil", new Ceil());
functionTable.put("mod", new Mod());
functionTable.put("max", new Max());
functionTable.put("min", new Min());
functionTable.put("log", new Log());
functionTable.put("ln", new Ln());
functionTable.put("and", new And());
functionTable.put("or", new Or());
functionTable.put("not", new Not());
functionTable.put("isNull", new IsNull());
functionTable.put("isNotNull", new IsNotNull());
functionTable.put("isBlank", new IsBlank());
functionTable.put("isNotBlank", new IsNotBlank());
controlTable.put("if", new If());
controlTable.put("with", new With());
controlTable.put("forEach", new ForEach());
controlTable.put("forNonBlank", new ForNonBlank());
} }
public Parser(String s) throws Exception { public Parser(String s) throws ParserException {
this(s, 0, s.length()); this(s, 0, s.length());
} }
public Parser(String s, int from, int to) throws Exception { public Parser(String s, int from, int to) throws ParserException {
_scanner = new Scanner(s, from, to); _scanner = new Scanner(s, from, to);
_token = _scanner.next(); _token = _scanner.next();
@ -118,13 +39,13 @@ public class Parser {
_token = _scanner.next(); _token = _scanner.next();
} }
protected Exception makeException(String desc) { protected ParserException makeException(String desc) {
int index = _token != null ? _token.start : _scanner.getIndex(); int index = _token != null ? _token.start : _scanner.getIndex();
return new Exception("Parsing error at offset " + index + ": " + desc); return new ParserException("Parsing error at offset " + index + ": " + desc);
} }
protected Evaluable parseExpression() throws Exception { protected Evaluable parseExpression() throws ParserException {
Evaluable sub = parseSubExpression(); Evaluable sub = parseSubExpression();
while (_token != null && while (_token != null &&
@ -143,7 +64,7 @@ public class Parser {
return sub; return sub;
} }
protected Evaluable parseSubExpression() throws Exception { protected Evaluable parseSubExpression() throws ParserException {
Evaluable sub = parseTerm(); Evaluable sub = parseTerm();
while (_token != null && while (_token != null &&
@ -162,7 +83,7 @@ public class Parser {
return sub; return sub;
} }
protected Evaluable parseTerm() throws Exception { protected Evaluable parseTerm() throws ParserException {
Evaluable factor = parseFactor(); Evaluable factor = parseFactor();
while (_token != null && while (_token != null &&
@ -181,7 +102,7 @@ public class Parser {
return factor; return factor;
} }
protected Evaluable parseFactor() throws Exception { protected Evaluable parseFactor() throws ParserException {
if (_token == null) { if (_token == null) {
throw makeException("Expression ends too early"); throw makeException("Expression ends too early");
} }
@ -210,8 +131,8 @@ public class Parser {
if (_token == null || _token.type != TokenType.Delimiter || !_token.text.equals("(")) { if (_token == null || _token.type != TokenType.Delimiter || !_token.text.equals("(")) {
eval = new VariableExpr(text); eval = new VariableExpr(text);
} else { } else {
Function f = functionTable.get(text); Function f = ControlFunctionRegistry.getFunction(text);
Control c = controlTable.get(text); Control c = ControlFunctionRegistry.getControl(text);
if (f == null && c == null) { if (f == null && c == null) {
throw makeException("Unknown function or control named " + text); throw makeException("Unknown function or control named " + text);
} }
@ -221,7 +142,12 @@ public class Parser {
List<Evaluable> args = parseExpressionList(")"); List<Evaluable> args = parseExpressionList(")");
if (c != null) { if (c != null) {
eval = new ControlCallExpr(makeArray(args), c); Evaluable[] argsA = makeArray(args);
String errorMessage = c.checkArguments(argsA);
if (errorMessage != null) {
throw makeException(errorMessage);
}
eval = new ControlCallExpr(argsA, c);
} else { } else {
eval = new FunctionCallExpr(makeArray(args), f); eval = new FunctionCallExpr(makeArray(args), f);
} }
@ -254,7 +180,7 @@ public class Parser {
if (_token != null && _token.type == TokenType.Delimiter && _token.text.equals("(")) { if (_token != null && _token.type == TokenType.Delimiter && _token.text.equals("(")) {
next(); // swallow ( next(); // swallow (
Function f = functionTable.get(identifier); Function f = ControlFunctionRegistry.getFunction(identifier);
if (f == null) { if (f == null) {
throw makeException("Unknown function " + identifier); throw makeException("Unknown function " + identifier);
} }
@ -272,7 +198,7 @@ public class Parser {
List<Evaluable> args = parseExpressionList("]"); List<Evaluable> args = parseExpressionList("]");
args.add(0, eval); args.add(0, eval);
eval = new FunctionCallExpr(makeArray(args), functionTable.get("get")); eval = new FunctionCallExpr(makeArray(args), ControlFunctionRegistry.getFunction("get"));
} else { } else {
break; break;
} }
@ -281,7 +207,7 @@ public class Parser {
return eval; return eval;
} }
protected List<Evaluable> parseExpressionList(String closingDelimiter) throws Exception { protected List<Evaluable> parseExpressionList(String closingDelimiter) throws ParserException {
List<Evaluable> l = new LinkedList<Evaluable>(); List<Evaluable> l = new LinkedList<Evaluable>();
if (_token != null && if (_token != null &&

View File

@ -10,7 +10,11 @@ public class VariableExpr implements Evaluable {
} }
public Object evaluate(Properties bindings) { public Object evaluate(Properties bindings) {
if (bindings.containsKey(_name)) {
return bindings.get(_name); return bindings.get(_name);
} else {
return new EvalError("No variable named " + _name);
}
} }
public String toString() { public String toString() {

View File

@ -8,37 +8,43 @@ import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.Control; import com.metaweb.gridworks.expr.Control;
import com.metaweb.gridworks.expr.EvalError;
import com.metaweb.gridworks.expr.Evaluable; import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.expr.VariableExpr; import com.metaweb.gridworks.expr.VariableExpr;
public class ForEach implements Control { public class ForEach implements Control {
public String checkArguments(Evaluable[] args) {
if (args.length != 3) {
return "forEach expects 3 arguments";
} else if (!(args[1] instanceof VariableExpr)) {
return "forEach expects second argument to be a variable name";
}
return null;
}
public Object call(Properties bindings, Evaluable[] args) { public Object call(Properties bindings, Evaluable[] args) {
if (args.length >= 3) {
Object o = args[0].evaluate(bindings); Object o = args[0].evaluate(bindings);
Evaluable var = args[1]; if (ExpressionUtils.isError(o)) {
String name = (var instanceof VariableExpr) ? ((VariableExpr) var).getName() : return o;
((String) var.evaluate(bindings)); } else if (o == null || !o.getClass().isArray()) {
return new EvalError("First argument to forEach is not an array");
}
String name = ((VariableExpr) args[1]).getName();
if (o != null) {
Object oldValue = bindings.get(name); Object oldValue = bindings.get(name);
try { try {
Object[] values; Object[] values = (Object[]) o;
if (o.getClass().isArray()) {
values = (Object[]) o;
} else {
values = new Object[] { o };
}
List<Object> results = new ArrayList<Object>(values.length); List<Object> results = new ArrayList<Object>(values.length);
for (Object v : values) { for (Object v : values) {
bindings.put(name, v); bindings.put(name, v);
Object r = args[2].evaluate(bindings); Object r = args[2].evaluate(bindings);
if (r != null) {
results.add(r); results.add(r);
} }
}
return results.toArray(); return results.toArray();
} finally { } finally {
@ -49,9 +55,6 @@ public class ForEach implements Control {
} }
} }
} }
}
return null;
}
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)
throws JSONException { throws JSONException {

View File

@ -11,15 +11,22 @@ import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.expr.VariableExpr; import com.metaweb.gridworks.expr.VariableExpr;
public class ForNonBlank implements Control { public class ForNonBlank implements Control {
public String checkArguments(Evaluable[] args) {
if (args.length != 4) {
return "forNonBlank expects 4 arguments";
} else if (!(args[1] instanceof VariableExpr)) {
return "forNonBlank expects second argument to be a variable name";
}
return null;
}
public Object call(Properties bindings, Evaluable[] args) { public Object call(Properties bindings, Evaluable[] args) {
if (args.length >= 3) {
Object o = args[0].evaluate(bindings); Object o = args[0].evaluate(bindings);
Evaluable var = args[1];
String name = (var instanceof VariableExpr) ? ((VariableExpr) var).getName() :
((String) var.evaluate(bindings));
if (!ExpressionUtils.isBlank(o)) { Evaluable var = args[1];
String name = ((VariableExpr) var).getName();
if (ExpressionUtils.isNonBlankData(o)) {
Object oldValue = bindings.containsKey(name) ? bindings.get(name) : null; Object oldValue = bindings.containsKey(name) ? bindings.get(name) : null;
bindings.put(name, o); bindings.put(name, o);
@ -32,12 +39,10 @@ public class ForNonBlank implements Control {
bindings.remove(name); bindings.remove(name);
} }
} }
} else if (args.length >= 4) { } else {
return args[3].evaluate(bindings); return args[3].evaluate(bindings);
} }
} }
return null;
}
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)
throws JSONException { throws JSONException {

View File

@ -1,6 +1,6 @@
package com.metaweb.gridworks.expr.controls; package com.metaweb.gridworks.expr.controls;
import java.util.Properties; import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
@ -10,20 +10,24 @@ import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.ExpressionUtils; import com.metaweb.gridworks.expr.ExpressionUtils;
public class If implements Control { public class If implements Control {
public String checkArguments(Evaluable[] args) {
public Object call(Properties bindings, Evaluable[] args) { if (args.length != 3) {
if (args.length >= 3) { return "if expects 3 arguments";
Object o = args[0].evaluate(bindings);
if (ExpressionUtils.isTrue(o)) {
return args[1].evaluate(bindings);
} else if (args.length >= 3) {
return args[2].evaluate(bindings);
}
} }
return null; return null;
} }
public Object call(Properties bindings, Evaluable[] args) {
Object o = args[0].evaluate(bindings);
if (ExpressionUtils.isError(o)) {
return o;
} else if (ExpressionUtils.isTrue(o)) {
return args[1].evaluate(bindings);
} else {
return args[2].evaluate(bindings);
}
}
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)
throws JSONException { throws JSONException {

View File

@ -7,21 +7,34 @@ import org.json.JSONWriter;
import com.metaweb.gridworks.expr.Control; import com.metaweb.gridworks.expr.Control;
import com.metaweb.gridworks.expr.Evaluable; import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.expr.VariableExpr; import com.metaweb.gridworks.expr.VariableExpr;
public class With implements Control { public class With implements Control {
public String checkArguments(Evaluable[] args) {
if (args.length != 3) {
return "with expects 3 arguments";
} else if (!(args[1] instanceof VariableExpr)) {
return "with expects second argument to be a variable name";
}
return null;
}
public Object call(Properties bindings, Evaluable[] args) { public Object call(Properties bindings, Evaluable[] args) {
if (args.length >= 3) {
Object o = args[0].evaluate(bindings); Object o = args[0].evaluate(bindings);
Evaluable var = args[1]; if (ExpressionUtils.isError(o)) {
String name = (var instanceof VariableExpr) ? ((VariableExpr) var).getName() : return o;
((String) var.evaluate(bindings)); }
String name = ((VariableExpr) args[1]).getName();
if (o != null) {
Object oldValue = bindings.get(name); Object oldValue = bindings.get(name);
try { try {
if (o != null) {
bindings.put(name, o); bindings.put(name, o);
} else {
bindings.remove(name);
}
return args[2].evaluate(bindings); return args[2].evaluate(bindings);
} finally { } finally {
@ -32,9 +45,6 @@ public class With implements Control {
} }
} }
} }
}
return null;
}
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)
throws JSONException { throws JSONException {

View File

@ -5,15 +5,17 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Ceil implements Function { public class Ceil implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
if (args.length == 1 && args[0] instanceof Number) { if (args.length == 1 && args[0] != null && args[0] instanceof Number) {
return (long) Math.ceil(((Number) args[0]).doubleValue()); return (long) Math.ceil(((Number) args[0]).doubleValue());
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a number");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class EndsWith implements Function { public class EndsWith implements Function {
@ -17,7 +19,7 @@ public class EndsWith implements Function {
return ((String) s1).endsWith((String) s2); return ((String) s1).endsWith((String) s2);
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 strings");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,15 +5,17 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Floor implements Function { public class Floor implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
if (args.length == 1 && args[0] instanceof Number) { if (args.length == 1 && args[0] != null && args[0] instanceof Number) {
return (long) Math.floor(((Number) args[0]).doubleValue()); return (long) Math.floor(((Number) args[0]).doubleValue());
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a number");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class IndexOf implements Function { public class IndexOf implements Function {
@ -17,7 +19,7 @@ public class IndexOf implements Function {
return ((String) s1).indexOf((String) s2); return ((String) s1).indexOf((String) s2);
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 strings");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -11,7 +11,7 @@ import com.metaweb.gridworks.expr.Function;
public class IsBlank implements Function { public class IsBlank implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
return args.length == 0 || ExpressionUtils.isBlank(args[0]); return args.length == 0 || !ExpressionUtils.isNonBlankData(args[0]);
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -11,14 +11,14 @@ import com.metaweb.gridworks.expr.Function;
public class IsNotBlank implements Function { public class IsNotBlank implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
return args.length > 0 && !ExpressionUtils.isBlank(args[0]); return args.length > 0 && ExpressionUtils.isNonBlankData(args[0]);
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)
throws JSONException { throws JSONException {
writer.object(); writer.object();
writer.key("description"); writer.value("Returns whether o is not null and not an empty string"); 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("params"); writer.value("o");
writer.key("returns"); writer.value("boolean"); writer.key("returns"); writer.value("boolean");
writer.endObject(); writer.endObject();

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Join implements Function { public class Join implements Function {
@ -33,7 +35,7 @@ public class Join implements Function {
return sb.toString(); return sb.toString();
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects an array and a string");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class LastIndexOf implements Function { public class LastIndexOf implements Function {
@ -17,7 +19,7 @@ public class LastIndexOf implements Function {
return ((String) s1).lastIndexOf((String) s2); return ((String) s1).lastIndexOf((String) s2);
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 strings");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Length implements Function { public class Length implements Function {
@ -23,7 +25,7 @@ public class Length implements Function {
} }
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects an array or a string");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,15 +5,17 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Ln implements Function { public class Ln implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
if (args.length == 1 && args[0] instanceof Number) { if (args.length == 1 && args[0] != null && args[0] instanceof Number) {
return Math.log(((Number) args[0]).doubleValue()); return Math.log(((Number) args[0]).doubleValue());
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a number");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,15 +5,17 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Log implements Function { public class Log implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
if (args.length == 1 && args[0] instanceof Number) { if (args.length == 1 && args[0] != null && args[0] instanceof Number) {
return Math.log10(((Number) args[0]).doubleValue()); return Math.log10(((Number) args[0]).doubleValue());
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a number");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,17 +5,21 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Max implements Function { public class Max implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
if (args.length == 2 && args[0] instanceof Number && args[1] instanceof Number) { if (args.length == 2 &&
args[0] != null && args[0] instanceof Number &&
args[1] != null && args[1] instanceof Number) {
return Math.max( return Math.max(
((Number) args[0]).doubleValue(), ((Number) args[0]).doubleValue(),
((Number) args[1]).doubleValue()); ((Number) args[1]).doubleValue());
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 numbers");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,17 +5,21 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Min implements Function { public class Min implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
if (args.length == 2 && args[0] instanceof Number && args[1] instanceof Number) { if (args.length == 2 &&
args[0] != null && args[0] instanceof Number &&
args[1] != null && args[1] instanceof Number) {
return Math.min( return Math.min(
((Number) args[0]).doubleValue(), ((Number) args[0]).doubleValue(),
((Number) args[1]).doubleValue()); ((Number) args[1]).doubleValue());
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 numbers");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,18 +5,22 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Mod implements Function { public class Mod implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
if (args.length == 2 && args[0] instanceof Number && args[1] instanceof Number) { if (args.length == 2 &&
args[0] != null && args[0] instanceof Number &&
args[1] != null && args[1] instanceof Number) {
int a = ((Number) args[0]).intValue(); int a = ((Number) args[0]).intValue();
int b = ((Number) args[0]).intValue(); int b = ((Number) args[0]).intValue();
return a % b; return a % b;
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 numbers");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,15 +5,17 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Not implements Function { public class Not implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
if (args.length > 0) { if (args.length == 1) {
return !objectToBoolean(args[0]); return !objectToBoolean(args[0]);
} }
return true; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a boolean");
} }
public static boolean objectToBoolean(Object o) { public static boolean objectToBoolean(Object o) {

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Replace implements Function { public class Replace implements Function {
@ -19,7 +21,7 @@ public class Replace implements Function {
return (v instanceof String ? (String) v : v.toString()).replace((String) find, (String) replace); return (v instanceof String ? (String) v : v.toString()).replace((String) find, (String) replace);
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 3 strings");
} }

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Reverse implements Function { public class Reverse implements Function {
@ -24,7 +26,7 @@ public class Reverse implements Function {
return r; return r;
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects an array");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,15 +5,17 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Round implements Function { public class Round implements Function {
public Object call(Properties bindings, Object[] args) { public Object call(Properties bindings, Object[] args) {
if (args.length == 1 && args[0] instanceof Number) { if (args.length == 1 && args[0] != null && args[0] instanceof Number) {
return ((Number) args[0]).longValue(); return ((Number) args[0]).longValue();
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a number");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -6,7 +6,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Sort implements Function { public class Sort implements Function {
@ -24,7 +26,7 @@ public class Sort implements Function {
return r; return r;
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects an array");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class Split implements Function { public class Split implements Function {
@ -17,7 +19,7 @@ public class Split implements Function {
return (v instanceof String ? (String) v : v.toString()).split((String) split); return (v instanceof String ? (String) v : v.toString()).split((String) split);
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 strings");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class StartsWith implements Function { public class StartsWith implements Function {
@ -17,7 +19,7 @@ public class StartsWith implements Function {
return ((String) s1).startsWith((String) s2); return ((String) s1).startsWith((String) s2);
} }
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 strings");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)
throws JSONException { throws JSONException {

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class ToLowercase implements Function { public class ToLowercase implements Function {
@ -14,7 +16,7 @@ public class ToLowercase implements Function {
Object o = args[0]; Object o = args[0];
return (o instanceof String ? (String) o : o.toString()).toLowerCase(); return (o instanceof String ? (String) o : o.toString()).toLowerCase();
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a string");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class ToTitlecase implements Function { public class ToTitlecase implements Function {
@ -28,7 +30,7 @@ public class ToTitlecase implements Function {
return sb.toString(); return sb.toString();
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a string");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -5,7 +5,9 @@ import java.util.Properties;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.metaweb.gridworks.expr.ControlFunctionRegistry;
import com.metaweb.gridworks.expr.Function; import com.metaweb.gridworks.expr.Function;
import com.metaweb.gridworks.expr.EvalError;
public class ToUppercase implements Function { public class ToUppercase implements Function {
@ -14,7 +16,7 @@ public class ToUppercase implements Function {
Object o = args[0]; Object o = args[0];
return (o instanceof String ? (String) o : o.toString()).toUpperCase(); return (o instanceof String ? (String) o : o.toString()).toUpperCase();
} }
return null; return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a string");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -53,11 +53,11 @@ public class ImporterUtilities {
} }
Object value = parseCellValue(text); Object value = parseCellValue(text);
if (ExpressionUtils.isBlank(value)) { if (ExpressionUtils.isNonBlankData(value)) {
row.cells.add(null);
} else {
row.cells.add(new Cell(value, null)); row.cells.add(new Cell(value, null));
hasData = true; hasData = true;
} else {
row.cells.add(null);
} }
} }
@ -72,11 +72,11 @@ public class ImporterUtilities {
String text = cells[c]; String text = cells[c];
Object value = parseCellValue(text); Object value = parseCellValue(text);
if (ExpressionUtils.isBlank(value)) { if (ExpressionUtils.isNonBlankData(value)) {
row.cells.add(null);
} else {
row.cells.add(new Cell(value, null)); row.cells.add(new Cell(value, null));
hasData = true; hasData = true;
} else {
row.cells.add(null);
} }
} }
return hasData; return hasData;

View File

@ -92,11 +92,11 @@ public class Project implements Serializable {
for (int g = 0; g < keyedGroups.size(); g++) { for (int g = 0; g < keyedGroups.size(); g++) {
Group group = keyedGroups.get(g); Group group = keyedGroups.get(g);
if (ExpressionUtils.isBlank(row.getCellValue(group.keyCellIndex))) { if (!ExpressionUtils.isNonBlankData(row.getCellValue(group.keyCellIndex))) {
int contextRowIndex = lastNonBlankRowsByGroup[g]; int contextRowIndex = lastNonBlankRowsByGroup[g];
if (contextRowIndex >= 0) { if (contextRowIndex >= 0) {
for (int dependentCellIndex : group.cellIndices) { for (int dependentCellIndex : group.cellIndices) {
if (!ExpressionUtils.isBlank(row.getCellValue(dependentCellIndex))) { if (ExpressionUtils.isNonBlankData(row.getCellValue(dependentCellIndex))) {
setRowDependency( setRowDependency(
row, row,
dependentCellIndex, dependentCellIndex,

View File

@ -40,7 +40,7 @@ public class ReconStats implements Serializable, Jsonizable {
for (Row row : project.rows) { for (Row row : project.rows) {
Cell cell = row.getCell(cellIndex); Cell cell = row.getCell(cellIndex);
if (cell != null && !ExpressionUtils.isBlank(cell.value)) { if (cell != null && ExpressionUtils.isNonBlankData(cell.value)) {
nonBlanks++; nonBlanks++;
if (cell.recon != null) { if (cell.recon != null) {

View File

@ -95,7 +95,7 @@ public class MultiValuedCellJoinOperation extends AbstractOperation {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
for (int r3 = r; r3 < r2; r3++) { for (int r3 = r; r3 < r2; r3++) {
Object value = project.rows.get(r3).getCellValue(cellIndex); Object value = project.rows.get(r3).getCellValue(cellIndex);
if (!ExpressionUtils.isBlank(value)) { if (ExpressionUtils.isNonBlankData(value)) {
if (sb.length() > 0) { if (sb.length() > 0) {
sb.append(_separator); sb.append(_separator);
} }

View File

@ -164,7 +164,7 @@ public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOper
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) { public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
Cell cell = row.getCell(_cellIndex); Cell cell = row.getCell(_cellIndex);
if (cell != null && if (cell != null &&
!ExpressionUtils.isBlank(cell.value) && ExpressionUtils.isNonBlankData(cell.value) &&
_similarValue.equals(cell.value)) { _similarValue.equals(cell.value)) {
Recon recon = null; Recon recon = null;

View File

@ -152,7 +152,7 @@ public class ReconOperation extends EngineDependentOperation {
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) { public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
if (_cellIndex < row.cells.size()) { if (_cellIndex < row.cells.size()) {
Cell cell = row.cells.get(_cellIndex); Cell cell = row.cells.get(_cellIndex);
if (cell != null && !ExpressionUtils.isBlank(cell.value)) { if (cell != null && ExpressionUtils.isNonBlankData(cell.value)) {
_entries.add(new ReconEntry(rowIndex, cell)); _entries.add(new ReconEntry(rowIndex, cell));
} }
} }

View File

@ -54,7 +54,7 @@ public class Transposer {
CellNode node2 = (CellNode) node; CellNode node2 = (CellNode) node;
Column column = project.columnModel.getColumnByName(node2.columnName); Column column = project.columnModel.getColumnByName(node2.columnName);
Cell cell = row.getCell(column.getCellIndex()); Cell cell = row.getCell(column.getCellIndex());
if (cell != null && !ExpressionUtils.isBlank(cell.value)) { if (cell != null && ExpressionUtils.isNonBlankData(cell.value)) {
if (node2 instanceof CellTopicNode) { if (node2 instanceof CellTopicNode) {
if (!((CellTopicNode) node2).createForNoReconMatch && if (!((CellTopicNode) node2).createForNoReconMatch &&
(cell.recon == null || cell.recon.judgment == Judgment.None)) { (cell.recon == null || cell.recon.judgment == Judgment.None)) {

View File

@ -170,13 +170,13 @@ ExpressionPreviewDialog.prototype._update = function() {
} else { } else {
self._results = null; self._results = null;
} }
self._renderPreview(expression); self._renderPreview(expression, data);
}, },
"json" "json"
); );
}; };
ExpressionPreviewDialog.prototype._renderPreview = function(expression) { ExpressionPreviewDialog.prototype._renderPreview = function(expression, data) {
var container = this._elmts.previewContainer.empty(); var container = this._elmts.previewContainer.empty();
var table = $('<table width="100%"></table>').appendTo(container)[0]; var table = $('<table width="100%"></table>').appendTo(container)[0];
@ -211,7 +211,10 @@ ExpressionPreviewDialog.prototype._renderPreview = function(expression) {
var v = this._results[i]; var v = this._results[i];
renderValue(tdValue, v); renderValue(tdValue, v);
} else { } else {
$('<span>error</span>').addClass("expression-preview-empty").appendTo(tdValue); // error
var message = (data.type == "parser") ? data.message : "internal error";
$('<span></span>').text(message).addClass("expression-preview-empty").appendTo(tdValue);
} }
} }
}; };

View File

@ -82,11 +82,11 @@
<td><div> <td><div>
<h2>Mac OSX</h2> <h2>Mac OSX</h2>
<center> <center>
<a class="download-link" href="gridworks-1.0.dmg"><table class="download-card"> <a class="download-link" href="gridworks-1.0a.dmg"><table class="download-card">
<tr> <tr>
<td width="1%"><img src="gridworks.png" /></td> <td width="1%"><img src="gridworks.png" /></td>
<td> <td>
<h3>Gridworks-1.0.dmg</h3> <h3>Gridworks-1.0a.dmg</h3>
<div class="instructions">Download, open, then drag<br/>icon to Applications folder</div> <div class="instructions">Download, open, then drag<br/>icon to Applications folder</div>
</td> </td>
</tr> </tr>
@ -96,11 +96,11 @@
<td><div> <td><div>
<h2>Windows</h2> <h2>Windows</h2>
<center> <center>
<a class="download-link" href="gridworks-1.0.zip"><table class="download-card"> <a class="download-link" href="gridworks-1.0a.zip"><table class="download-card">
<tr> <tr>
<td width="1%"><img src="gridworks.png" /></td> <td width="1%"><img src="gridworks.png" /></td>
<td> <td>
<h3>Gridworks-1.0.zip</h3> <h3>Gridworks-1.0a.zip</h3>
<div class="instructions">Download, unzip, and<br/>run .exe inside</div> <div class="instructions">Download, unzip, and<br/>run .exe inside</div>
</td> </td>
</tr> </tr>