Fix FillDown and BlankDown operations on records.

Closes #472.
This commit is contained in:
Antonin Delpeuch 2018-04-21 22:11:54 +02:00
parent 6235786a5b
commit 53c12ca2df
4 changed files with 166 additions and 4 deletions

View File

@ -40,6 +40,7 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.google.refine.browsing.Engine.Mode;
import com.google.refine.browsing.RowVisitor; import com.google.refine.browsing.RowVisitor;
import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.ExpressionUtils;
import com.google.refine.model.AbstractOperation; import com.google.refine.model.AbstractOperation;
@ -97,15 +98,18 @@ public class BlankDownOperation extends EngineDependentMassCellOperation {
@Override @Override
protected RowVisitor createRowVisitor(Project project, List<CellChange> cellChanges, long historyEntryID) throws Exception { protected RowVisitor createRowVisitor(Project project, List<CellChange> cellChanges, long historyEntryID) throws Exception {
Column column = project.columnModel.getColumnByName(_columnName); Column column = project.columnModel.getColumnByName(_columnName);
Mode engineMode = createEngine(project).getMode();
return new RowVisitor() { return new RowVisitor() {
int cellIndex; int cellIndex;
List<CellChange> cellChanges; List<CellChange> cellChanges;
Cell previousCell; Cell previousCell;
Mode engineMode;
public RowVisitor init(int cellIndex, List<CellChange> cellChanges) { public RowVisitor init(int cellIndex, List<CellChange> cellChanges, Mode engineMode) {
this.cellIndex = cellIndex; this.cellIndex = cellIndex;
this.cellChanges = cellChanges; this.cellChanges = cellChanges;
this.engineMode = engineMode;
return this; return this;
} }
@ -121,6 +125,9 @@ public class BlankDownOperation extends EngineDependentMassCellOperation {
@Override @Override
public boolean visit(Project project, int rowIndex, Row row) { public boolean visit(Project project, int rowIndex, Row row) {
if (engineMode.equals(Mode.RecordBased) && ExpressionUtils.isNonBlankData(row.getCellValue(0))) {
previousCell = null;
}
Object value = row.getCellValue(cellIndex); Object value = row.getCellValue(cellIndex);
if (ExpressionUtils.isNonBlankData(value)) { if (ExpressionUtils.isNonBlankData(value)) {
Cell cell = row.getCell(cellIndex); Cell cell = row.getCell(cellIndex);
@ -134,6 +141,6 @@ public class BlankDownOperation extends EngineDependentMassCellOperation {
} }
return false; return false;
} }
}.init(column.getCellIndex(), cellChanges); }.init(column.getCellIndex(), cellChanges, engineMode);
} }
} }

View File

@ -40,6 +40,8 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONWriter; import org.json.JSONWriter;
import com.google.refine.browsing.Engine;
import com.google.refine.browsing.Engine.Mode;
import com.google.refine.browsing.RowVisitor; import com.google.refine.browsing.RowVisitor;
import com.google.refine.expr.ExpressionUtils; import com.google.refine.expr.ExpressionUtils;
import com.google.refine.model.AbstractOperation; import com.google.refine.model.AbstractOperation;
@ -97,15 +99,19 @@ public class FillDownOperation extends EngineDependentMassCellOperation {
@Override @Override
protected RowVisitor createRowVisitor(Project project, List<CellChange> cellChanges, long historyEntryID) throws Exception { protected RowVisitor createRowVisitor(Project project, List<CellChange> cellChanges, long historyEntryID) throws Exception {
Column column = project.columnModel.getColumnByName(_columnName); Column column = project.columnModel.getColumnByName(_columnName);
Engine engine = createEngine(project);
Mode engineMode = engine.getMode();
return new RowVisitor() { return new RowVisitor() {
int cellIndex; int cellIndex;
List<CellChange> cellChanges; List<CellChange> cellChanges;
Cell previousCell; Cell previousCell;
Mode engineMode;
public RowVisitor init(int cellIndex, List<CellChange> cellChanges) { public RowVisitor init(int cellIndex, List<CellChange> cellChanges, Mode engineMode) {
this.cellIndex = cellIndex; this.cellIndex = cellIndex;
this.cellChanges = cellChanges; this.cellChanges = cellChanges;
this.engineMode = engineMode;
return this; return this;
} }
@ -122,6 +128,9 @@ public class FillDownOperation extends EngineDependentMassCellOperation {
@Override @Override
public boolean visit(Project project, int rowIndex, Row row) { public boolean visit(Project project, int rowIndex, Row row) {
Object value = row.getCellValue(cellIndex); Object value = row.getCellValue(cellIndex);
if (engineMode.equals(Mode.RecordBased) && ExpressionUtils.isNonBlankData(row.getCellValue(0))) {
previousCell = null;
}
if (ExpressionUtils.isNonBlankData(value)) { if (ExpressionUtils.isNonBlankData(value)) {
previousCell = row.getCell(cellIndex); previousCell = row.getCell(cellIndex);
} else if (previousCell != null) { } else if (previousCell != null) {
@ -130,6 +139,6 @@ public class FillDownOperation extends EngineDependentMassCellOperation {
} }
return false; return false;
} }
}.init(column.getCellIndex(), cellChanges); }.init(column.getCellIndex(), cellChanges, engineMode);
} }
} }

View File

@ -0,0 +1,64 @@
package com.google.refine.tests.operations.cell;
import java.util.Properties;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.refine.ProjectManager;
import com.google.refine.model.AbstractOperation;
import com.google.refine.model.Project;
import com.google.refine.operations.cell.BlankDownOperation;
import com.google.refine.process.Process;
import com.google.refine.tests.RefineTest;
public class BlankDownTests extends RefineTest {
Project project = null;
@BeforeMethod
public void setUp() {
project = createCSVProject(
"key,first,second\n"+
"a,b,c\n"+
",d,c\n"+
"e,f,c\n"+
",,c\n");
}
@AfterMethod
public void tearDown() {
ProjectManager.singleton.deleteProject(project.id);
}
@Test
public void testBlankDownRecords() throws Exception {
AbstractOperation op = new BlankDownOperation(
new JSONObject("{\"mode\":\"record-based\",\"facets\":[]}"),
"second");
Process process = op.createProcess(project, new Properties());
process.performImmediate();
Assert.assertEquals("c", project.rows.get(0).cells.get(2).value);
Assert.assertNull(project.rows.get(1).cells.get(2));
Assert.assertEquals("c", project.rows.get(2).cells.get(2).value);
Assert.assertNull(project.rows.get(3).cells.get(2));
}
@Test
public void testBlankDownRows() throws Exception {
AbstractOperation op = new BlankDownOperation(
new JSONObject("{\"mode\":\"row-based\",\"facets\":[]}"),
"second");
Process process = op.createProcess(project, new Properties());
process.performImmediate();
Assert.assertEquals("c", project.rows.get(0).cells.get(2).value);
Assert.assertNull(project.rows.get(1).cells.get(2));
Assert.assertNull(project.rows.get(2).cells.get(2));
Assert.assertNull(project.rows.get(3).cells.get(2));
}
}

View File

@ -0,0 +1,82 @@
package com.google.refine.tests.operations.cell;
import java.util.Properties;
import org.json.JSONObject;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.refine.ProjectManager;
import com.google.refine.model.AbstractOperation;
import com.google.refine.model.Project;
import com.google.refine.operations.cell.FillDownOperation;
import com.google.refine.tests.RefineTest;
import com.google.refine.process.Process;
public class FillDownTests extends RefineTest {
Project project = null;
@BeforeMethod
public void setUp() {
project = createCSVProject(
"key,first,second\n"+
"a,b,c\n"+
",d,\n"+
"e,f,\n"+
",,h\n");
}
@AfterMethod
public void tearDown() {
ProjectManager.singleton.deleteProject(project.id);
}
@Test
public void testFillDownRecordKey() throws Exception {
AbstractOperation op = new FillDownOperation(
new JSONObject("{\"mode\":\"record-based\",\"facets\":[]}"),
"key");
Process process = op.createProcess(project, new Properties());
process.performImmediate();
Assert.assertEquals("a", project.rows.get(0).cells.get(0).value);
Assert.assertEquals("a", project.rows.get(1).cells.get(0).value);
Assert.assertEquals("e", project.rows.get(2).cells.get(0).value);
Assert.assertEquals("e", project.rows.get(3).cells.get(0).value);
}
// For issue #742
// https://github.com/OpenRefine/OpenRefine/issues/742
@Test
public void testFillDownRecords() throws Exception {
AbstractOperation op = new FillDownOperation(
new JSONObject("{\"mode\":\"record-based\",\"facets\":[]}"),
"second");
Process process = op.createProcess(project, new Properties());
process.performImmediate();
Assert.assertEquals("c", project.rows.get(0).cells.get(2).value);
Assert.assertEquals("c", project.rows.get(1).cells.get(2).value);
Assert.assertNull(project.rows.get(2).cells.get(2));
Assert.assertEquals("h", project.rows.get(3).cells.get(2).value);
}
// For issue #742
// https://github.com/OpenRefine/OpenRefine/issues/742
@Test
public void testFillDownRows() throws Exception {
AbstractOperation op = new FillDownOperation(
new JSONObject("{\"mode\":\"row-based\",\"facets\":[]}"),
"second");
Process process = op.createProcess(project, new Properties());
process.performImmediate();
Assert.assertEquals("c", project.rows.get(0).cells.get(2).value);
Assert.assertEquals("c", project.rows.get(1).cells.get(2).value);
Assert.assertEquals("c", project.rows.get(2).cells.get(2).value);
Assert.assertEquals("h", project.rows.get(3).cells.get(2).value);
}
}