support default project name and column name for cross() (#2518)

This commit is contained in:
Lu Liu 2020-05-22 15:39:57 +08:00 committed by GitHub
parent f478356e17
commit e89eaf0ee2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 10 deletions

View File

@ -3,6 +3,7 @@ package com.google.refine;
import com.google.refine.expr.ExpressionUtils;
import com.google.refine.expr.HasFieldsListImpl;
import com.google.refine.expr.WrappedRow;
import com.google.refine.expr.functions.Cross;
import com.google.refine.model.Column;
import com.google.refine.model.Project;
import com.google.refine.model.Row;
@ -76,6 +77,14 @@ public class LookupCacheManager {
return;
}
// if this is a lookup on the index column
if (lookup.targetColumnName.equals(Cross.INDEX_COLUMN_NAME)) {
for (int r = 0; r < targetProject.rows.size(); r++) {
lookup.valueToRowIndices.put(String.valueOf(r) , Collections.singletonList(r));
}
return; // return directly
}
Column targetColumn = targetProject.columnModel.getColumnByName(lookup.targetColumnName);
if (targetColumn == null) {
throw new LookupException("Unable to find column " + lookup.targetColumnName + " in project " + targetProjectMetadata.getName());

View File

@ -41,24 +41,37 @@ import com.google.refine.expr.EvalError;
import com.google.refine.expr.WrappedCell;
import com.google.refine.grel.ControlFunctionRegistry;
import com.google.refine.grel.Function;
import com.google.refine.model.Project;
import com.google.refine.util.GetProjectIDException;
import com.google.refine.util.LookupException;
public class Cross implements Function {
public static final String INDEX_COLUMN_NAME = "_OpenRefine_Index_Column_Name_";
@Override
public Object call(Properties bindings, Object[] args) {
if (args.length == 3) {
if (1 <= args.length && args.length <= 3) {
// 1st argument can take either value or cell(for backward compatibility)
Object v = args[0];
Object targetProjectName = args[1];
Object targetColumnName = args[2];
// if 2nd argument is omitted or set to "", use the current project name
Object targetProjectName = "";
boolean isCurrentProject = false;
if (args.length < 2 || args[1].equals("")) {
isCurrentProject = true;
} else {
targetProjectName = args[1];
}
// if 3rd argument is omitted or set to "", use the index column
Object targetColumnName = args.length < 3 || args[2].equals("") ? INDEX_COLUMN_NAME: args[2];
long targetProjectID;
ProjectLookup lookup;
if (v != null && targetProjectName instanceof String && targetColumnName instanceof String) {
try {
targetProjectID = ProjectManager.singleton.getProjectID((String) targetProjectName);
targetProjectID = isCurrentProject ? ((Project) bindings.get("project")).id :
ProjectManager.singleton.getProjectID((String) targetProjectName);
} catch (GetProjectIDException e) {
return new EvalError(e.getMessage());
}
@ -76,17 +89,21 @@ public class Cross implements Function {
}
}
}
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a cell or value, a project name to look up, and a column name in that project");
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a cell or value, a project name to look up (optional), and a column name in that project (optional)");
}
@Override
public String getDescription() {
return "Looks up the given value in the target column of the target project, returns an array of matched rows, cell will be interpreted as cell.value. Two values match if and only if they have the same string representation";
return "Looks up the given value in the target column of the target project, returns an array of matched rows. Two values match if and only if they have the same string representation. " +
"The first argument will be interpreted as cell.value if set to cell. " +
"The second argument will be interpreted as the current project name if omitted or set to \"\". " +
"The third argument will be interpreted as the index (starts from 0) column if omitted or set to \"\"";
}
@Override
public String getParams() {
return "cell or value, string projectName, string columnName";
return "cell or value, string projectName (optional), string columnName (optional)";
}
@Override

View File

@ -163,6 +163,49 @@ public class CrossTests extends RefineTest {
Assert.assertEquals(address, "50 Broadway Ave.");
}
@Test
// lookup the row with index 0 in the current project
public void crossFunctionOneArgumentTest() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", 0)).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "mary");
}
@Test
public void crossFunctionOneArgumentTest1() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", 0, "")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "mary");
}
@Test
public void crossFunctionOneArgumentTest2() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", 1, "", "")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "john");
}
@Test
public void crossFunctionTwoArgumentTest() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", "lamp", "", "gift")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "mary");
}
@Test
public void crossFunctionTwoArgumentTest1() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", 0, "My Address Book")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "120 Main St.");
}
@Test
public void crossFunctionTwoArgumentTest2() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", 0, "My Address Book", "")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "120 Main St.");
}
@Test
public void crossFunctionOneToOneTest() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", "mary", "My Address Book", "friend")).get(0)).row);
@ -328,7 +371,7 @@ public class CrossTests extends RefineTest {
@Test
public void crossFunctionNonLiteralValue() throws Exception {
Assert.assertEquals(((EvalError) invoke("cross", null, "My Address Book", "friend")).message,
"cross expects a cell or value, a project name to look up, and a column name in that project");
"cross expects a cell or value, a project name to look up (optional), and a column name in that project (optional)");
}
/**
@ -349,7 +392,11 @@ public class CrossTests extends RefineTest {
@Test
public void serializeCross() {
String json = "{\"description\":\"Looks up the given value in the target column of the target project, returns an array of matched rows, cell will be interpreted as cell.value. Two values match if and only if they have the same string representation\",\"params\":\"cell or value, string projectName, string columnName\",\"returns\":\"array\"}";
String json = "{\"description\":\"Looks up the given value in the target column of the target project, returns an array of matched rows. Two values match if and only if they have the same string representation. " +
"The first argument will be interpreted as cell.value if set to cell. " +
"The second argument will be interpreted as the current project name if omitted or set to \\\"\\\". " +
"The third argument will be interpreted as the index (starts from 0) column if omitted or set to \\\"\\\"\"," +
"\"params\":\"cell or value, string projectName (optional), string columnName (optional)\",\"returns\":\"array\"}";
TestUtils.isSerializedTo(new Cross(), json);
}
}