Small refactoring: introduced RowEvaluable interface to abstract out the evaluation of an expression on a row.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@846 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-05-24 17:14:54 +00:00
parent 015b5a92ae
commit 38d5b3dbde
15 changed files with 153 additions and 93 deletions

View File

@ -87,7 +87,7 @@ public class Engine implements Jsonizable {
ConjunctiveFilteredRows cfr = new ConjunctiveFilteredRows();
for (Facet facet : _facets) {
if (facet != except) {
RowFilter rowFilter = facet.getRowFilter();
RowFilter rowFilter = facet.getRowFilter(_project);
if (rowFilter != null) {
cfr.add(rowFilter);
}
@ -125,7 +125,7 @@ public class Engine implements Jsonizable {
ConjunctiveFilteredRecords cfr = new ConjunctiveFilteredRecords();
for (Facet facet : _facets) {
if (facet != except) {
RecordFilter recordFilter = facet.getRecordFilter();
RecordFilter recordFilter = facet.getRecordFilter(_project);
if (recordFilter != null) {
cfr.add(recordFilter);
}

View File

@ -13,9 +13,9 @@ import com.metaweb.gridworks.model.Project;
* Interface of facets.
*/
public interface Facet extends Jsonizable {
public RowFilter getRowFilter();
public RowFilter getRowFilter(Project project);
public RecordFilter getRecordFilter();
public RecordFilter getRecordFilter(Project project);
public void computeChoices(Project project, FilteredRows filteredRows);

View File

@ -148,7 +148,7 @@ public class ListFacet implements Facet {
}
@Override
public RowFilter getRowFilter() {
public RowFilter getRowFilter(Project project) {
return
_eval == null ||
_errorMessage != null ||
@ -165,8 +165,8 @@ public class ListFacet implements Facet {
}
@Override
public RecordFilter getRecordFilter() {
RowFilter rowFilter = getRowFilter();
public RecordFilter getRecordFilter(Project project) {
RowFilter rowFilter = getRowFilter(project);
return rowFilter == null ? null : new AnyRowRecordFilter(rowFilter);
}

View File

@ -12,10 +12,12 @@ import com.metaweb.gridworks.browsing.RecordFilter;
import com.metaweb.gridworks.browsing.RowFilter;
import com.metaweb.gridworks.browsing.filters.AnyRowRecordFilter;
import com.metaweb.gridworks.browsing.filters.ExpressionNumberComparisonRowFilter;
import com.metaweb.gridworks.browsing.util.ExpressionBasedRowEvaluable;
import com.metaweb.gridworks.browsing.util.ExpressionNumericValueBinner;
import com.metaweb.gridworks.browsing.util.NumericBinIndex;
import com.metaweb.gridworks.browsing.util.NumericBinRecordIndex;
import com.metaweb.gridworks.browsing.util.NumericBinRowIndex;
import com.metaweb.gridworks.browsing.util.RowEvaluable;
import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.MetaParser;
import com.metaweb.gridworks.expr.ParsingException;
@ -158,10 +160,10 @@ public class RangeFacet implements Facet {
}
}
public RowFilter getRowFilter() {
public RowFilter getRowFilter(Project project) {
if (_eval != null && _errorMessage == null && _selected) {
return new ExpressionNumberComparisonRowFilter(
_eval, _columnName, _cellIndex, _selectNumeric, _selectNonNumeric, _selectBlank, _selectError) {
getRowEvaluable(project), _selectNumeric, _selectNonNumeric, _selectBlank, _selectError) {
protected boolean checkValue(double d) {
return d >= _from && d < _to;
@ -173,26 +175,27 @@ public class RangeFacet implements Facet {
}
@Override
public RecordFilter getRecordFilter() {
RowFilter rowFilter = getRowFilter();
public RecordFilter getRecordFilter(Project project) {
RowFilter rowFilter = getRowFilter(project);
return rowFilter == null ? null : new AnyRowRecordFilter(rowFilter);
}
public void computeChoices(Project project, FilteredRows filteredRows) {
if (_eval != null && _errorMessage == null) {
Column column = project.columnModel.getColumnByCellIndex(_cellIndex);
RowEvaluable rowEvaluable = getRowEvaluable(project);
Column column = project.columnModel.getColumnByCellIndex(_cellIndex);
String key = "numeric-bin:row-based:" + _expression;
NumericBinIndex index = (NumericBinIndex) column.getPrecompute(key);
if (index == null) {
index = new NumericBinRowIndex(project, _columnName, _cellIndex, _eval);
index = new NumericBinRowIndex(project, rowEvaluable);
column.setPrecompute(key, index);
}
retrieveDataFromBaseBinIndex(index);
ExpressionNumericValueBinner binner =
new ExpressionNumericValueBinner(_eval, _columnName, _cellIndex, index);
new ExpressionNumericValueBinner(rowEvaluable, index);
filteredRows.accept(project, binner);
retrieveDataFromBinner(binner);
@ -201,19 +204,20 @@ public class RangeFacet implements Facet {
public void computeChoices(Project project, FilteredRecords filteredRecords) {
if (_eval != null && _errorMessage == null) {
Column column = project.columnModel.getColumnByCellIndex(_cellIndex);
RowEvaluable rowEvaluable = getRowEvaluable(project);
Column column = project.columnModel.getColumnByCellIndex(_cellIndex);
String key = "numeric-bin:record-based:" + _expression;
NumericBinIndex index = (NumericBinIndex) column.getPrecompute(key);
if (index == null) {
index = new NumericBinRecordIndex(project, _columnName, _cellIndex, _eval);
index = new NumericBinRecordIndex(project, rowEvaluable);
column.setPrecompute(key, index);
}
retrieveDataFromBaseBinIndex(index);
ExpressionNumericValueBinner binner =
new ExpressionNumericValueBinner(_eval, _columnName, _cellIndex, index);
new ExpressionNumericValueBinner(rowEvaluable, index);
filteredRecords.accept(project, binner);
@ -221,6 +225,10 @@ public class RangeFacet implements Facet {
}
}
protected RowEvaluable getRowEvaluable(Project project) {
return new ExpressionBasedRowEvaluable(_columnName, _cellIndex, _eval);
}
protected void retrieveDataFromBaseBinIndex(NumericBinIndex index) {
_min = index.getMin();
_max = index.getMax();

View File

@ -24,6 +24,7 @@ import com.metaweb.gridworks.browsing.RecordFilter;
import com.metaweb.gridworks.browsing.RowFilter;
import com.metaweb.gridworks.browsing.filters.AnyRowRecordFilter;
import com.metaweb.gridworks.browsing.filters.DualExpressionsNumberComparisonRowFilter;
import com.metaweb.gridworks.browsing.util.ExpressionBasedRowEvaluable;
import com.metaweb.gridworks.browsing.util.NumericBinIndex;
import com.metaweb.gridworks.browsing.util.NumericBinRecordIndex;
import com.metaweb.gridworks.browsing.util.NumericBinRowIndex;
@ -251,7 +252,7 @@ public class ScatterplotFacet implements Facet {
}
public RowFilter getRowFilter() {
public RowFilter getRowFilter(Project project) {
if (selected &&
eval_x != null && errorMessage_x == null &&
eval_y != null && errorMessage_y == null)
@ -276,8 +277,8 @@ public class ScatterplotFacet implements Facet {
}
@Override
public RecordFilter getRecordFilter() {
RowFilter rowFilter = getRowFilter();
public RecordFilter getRecordFilter(Project project) {
RowFilter rowFilter = getRowFilter(project);
return rowFilter == null ? null : new AnyRowRecordFilter(rowFilter);
}
@ -389,8 +390,8 @@ public class ScatterplotFacet implements Facet {
NumericBinIndex index = (NumericBinIndex) column.getPrecompute(key);
if (index == null) {
index = "row-based".equals(mode) ?
new NumericBinRowIndex(project, column.getName(), column.getCellIndex(), eval) :
new NumericBinRecordIndex(project, column.getName(), column.getCellIndex(), eval);
new NumericBinRowIndex(project, new ExpressionBasedRowEvaluable(column.getName(), column.getCellIndex(), eval)) :
new NumericBinRecordIndex(project, new ExpressionBasedRowEvaluable(column.getName(), column.getCellIndex(), eval));
column.setPrecompute(key, index);
}

View File

@ -78,7 +78,7 @@ public class TextSearchFacet implements Facet {
}
@Override
public RowFilter getRowFilter() {
public RowFilter getRowFilter(Project project) {
if (_query == null || _query.length() == 0) {
return null;
} else if ("regex".equals(_mode) && _pattern == null) {
@ -103,8 +103,8 @@ public class TextSearchFacet implements Facet {
}
@Override
public RecordFilter getRecordFilter() {
RowFilter rowFilter = getRowFilter();
public RecordFilter getRecordFilter(Project project) {
RowFilter rowFilter = getRowFilter(project);
return rowFilter == null ? null : new AnyRowRecordFilter(rowFilter);
}

View File

@ -4,9 +4,8 @@ import java.util.Collection;
import java.util.Properties;
import com.metaweb.gridworks.browsing.RowFilter;
import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.browsing.util.RowEvaluable;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
@ -17,26 +16,20 @@ import com.metaweb.gridworks.model.Row;
* values.
*/
abstract public class ExpressionNumberComparisonRowFilter implements RowFilter {
final protected Evaluable _evaluable;
final protected String _columnName;
final protected int _cellIndex;
final protected boolean _selectNumeric;
final protected boolean _selectNonNumeric;
final protected boolean _selectBlank;
final protected boolean _selectError;
final protected RowEvaluable _rowEvaluable;
final protected boolean _selectNumeric;
final protected boolean _selectNonNumeric;
final protected boolean _selectBlank;
final protected boolean _selectError;
public ExpressionNumberComparisonRowFilter(
Evaluable evaluable,
String columnName,
int cellIndex,
RowEvaluable rowEvaluable,
boolean selectNumeric,
boolean selectNonNumeric,
boolean selectBlank,
boolean selectError
) {
_evaluable = evaluable;
_columnName = columnName;
_cellIndex = cellIndex;
_rowEvaluable = rowEvaluable;
_selectNumeric = selectNumeric;
_selectNonNumeric = selectNonNumeric;
_selectBlank = selectBlank;
@ -44,12 +37,9 @@ abstract public class ExpressionNumberComparisonRowFilter implements RowFilter {
}
public boolean filterRow(Project project, int rowIndex, Row row) {
Cell cell = _cellIndex < 0 ? null : row.getCell(_cellIndex);
Properties bindings = ExpressionUtils.createBindings(project);
ExpressionUtils.bind(bindings, row, rowIndex, _columnName, cell);
Object value = _evaluable.evaluate(bindings);
Object value = _rowEvaluable.eval(project, rowIndex, row, bindings);
if (value != null) {
if (value.getClass().isArray()) {
Object[] a = (Object[]) value;

View File

@ -0,0 +1,34 @@
package com.metaweb.gridworks.browsing.util;
import java.util.Properties;
import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
public class ExpressionBasedRowEvaluable implements RowEvaluable {
final protected String _columnName;
final protected int _cellIndex;
final protected Evaluable _eval;
public ExpressionBasedRowEvaluable(
String columnName, int cellIndex, Evaluable eval) {
_columnName = columnName;
_cellIndex = cellIndex;
_eval = eval;
}
@Override
public Object eval(
Project project, int rowIndex, Row row, Properties bindings) {
Cell cell = row.getCell(_cellIndex);
ExpressionUtils.bind(bindings, row, rowIndex, _columnName, cell);
return _eval.evaluate(bindings);
}
}

View File

@ -2,6 +2,7 @@ package com.metaweb.gridworks.browsing.util;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@ -107,11 +108,7 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor
}
protected void visitRow(Project project, int rowIndex, Row row, Properties bindings, int index) {
Cell cell = _cellIndex < 0 ? null : row.getCell(_cellIndex);
ExpressionUtils.bind(bindings, row, rowIndex, _columnName, cell);
Object value = _evaluable.evaluate(bindings);
Object value = evalRow(project, rowIndex, row, bindings);
if (value != null) {
if (value.getClass().isArray()) {
Object[] a = (Object[]) value;
@ -130,6 +127,14 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor
}
}
protected Object evalRow(Project project, int rowIndex, Row row, Properties bindings) {
Cell cell = _cellIndex < 0 ? null : row.getCell(_cellIndex);
ExpressionUtils.bind(bindings, row, rowIndex, _columnName, cell);
return _evaluable.evaluate(bindings);
}
protected void processValue(Object value, int index) {
if (ExpressionUtils.isError(value)) {
hasError = true;
@ -155,4 +160,41 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor
hasBlank = true;
}
}
public RowEvaluable getChoiceCountRowEvaluable() {
return new RowEvaluable() {
@Override
public Object eval(Project project, int rowIndex, Row row, Properties bindings) {
Object value = evalRow(project, rowIndex, row, bindings);
if (value != null) {
if (value.getClass().isArray()) {
Object[] a = (Object[]) value;
for (int i = 0; i < a.length; i++) {
a[i] = getValueCount(a[i]);
}
return a;
} else if (value instanceof Collection<?>) {
List<Object> list = ExpressionUtils.toObjectList(value);
int count = list.size();
for (int i = 0; i < count; i++) {
list.set(i, getValueCount(list.get(i)));
}
return list;
}
}
return getValueCount(value);
}
protected Integer getValueCount(Object value) {
if (value == null) {
return blankCount;
} else if (ExpressionUtils.isError(value)) {
return errorCount;
} else {
return choices.get(value).count;
}
}
};
}
}

View File

@ -5,9 +5,7 @@ import java.util.Properties;
import com.metaweb.gridworks.browsing.RecordVisitor;
import com.metaweb.gridworks.browsing.RowVisitor;
import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Record;
import com.metaweb.gridworks.model.Row;
@ -20,9 +18,7 @@ public class ExpressionNumericValueBinner implements RowVisitor, RecordVisitor {
/*
* Configuration
*/
final protected Evaluable _evaluable;
final protected String _columnName;
final protected int _cellIndex;
final protected RowEvaluable _rowEvaluable;
final protected NumericBinIndex _index; // base bins
/*
@ -42,10 +38,8 @@ public class ExpressionNumericValueBinner implements RowVisitor, RecordVisitor {
protected boolean hasNumeric;
protected boolean hasNonNumeric;
public ExpressionNumericValueBinner(Evaluable evaluable, String columnName, int cellIndex, NumericBinIndex index) {
_evaluable = evaluable;
_columnName = columnName;
_cellIndex = cellIndex;
public ExpressionNumericValueBinner(RowEvaluable rowEvaluable, NumericBinIndex index) {
_rowEvaluable = rowEvaluable;
_index = index;
bins = new int[_index.getBins().length];
}
@ -109,12 +103,7 @@ public class ExpressionNumericValueBinner implements RowVisitor, RecordVisitor {
}
protected void processRow(Project project, int rowIndex, Row row, Properties bindings) {
Cell cell = row.getCell(_cellIndex);
ExpressionUtils.bind(bindings, row, rowIndex, _columnName, cell);
Object value = _evaluable.evaluate(bindings);
Object value = _rowEvaluable.eval(project, rowIndex, row, bindings);
if (value != null) {
if (value.getClass().isArray()) {
Object[] a = (Object[]) value;

View File

@ -5,9 +5,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Properties;
import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.model.Cell;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
@ -40,15 +38,15 @@ abstract public class NumericBinIndex {
protected boolean _hasNumeric = false;
protected boolean _hasBlank = false;
abstract protected void iterate(Project project, String columnName, int cellIndex, Evaluable eval, List<Double> allValues);
abstract protected void iterate(Project project, RowEvaluable rowEvaluable, List<Double> allValues);
public NumericBinIndex(Project project, String columnName, int cellIndex, Evaluable eval) {
public NumericBinIndex(Project project, RowEvaluable rowEvaluable) {
_min = Double.POSITIVE_INFINITY;
_max = Double.NEGATIVE_INFINITY;
List<Double> allValues = new ArrayList<Double>();
iterate(project, columnName, cellIndex, eval, allValues);
iterate(project, rowEvaluable, allValues);
_numbericValueCount = allValues.size();
@ -134,19 +132,13 @@ abstract public class NumericBinIndex {
protected void processRow(
Project project,
String columnName,
int cellIndex,
Evaluable eval,
RowEvaluable rowEvaluable,
List<Double> allValues,
int rowIndex,
Row row,
Properties bindings
) {
Cell cell = row.getCell(cellIndex);
ExpressionUtils.bind(bindings, row, rowIndex, columnName, cell);
Object value = eval.evaluate(bindings);
Object value = rowEvaluable.eval(project, rowIndex, row, bindings);
if (ExpressionUtils.isError(value)) {
_hasError = true;

View File

@ -3,23 +3,19 @@ package com.metaweb.gridworks.browsing.util;
import java.util.List;
import java.util.Properties;
import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Record;
import com.metaweb.gridworks.model.Row;
public class NumericBinRecordIndex extends NumericBinIndex {
public NumericBinRecordIndex(Project project, String columnName,
int cellIndex, Evaluable eval) {
super(project, columnName, cellIndex, eval);
public NumericBinRecordIndex(Project project, RowEvaluable rowEvaluable) {
super(project, rowEvaluable);
}
@Override
protected void iterate(
Project project, String columnName, int cellIndex,
Evaluable eval, List<Double> allValues) {
Project project, RowEvaluable rowEvaluable, List<Double> allValues) {
Properties bindings = ExpressionUtils.createBindings(project);
int count = project.recordModel.getRecordCount();
@ -32,7 +28,7 @@ public class NumericBinRecordIndex extends NumericBinIndex {
for (int i = record.fromRowIndex; i < record.toRowIndex; i++) {
Row row = project.rows.get(i);
processRow(project, columnName, cellIndex, eval, allValues, i, row, bindings);
processRow(project, rowEvaluable, allValues, i, row, bindings);
}
postprocessing();

View File

@ -3,22 +3,19 @@ package com.metaweb.gridworks.browsing.util;
import java.util.List;
import java.util.Properties;
import com.metaweb.gridworks.expr.Evaluable;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
public class NumericBinRowIndex extends NumericBinIndex {
public NumericBinRowIndex(Project project, String columnName,
int cellIndex, Evaluable eval) {
public NumericBinRowIndex(Project project, RowEvaluable rowEvaluable) {
super(project, columnName, cellIndex, eval);
super(project, rowEvaluable);
}
@Override
protected void iterate(
Project project, String columnName, int cellIndex,
Evaluable eval, List<Double> allValues) {
Project project, RowEvaluable rowEvaluable, List<Double> allValues) {
Properties bindings = ExpressionUtils.createBindings(project);
@ -27,7 +24,7 @@ public class NumericBinRowIndex extends NumericBinIndex {
preprocessing();
processRow(project, columnName, cellIndex, eval, allValues, i, row, bindings);
processRow(project, rowEvaluable, allValues, i, row, bindings);
postprocessing();
}

View File

@ -0,0 +1,10 @@
package com.metaweb.gridworks.browsing.util;
import java.util.Properties;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
public interface RowEvaluable {
public Object eval(Project project, int rowIndex, Row row, Properties bindings);
}

View File

@ -9,6 +9,7 @@ import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONWriter;
import com.metaweb.gridworks.browsing.util.ExpressionBasedRowEvaluable;
import com.metaweb.gridworks.browsing.util.NumericBinIndex;
import com.metaweb.gridworks.browsing.util.NumericBinRowIndex;
import com.metaweb.gridworks.commands.Command;
@ -60,7 +61,7 @@ public class GetColumnsInfoCommand extends Command {
}
NumericBinIndex index = (NumericBinIndex) column.getPrecompute(key);
if (index == null) {
index = new NumericBinRowIndex(project, column.getName(), column.getCellIndex(), eval);
index = new NumericBinRowIndex(project, new ExpressionBasedRowEvaluable(column.getName(), column.getCellIndex(), eval));
column.setPrecompute(key, index);
}
return index;