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;
|
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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user