Support UI json format for ColumnDetail

This commit is contained in:
Antonin Delpeuch 2018-11-26 21:29:18 +09:00
parent 1e578384e2
commit 70d0e9b283
2 changed files with 139 additions and 6 deletions

View File

@ -33,6 +33,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.model.recon; package com.google.refine.model.recon;
import static org.testng.Assert.assertNotNull;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -82,6 +84,12 @@ public class StandardReconConfig extends ReconConfig {
@JsonProperty("propertyID") @JsonProperty("propertyID")
final public String 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 @JsonCreator
public ColumnDetail( public ColumnDetail(
@JsonProperty("column") @JsonProperty("column")
@ -89,15 +97,26 @@ public class StandardReconConfig extends ReconConfig {
@JsonProperty("propertyName") @JsonProperty("propertyName")
String propertyName, String propertyName,
@JsonProperty("propertyID") @JsonProperty("propertyID")
String propertyID) { String propertyID,
@JsonProperty("property")
ReconType property) {
this.columnName = columnName; this.columnName = columnName;
this.propertyName = propertyName; this.propertyName = property == null ? propertyName : property.name;
this.propertyID = propertyID; 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 { static public StandardReconConfig reconstruct(String json) throws IOException {
return ParsingUtilities.mapper.readValue(json, ReconConfig.class); return ParsingUtilities.mapper.readValue(json, StandardReconConfig.class);
} }
static protected class StandardReconJob extends ReconJob { static protected class StandardReconJob extends ReconJob {
@ -108,6 +127,11 @@ public class StandardReconConfig extends ReconConfig {
public int getKey() { public int getKey() {
return code.hashCode(); return code.hashCode();
} }
@Override
public String toString() {
return code;
}
} }
@JsonProperty("service") @JsonProperty("service")
@ -144,7 +168,10 @@ public class StandardReconConfig extends ReconConfig {
List<ColumnDetail> columnDetails, List<ColumnDetail> columnDetails,
@JsonProperty("limit") @JsonProperty("limit")
int 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( public StandardReconConfig(
@ -245,6 +272,15 @@ public class StandardReconConfig extends ReconConfig {
this.pid = pid; this.pid = pid;
this.v = v; this.v = v;
} }
@Override
public String toString() {
try {
return ParsingUtilities.mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
return super.toString();
}
}
} }
protected static class ReconQuery { protected static class ReconQuery {
@ -284,6 +320,15 @@ public class StandardReconConfig extends ReconConfig {
this.properties = properties; this.properties = properties;
this.limit = limit; this.limit = limit;
} }
@Override
public String toString() {
try {
return ParsingUtilities.mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
return super.toString();
}
}
} }
public static class ReconResult { public static class ReconResult {
@ -313,6 +358,15 @@ public class StandardReconConfig extends ReconConfig {
return result; return result;
} }
@Override
public String toString() {
try {
return ParsingUtilities.mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
return super.toString();
}
}
} }
@Override @Override

View File

@ -1,7 +1,9 @@
package com.google.refine.tests.model.recon; package com.google.refine.tests.model.recon;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -10,8 +12,14 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; 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.ReconConfig;
import com.google.refine.model.recon.ReconJob;
import com.google.refine.model.recon.StandardReconConfig; 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.OperationRegistry;
import com.google.refine.operations.recon.ReconOperation; import com.google.refine.operations.recon.ReconOperation;
import com.google.refine.tests.RefineTest; import com.google.refine.tests.RefineTest;
@ -93,4 +101,75 @@ public class StandardReconConfigTests extends RefineTest {
String fullJson = ParsingUtilities.mapper.writeValueAsString(config); String fullJson = ParsingUtilities.mapper.writeValueAsString(config);
assertEquals(fullJson.indexOf("\"mode\"", fullJson.indexOf("\"mode\"")+1), -1); 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);
}
} }