aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@yahoo-inc.com>2017-01-23 11:14:22 +0100
committerTor Brede Vekterli <vekterli@yahoo-inc.com>2017-01-23 11:18:58 +0100
commit221524523637b8ae4b2798c43da3284265389106 (patch)
tree0de8acc94edcc5753a11415e779aa953bdf5f4fa
parent12c42638b7374bfd2f6ce379bf9b8f3986cfe2a2 (diff)
Add JSON serialization of non-empty reference fields
-rw-r--r--document/src/main/java/com/yahoo/document/ReferenceDataType.java19
-rw-r--r--document/src/main/java/com/yahoo/document/json/DocumentUpdateJsonSerializer.java2
-rw-r--r--document/src/main/java/com/yahoo/document/json/JsonReader.java8
-rw-r--r--document/src/main/java/com/yahoo/document/json/JsonSerializationHelper.java10
-rw-r--r--document/src/main/java/com/yahoo/document/json/JsonWriter.java4
-rw-r--r--document/src/test/java/com/yahoo/document/json/DocumentUpdateJsonSerializerTest.java19
-rw-r--r--document/src/test/java/com/yahoo/document/json/JsonWriterTestCase.java183
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
+
}