Added start() and end() methods to RowVisitor and RecordVisitor so visitors can do things before and after all visitations.

Added sorting package. It's not hooked up, yet.

git-svn-id: http://google-refine.googlecode.com/svn/trunk@834 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-05-20 22:10:34 +00:00
parent 0709ec3f92
commit 496823e564
37 changed files with 824 additions and 25 deletions

View File

@ -51,11 +51,17 @@ public class Engine implements Jsonizable {
return new FilteredRows() {
@Override
public void accept(Project project, RowVisitor visitor) {
int c = project.rows.size();
for (int rowIndex = 0; rowIndex < c; rowIndex++) {
Row row = project.rows.get(rowIndex);
visitor.visit(project, rowIndex, row);
}
try {
visitor.start(project);
int c = project.rows.size();
for (int rowIndex = 0; rowIndex < c; rowIndex++) {
Row row = project.rows.get(rowIndex);
visitor.visit(project, rowIndex, row);
}
} finally {
visitor.end(project);
}
}
};
}
@ -86,10 +92,16 @@ public class Engine implements Jsonizable {
return new FilteredRecords() {
@Override
public void accept(Project project, RecordVisitor visitor) {
int c = project.recordModel.getRecordCount();
for (int r = 0; r < c; r++) {
visitor.visit(project, project.recordModel.getRecord(r));
}
try {
visitor.start(project);
int c = project.recordModel.getRecordCount();
for (int r = 0; r < c; r++) {
visitor.visit(project, project.recordModel.getRecord(r));
}
} finally {
visitor.end(project);
}
}
};
}

View File

@ -8,8 +8,12 @@ import com.metaweb.gridworks.model.Record;
* particular criteria, such as facets' constraints.
*/
public interface RecordVisitor {
public void start(Project project); // called before any visit() call
public boolean visit(
Project project,
Record record
);
public void end(Project project); // called after all visit() calls
}

View File

@ -8,9 +8,13 @@ import com.metaweb.gridworks.model.Row;
* particular criteria, such as facets' constraints.
*/
public interface RowVisitor {
public void start(Project project); // called before any visit() call
public boolean visit(
Project project,
int rowIndex, // zero-based row index
Row row
);
public void end(Project project); // called after all visit() calls
}

View File

@ -87,6 +87,16 @@ public class ScatterplotDrawingRowVisitor implements RowVisitor, RecordVisitor {
g2.setPaint(color);
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
@Override
public boolean visit(Project project, int rowIndex, Row row) {
Cell cellx = row.getCell(col_x);

View File

@ -21,15 +21,21 @@ public class ConjunctiveFilteredRecords implements FilteredRecords {
@Override
public void accept(Project project, RecordVisitor visitor) {
int c = project.recordModel.getRecordCount();
for (int r = 0; r < c; r++) {
Record record = project.recordModel.getRecord(r);
if (matchRecord(project, record)) {
if (visitor.visit(project, record)) {
return;
}
}
}
try {
visitor.start(project);
int c = project.recordModel.getRecordCount();
for (int r = 0; r < c; r++) {
Record record = project.recordModel.getRecord(r);
if (matchRecord(project, record)) {
if (visitor.visit(project, record)) {
return;
}
}
}
} finally {
visitor.end(project);
}
}
protected boolean matchRecord(Project project, Record record) {

View File

@ -21,13 +21,19 @@ public class ConjunctiveFilteredRows implements FilteredRows {
}
public void accept(Project project, RowVisitor visitor) {
int c = project.rows.size();
for (int rowIndex = 0; rowIndex < c; rowIndex++) {
Row row = project.rows.get(rowIndex);
if (matchRow(project, rowIndex, row)) {
visitRow(project, visitor, rowIndex, row);
}
}
try {
visitor.start(project);
int c = project.rows.size();
for (int rowIndex = 0; rowIndex < c; rowIndex++) {
Row row = project.rows.get(rowIndex);
if (matchRow(project, rowIndex, row)) {
visitRow(project, visitor, rowIndex, row);
}
}
} finally {
visitor.end(project);
}
}
protected void visitRow(Project project, RowVisitor visitor, int rowIndex, Row row) {

View File

@ -56,6 +56,16 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor
_cellIndex = cellIndex;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
hasError = false;
hasBlank = false;

View File

@ -50,6 +50,16 @@ public class ExpressionNumericValueBinner implements RowVisitor, RecordVisitor {
bins = new int[_index.getBins().length];
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
@Override
public boolean visit(Project project, int rowIndex, Row row) {
resetFlags();

View File

@ -12,6 +12,16 @@ public class RowVisitorAsRecordVisitor implements RecordVisitor {
_rowVisitor = rowVisitor;
}
@Override
public void start(Project project) {
_rowVisitor.start(project);
}
@Override
public void end(Project project) {
_rowVisitor.end(project);
}
@Override
public boolean visit(Project project, Record record) {
for (int r = record.fromRowIndex; r < record.toRowIndex; r++) {

View File

@ -66,6 +66,16 @@ public class BinningClusterer extends Clusterer {
}
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(_colindex);
if (cell != null && cell.value != null) {

View File

@ -80,6 +80,16 @@ public class kNNClusterer extends Clusterer {
}
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(_colindex);
if (cell != null && cell.value != null) {
@ -121,6 +131,16 @@ public class kNNClusterer extends Clusterer {
_clusterer = new NGramClusterer(_distance, _blockingNgramSize);
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(_colindex);
if (cell != null && cell.value != null) {

View File

@ -94,6 +94,16 @@ public class GetRowsCommand extends Command {
this.options = options;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
if (total >= start && total < start + limit) {
internalVisit(project, rowIndex, row);

View File

@ -56,6 +56,16 @@ public class HtmlTableExporter implements Exporter {
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
try {
writer.write("<tr>");

View File

@ -48,6 +48,16 @@ public class TsvExporter implements Exporter {
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
boolean first = true;
try {

View File

@ -64,6 +64,16 @@ public class XlsExporter implements Exporter {
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
org.apache.poi.ss.usermodel.Row r = sheet.createRow(rowCount++);

View File

@ -135,6 +135,16 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(cellIndex);
Cell newCell = null;

View File

@ -234,6 +234,16 @@ public class ColumnSplitOperation extends EngineDependentOperation {
this.tuples = tuples;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Object value = row.getCellValue(cellIndex);
if (ExpressionUtils.isNonBlankData(value)) {

View File

@ -148,6 +148,17 @@ public class ExtendDataOperation extends EngineDependentOperation {
_rowIndices = rowIndices;
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(_cellIndex);
if (cell != null && cell.recon != null && cell.recon.match != null) {

View File

@ -196,6 +196,16 @@ public class MassEditOperation extends EngineDependentMassCellOperation {
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(cellIndex);
Cell newCell = null;

View File

@ -74,6 +74,16 @@ public class ReconDiscardJudgmentsOperation extends EngineDependentMassCellOpera
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(cellIndex);
if (cell != null && cell.recon != null) {

View File

@ -162,6 +162,16 @@ public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOper
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(_cellIndex);
if (cell != null && ExpressionUtils.isNonBlankData(cell.value)) {

View File

@ -84,6 +84,16 @@ public class ReconMarkNewTopicsOperation extends EngineDependentMassCellOperatio
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(cellIndex);
if (cell != null) {

View File

@ -75,6 +75,16 @@ public class ReconMatchBestCandidatesOperation extends EngineDependentMassCellOp
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
if (cellIndex < row.cells.size()) {
Cell cell = row.cells.get(cellIndex);

View File

@ -108,6 +108,16 @@ public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOpe
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(cellIndex);
if (cell != null) {

View File

@ -176,6 +176,16 @@ public class ReconOperation extends EngineDependentOperation {
FilteredRows filteredRows = engine.getAllFilteredRows();
filteredRows.accept(_project, new RowVisitor() {
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
if (_cellIndex < row.cells.size()) {
Cell cell = row.cells.get(_cellIndex);

View File

@ -78,6 +78,16 @@ public class RowFlagOperation extends EngineDependentOperation {
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
if (row.flagged != _flagged) {
RowFlagChange change = new RowFlagChange(rowIndex, _flagged);

View File

@ -70,6 +70,16 @@ public class RowRemovalOperation extends EngineDependentOperation {
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
rowIndices.add(rowIndex);

View File

@ -78,6 +78,16 @@ public class RowStarOperation extends EngineDependentOperation {
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
if (row.starred != _starred) {
RowStarChange change = new RowStarChange(rowIndex, _starred);

View File

@ -119,6 +119,16 @@ public class TextTransformOperation extends EngineDependentMassCellOperation {
return this;
}
@Override
public void start(Project project) {
// nothing to do
}
@Override
public void end(Project project) {
// nothing to do
}
public boolean visit(Project project, int rowIndex, Row row) {
Cell cell = row.getCell(cellIndex);
Cell newCell = null;

View File

@ -0,0 +1,136 @@
package com.metaweb.gridworks.sorting;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.metaweb.gridworks.expr.EvalError;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.sorting.Criterion.KeyMaker;
abstract public class BaseSorter {
protected Criterion[] _criteria;
protected KeyMaker[] _keyMakers;
protected ComparatorWrapper[] _comparatorWrappers;
protected List<Object[]> _keys;
public class ComparatorWrapper {
final public int criterionIndex;
final protected int multiplier;
public ComparatorWrapper(int criterionIndex) {
this.criterionIndex = criterionIndex;
this.multiplier = _criteria[criterionIndex].reverse ? -1 : 1;
}
public Object getKey(Project project, Object o, int index) {
Object[] keys = _keys.get(index);
if (keys == null) {
keys = makeKeys(project, o, index);
_keys.set(index, keys);
}
return keys[criterionIndex];
}
public int compare(Project project, Object o1, int i1, Object o2, int i2) {
Criterion c = _criteria[criterionIndex];
Object key1 = getKey(project, o1, i1);
Object key2 = getKey(project, o2, i2);
if (key1 == null) {
if (key2 == null) {
return 0;
} else if (key2 instanceof EvalError) {
return c.blankPosition - c.errorPosition;
} else {
return c.blankPosition;
}
} else if (key1 instanceof EvalError) {
if (key2 == null) {
return c.errorPosition - c.blankPosition;
} else if (key2 instanceof EvalError) {
return 0;
} else {
return c.errorPosition;
}
} else {
if (key2 == null) {
return -c.blankPosition;
} else if (key2 instanceof EvalError) {
return -c.errorPosition;
} else {
return _keyMakers[criterionIndex].compareKeys(key1, key2) * multiplier;
}
}
}
}
public void initializeFromJSON(Project project, JSONObject obj) throws JSONException {
if (obj.has("criteria") && !obj.isNull("criteria")) {
JSONArray a = obj.getJSONArray("criteria");
int count = a.length();
_criteria = new Criterion[count];
_keyMakers = new KeyMaker[count];
_comparatorWrappers = new ComparatorWrapper[count];
for (int i = 0; i < count; i++) {
JSONObject obj2 = a.getJSONObject(i);
_criteria[i] = createCriterionFromJSON(project, obj2);
_keyMakers[i] = _criteria[i].createKeyMaker();
_comparatorWrappers[i] = new ComparatorWrapper(i);
}
} else {
_criteria = new Criterion[0];
_keyMakers = new KeyMaker[0];
_comparatorWrappers = new ComparatorWrapper[0];
}
}
public boolean hasCriteria() {
return _criteria != null && _criteria.length > 0;
}
protected Criterion createCriterionFromJSON(Project project, JSONObject obj) throws JSONException {
String valueType = "string";
if (obj.has("valueType") && !obj.isNull("valueType")) {
valueType = obj.getString("valueType");
}
Criterion c = null;
if ("boolean".equals(valueType)) {
c = new BooleanCriterion();
} else if ("date".equals(valueType)) {
c = new DateCriterion();
} else if ("number".equals(valueType)) {
c = new NumberCriterion();
} else {
c = new StringCriterion();
}
c.initializeFromJSON(project, obj);
return c;
}
abstract protected Object makeKey(
Project project, KeyMaker keyMaker, Criterion c, Object o, int index);
protected Object[] makeKeys(Project project, Object o, int index) {
Object[] keys = new Object[_keyMakers.length];
for (int i = 0; i < keys.length; i++) {
keys[i] = makeKey(project, _keyMakers[i], _criteria[i], o, index);
}
return keys;
}
protected int compare(Project project, Object o1, int i1, Object o2, int i2) {
int c = 0;
for (int i = 0; c == 0 && i < _comparatorWrappers.length; i++) {
c = _comparatorWrappers[i].compare(project, o1, i1, o2, i2);
}
return c;
}
}

View File

@ -0,0 +1,32 @@
package com.metaweb.gridworks.sorting;
import com.metaweb.gridworks.expr.EvalError;
import com.metaweb.gridworks.expr.ExpressionUtils;
public class BooleanCriterion extends Criterion {
final static protected EvalError s_error = new EvalError("Not a boolean");
@Override
public KeyMaker createKeyMaker() {
return new KeyMaker() {
@Override
protected Object makeKey(Object value) {
if (ExpressionUtils.isNonBlankData(value)) {
if (value instanceof Boolean) {
return value;
} else if (value instanceof String) {
return Boolean.parseBoolean((String) value);
} else {
return s_error;
}
}
return value;
}
@Override
public int compareKeys(Object key1, Object key2) {
return ((Boolean) key1).compareTo((Boolean) key2);
}
};
}
}

View File

@ -0,0 +1,94 @@
package com.metaweb.gridworks.sorting;
import org.json.JSONException;
import org.json.JSONObject;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.model.Column;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Record;
import com.metaweb.gridworks.model.Row;
abstract public class Criterion {
public String columnName;
protected int cellIndex;
// These take on positive and negative values to indicate where blanks and errors
// go relative to non-blank values. They are also relative to each another.
// Blanks and errors are not affected by the reverse flag.
public int blankPosition = 1;
public int errorPosition = 2;
public boolean reverse;
public void initializeFromJSON(Project project, JSONObject obj) throws JSONException {
if (obj.has("column") && !obj.isNull("column")) {
columnName = obj.getString("column");
Column column = project.columnModel.getColumnByName(columnName);
cellIndex = column != null ? column.getCellIndex() : -1;
}
if (obj.has("blankPosition") && !obj.isNull("blankPosition")) {
blankPosition = obj.getInt("blankPosition");
}
if (obj.has("errorPosition") && !obj.isNull("errorPosition")) {
blankPosition = obj.getInt("errorPosition");
}
if (obj.has("reverse") && !obj.isNull("reverse")) {
reverse = obj.getBoolean("reverse");
}
}
abstract public class KeyMaker {
public Object makeKey(Project project, Record record) {
Object error = null;
Object finalKey = null;
for (int r = record.fromRowIndex; r < record.toRowIndex; r++) {
Object key = makeKey(project, project.rows.get(r), r);
if (ExpressionUtils.isError(key)) {
error = key;
} else if (ExpressionUtils.isNonBlankData(key)) {
if (finalKey == null) {
finalKey = key;
} else {
int c = compareKeys(finalKey, key);
if (reverse) {
if (c < 0) { // key > finalKey
finalKey = key;
}
} else {
if (c > 0) { // key < finalKey
finalKey = key;
}
}
}
}
}
if (finalKey != null) {
return finalKey;
} else if (error != null) {
return error;
} else {
return null;
}
}
public Object makeKey(Project project, Row row, int rowIndex) {
if (cellIndex < 0) {
return null;
} else {
Object value = row.getCellValue(cellIndex);
return makeKey(value);
}
}
abstract public int compareKeys(Object key1, Object key2);
abstract protected Object makeKey(Object value);
}
abstract public KeyMaker createKeyMaker();
}

View File

@ -0,0 +1,35 @@
package com.metaweb.gridworks.sorting;
import java.util.Calendar;
import java.util.Date;
import com.metaweb.gridworks.expr.EvalError;
import com.metaweb.gridworks.expr.ExpressionUtils;
public class DateCriterion extends Criterion {
final static protected EvalError s_error = new EvalError("Not a date");
@Override
public KeyMaker createKeyMaker() {
return new KeyMaker() {
@Override
protected Object makeKey(Object value) {
if (ExpressionUtils.isNonBlankData(value)) {
if (value instanceof Date) {
return value;
} else if (value instanceof Calendar) {
return ((Calendar) value).getTime();
} else {
return s_error;
}
}
return value;
}
@Override
public int compareKeys(Object key1, Object key2) {
return ((Date) key1).compareTo((Date) key2);
}
};
}
}

View File

@ -0,0 +1,50 @@
package com.metaweb.gridworks.sorting;
import java.util.Calendar;
import java.util.Date;
import com.metaweb.gridworks.expr.EvalError;
import com.metaweb.gridworks.expr.ExpressionUtils;
public class NumberCriterion extends Criterion {
final static protected EvalError s_error = new EvalError("Not a number");
@Override
public KeyMaker createKeyMaker() {
return new KeyMaker() {
@Override
protected Object makeKey(Object value) {
if (ExpressionUtils.isNonBlankData(value)) {
if (value instanceof Number) {
return value;
} else if (value instanceof Boolean) {
return ((Boolean) value).booleanValue() ? 1 : 0;
} else if (value instanceof Date) {
return ((Date) value).getTime();
} else if (value instanceof Calendar) {
return ((Calendar) value).getTime().getTime();
} else if (value instanceof String) {
try {
double d = Double.parseDouble((String) value);
if (!Double.isNaN(d)) {
return d;
}
} catch (NumberFormatException e) {
// fall through
}
}
return s_error;
}
return value;
}
@Override
public int compareKeys(Object key1, Object key2) {
double d1 = ((Number) key1).doubleValue();
double d2 = ((Number) key2).doubleValue();
return d1 < d2 ? -1 : (d1 > d2 ? 1 : 0);
}
};
}
}

View File

@ -0,0 +1,60 @@
package com.metaweb.gridworks.sorting;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.metaweb.gridworks.browsing.RecordVisitor;
import com.metaweb.gridworks.browsing.RowVisitor;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Record;
import com.metaweb.gridworks.sorting.Criterion.KeyMaker;
public class SortingRecordVisitor extends BaseSorter implements RecordVisitor {
final protected RowVisitor _visitor;
protected List<Record> _records;
public SortingRecordVisitor(RowVisitor visitor) {
_visitor = visitor;
}
@Override
public void start(Project project) {
_records = new ArrayList<Record>(project.recordModel.getRecordCount());
}
@Override
public void end(Project project) {
_visitor.start(project);
Collections.sort(_records, new Comparator<Record>() {
Project project;
Comparator<Record> init(Project project) {
this.project = project;
return this;
}
@Override
public int compare(Record o1, Record o2) {
return SortingRecordVisitor.this.compare(project, o1, o1.recordIndex, o2, o2.recordIndex);
}
}.init(project));
_visitor.end(project);
}
@Override
public boolean visit(Project project, Record record) {
_records.add(record);
return false;
}
@Override
protected Object makeKey(
Project project, KeyMaker keyMaker, Criterion c, Object o, int index) {
return keyMaker.makeKey(project, (Record) o);
}
}

View File

@ -0,0 +1,69 @@
package com.metaweb.gridworks.sorting;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.metaweb.gridworks.browsing.RowVisitor;
import com.metaweb.gridworks.model.Project;
import com.metaweb.gridworks.model.Row;
import com.metaweb.gridworks.sorting.Criterion.KeyMaker;
public class SortingRowVisitor extends BaseSorter implements RowVisitor {
final protected RowVisitor _visitor;
protected List<IndexedRow> _indexedRows;
static protected class IndexedRow {
final int index;
final Row row;
IndexedRow(int index, Row row) {
this.index = index;
this.row = row;
}
}
public SortingRowVisitor(RowVisitor visitor) {
_visitor = visitor;
}
@Override
public void start(Project project) {
_indexedRows = new ArrayList<IndexedRow>(project.rows.size());
}
@Override
public void end(Project project) {
_visitor.start(project);
Collections.sort(_indexedRows, new Comparator<IndexedRow>() {
Project project;
Comparator<IndexedRow> init(Project project) {
this.project = project;
return this;
}
@Override
public int compare(IndexedRow o1, IndexedRow o2) {
return SortingRowVisitor.this.compare(project, o1.row, o1.index, o2.row, o2.index);
}
}.init(project));
_visitor.end(project);
}
@Override
public boolean visit(Project project, int rowIndex, Row row) {
_indexedRows.add(new IndexedRow(rowIndex, row));
return false;
}
@Override
protected Object makeKey(
Project project, KeyMaker keyMaker, Criterion c, Object o, int index) {
return keyMaker.makeKey(project, (Row) o, index);
}
}

View File

@ -0,0 +1,40 @@
package com.metaweb.gridworks.sorting;
import org.json.JSONException;
import org.json.JSONObject;
import com.metaweb.gridworks.expr.ExpressionUtils;
import com.metaweb.gridworks.model.Project;
public class StringCriterion extends Criterion {
public boolean caseSensitive;
@Override
public void initializeFromJSON(Project project, JSONObject obj) throws JSONException {
super.initializeFromJSON(project, obj);
if (obj.has("caseSensitive") && !obj.isNull("caseSensitive")) {
caseSensitive = obj.getBoolean("caseSensitive");
}
}
@Override
public KeyMaker createKeyMaker() {
return new KeyMaker() {
@Override
protected Object makeKey(Object value) {
return (ExpressionUtils.isNonBlankData(value) && !(value instanceof String)) ?
value.toString() : value;
}
@Override
public int compareKeys(Object key1, Object key2) {
if (StringCriterion.this.caseSensitive) {
return ((String) key1).compareTo((String) key2);
} else {
return ((String) key1).compareToIgnoreCase((String) key2);
}
}
};
}
}