Support lookup by numbers for GREL cross function (#2468)

* support int & long argument for cross function

* support any types of a cell value
This commit is contained in:
Lu Liu 2020-03-26 15:57:10 +08:00 committed by GitHub
parent b602a5622e
commit f2b06418da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 35 deletions

View File

@ -56,10 +56,7 @@ public class Cross implements Function {
long targetProjectID; long targetProjectID;
ProjectLookup lookup; ProjectLookup lookup;
if (v != null && if (v != null && targetProjectName instanceof String && targetColumnName instanceof String) {
(v instanceof String || v instanceof WrappedCell) &&
targetProjectName != null && targetProjectName instanceof String &&
targetColumnName != null && targetColumnName instanceof String) {
try { try {
targetProjectID = ProjectManager.singleton.getProjectID((String) targetProjectName); targetProjectID = ProjectManager.singleton.getProjectID((String) targetProjectName);
} catch (GetProjectIDException e) { } catch (GetProjectIDException e) {
@ -71,24 +68,25 @@ public class Cross implements Function {
} catch (LookupException e) { } catch (LookupException e) {
return new EvalError(e.getMessage()); return new EvalError(e.getMessage());
} }
if (v instanceof String) {
return lookup.getRows(v); if (v instanceof WrappedCell) {
} else {
return lookup.getRows(((WrappedCell) v).cell.value); return lookup.getRows(((WrappedCell) v).cell.value);
} else {
return lookup.getRows(v);
} }
} }
} }
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a string or cell, a project name to join with, and a column name in that project"); return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a cell or cell value, a project name to look up, and a column name in that project");
} }
@Override @Override
public String getDescription() { public String getDescription() {
return "join with another project by column"; 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";
} }
@Override @Override
public String getParams() { public String getParams() {
return "cell c or string value, string projectName, string columnName"; return "cell c or object value, string projectName, string columnName";
} }
@Override @Override

View File

@ -28,7 +28,6 @@ package com.google.refine.expr.functions;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Properties; import java.util.Properties;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -81,7 +80,9 @@ public class CrossTests extends RefineTest {
+ "anne,17 Morning Crescent\n" + "anne,17 Morning Crescent\n"
+ "2017-05-12T05:45:00Z,dateTime\n" + "2017-05-12T05:45:00Z,dateTime\n"
+ "1600,integer\n" + "1600,integer\n"
+ "true,boolean\n"; + "123456789123456789,long\n"
+ "true,boolean\n"
+ "3.14,double\n";
projectAddress = createCSVProject(projectName, input); projectAddress = createCSVProject(projectName, input);
projectName = "Christmas Gifts"; projectName = "Christmas Gifts";
@ -90,6 +91,7 @@ public class CrossTests extends RefineTest {
+ "clock,john\n" + "clock,john\n"
+ "dateTime,2017-05-12T05:45:00Z\n" + "dateTime,2017-05-12T05:45:00Z\n"
+ "integer,1600\n" + "integer,1600\n"
+ "123456789123456789,long\n"
+ "boolean,true\n"; + "boolean,true\n";
projectGift = createCSVProject(projectName, input); projectGift = createCSVProject(projectName, input);
projectName = "Duplicate"; projectName = "Duplicate";
@ -103,10 +105,13 @@ public class CrossTests extends RefineTest {
//Add some non-string value cells to each project //Add some non-string value cells to each project
projectAddress.rows.get(4).cells.set(0, new Cell(dateTimeValue, null)); projectAddress.rows.get(4).cells.set(0, new Cell(dateTimeValue, null));
projectAddress.rows.get(5).cells.set(0, new Cell(1600, null)); projectAddress.rows.get(5).cells.set(0, new Cell(1600, null));
projectAddress.rows.get(6).cells.set(0, new Cell(true, null)); projectAddress.rows.get(6).cells.set(0, new Cell(123456789123456789L, null));
projectAddress.rows.get(7).cells.set(0, new Cell(true, null));
projectAddress.rows.get(8).cells.set(0, new Cell(3.14, null));
projectGift.rows.get(2).cells.set(1, new Cell(dateTimeValue, null)); projectGift.rows.get(2).cells.set(1, new Cell(dateTimeValue, null));
projectGift.rows.get(3).cells.set(1, new Cell(1600, null)); projectGift.rows.get(3).cells.set(1, new Cell(1600, null));
projectGift.rows.get(4).cells.set(1, new Cell(true, null)); projectGift.rows.get(4).cells.set(1, new Cell(123456789123456789L, null));
projectGift.rows.get(5).cells.set(1, new Cell(true, null));
// add a column address based on column recipient // add a column address based on column recipient
bindings.put("columnName", "recipient"); bindings.put("columnName", "recipient");
@ -139,7 +144,7 @@ public class CrossTests extends RefineTest {
Project project = (Project) bindings.get("project"); Project project = (Project) bindings.get("project");
Cell c = project.rows.get(0).cells.get(1); Cell c = project.rows.get(0).cells.get(1);
WrappedCell lookup = new WrappedCell(project, "recipient", c); WrappedCell lookup = new WrappedCell(project, "recipient", c);
Row row = ((Row)((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row); Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString(); String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "50 Broadway Ave."); Assert.assertEquals(address, "50 Broadway Ave.");
} }
@ -151,24 +156,24 @@ public class CrossTests extends RefineTest {
bindings.put("columnName", "gift"); // change the based column bindings.put("columnName", "gift"); // change the based column
Cell c = project.rows.get(0).cells.get(1); Cell c = project.rows.get(0).cells.get(1);
WrappedCell lookup = new WrappedCell(project, "recipient", c); WrappedCell lookup = new WrappedCell(project, "recipient", c);
Row row = ((Row)((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row); Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString(); String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "50 Broadway Ave."); Assert.assertEquals(address, "50 Broadway Ave.");
} }
@Test @Test
public void crossFunctionOneToOneTest() throws Exception { public void crossFunctionOneToOneTest() throws Exception {
Row row = ((Row)((WrappedRow) ((HasFieldsListImpl) invoke("cross", "mary", "My Address Book", "friend")).get(0)).row); Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", "mary", "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString(); String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "50 Broadway Ave."); Assert.assertEquals(address, "50 Broadway Ave.");
} }
/** /**
* To demonstrate that the cross function can join multiple rows. * To demonstrate that the cross function can look up multiple rows.
*/ */
@Test @Test
public void crossFunctionOneToManyTest() throws Exception { public void crossFunctionOneToManyTest() throws Exception {
Row row = ((Row)((WrappedRow) ((HasFieldsListImpl) invoke("cross", "john", "My Address Book", "friend")).get(1)).row); Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", "john", "My Address Book", "friend")).get(1)).row);
String address = row.getCell(1).value.toString(); String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "999 XXXXXX St."); Assert.assertEquals(address, "999 XXXXXX St.");
} }
@ -184,7 +189,7 @@ public class CrossTests extends RefineTest {
Project project = (Project) bindings.get("project"); Project project = (Project) bindings.get("project");
Cell c = project.rows.get(2).cells.get(1); Cell c = project.rows.get(2).cells.get(1);
WrappedCell lookup = new WrappedCell(project, "recipient", c); WrappedCell lookup = new WrappedCell(project, "recipient", c);
Row row = ((Row)((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row); Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString(); String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "dateTime"); Assert.assertEquals(address, "dateTime");
} }
@ -194,7 +199,7 @@ public class CrossTests extends RefineTest {
Project project = (Project) bindings.get("project"); Project project = (Project) bindings.get("project");
Cell c = project.rows.get(3).cells.get(1); Cell c = project.rows.get(3).cells.get(1);
WrappedCell lookup = new WrappedCell(project, "recipient", c); WrappedCell lookup = new WrappedCell(project, "recipient", c);
Row row = ((Row)((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row); Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString(); String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "integer"); Assert.assertEquals(address, "integer");
} }
@ -202,13 +207,47 @@ public class CrossTests extends RefineTest {
@Test @Test
public void crossFunctionBooleanTest() throws Exception { public void crossFunctionBooleanTest() throws Exception {
Project project = (Project) bindings.get("project"); Project project = (Project) bindings.get("project");
Cell c = project.rows.get(4).cells.get(1); Cell c = project.rows.get(5).cells.get(1);
WrappedCell lookup = new WrappedCell(project, "recipient", c); WrappedCell lookup = new WrappedCell(project, "recipient", c);
Row row = ((Row)((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row); Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", lookup, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString(); String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "boolean"); Assert.assertEquals(address, "boolean");
} }
@Test
public void crossFunctionIntegerArgumentTest() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", 1600, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "integer");
}
@Test
public void crossFunctionLongArgumentTest() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", 123456789123456789L, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "long");
}
@Test
public void crossFunctionDoubleArgumentTest() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", 3.14, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "double");
}
@Test
public void crossFunctionDateTimeArgumentTest() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", dateTimeValue, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "dateTime");
}
@Test
public void crossFunctionBooleanArgumentTest() throws Exception {
Row row = (((WrappedRow) ((HasFieldsListImpl) invoke("cross", true, "My Address Book", "friend")).get(0)).row);
String address = row.getCell(1).value.toString();
Assert.assertEquals(address, "boolean");
}
/** /**
* If no match, return null. * If no match, return null.
@ -224,18 +263,12 @@ public class CrossTests extends RefineTest {
/** /**
* *
* rest of cells shows "Error: cross expects a string or cell, a project name to join with, and a column name in that project" * rest of cells shows "Error: cross expects a cell or cell value, a project name to look up, and a column name in that project"
*/ */
@Test @Test
public void crossFunctionNonLiteralValue() throws Exception { public void crossFunctionNonLiteralValue() throws Exception {
Assert.assertEquals(((EvalError) invoke("cross", 1, "My Address Book", "friend")).message,
"cross expects a string or cell, a project name to join with, and a column name in that project");
Assert.assertEquals(((EvalError) invoke("cross", null, "My Address Book", "friend")).message, Assert.assertEquals(((EvalError) invoke("cross", null, "My Address Book", "friend")).message,
"cross expects a string or cell, a project name to join with, and a column name in that project"); "cross expects a cell or cell value, a project name to look up, and a column name in that project");
Assert.assertEquals(((EvalError) invoke("cross", Calendar.getInstance(), "My Address Book", "friend")).message,
"cross expects a string or cell, a project name to join with, and a column name in that project");
} }
/** /**
@ -256,7 +289,7 @@ public class CrossTests extends RefineTest {
@Test @Test
public void serializeCross() { public void serializeCross() {
String json = "{\"description\":\"join with another project by column\",\"params\":\"cell c or string 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, cell will be interpreted as cell.value\",\"params\":\"cell c or object value, string projectName, string columnName\",\"returns\":\"array\"}";
TestUtils.isSerializedTo(new Cross(), json); TestUtils.isSerializedTo(new Cross(), json);
} }
} }