From 70d0e9b2831d06b97fe8bff04820d9e3b503567a Mon Sep 17 00:00:00 2001 From: Antonin Delpeuch Date: Mon, 26 Nov 2018 21:29:18 +0900 Subject: [PATCH] Support UI json format for ColumnDetail --- .../model/recon/StandardReconConfig.java | 66 ++++++++++++++-- .../model/recon/StandardReconConfigTests.java | 79 +++++++++++++++++++ 2 files changed, 139 insertions(+), 6 deletions(-) diff --git a/main/src/com/google/refine/model/recon/StandardReconConfig.java b/main/src/com/google/refine/model/recon/StandardReconConfig.java index 0816d3237..44a4f7b16 100644 --- a/main/src/com/google/refine/model/recon/StandardReconConfig.java +++ b/main/src/com/google/refine/model/recon/StandardReconConfig.java @@ -33,6 +33,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.google.refine.model.recon; +import static org.testng.Assert.assertNotNull; + import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; @@ -82,6 +84,12 @@ public class StandardReconConfig extends ReconConfig { @JsonProperty("propertyID") final public String propertyID; + /** + * Unfortunately the format of ColumnDetail + * is inconsistent in the UI and the backend + * so we need to support two deserialization formats. + * See the tests for that. + */ @JsonCreator public ColumnDetail( @JsonProperty("column") @@ -89,15 +97,26 @@ public class StandardReconConfig extends ReconConfig { @JsonProperty("propertyName") String propertyName, @JsonProperty("propertyID") - String propertyID) { + String propertyID, + @JsonProperty("property") + ReconType property) { this.columnName = columnName; - this.propertyName = propertyName; - this.propertyID = propertyID; + this.propertyName = property == null ? propertyName : property.name; + this.propertyID = property == null ? propertyID : property.id; } + + @Override + public String toString() { + try { + return ParsingUtilities.mapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + return super.toString(); + } + } } - static public ReconConfig reconstruct(String json) throws IOException { - return ParsingUtilities.mapper.readValue(json, ReconConfig.class); + static public StandardReconConfig reconstruct(String json) throws IOException { + return ParsingUtilities.mapper.readValue(json, StandardReconConfig.class); } static protected class StandardReconJob extends ReconJob { @@ -108,6 +127,11 @@ public class StandardReconConfig extends ReconConfig { public int getKey() { return code.hashCode(); } + + @Override + public String toString() { + return code; + } } @JsonProperty("service") @@ -144,7 +168,10 @@ public class StandardReconConfig extends ReconConfig { List columnDetails, @JsonProperty("limit") int limit) { - this(service, identifierSpace, schemaSpace, type.id, type.name, autoMatch, columnDetails, limit); + this(service, identifierSpace, schemaSpace, + type != null ? type.id : null, + type != null ? type.name : null, + autoMatch, columnDetails, limit); } public StandardReconConfig( @@ -245,6 +272,15 @@ public class StandardReconConfig extends ReconConfig { this.pid = pid; this.v = v; } + + @Override + public String toString() { + try { + return ParsingUtilities.mapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + return super.toString(); + } + } } protected static class ReconQuery { @@ -284,6 +320,15 @@ public class StandardReconConfig extends ReconConfig { this.properties = properties; this.limit = limit; } + + @Override + public String toString() { + try { + return ParsingUtilities.mapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + return super.toString(); + } + } } public static class ReconResult { @@ -313,6 +358,15 @@ public class StandardReconConfig extends ReconConfig { return result; } + + @Override + public String toString() { + try { + return ParsingUtilities.mapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + return super.toString(); + } + } } @Override diff --git a/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java b/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java index 2e4466c27..0019d5929 100644 --- a/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java +++ b/main/tests/server/src/com/google/refine/tests/model/recon/StandardReconConfigTests.java @@ -1,7 +1,9 @@ package com.google.refine.tests.model.recon; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import java.io.IOException; import java.util.ArrayList; import org.slf4j.LoggerFactory; @@ -10,8 +12,14 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.refine.model.Project; +import com.google.refine.model.Row; import com.google.refine.model.recon.ReconConfig; +import com.google.refine.model.recon.ReconJob; import com.google.refine.model.recon.StandardReconConfig; +import com.google.refine.model.recon.StandardReconConfig.ColumnDetail; import com.google.refine.operations.OperationRegistry; import com.google.refine.operations.recon.ReconOperation; import com.google.refine.tests.RefineTest; @@ -93,4 +101,75 @@ public class StandardReconConfigTests extends RefineTest { String fullJson = ParsingUtilities.mapper.writeValueAsString(config); assertEquals(fullJson.indexOf("\"mode\"", fullJson.indexOf("\"mode\"")+1), -1); } + + @Test + public void testReconstructNoType() throws IOException { + String json = "{\"mode\":\"standard-service\"," + + "\"service\":\"https://tools.wmflabs.org/openrefine-wikidata/en/api\"," + + "\"identifierSpace\":\"http://www.wikidata.org/entity/\"," + + "\"schemaSpace\":\"http://www.wikidata.org/prop/direct/\"," + + "\"type\":null," + + "\"autoMatch\":true," + + "\"columnDetails\":[" + + " {\"column\":\"_ - id\"," + + " \"property\":{\"id\":\"P3153\",\"name\":\"Crossref funder ID\"}}" + + "]," + + "\"limit\":0}"; + StandardReconConfig config = StandardReconConfig.reconstruct(json); + assertNull(config.typeID); + assertNull(config.typeName); + } + + @Test + public void formulateQueryTest() throws IOException { + Project project = createCSVProject("title,director\n" + + "mulholland drive,david lynch"); + + String config = " {\n" + + " \"mode\": \"standard-service\",\n" + + " \"service\": \"https://tools.wmflabs.org/openrefine-wikidata/en/api\",\n" + + " \"identifierSpace\": \"http://www.wikidata.org/entity/\",\n" + + " \"schemaSpace\": \"http://www.wikidata.org/prop/direct/\",\n" + + " \"type\": {\n" + + " \"id\": \"Q1234\",\n" + + " \"name\": \"movie\"\n" + + " },\n" + + " \"autoMatch\": true,\n" + + " \"columnDetails\": [\n" + + " {\n" + + " \"column\": \"director\",\n" + + " \"propertyName\": \"Director\",\n" + + " \"propertyID\": \"P123\"\n" + + " }\n" + + " ]}"; + StandardReconConfig r = StandardReconConfig.reconstruct(config); + Row row = project.rows.get(0); + ReconJob job = r.createJob(project, 0, row, "title", row.getCell(0)); + TestUtils.assertEqualAsJson("{" + + "\"query\":\"mulholland drive\"," + + "\"type\":\"Q1234\"," + + "\"properties\":[" + + " {\"pid\":\"P123\",\"v\":\"david lynch\"}" + + "]," + + "\"type_strict\":\"should\"}", job.toString()); + } + + /** + * The UI format and the backend format differ for serialization + * (the UI never deserializes and the backend serialization did not matter). + * TODO: change the frontend so it uses the same format. + */ + @Test + public void deserializeColumnDetail() throws JsonParseException, JsonMappingException, IOException { + String uiJson = "{\"column\":\"director\"," + + "\"property\":{" + + " \"id\":\"P123\"," + + " \"name\":\"Director\"" + + "}}"; + String backendJson = "{\"column\":\"director\"," + + "\"propertyID\":\"P123\"," + + "\"propertyName\":\"Director\"}"; + ColumnDetail cd = ParsingUtilities.mapper.readValue(uiJson, ColumnDetail.class); + TestUtils.isSerializedTo(cd, backendJson); + } }