Documented expr.* packages.

Converted some tabs into spaces.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@332 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-03-22 00:54:56 +00:00
parent 60f60507f7
commit 60dd7eab82
14 changed files with 174 additions and 140 deletions

View File

@ -8,6 +8,12 @@ import org.json.JSONWriter;
import com.metaweb.gridworks.Jsonizable; import com.metaweb.gridworks.Jsonizable;
/**
* An error that occurs during the evaluation of an Evaluable. Errors are values, too
* because they can be stored in cells just like strings, numbers, etc. Errors are not
* thrown because an error might occupy just one element in an array and doesn't need
* to make the whole array erroneous.
*/
public class EvalError implements Serializable, Jsonizable { public class EvalError implements Serializable, Jsonizable {
private static final long serialVersionUID = -102681220092874080L; private static final long serialVersionUID = -102681220092874080L;

View File

@ -2,6 +2,15 @@ package com.metaweb.gridworks.expr;
import java.util.Properties; import java.util.Properties;
/**
* Interface for evaluable expressions in any arbitrary language.
*/
public interface Evaluable { public interface Evaluable {
/**
* Evaluate this expression in the given environment (bindings).
*
* @param bindings
* @return
*/
public Object evaluate(Properties bindings); public Object evaluate(Properties bindings);
} }

View File

@ -64,13 +64,15 @@ public class ExpressionUtils {
} }
static public boolean sameValue(Object v1, Object v2) { static public boolean sameValue(Object v1, Object v2) {
if (v1 == null) { if (v1 == null) {
return (v2 == null) || (v2 instanceof String && ((String) v2).length() == 0); return (v2 == null)
} else if (v2 == null) { || (v2 instanceof String && ((String) v2).length() == 0);
return (v1 == null) || (v1 instanceof String && ((String) v1).length() == 0); } else if (v2 == null) {
} else { return (v1 == null)
return v1.equals(v2); || (v1 instanceof String && ((String) v1).length() == 0);
} } else {
return v1.equals(v2);
}
} }
static public boolean isStorable(Object v) { static public boolean isStorable(Object v) {
@ -90,12 +92,12 @@ public class ExpressionUtils {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static public List<Object> toObjectList(Object v) { static public List<Object> toObjectList(Object v) {
return (List<Object>) v; return (List<Object>) v;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static public Collection<Object> toObjectCollection(Object v) { static public Collection<Object> toObjectCollection(Object v) {
return (Collection<Object>) v; return (Collection<Object>) v;
} }
} }

View File

@ -2,6 +2,10 @@ package com.metaweb.gridworks.expr;
import java.util.Properties; import java.util.Properties;
/**
* Interface for objects that have named fields, which can be retrieved using the
* dot notation or the bracket notation, e.g., cells.Country, cells["Type of Disaster"].
*/
public interface HasFields { public interface HasFields {
public Object getField(String name, Properties bindings); public Object getField(String name, Properties bindings);
} }

View File

@ -19,22 +19,22 @@ public class JythonEvaluable implements Evaluable {
private static PythonInterpreter _engine = new PythonInterpreter(); private static PythonInterpreter _engine = new PythonInterpreter();
public JythonEvaluable(String s) { public JythonEvaluable(String s) {
// indent and create a function out of the code // indent and create a function out of the code
String[] lines = s.split("\r\n|\r|\n"); String[] lines = s.split("\r\n|\r|\n");
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append("def " + s_functionName + "(value, cell, cells, row, rowIndex):"); sb.append("def " + s_functionName + "(value, cell, cells, row, rowIndex):");
for (int i = 0; i < lines.length; i++) { for (int i = 0; i < lines.length; i++) {
sb.append("\n " + lines[i]); sb.append("\n " + lines[i]);
} }
_engine.exec(sb.toString()); _engine.exec(sb.toString());
} }
public Object evaluate(Properties bindings) { public Object evaluate(Properties bindings) {
try { try {
// call the temporary PyFunction directly // call the temporary PyFunction directly
Object result = ((PyFunction)_engine.get(s_functionName)).__call__( Object result = ((PyFunction)_engine.get(s_functionName)).__call__(
new PyObject[] { new PyObject[] {
Py.java2py( bindings.get("value") ), Py.java2py( bindings.get("value") ),
new JythonHasFieldsWrapper((HasFields) bindings.get("cell"), bindings), new JythonHasFieldsWrapper((HasFields) bindings.get("cell"), bindings),
@ -42,15 +42,15 @@ public class JythonEvaluable implements Evaluable {
new JythonHasFieldsWrapper((HasFields) bindings.get("row"), bindings), new JythonHasFieldsWrapper((HasFields) bindings.get("row"), bindings),
Py.java2py( bindings.get("rowIndex") ) Py.java2py( bindings.get("rowIndex") )
} }
); );
return unwrap(result); return unwrap(result);
} catch (PyException e) { } catch (PyException e) {
return new EvalError(e.toString()); return new EvalError(e.toString());
} }
} }
protected Object unwrap(Object result) { protected Object unwrap(Object result) {
if (result != null) { if (result != null) {
if (result instanceof JythonObjectWrapper) { if (result instanceof JythonObjectWrapper) {
return ((JythonObjectWrapper) result)._obj; return ((JythonObjectWrapper) result)._obj;
@ -64,12 +64,12 @@ public class JythonEvaluable implements Evaluable {
} }
return result; return result;
} }
protected Object unwrap(PyObject po) { protected Object unwrap(PyObject po) {
if (po instanceof PyNone) { if (po instanceof PyNone) {
return null; return null;
} else if (po.isNumberType()) { } else if (po.isNumberType()) {
return po.asDouble(); return po.asDouble();
} else if (po.isSequenceType()) { } else if (po.isSequenceType()) {
Iterator<PyObject> i = po.asIterable().iterator(); Iterator<PyObject> i = po.asIterable().iterator();
@ -83,5 +83,5 @@ public class JythonEvaluable implements Evaluable {
} else { } else {
return po; return po;
} }
} }
} }

View File

@ -5,34 +5,34 @@ import java.util.Properties;
import org.python.core.PyObject; import org.python.core.PyObject;
import org.python.core.PyString; import org.python.core.PyString;
public class JythonHasFieldsWrapper extends PyObject { public class JythonHasFieldsWrapper extends PyObject {
private static final long serialVersionUID = -1275353513262385099L; private static final long serialVersionUID = -1275353513262385099L;
public HasFields _obj; public HasFields _obj;
private Properties _bindings;
public JythonHasFieldsWrapper(HasFields obj, Properties bindings) { private Properties _bindings;
_obj = obj;
_bindings = bindings;
}
public PyObject __finditem__(PyObject key) { public JythonHasFieldsWrapper(HasFields obj, Properties bindings) {
String k = (String) key.__tojava__(String.class); _obj = obj;
Object v = _obj.getField(k, _bindings); _bindings = bindings;
if (v != null) { }
if (v instanceof HasFields) {
return new JythonHasFieldsWrapper((HasFields) v, _bindings); public PyObject __finditem__(PyObject key) {
} else if (v instanceof String) { String k = (String) key.__tojava__(String.class);
return new PyString((String) v); Object v = _obj.getField(k, _bindings);
} else if (v instanceof PyObject) { if (v != null) {
return (PyObject) v; if (v instanceof HasFields) {
} else { return new JythonHasFieldsWrapper((HasFields) v, _bindings);
return new JythonObjectWrapper(v); } else if (v instanceof String) {
} return new PyString((String) v);
} else { } else if (v instanceof PyObject) {
return null; return (PyObject) v;
} } else {
} return new JythonObjectWrapper(v);
}
} else {
return null;
}
}
} }

View File

@ -5,13 +5,13 @@ import org.python.core.PyObject;
public class JythonObjectWrapper extends PyObject { public class JythonObjectWrapper extends PyObject {
private static final long serialVersionUID = -6608115027151667441L; private static final long serialVersionUID = -6608115027151667441L;
public Object _obj; public Object _obj;
public JythonObjectWrapper(Object obj) { public JythonObjectWrapper(Object obj) {
_obj = obj; _obj = obj;
} }
public String toString() { public String toString() {
return _obj.getClass().getSimpleName(); return _obj.getClass().getSimpleName();
} }
} }

View File

@ -8,6 +8,15 @@ import clojure.lang.IFn;
import com.metaweb.gridworks.gel.Parser; import com.metaweb.gridworks.gel.Parser;
abstract public class MetaParser { abstract public class MetaParser {
/**
* Parse an expression that might have a language prefix into an Evaluable.
* Expressions without valid prefixes or without any prefix are assumed to be
* GEL expressions.
*
* @param s
* @return
* @throws ParsingException
*/
static public Evaluable parse(String s) throws ParsingException { static public Evaluable parse(String s) throws ParsingException {
String language = "gel"; String language = "gel";

View File

@ -26,9 +26,9 @@ public class Get implements Function {
} else { } else {
if (from instanceof Number && (to == null || to instanceof Number)) { if (from instanceof Number && (to == null || to instanceof Number)) {
if (v.getClass().isArray() || v instanceof List<?>) { if (v.getClass().isArray() || v instanceof List<?>) {
int length = v.getClass().isArray() ? int length = v.getClass().isArray() ?
((Object[]) v).length : ((Object[]) v).length :
ExpressionUtils.toObjectList(v).size(); ExpressionUtils.toObjectList(v).size();
int start = ((Number) from).intValue(); int start = ((Number) from).intValue();
if (start < 0) { if (start < 0) {
@ -38,9 +38,9 @@ public class Get implements Function {
if (to == null) { if (to == null) {
return start >= length ? null : return start >= length ? null :
(v.getClass().isArray() ? (v.getClass().isArray() ?
((Object[]) v)[start] : ((Object[]) v)[start] :
ExpressionUtils.toObjectList(v).get(start)); ExpressionUtils.toObjectList(v).get(start));
} else { } else {
int end = to != null && to instanceof Number ? int end = to != null && to instanceof Number ?
((Number) to).intValue() : length; ((Number) to).intValue() : length;
@ -51,15 +51,15 @@ public class Get implements Function {
end = Math.min(length, Math.max(start, end)); end = Math.min(length, Math.max(start, end));
if (end > start) { if (end > start) {
if (v.getClass().isArray()) { if (v.getClass().isArray()) {
Object[] a2 = new Object[end - start]; Object[] a2 = new Object[end - start];
System.arraycopy((Object[]) v, start, a2, 0, end - start); System.arraycopy((Object[]) v, start, a2, 0, end - start);
return a2; return a2;
} else { } else {
return ExpressionUtils.toObjectList(v).subList(start, end); return ExpressionUtils.toObjectList(v).subList(start, end);
} }
} }
} }
} else { } else {

View File

@ -19,9 +19,9 @@ public class Slice implements Function {
if (v != null && from != null && from instanceof Number && (to == null || to instanceof Number)) { if (v != null && from != null && from instanceof Number && (to == null || to instanceof Number)) {
if (v.getClass().isArray() || v instanceof List<?>) { if (v.getClass().isArray() || v instanceof List<?>) {
int length = v.getClass().isArray() ? int length = v.getClass().isArray() ?
((Object[]) v).length : ((Object[]) v).length :
ExpressionUtils.toObjectList(v).size(); ExpressionUtils.toObjectList(v).size();
int start = ((Number) from).intValue(); int start = ((Number) from).intValue();
int end = to != null && to instanceof Number ? int end = to != null && to instanceof Number ?
@ -37,15 +37,15 @@ public class Slice implements Function {
} }
end = Math.min(length, Math.max(start, end)); end = Math.min(length, Math.max(start, end));
if (v.getClass().isArray()) { if (v.getClass().isArray()) {
Object[] a2 = new Object[end - start]; Object[] a2 = new Object[end - start];
System.arraycopy((Object[]) v, start, a2, 0, end - start); System.arraycopy((Object[]) v, start, a2, 0, end - start);
return a2; return a2;
} else { } else {
return ExpressionUtils.toObjectList(v).subList(start, end); return ExpressionUtils.toObjectList(v).subList(start, end);
} }
} else { } else {
String s = (v instanceof String ? (String) v : v.toString()); String s = (v instanceof String ? (String) v : v.toString());

View File

@ -1,6 +1,7 @@
package com.metaweb.gridworks.expr.functions; package com.metaweb.gridworks.expr.functions;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
@ -20,18 +21,21 @@ public class Type implements Function {
if (v != null) { if (v != null) {
if (v instanceof String) { if (v instanceof String) {
return "string"; return "string";
} else if (v instanceof Calendar) { } else if (v instanceof Calendar || v instanceof Date) {
return "date"; return "date";
} else if (v instanceof Number) { } else if (v instanceof Number) {
return "number"; return "number";
} else if (v.getClass().isArray() || v instanceof List<?>) { } else if (v.getClass().isArray() || v instanceof List<?>) {
return "array"; return "array";
} else if (v instanceof EvalError) {
return "error";
} else { } else {
return v.getClass().getName(); return v.getClass().getName();
} }
} }
return "undefined";
} }
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a parameter"); return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects one argument");
} }
public void write(JSONWriter writer, Properties options) public void write(JSONWriter writer, Properties options)

View File

@ -18,21 +18,21 @@ public class Reverse implements Function {
Object v = args[0]; Object v = args[0];
if (v != null && (v.getClass().isArray() || v instanceof List<?>)) { if (v != null && (v.getClass().isArray() || v instanceof List<?>)) {
int length = v.getClass().isArray() ? int length = v.getClass().isArray() ?
((Object[]) v).length : ((Object[]) v).length :
ExpressionUtils.toObjectList(v).size(); ExpressionUtils.toObjectList(v).size();
Object[] r = new Object[length]; Object[] r = new Object[length];
if (v.getClass().isArray()) { if (v.getClass().isArray()) {
Object[] a = (Object[]) v; Object[] a = (Object[]) v;
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
r[i] = a[r.length - i - 1]; r[i] = a[r.length - i - 1];
} }
} else { } else {
List<Object> a = ExpressionUtils.toObjectList(v); List<Object> a = ExpressionUtils.toObjectList(v);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
r[i] = a.get(r.length - i - 1); r[i] = a.get(r.length - i - 1);
} }
} }
return r; return r;
} }

View File

@ -20,19 +20,19 @@ public class Sort implements Function {
Object v = args[0]; Object v = args[0];
if (v != null) { if (v != null) {
if (v.getClass().isArray()) { if (v.getClass().isArray()) {
Object[] a = (Object[]) v; Object[] a = (Object[]) v;
Object[] r = a.clone(); Object[] r = a.clone();
Arrays.sort(r, 0, r.length); Arrays.sort(r, 0, r.length);
return r; return r;
} else if (v instanceof List<?>) { } else if (v instanceof List<?>) {
List<? extends Comparable> a = (List<? extends Comparable>) v; List<? extends Comparable> a = (List<? extends Comparable>) v;
Collections.sort(a); Collections.sort(a);
return a; return a;
} }
} }
} }
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects an array"); return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects an array");

View File

@ -18,28 +18,28 @@ public class Sum implements Function {
Object v = args[0]; Object v = args[0];
if (v != null && (v.getClass().isArray() || v instanceof List<?>)) { if (v != null && (v.getClass().isArray() || v instanceof List<?>)) {
int length = v.getClass().isArray() ? int length = v.getClass().isArray() ?
((Object[]) v).length : ((Object[]) v).length :
ExpressionUtils.toObjectList(v).size(); ExpressionUtils.toObjectList(v).size();
double total = 0; double total = 0;
if (v.getClass().isArray()) { if (v.getClass().isArray()) {
Object[] a = (Object[]) v; Object[] a = (Object[]) v;
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
Object n = a[length - i - 1]; Object n = a[length - i - 1];
if (n instanceof Number) { if (n instanceof Number) {
total += ((Number) n).doubleValue(); total += ((Number) n).doubleValue();
} }
} }
} else { } else {
List<Object> a = ExpressionUtils.toObjectList(v); List<Object> a = ExpressionUtils.toObjectList(v);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
Object n = a.get(length - i - 1); Object n = a.get(length - i - 1);
if (n instanceof Number) { if (n instanceof Number) {
total += ((Number) n).doubleValue(); total += ((Number) n).doubleValue();
} }
} }
} }
return total; return total;
} }