diff options
author | Tor Brede Vekterli <vekterli@yahoo-inc.com> | 2017-01-23 11:14:22 +0100 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@yahoo-inc.com> | 2017-01-23 11:18:58 +0100 |
commit | 221524523637b8ae4b2798c43da3284265389106 (patch) | |
tree | 0de8acc94edcc5753a11415e779aa953bdf5f4fa | |
parent | 12c42638b7374bfd2f6ce379bf9b8f3986cfe2a2 (diff) |
Add JSON serialization of non-empty reference fields
7 files changed, 168 insertions, 77 deletions
diff --git a/document/src/main/java/com/yahoo/document/ReferenceDataType.java b/document/src/main/java/com/yahoo/document/ReferenceDataType.java index 0c8d8fcc2d8..89249c4a8e4 100644 --- a/document/src/main/java/com/yahoo/document/ReferenceDataType.java +++ b/document/src/main/java/com/yahoo/document/ReferenceDataType.java @@ -9,11 +9,26 @@ public class ReferenceDataType extends DataType { private final DocumentType targetType; public ReferenceDataType(DocumentType targetType, int id) { - super("Reference<" + targetType.getName() + ">", id); + super(buildTypeName(targetType), id); this.targetType = targetType; } - public DataType getTargetType() { return targetType; } + private ReferenceDataType(DocumentType targetType) { + super(buildTypeName(targetType), 0); + setId(getName().hashCode()); + this.targetType = targetType; + } + + private static String buildTypeName(DocumentType targetType) { + return "Reference<" + targetType.getName() + ">"; + } + + // Creates a new type where the numeric ID is based no the hash of targetType + public static ReferenceDataType createWithInferredId(DocumentType targetType) { + return new ReferenceDataType(targetType); + } + + public DocumentType getTargetType() { return targetType; } @Override public ReferenceFieldValue createFieldValue() { diff --git a/document/src/main/java/com/yahoo/document/json/DocumentUpdateJsonSerializer.java b/document/src/main/java/com/yahoo/document/json/DocumentUpdateJsonSerializer.java index af156f9dea0..a6aeb5c3bb5 100644 --- a/document/src/main/java/com/yahoo/document/json/DocumentUpdateJsonSerializer.java +++ b/document/src/main/java/com/yahoo/document/json/DocumentUpdateJsonSerializer.java @@ -273,7 +273,7 @@ public class DocumentUpdateJsonSerializer @Override public void write(FieldBase field, ReferenceFieldValue value) { - // TODO! + serializeReferenceField(generator, field, value); } @Override diff --git a/document/src/main/java/com/yahoo/document/json/JsonReader.java b/document/src/main/java/com/yahoo/document/json/JsonReader.java index e0740338aae..2315adc5f0f 100644 --- a/document/src/main/java/com/yahoo/document/json/JsonReader.java +++ b/document/src/main/java/com/yahoo/document/json/JsonReader.java @@ -21,6 +21,7 @@ import com.yahoo.document.DocumentUpdate; import com.yahoo.document.Field; import com.yahoo.document.MapDataType; import com.yahoo.document.PositionDataType; +import com.yahoo.document.ReferenceDataType; import com.yahoo.document.TestAndSetCondition; import com.yahoo.document.WeightedSetDataType; import com.yahoo.document.datatypes.CollectionFieldValue; @@ -49,7 +50,7 @@ import java.util.Optional; * Initialize Vespa documents/updates/removes from an InputStream containing a * valid JSON representation of a feed. * - * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a> + * @author Steinar Knutsen * @since 5.1.25 */ @Beta @@ -646,6 +647,11 @@ public class JsonReader { return expectedType.createFieldValue(new Base64().decode(buffer.currentText())); } else if (expectedType.equals(PositionDataType.INSTANCE)) { return PositionDataType.fromString(buffer.currentText()); + } else if (expectedType instanceof ReferenceDataType) { + // TODO wrappu wrappu + FieldValue value = expectedType.createFieldValue(); + value.assign(new DocumentId(buffer.currentText())); + return value; } else { return expectedType.createFieldValue(buffer.currentText()); } diff --git a/document/src/main/java/com/yahoo/document/json/JsonSerializationHelper.java b/document/src/main/java/com/yahoo/document/json/JsonSerializationHelper.java index 8c6ee898c0e..dcd49479767 100644 --- a/document/src/main/java/com/yahoo/document/json/JsonSerializationHelper.java +++ b/document/src/main/java/com/yahoo/document/json/JsonSerializationHelper.java @@ -14,6 +14,7 @@ import com.yahoo.document.datatypes.LongFieldValue; import com.yahoo.document.datatypes.MapFieldValue; import com.yahoo.document.datatypes.PredicateFieldValue; import com.yahoo.document.datatypes.Raw; +import com.yahoo.document.datatypes.ReferenceFieldValue; import com.yahoo.document.datatypes.StringFieldValue; import com.yahoo.document.datatypes.Struct; import com.yahoo.document.datatypes.StructuredFieldValue; @@ -104,6 +105,15 @@ public class JsonSerializationHelper { generator.writeEndObject(); } + public static void serializeReferenceField(JsonGenerator generator, FieldBase field, ReferenceFieldValue value) { + wrapIOException(() -> { + fieldNameIfNotNull(generator, field); + // TODO need testing of empty reference! + if (value.getDocumentId().isPresent()) { + generator.writeString(value.getDocumentId().get().toString()); + } + }); + } public static void serializeStringField(JsonGenerator generator, FieldBase field, StringFieldValue value) { // Hide empty strings diff --git a/document/src/main/java/com/yahoo/document/json/JsonWriter.java b/document/src/main/java/com/yahoo/document/json/JsonWriter.java index 734b16253fb..6ad526a2aaa 100644 --- a/document/src/main/java/com/yahoo/document/json/JsonWriter.java +++ b/document/src/main/java/com/yahoo/document/json/JsonWriter.java @@ -42,7 +42,7 @@ import static com.yahoo.document.json.JsonSerializationHelper.*; /** * Serialize Document and other FieldValue instances as JSON. * - * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a> + * @author Steinar Knutsen */ public class JsonWriter implements DocumentWriter { @@ -184,7 +184,7 @@ public class JsonWriter implements DocumentWriter { @Override public void write(FieldBase field, ReferenceFieldValue value) { - // TODO! + serializeReferenceField(generator, field, value); } @Override diff --git a/document/src/test/java/com/yahoo/document/json/DocumentUpdateJsonSerializerTest.java b/document/src/test/java/com/yahoo/document/json/DocumentUpdateJsonSerializerTest.java index a0f993fd2fc..6a6ab1a9334 100644 --- a/document/src/test/java/com/yahoo/document/json/DocumentUpdateJsonSerializerTest.java +++ b/document/src/test/java/com/yahoo/document/json/DocumentUpdateJsonSerializerTest.java @@ -10,6 +10,7 @@ import com.yahoo.document.DocumentUpdate; import com.yahoo.document.Field; import com.yahoo.document.MapDataType; import com.yahoo.document.PositionDataType; +import com.yahoo.document.ReferenceDataType; import com.yahoo.document.TensorDataType; import com.yahoo.document.WeightedSetDataType; import com.yahoo.tensor.TensorType; @@ -33,16 +34,20 @@ public class DocumentUpdateJsonSerializerTest { final static DocumentTypeManager types = new DocumentTypeManager(); final static JsonFactory parserFactory = new JsonFactory(); final static DocumentType docType = new DocumentType("doctype"); + final static DocumentType refTargetDocType = new DocumentType("target_doctype"); final static String DEFAULT_DOCUMENT_ID = "id:test:doctype::1"; static { + types.registerDocumentType(refTargetDocType); + docType.addField(new Field("string_field", DataType.STRING)); docType.addField(new Field("int_field", DataType.INT)); docType.addField(new Field("float_field", DataType.FLOAT)); docType.addField(new Field("double_field", DataType.DOUBLE)); docType.addField(new Field("byte_field", DataType.BYTE)); docType.addField(new Field("tensor_field", new TensorDataType(tensorType))); + docType.addField(new Field("reference_field", new ReferenceDataType(refTargetDocType, 777))); docType.addField(new Field("predicate_field", DataType.PREDICATE)); docType.addField(new Field("raw_field", DataType.RAW)); docType.addField(new Field("int_array", new ArrayDataType(DataType.INT))); @@ -253,6 +258,20 @@ public class DocumentUpdateJsonSerializerTest { } @Test + public void reference_field_id_can_be_update_assigned_new_id() { + deSerializeAndSerializeJsonAndMatch(inputJson( + "{", + " 'update': 'DOCUMENT_ID',", + " 'fields': {", + " 'reference_field': {", + " 'assign': 'id:ns:target_doctype::foo'", + " }", + " }", + "}" + )); + } + + @Test public void testAssignPredicate() { deSerializeAndSerializeJsonAndMatch(inputJson( "{", diff --git a/document/src/test/java/com/yahoo/document/json/JsonWriterTestCase.java b/document/src/test/java/com/yahoo/document/json/JsonWriterTestCase.java index 57b3e088efc..bd2367aa333 100644 --- a/document/src/test/java/com/yahoo/document/json/JsonWriterTestCase.java +++ b/document/src/test/java/com/yahoo/document/json/JsonWriterTestCase.java @@ -2,9 +2,7 @@ package com.yahoo.document.json; import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.io.JsonStringEncoder; -import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.yahoo.document.ArrayDataType; import com.yahoo.document.DataType; @@ -18,6 +16,7 @@ import com.yahoo.document.DocumentTypeManager; import com.yahoo.document.Field; import com.yahoo.document.MapDataType; import com.yahoo.document.PositionDataType; +import com.yahoo.document.ReferenceDataType; import com.yahoo.document.StructDataType; import com.yahoo.document.TensorDataType; import com.yahoo.document.WeightedSetDataType; @@ -52,75 +51,109 @@ public class JsonWriterTestCase { @Before public void setUp() throws Exception { types = new DocumentTypeManager(); - { - DocumentType x = new DocumentType("smoke"); - x.addField(new Field("something", DataType.STRING)); - x.addField(new Field("nalle", DataType.STRING)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("mirrors"); - StructDataType woo = new StructDataType("woo"); - woo.addField(new Field("sandra", DataType.STRING)); - woo.addField(new Field("cloud", DataType.STRING)); - x.addField(new Field("skuggsjaa", woo)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("testarray"); - DataType d = new ArrayDataType(DataType.STRING); - x.addField(new Field("actualarray", d)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("testset"); - DataType d = new WeightedSetDataType(DataType.STRING, true, true); - x.addField(new Field("actualset", d)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("testmap"); - DataType d = new MapDataType(DataType.STRING, DataType.STRING); - x.addField(new Field("actualmap", d)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("testraw"); - DataType d = DataType.RAW; - x.addField(new Field("actualraw", d)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("testpredicate"); - DataType d = DataType.PREDICATE; - x.addField(new Field("actualpredicate", d)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("testMapStringToArrayOfInt"); - DataType value = new ArrayDataType(DataType.INT); - DataType d = new MapDataType(DataType.STRING, value); - x.addField(new Field("actualMapStringToArrayOfInt", d)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("testsinglepos"); - DataType d = PositionDataType.INSTANCE; - x.addField(new Field("singlepos", d)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("testmultipos"); - DataType d = new ArrayDataType(PositionDataType.INSTANCE); - x.addField(new Field("multipos", d)); - types.registerDocumentType(x); - } - { - DocumentType x = new DocumentType("testtensor"); - TensorType tensorType = new TensorType.Builder().mapped("x").mapped("y").build(); - x.addField(new Field("tensorfield", new TensorDataType(tensorType))); - types.registerDocumentType(x); - } + registerAllTestDocumentTypes(); + } + + private void registerAllTestDocumentTypes() { + registerSmokeDocumentType(); + registerMirrorsDocumentType(); + registerArrayDocumentType(); + registerSetDocumentType(); + registerMapDocumentType(); + registerRawDocumentType(); + registerPredicateDocumentType(); + registerMapToStringToArrayDocumentType(); + registerSinglePositionDocumentType(); + registerMultiPositionDocumentType(); + registerTensorDocumentType(); + registerReferenceDocumentType(); + } + + private void registerReferenceDocumentType() { + DocumentType docTypeWithRef = new DocumentType("testrefs"); + ReferenceDataType type = ReferenceDataType.createWithInferredId(types.getDocumentType("smoke")); + docTypeWithRef.addField(new Field("ref_field", type)); + types.registerDocumentType(docTypeWithRef); + } + + private void registerTensorDocumentType() { + DocumentType x = new DocumentType("testtensor"); + TensorType tensorType = new TensorType.Builder().mapped("x").mapped("y").build(); + x.addField(new Field("tensorfield", new TensorDataType(tensorType))); + types.registerDocumentType(x); + } + + private void registerMultiPositionDocumentType() { + DocumentType x = new DocumentType("testmultipos"); + DataType d = new ArrayDataType(PositionDataType.INSTANCE); + x.addField(new Field("multipos", d)); + types.registerDocumentType(x); + } + + private void registerSinglePositionDocumentType() { + DocumentType x = new DocumentType("testsinglepos"); + DataType d = PositionDataType.INSTANCE; + x.addField(new Field("singlepos", d)); + types.registerDocumentType(x); + } + + private void registerMapToStringToArrayDocumentType() { + DocumentType x = new DocumentType("testMapStringToArrayOfInt"); + DataType value = new ArrayDataType(DataType.INT); + DataType d = new MapDataType(DataType.STRING, value); + x.addField(new Field("actualMapStringToArrayOfInt", d)); + types.registerDocumentType(x); + } + + private void registerPredicateDocumentType() { + DocumentType x = new DocumentType("testpredicate"); + DataType d = DataType.PREDICATE; + x.addField(new Field("actualpredicate", d)); + types.registerDocumentType(x); + } + + private void registerRawDocumentType() { + DocumentType x = new DocumentType("testraw"); + DataType d = DataType.RAW; + x.addField(new Field("actualraw", d)); + types.registerDocumentType(x); + } + + private void registerMapDocumentType() { + DocumentType x = new DocumentType("testmap"); + DataType d = new MapDataType(DataType.STRING, DataType.STRING); + x.addField(new Field("actualmap", d)); + types.registerDocumentType(x); + } + + private void registerSetDocumentType() { + DocumentType x = new DocumentType("testset"); + DataType d = new WeightedSetDataType(DataType.STRING, true, true); + x.addField(new Field("actualset", d)); + types.registerDocumentType(x); + } + + private void registerArrayDocumentType() { + DocumentType x = new DocumentType("testarray"); + DataType d = new ArrayDataType(DataType.STRING); + x.addField(new Field("actualarray", d)); + types.registerDocumentType(x); + } + + private void registerMirrorsDocumentType() { + DocumentType x = new DocumentType("mirrors"); + StructDataType woo = new StructDataType("woo"); + woo.addField(new Field("sandra", DataType.STRING)); + woo.addField(new Field("cloud", DataType.STRING)); + x.addField(new Field("skuggsjaa", woo)); + types.registerDocumentType(x); + } + + private void registerSmokeDocumentType() { + DocumentType x = new DocumentType("smoke"); + x.addField(new Field("something", DataType.STRING)); + x.addField(new Field("nalle", DataType.STRING)); + types.registerDocumentType(x); } @After @@ -345,4 +378,12 @@ public class JsonWriterTestCase { assertEqualJson(asDocument(docId, outputFields), JsonWriter.toByteArray(doc)); } + @Test + public void non_empty_reference_field_is_roundtrip_json_serialized() throws IOException { + roundTripEquality("id:unittest:testrefs::helloworld", + "{ \"ref_field\": \"id:unittest:smoke::and_mirrors_too\" }"); + } + + // TODO empty ref fields + } |