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:
parent
0709ec3f92
commit
496823e564
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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++) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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>");
|
||||
|
@ -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 {
|
||||
|
@ -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++);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
136
src/main/java/com/metaweb/gridworks/sorting/BaseSorter.java
Normal file
136
src/main/java/com/metaweb/gridworks/sorting/BaseSorter.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
94
src/main/java/com/metaweb/gridworks/sorting/Criterion.java
Normal file
94
src/main/java/com/metaweb/gridworks/sorting/Criterion.java
Normal 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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user