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:
parent
60f60507f7
commit
60dd7eab82
@ -8,6 +8,12 @@ import org.json.JSONWriter;
|
||||
|
||||
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 {
|
||||
private static final long serialVersionUID = -102681220092874080L;
|
||||
|
||||
|
@ -2,6 +2,15 @@ package com.metaweb.gridworks.expr;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Interface for evaluable expressions in any arbitrary language.
|
||||
*/
|
||||
public interface Evaluable {
|
||||
/**
|
||||
* Evaluate this expression in the given environment (bindings).
|
||||
*
|
||||
* @param bindings
|
||||
* @return
|
||||
*/
|
||||
public Object evaluate(Properties bindings);
|
||||
}
|
||||
|
@ -64,13 +64,15 @@ public class ExpressionUtils {
|
||||
}
|
||||
|
||||
static public boolean sameValue(Object v1, Object v2) {
|
||||
if (v1 == null) {
|
||||
return (v2 == null) || (v2 instanceof String && ((String) v2).length() == 0);
|
||||
} else if (v2 == null) {
|
||||
return (v1 == null) || (v1 instanceof String && ((String) v1).length() == 0);
|
||||
} else {
|
||||
return v1.equals(v2);
|
||||
}
|
||||
if (v1 == null) {
|
||||
return (v2 == null)
|
||||
|| (v2 instanceof String && ((String) v2).length() == 0);
|
||||
} else if (v2 == null) {
|
||||
return (v1 == null)
|
||||
|| (v1 instanceof String && ((String) v1).length() == 0);
|
||||
} else {
|
||||
return v1.equals(v2);
|
||||
}
|
||||
}
|
||||
|
||||
static public boolean isStorable(Object v) {
|
||||
@ -90,12 +92,12 @@ public class ExpressionUtils {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static public List<Object> toObjectList(Object v) {
|
||||
return (List<Object>) v;
|
||||
static public List<Object> toObjectList(Object v) {
|
||||
return (List<Object>) v;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static public Collection<Object> toObjectCollection(Object v) {
|
||||
return (Collection<Object>) v;
|
||||
static public Collection<Object> toObjectCollection(Object v) {
|
||||
return (Collection<Object>) v;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,10 @@ package com.metaweb.gridworks.expr;
|
||||
|
||||
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 Object getField(String name, Properties bindings);
|
||||
}
|
||||
|
@ -19,22 +19,22 @@ public class JythonEvaluable implements Evaluable {
|
||||
private static PythonInterpreter _engine = new PythonInterpreter();
|
||||
|
||||
public JythonEvaluable(String s) {
|
||||
// indent and create a function out of the code
|
||||
String[] lines = s.split("\r\n|\r|\n");
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("def " + s_functionName + "(value, cell, cells, row, rowIndex):");
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
sb.append("\n " + lines[i]);
|
||||
}
|
||||
|
||||
// indent and create a function out of the code
|
||||
String[] lines = s.split("\r\n|\r|\n");
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("def " + s_functionName + "(value, cell, cells, row, rowIndex):");
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
sb.append("\n " + lines[i]);
|
||||
}
|
||||
|
||||
_engine.exec(sb.toString());
|
||||
}
|
||||
|
||||
public Object evaluate(Properties bindings) {
|
||||
try {
|
||||
// call the temporary PyFunction directly
|
||||
Object result = ((PyFunction)_engine.get(s_functionName)).__call__(
|
||||
public Object evaluate(Properties bindings) {
|
||||
try {
|
||||
// call the temporary PyFunction directly
|
||||
Object result = ((PyFunction)_engine.get(s_functionName)).__call__(
|
||||
new PyObject[] {
|
||||
Py.java2py( bindings.get("value") ),
|
||||
new JythonHasFieldsWrapper((HasFields) bindings.get("cell"), bindings),
|
||||
@ -42,15 +42,15 @@ public class JythonEvaluable implements Evaluable {
|
||||
new JythonHasFieldsWrapper((HasFields) bindings.get("row"), bindings),
|
||||
Py.java2py( bindings.get("rowIndex") )
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
return unwrap(result);
|
||||
} catch (PyException e) {
|
||||
return new EvalError(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected Object unwrap(Object result) {
|
||||
return unwrap(result);
|
||||
} catch (PyException e) {
|
||||
return new EvalError(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected Object unwrap(Object result) {
|
||||
if (result != null) {
|
||||
if (result instanceof JythonObjectWrapper) {
|
||||
return ((JythonObjectWrapper) result)._obj;
|
||||
@ -64,12 +64,12 @@ public class JythonEvaluable implements Evaluable {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Object unwrap(PyObject po) {
|
||||
if (po instanceof PyNone) {
|
||||
return null;
|
||||
} else if (po.isNumberType()) {
|
||||
}
|
||||
|
||||
protected Object unwrap(PyObject po) {
|
||||
if (po instanceof PyNone) {
|
||||
return null;
|
||||
} else if (po.isNumberType()) {
|
||||
return po.asDouble();
|
||||
} else if (po.isSequenceType()) {
|
||||
Iterator<PyObject> i = po.asIterable().iterator();
|
||||
@ -83,5 +83,5 @@ public class JythonEvaluable implements Evaluable {
|
||||
} else {
|
||||
return po;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,34 +5,34 @@ import java.util.Properties;
|
||||
import org.python.core.PyObject;
|
||||
import org.python.core.PyString;
|
||||
|
||||
|
||||
public class JythonHasFieldsWrapper extends PyObject {
|
||||
private static final long serialVersionUID = -1275353513262385099L;
|
||||
|
||||
public HasFields _obj;
|
||||
private Properties _bindings;
|
||||
|
||||
public JythonHasFieldsWrapper(HasFields obj, Properties bindings) {
|
||||
_obj = obj;
|
||||
_bindings = bindings;
|
||||
}
|
||||
|
||||
public PyObject __finditem__(PyObject key) {
|
||||
String k = (String) key.__tojava__(String.class);
|
||||
Object v = _obj.getField(k, _bindings);
|
||||
if (v != null) {
|
||||
if (v instanceof HasFields) {
|
||||
return new JythonHasFieldsWrapper((HasFields) v, _bindings);
|
||||
} else if (v instanceof String) {
|
||||
return new PyString((String) v);
|
||||
} else if (v instanceof PyObject) {
|
||||
return (PyObject) v;
|
||||
} else {
|
||||
return new JythonObjectWrapper(v);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public HasFields _obj;
|
||||
|
||||
private Properties _bindings;
|
||||
|
||||
public JythonHasFieldsWrapper(HasFields obj, Properties bindings) {
|
||||
_obj = obj;
|
||||
_bindings = bindings;
|
||||
}
|
||||
|
||||
public PyObject __finditem__(PyObject key) {
|
||||
String k = (String) key.__tojava__(String.class);
|
||||
Object v = _obj.getField(k, _bindings);
|
||||
if (v != null) {
|
||||
if (v instanceof HasFields) {
|
||||
return new JythonHasFieldsWrapper((HasFields) v, _bindings);
|
||||
} else if (v instanceof String) {
|
||||
return new PyString((String) v);
|
||||
} else if (v instanceof PyObject) {
|
||||
return (PyObject) v;
|
||||
} else {
|
||||
return new JythonObjectWrapper(v);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,14 +4,14 @@ import org.python.core.PyObject;
|
||||
|
||||
public class JythonObjectWrapper extends PyObject {
|
||||
private static final long serialVersionUID = -6608115027151667441L;
|
||||
|
||||
public Object _obj;
|
||||
|
||||
public JythonObjectWrapper(Object obj) {
|
||||
_obj = obj;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return _obj.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
public Object _obj;
|
||||
|
||||
public JythonObjectWrapper(Object obj) {
|
||||
_obj = obj;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return _obj.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,15 @@ import clojure.lang.IFn;
|
||||
import com.metaweb.gridworks.gel.Parser;
|
||||
|
||||
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 {
|
||||
String language = "gel";
|
||||
|
||||
|
@ -26,10 +26,10 @@ public class Get implements Function {
|
||||
} else {
|
||||
if (from instanceof Number && (to == null || to instanceof Number)) {
|
||||
if (v.getClass().isArray() || v instanceof List<?>) {
|
||||
int length = v.getClass().isArray() ?
|
||||
((Object[]) v).length :
|
||||
ExpressionUtils.toObjectList(v).size();
|
||||
|
||||
int length = v.getClass().isArray() ?
|
||||
((Object[]) v).length :
|
||||
ExpressionUtils.toObjectList(v).size();
|
||||
|
||||
int start = ((Number) from).intValue();
|
||||
if (start < 0) {
|
||||
start = length + start;
|
||||
@ -38,9 +38,9 @@ public class Get implements Function {
|
||||
|
||||
if (to == null) {
|
||||
return start >= length ? null :
|
||||
(v.getClass().isArray() ?
|
||||
((Object[]) v)[start] :
|
||||
ExpressionUtils.toObjectList(v).get(start));
|
||||
(v.getClass().isArray() ?
|
||||
((Object[]) v)[start] :
|
||||
ExpressionUtils.toObjectList(v).get(start));
|
||||
} else {
|
||||
int end = to != null && to instanceof Number ?
|
||||
((Number) to).intValue() : length;
|
||||
@ -51,15 +51,15 @@ public class Get implements Function {
|
||||
end = Math.min(length, Math.max(start, end));
|
||||
|
||||
if (end > start) {
|
||||
if (v.getClass().isArray()) {
|
||||
if (v.getClass().isArray()) {
|
||||
Object[] a2 = new Object[end - start];
|
||||
|
||||
System.arraycopy((Object[]) v, start, a2, 0, end - start);
|
||||
|
||||
return a2;
|
||||
} else {
|
||||
return ExpressionUtils.toObjectList(v).subList(start, end);
|
||||
}
|
||||
} else {
|
||||
return ExpressionUtils.toObjectList(v).subList(start, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -19,10 +19,10 @@ public class Slice implements Function {
|
||||
|
||||
if (v != null && from != null && from instanceof Number && (to == null || to instanceof Number)) {
|
||||
if (v.getClass().isArray() || v instanceof List<?>) {
|
||||
int length = v.getClass().isArray() ?
|
||||
((Object[]) v).length :
|
||||
ExpressionUtils.toObjectList(v).size();
|
||||
|
||||
int length = v.getClass().isArray() ?
|
||||
((Object[]) v).length :
|
||||
ExpressionUtils.toObjectList(v).size();
|
||||
|
||||
int start = ((Number) from).intValue();
|
||||
int end = to != null && to instanceof Number ?
|
||||
((Number) to).intValue() : length;
|
||||
@ -37,15 +37,15 @@ public class Slice implements Function {
|
||||
}
|
||||
end = Math.min(length, Math.max(start, end));
|
||||
|
||||
if (v.getClass().isArray()) {
|
||||
if (v.getClass().isArray()) {
|
||||
Object[] a2 = new Object[end - start];
|
||||
|
||||
System.arraycopy((Object[]) v, start, a2, 0, end - start);
|
||||
|
||||
return a2;
|
||||
} else {
|
||||
return ExpressionUtils.toObjectList(v).subList(start, end);
|
||||
}
|
||||
} else {
|
||||
return ExpressionUtils.toObjectList(v).subList(start, end);
|
||||
}
|
||||
} else {
|
||||
String s = (v instanceof String ? (String) v : v.toString());
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.metaweb.gridworks.expr.functions;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
@ -20,18 +21,21 @@ public class Type implements Function {
|
||||
if (v != null) {
|
||||
if (v instanceof String) {
|
||||
return "string";
|
||||
} else if (v instanceof Calendar) {
|
||||
} else if (v instanceof Calendar || v instanceof Date) {
|
||||
return "date";
|
||||
} else if (v instanceof Number) {
|
||||
return "number";
|
||||
} else if (v.getClass().isArray() || v instanceof List<?>) {
|
||||
return "array";
|
||||
} else if (v instanceof EvalError) {
|
||||
return "error";
|
||||
} else {
|
||||
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)
|
||||
|
@ -18,21 +18,21 @@ public class Reverse implements Function {
|
||||
Object v = args[0];
|
||||
|
||||
if (v != null && (v.getClass().isArray() || v instanceof List<?>)) {
|
||||
int length = v.getClass().isArray() ?
|
||||
((Object[]) v).length :
|
||||
ExpressionUtils.toObjectList(v).size();
|
||||
|
||||
int length = v.getClass().isArray() ?
|
||||
((Object[]) v).length :
|
||||
ExpressionUtils.toObjectList(v).size();
|
||||
|
||||
Object[] r = new Object[length];
|
||||
if (v.getClass().isArray()) {
|
||||
Object[] a = (Object[]) v;
|
||||
for (int i = 0; i < length; i++) {
|
||||
r[i] = a[r.length - i - 1];
|
||||
}
|
||||
Object[] a = (Object[]) v;
|
||||
for (int i = 0; i < length; i++) {
|
||||
r[i] = a[r.length - i - 1];
|
||||
}
|
||||
} else {
|
||||
List<Object> a = ExpressionUtils.toObjectList(v);
|
||||
for (int i = 0; i < length; i++) {
|
||||
r[i] = a.get(r.length - i - 1);
|
||||
}
|
||||
List<Object> a = ExpressionUtils.toObjectList(v);
|
||||
for (int i = 0; i < length; i++) {
|
||||
r[i] = a.get(r.length - i - 1);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -20,19 +20,19 @@ public class Sort implements Function {
|
||||
Object v = args[0];
|
||||
|
||||
if (v != null) {
|
||||
if (v.getClass().isArray()) {
|
||||
Object[] a = (Object[]) v;
|
||||
Object[] r = a.clone();
|
||||
|
||||
Arrays.sort(r, 0, r.length);
|
||||
|
||||
return r;
|
||||
} else if (v instanceof List<?>) {
|
||||
List<? extends Comparable> a = (List<? extends Comparable>) v;
|
||||
Collections.sort(a);
|
||||
|
||||
return a;
|
||||
}
|
||||
if (v.getClass().isArray()) {
|
||||
Object[] a = (Object[]) v;
|
||||
Object[] r = a.clone();
|
||||
|
||||
Arrays.sort(r, 0, r.length);
|
||||
|
||||
return r;
|
||||
} else if (v instanceof List<?>) {
|
||||
List<? extends Comparable> a = (List<? extends Comparable>) v;
|
||||
Collections.sort(a);
|
||||
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects an array");
|
||||
|
@ -18,28 +18,28 @@ public class Sum implements Function {
|
||||
Object v = args[0];
|
||||
|
||||
if (v != null && (v.getClass().isArray() || v instanceof List<?>)) {
|
||||
int length = v.getClass().isArray() ?
|
||||
((Object[]) v).length :
|
||||
ExpressionUtils.toObjectList(v).size();
|
||||
int length = v.getClass().isArray() ?
|
||||
((Object[]) v).length :
|
||||
ExpressionUtils.toObjectList(v).size();
|
||||
|
||||
double total = 0;
|
||||
|
||||
if (v.getClass().isArray()) {
|
||||
Object[] a = (Object[]) v;
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object n = a[length - i - 1];
|
||||
if (n instanceof Number) {
|
||||
total += ((Number) n).doubleValue();
|
||||
}
|
||||
}
|
||||
Object[] a = (Object[]) v;
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object n = a[length - i - 1];
|
||||
if (n instanceof Number) {
|
||||
total += ((Number) n).doubleValue();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<Object> a = ExpressionUtils.toObjectList(v);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object n = a.get(length - i - 1);
|
||||
if (n instanceof Number) {
|
||||
total += ((Number) n).doubleValue();
|
||||
}
|
||||
}
|
||||
List<Object> a = ExpressionUtils.toObjectList(v);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object n = a.get(length - i - 1);
|
||||
if (n instanceof Number) {
|
||||
total += ((Number) n).doubleValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user