Added support for including dependent rows in row visiting. Facets still don't count them, though.
git-svn-id: http://google-refine.googlecode.com/svn/trunk@282 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
parent
7e2667ab45
commit
af3cb76056
@ -9,10 +9,12 @@ import com.metaweb.gridworks.model.Row;
|
||||
|
||||
public class ConjunctiveFilteredRows implements FilteredRows {
|
||||
final protected List<RowFilter> _rowFilters = new LinkedList<RowFilter>();
|
||||
final protected boolean _contextual;
|
||||
final protected boolean _includeContextual;
|
||||
final protected boolean _includeDependent;
|
||||
|
||||
public ConjunctiveFilteredRows(boolean contextual) {
|
||||
_contextual = contextual;
|
||||
public ConjunctiveFilteredRows(boolean includeContextual, boolean includeDependent) {
|
||||
_includeContextual = includeContextual;
|
||||
_includeDependent = includeDependent;
|
||||
}
|
||||
|
||||
public void add(RowFilter rowFilter) {
|
||||
@ -20,63 +22,66 @@ public class ConjunctiveFilteredRows implements FilteredRows {
|
||||
}
|
||||
|
||||
public void accept(Project project, RowVisitor visitor) {
|
||||
if (_contextual) {
|
||||
contextualAccept(project, visitor);
|
||||
} else {
|
||||
simpleAccept(project, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
protected void simpleAccept(Project project, RowVisitor visitor) {
|
||||
for (int i = 0; i < project.rows.size(); i++) {
|
||||
Row row = project.rows.get(i);
|
||||
|
||||
boolean ok = true;
|
||||
for (RowFilter rowFilter : _rowFilters) {
|
||||
if (!rowFilter.filterRow(project, i, row)) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
visitor.visit(project, i, row, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void contextualAccept(Project project, RowVisitor visitor) {
|
||||
int lastVisitedRow = -1;
|
||||
int lastRecordRowAccepted = -1;
|
||||
|
||||
for (int i = 0; i < project.rows.size(); i++) {
|
||||
int c = project.rows.size();
|
||||
for (int i = 0; i < c; i++) {
|
||||
Row row = project.rows.get(i);
|
||||
|
||||
boolean ok = true;
|
||||
for (RowFilter rowFilter : _rowFilters) {
|
||||
if (!rowFilter.filterRow(project, i, row)) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checkRow(project, i, row)) {
|
||||
if (row.recordIndex >= 0) {
|
||||
// this is a record row itself
|
||||
|
||||
if (ok) {
|
||||
if (row.contextRows != null && lastVisitedRow < i - 1) {
|
||||
for (int contextRowIndex : row.contextRows) {
|
||||
if (contextRowIndex > lastVisitedRow) {
|
||||
visitor.visit(
|
||||
project,
|
||||
contextRowIndex,
|
||||
project.rows.get(contextRowIndex),
|
||||
true
|
||||
);
|
||||
lastVisitedRow = contextRowIndex;
|
||||
}
|
||||
lastRecordRowAccepted = i;
|
||||
}
|
||||
|
||||
visitRow(project, visitor, i, row, lastVisitedRow);
|
||||
|
||||
lastVisitedRow = i;
|
||||
} else if (
|
||||
_includeDependent &&
|
||||
row.recordIndex < 0 &&
|
||||
row.contextRows != null &&
|
||||
row.contextRows.size() > 0) {
|
||||
|
||||
if (row.contextRows.get(0) == lastRecordRowAccepted) {
|
||||
visitor.visit(project, i, row, false, true);
|
||||
lastVisitedRow = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void visitRow(Project project, RowVisitor visitor, int rowIndex, Row row, int lastVisitedRow) {
|
||||
if (_includeContextual) {
|
||||
if (row.contextRows != null && lastVisitedRow < rowIndex - 1) {
|
||||
for (int contextRowIndex : row.contextRows) {
|
||||
if (contextRowIndex > lastVisitedRow) {
|
||||
visitor.visit(
|
||||
project,
|
||||
contextRowIndex,
|
||||
project.rows.get(contextRowIndex),
|
||||
true,
|
||||
false
|
||||
);
|
||||
lastVisitedRow = contextRowIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitor.visit(project, i, row, false);
|
||||
lastVisitedRow = i;
|
||||
visitor.visit(project, rowIndex, row, false, false);
|
||||
} else {
|
||||
visitor.visit(project, rowIndex, row, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean checkRow(Project project, int rowIndex, Row row) {
|
||||
for (RowFilter rowFilter : _rowFilters) {
|
||||
if (!rowFilter.filterRow(project, rowIndex, row)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -20,17 +20,18 @@ import com.metaweb.gridworks.model.Project;
|
||||
public class Engine implements Jsonizable {
|
||||
protected Project _project;
|
||||
protected List<Facet> _facets = new LinkedList<Facet>();
|
||||
protected boolean _includeDependent;
|
||||
|
||||
public Engine(Project project) {
|
||||
_project = project;
|
||||
}
|
||||
|
||||
public FilteredRows getAllFilteredRows(boolean contextual) {
|
||||
return getFilteredRows(null, contextual);
|
||||
public FilteredRows getAllFilteredRows(boolean includeContextual) {
|
||||
return getFilteredRows(null, includeContextual);
|
||||
}
|
||||
|
||||
public FilteredRows getFilteredRows(Facet except, boolean contextual) {
|
||||
ConjunctiveFilteredRows cfr = new ConjunctiveFilteredRows(contextual);
|
||||
public FilteredRows getFilteredRows(Facet except, boolean includeContextual) {
|
||||
ConjunctiveFilteredRows cfr = new ConjunctiveFilteredRows(includeContextual, _includeDependent);
|
||||
for (Facet facet : _facets) {
|
||||
if (facet != except) {
|
||||
RowFilter rowFilter = facet.getRowFilter();
|
||||
@ -64,6 +65,10 @@ public class Engine implements Jsonizable {
|
||||
_facets.add(facet);
|
||||
}
|
||||
}
|
||||
|
||||
if (o.has("includeDependent") && !o.isNull("includeDependent")) {
|
||||
_includeDependent = o.getBoolean("includeDependent");
|
||||
}
|
||||
}
|
||||
|
||||
public void computeFacets() throws JSONException {
|
||||
@ -78,11 +83,13 @@ public class Engine implements Jsonizable {
|
||||
throws JSONException {
|
||||
|
||||
writer.object();
|
||||
writer.key("facets"); writer.array();
|
||||
for (Facet facet : _facets) {
|
||||
facet.write(writer, options);
|
||||
}
|
||||
writer.endArray();
|
||||
writer.key("facets");
|
||||
writer.array();
|
||||
for (Facet facet : _facets) {
|
||||
facet.write(writer, options);
|
||||
}
|
||||
writer.endArray();
|
||||
writer.key("includeDependent"); writer.value(_includeDependent);
|
||||
writer.endObject();
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,11 @@ import com.metaweb.gridworks.model.Project;
|
||||
import com.metaweb.gridworks.model.Row;
|
||||
|
||||
public interface RowVisitor {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual);
|
||||
|
||||
public boolean visit(
|
||||
Project project,
|
||||
int rowIndex, // zero-based row index
|
||||
Row row,
|
||||
boolean contextual, // true if this row is included because it's the context row of an included row
|
||||
boolean dependent // true if this row is included because it depends on an included row
|
||||
);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public class ExpressionNominalRowGrouper implements RowVisitor {
|
||||
_cellIndex = cellIndex;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = _cellIndex < 0 ? null : row.getCell(_cellIndex);
|
||||
|
||||
Properties bindings = ExpressionUtils.createBindings(project);
|
||||
|
@ -28,7 +28,7 @@ public class ExpressionNumericRowBinner implements RowVisitor {
|
||||
bins = new int[_index.getBins().length];
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.getCell(_cellIndex);
|
||||
|
||||
Properties bindings = ExpressionUtils.createBindings(project);
|
||||
|
@ -62,7 +62,7 @@ public class BinningClusterer extends Clusterer {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.getCell(_colindex);
|
||||
if (cell != null && cell.value != null) {
|
||||
String v = cell.value.toString();
|
||||
|
@ -76,7 +76,7 @@ public class kNNClusterer extends Clusterer {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.cells.get(_colindex);
|
||||
if (cell != null && cell.value != null) {
|
||||
Object v = cell.value;
|
||||
@ -114,7 +114,7 @@ public class kNNClusterer extends Clusterer {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.getCell(_colindex);
|
||||
if (cell != null && cell.value != null) {
|
||||
Object v = cell.value;
|
||||
|
@ -53,7 +53,7 @@ public class GetRowsCommand extends Command {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean internalVisit(int rowIndex, Row row, boolean contextual) {
|
||||
public boolean internalVisit(int rowIndex, Row row, boolean contextual, boolean includeDependent) {
|
||||
try {
|
||||
if (contextual) {
|
||||
options.put("extra", extra);
|
||||
@ -99,19 +99,19 @@ public class GetRowsCommand extends Command {
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
boolean r = false;
|
||||
|
||||
if (total >= start && total < start + limit) {
|
||||
r = internalVisit(rowIndex, row, contextual);
|
||||
r = internalVisit(rowIndex, row, includeContextual, includeDependent);
|
||||
}
|
||||
if (!contextual) {
|
||||
if (!includeContextual) {
|
||||
total++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
protected boolean internalVisit(int rowIndex, Row row, boolean contextual) {
|
||||
protected boolean internalVisit(int rowIndex, Row row, boolean contextual, boolean includeDependent) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class TsvExporter implements Exporter {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual, boolean includeDependent) {
|
||||
boolean first = true;
|
||||
try {
|
||||
for (Column column : project.columnModel.columns) {
|
||||
|
@ -246,13 +246,17 @@ public class Project {
|
||||
lastNonBlankRowsByGroup[i] = -1;
|
||||
}
|
||||
|
||||
int rowCount = rows.size();
|
||||
int groupCount = keyedGroups.size();
|
||||
|
||||
int recordIndex = 0;
|
||||
for (int r = 0; r < rows.size(); r++) {
|
||||
for (int r = 0; r < rowCount; r++) {
|
||||
Row row = rows.get(r);
|
||||
row.contextRows = null;
|
||||
row.contextRowSlots = null;
|
||||
row.contextCellSlots = null;
|
||||
|
||||
for (int g = 0; g < keyedGroups.size(); g++) {
|
||||
for (int g = 0; g < groupCount; g++) {
|
||||
Group group = keyedGroups.get(g);
|
||||
|
||||
if (!ExpressionUtils.isNonBlankData(row.getCellValue(group.keyCellIndex))) {
|
||||
@ -296,6 +300,7 @@ public class Project {
|
||||
|
||||
rootKeyedGroup.cellIndices = new int[count - 1];
|
||||
rootKeyedGroup.keyCellIndex = columnModel.columns.get(columnModel.getKeyColumnIndex()).getCellIndex();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i < rootKeyedGroup.keyCellIndex) {
|
||||
rootKeyedGroup.cellIndices[i] = i;
|
||||
|
@ -121,10 +121,10 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
|
||||
Properties bindings = ExpressionUtils.createBindings(project);
|
||||
|
||||
return new RowVisitor() {
|
||||
int cellIndex;
|
||||
Properties bindings;
|
||||
List<CellAtRow> cellsAtRows;
|
||||
Evaluable eval;
|
||||
int cellIndex;
|
||||
Properties bindings;
|
||||
List<CellAtRow> cellsAtRows;
|
||||
Evaluable eval;
|
||||
|
||||
public RowVisitor init(int cellIndex, Properties bindings, List<CellAtRow> cellsAtRows, Evaluable eval) {
|
||||
this.cellIndex = cellIndex;
|
||||
@ -134,7 +134,7 @@ public class ColumnAdditionOperation extends EngineDependentOperation {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.getCell(cellIndex);
|
||||
|
||||
ExpressionUtils.bind(bindings, row, rowIndex, cell);
|
||||
|
@ -163,7 +163,7 @@ public class MassEditOperation extends EngineDependentMassCellOperation {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.getCell(cellIndex);
|
||||
|
||||
ExpressionUtils.bind(bindings, row, rowIndex, cell);
|
||||
|
@ -69,7 +69,7 @@ public class ReconDiscardJudgmentsOperation extends EngineDependentMassCellOpera
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.getCell(cellIndex);
|
||||
if (cell != null && cell.recon != null) {
|
||||
Recon recon = cell.recon.dup();
|
||||
|
@ -159,7 +159,7 @@ public class ReconJudgeSimilarCellsOperation extends EngineDependentMassCellOper
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.getCell(_cellIndex);
|
||||
if (cell != null &&
|
||||
ExpressionUtils.isNonBlankData(cell.value) &&
|
||||
|
@ -82,7 +82,7 @@ public class ReconMarkNewTopicsOperation extends EngineDependentMassCellOperatio
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.getCell(cellIndex);
|
||||
if (cell != null) {
|
||||
Recon recon = null;
|
||||
|
@ -69,7 +69,7 @@ public class ReconMatchBestCandidatesOperation extends EngineDependentMassCellOp
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
if (cellIndex < row.cells.size()) {
|
||||
Cell cell = row.cells.get(cellIndex);
|
||||
if (cell.recon != null) {
|
||||
|
@ -103,7 +103,7 @@ public class ReconMatchSpecificTopicOperation extends EngineDependentMassCellOpe
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
if (cellIndex < row.cells.size()) {
|
||||
Cell cell = row.cells.get(cellIndex);
|
||||
|
||||
|
@ -170,7 +170,7 @@ public class ReconOperation extends EngineDependentOperation {
|
||||
|
||||
FilteredRows filteredRows = engine.getAllFilteredRows(false);
|
||||
filteredRows.accept(_project, new RowVisitor() {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
if (_cellIndex < row.cells.size()) {
|
||||
Cell cell = row.cells.get(_cellIndex);
|
||||
if (cell != null && ExpressionUtils.isNonBlankData(cell.value)) {
|
||||
|
@ -77,7 +77,7 @@ public class RowStarOperation extends EngineDependentOperation {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
if (row.starred != _starred) {
|
||||
RowStarChange change = new RowStarChange(rowIndex, _starred);
|
||||
|
||||
|
@ -118,7 +118,7 @@ public class TextTransformOperation extends EngineDependentMassCellOperation {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean contextual) {
|
||||
public boolean visit(Project project, int rowIndex, Row row, boolean includeContextual, boolean includeDependent) {
|
||||
Cell cell = row.getCell(cellIndex);
|
||||
Object oldValue = cell != null ? cell.value : null;
|
||||
|
||||
|
@ -42,7 +42,10 @@ BrowsingEngine.prototype._initializeUI = function() {
|
||||
|
||||
this._div.html(
|
||||
'<div class="browsing-panel-indicator" bind="indicator"><img src="images/small-spinner.gif" /> refreshing facets ...</div>' +
|
||||
'<div class="browsing-panel-controls" bind="controls"><a href="javascript:{}" bind="refreshLink">refresh facets</a></div>' +
|
||||
'<div class="browsing-panel-controls" bind="controls">' +
|
||||
'<input type="checkbox" bind="includeDependentRowsCheck" /> show dependent rows • ' +
|
||||
'<a href="javascript:{}" bind="refreshLink">refresh</a></div>' +
|
||||
'</div>' +
|
||||
'<ul bind="facets" class="facets-container"></ul>'
|
||||
);
|
||||
this._elmts = DOM.bind(this._div);
|
||||
@ -54,6 +57,10 @@ BrowsingEngine.prototype._initializeUI = function() {
|
||||
});
|
||||
this._elmts.facets.disableSelection();
|
||||
|
||||
this._elmts.includeDependentRowsCheck.change(function() {
|
||||
Gridworks.update({ engineChanged: true });
|
||||
});
|
||||
|
||||
this._elmts.refreshLink.click(function() { self.update(); });
|
||||
};
|
||||
|
||||
@ -73,7 +80,10 @@ BrowsingEngine.prototype._updateFacetOrder = function() {
|
||||
};
|
||||
|
||||
BrowsingEngine.prototype.getJSON = function(keepUnrestrictedFacets) {
|
||||
var a = { facets: [] };
|
||||
var a = {
|
||||
facets: [],
|
||||
includeDependent: this._elmts.includeDependentRowsCheck[0].checked
|
||||
};
|
||||
for (var i = 0; i < this._facets.length; i++) {
|
||||
var facet = this._facets[i];
|
||||
if (keepUnrestrictedFacets || facet.facet.hasSelection()) {
|
||||
|
Loading…
Reference in New Issue
Block a user