summaryrefslogtreecommitdiffstats
path: root/document
diff options
context:
space:
mode:
authorHaakon Dybdahl <dybdahl@yahoo-inc.com>2017-02-09 09:12:00 +0100
committerHaakon Dybdahl <dybdahl@yahoo-inc.com>2017-02-09 09:12:00 +0100
commitd0b20ef66b3bd7ff6ebd6ee4ebabc041cd1951f5 (patch)
tree60b0dc997559bc62da46a2e134e47fb0e830b847 /document
parent0c97a6cb140d8aa4e3f123bed0fb3563ef64f727 (diff)
Move stuff around, not perfect yet..
Diffstat (limited to 'document')
-rw-r--r--document/src/main/java/com/yahoo/document/json/JsonReader.java524
-rw-r--r--document/src/main/java/com/yahoo/document/json/JsonSerializationHelper.java16
-rw-r--r--document/src/main/java/com/yahoo/document/json/TokenBuffer.java26
-rw-r--r--document/src/main/java/com/yahoo/document/json/document/DocumentParser.java86
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/AddRemoveCreator.java67
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/ArrayReader.java35
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/CompositeReader.java47
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/DocumentParseInfo.java16
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/DocumentToFields.java65
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/MapReader.java110
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/SingleValueReader.java59
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/StructReader.java31
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/TensorReader.java64
-rw-r--r--document/src/main/java/com/yahoo/document/json/readers/WeightedSetReader.java31
-rw-r--r--document/src/test/java/com/yahoo/document/json/JsonReaderTestCase.java53
-rw-r--r--document/src/test/java/com/yahoo/document/json/JsonWriterTestCase.java11
16 files changed, 705 insertions, 536 deletions
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 6525cbd6cab..c879ed337ba 100644
--- a/document/src/main/java/com/yahoo/document/json/JsonReader.java
+++ b/document/src/main/java/com/yahoo/document/json/JsonReader.java
@@ -6,9 +6,6 @@ import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
-import com.yahoo.collections.Pair;
-import com.yahoo.document.ArrayDataType;
-import com.yahoo.document.CollectionDataType;
import com.yahoo.document.DataType;
import com.yahoo.document.Document;
import com.yahoo.document.DocumentId;
@@ -19,33 +16,28 @@ import com.yahoo.document.DocumentType;
import com.yahoo.document.DocumentTypeManager;
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;
import com.yahoo.document.datatypes.FieldValue;
-import com.yahoo.document.datatypes.IntegerFieldValue;
-import com.yahoo.document.datatypes.MapFieldValue;
import com.yahoo.document.datatypes.StructuredFieldValue;
-import com.yahoo.document.datatypes.TensorFieldValue;
-import com.yahoo.document.datatypes.WeightedSet;
-import com.yahoo.document.json.TokenBuffer.Token;
+import com.yahoo.document.json.document.DocumentParser;
+import com.yahoo.document.json.readers.DocumentParseInfo;
+import com.yahoo.document.json.readers.DocumentToFields;
+import com.yahoo.document.json.readers.MapReader;
import com.yahoo.document.update.FieldUpdate;
import com.yahoo.document.update.MapValueUpdate;
import com.yahoo.document.update.ValueUpdate;
-import com.yahoo.tensor.MappedTensor;
-import com.yahoo.tensor.Tensor;
-import com.yahoo.tensor.TensorType;
import org.apache.commons.codec.binary.Base64;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Optional;
+import static com.yahoo.document.json.readers.AddRemoveCreator.createAddsOrRemoves;
+import static com.yahoo.document.json.readers.CompositeReader.populateComposite;
+import static com.yahoo.document.json.readers.SingleValueReader.readSingleUpdate;
+
/**
* Initialize Vespa documents/updates/removes from an InputStream containing a
* valid JSON representation of a feed.
@@ -56,47 +48,28 @@ import java.util.Optional;
@Beta
public class JsonReader {
- private enum FieldOperation {
+ public Optional<DocumentParseInfo> parseDocument() {
+ return DocumentParser.parseDocument(parser);
+ }
+
+ public enum FieldOperation {
ADD, REMOVE
}
+ public static final String FIELDS = "fields";
+ public static final String REMOVE = "remove";
- static final String MAP_KEY = "key";
- static final String MAP_VALUE = "value";
- static final String FIELDS = "fields";
- static final String REMOVE = "remove";
- static final String UPDATE_INCREMENT = "increment";
- static final String UPDATE_DECREMENT = "decrement";
- static final String UPDATE_MULTIPLY = "multiply";
- static final String UPDATE_DIVIDE = "divide";
- static final String TENSOR_DIMENSIONS = "dimensions";
- static final String TENSOR_CELLS = "cells";
- static final String TENSOR_ADDRESS = "address";
- static final String TENSOR_VALUE = "value";
-
- private static final String UPDATE = "update";
- private static final String PUT = "put";
- private static final String ID = "id";
- private static final String CONDITION = "condition";
- private static final String CREATE_IF_NON_EXISTENT = "create";
- private static final String UPDATE_ASSIGN = "assign";
+ public static final String CONDITION = "condition";
+ public static final String CREATE_IF_NON_EXISTENT = "create";
private static final String UPDATE_REMOVE = "remove";
- private static final String UPDATE_MATCH = "match";
+ public static final String UPDATE_MATCH = "match";
private static final String UPDATE_ADD = "add";
- private static final String UPDATE_ELEMENT = "element";
+ public static final String UPDATE_ELEMENT = "element";
private final JsonParser parser;
private final DocumentTypeManager typeManager;
private ReaderState state = ReaderState.AT_START;
- static class DocumentParseInfo {
- public DocumentId documentId;
- public Optional<Boolean> create = Optional.empty();
- Optional<String> condition = Optional.empty();
- SupportedOperation operationType = null;
- TokenBuffer fieldsBuffer = new TokenBuffer();
- }
-
- enum SupportedOperation {
+ public enum SupportedOperation {
PUT, UPDATE, REMOVE
}
@@ -123,7 +96,7 @@ public class JsonReader {
*/
public DocumentOperation readSingleDocument(SupportedOperation operationType, String docIdString) {
DocumentId docId = new DocumentId(docIdString);
- DocumentParseInfo documentParseInfo = parseToDocumentsFieldsAndInsertFieldsIntoBuffer(docId);
+ DocumentParseInfo documentParseInfo = DocumentToFields.parseToDocumentsFieldsAndInsertFieldsIntoBuffer(parser, docId);
documentParseInfo.operationType = operationType;
DocumentOperation operation = createDocumentOperation(documentParseInfo.fieldsBuffer, documentParseInfo);
operation.setCondition(TestAndSetCondition.fromConditionString(documentParseInfo.condition));
@@ -143,7 +116,7 @@ public class JsonReader {
break;
}
- Optional<DocumentParseInfo> documentParseInfo = parseDocument();
+ Optional<DocumentParseInfo> documentParseInfo = DocumentParser.parseDocument(parser);
if (! documentParseInfo.isPresent()) {
state = ReaderState.END_OF_FEED;
@@ -190,14 +163,14 @@ public class JsonReader {
void readUpdate(TokenBuffer buffer, DocumentUpdate next) {
if (buffer.size() == 0) {
- bufferFields(buffer, nextToken(parser));
+ bufferFields(parser, buffer, nextToken(parser));
}
populateUpdateFromBuffer(buffer, next);
}
void readPut(TokenBuffer buffer, DocumentPut put) {
if (buffer.size() == 0) {
- bufferFields(buffer, nextToken(parser));
+ bufferFields(parser, buffer, nextToken(parser));
}
JsonToken t = buffer.currentToken();
try {
@@ -207,56 +180,6 @@ public class JsonReader {
}
}
- private DocumentParseInfo parseToDocumentsFieldsAndInsertFieldsIntoBuffer(DocumentId documentId) {
- long indentLevel = 0;
- DocumentParseInfo documentParseInfo = new DocumentParseInfo();
- documentParseInfo.documentId = documentId;
- while (true) {
- // we should now be at the start of a feed operation or at the end of the feed
- JsonToken t = nextToken(parser);
- if (t == null) {
- throw new IllegalArgumentException("Could not read document, no document?");
- }
- switch (t) {
- case START_OBJECT:
- indentLevel++;
- break;
- case END_OBJECT:
- indentLevel--;
- break;
- case START_ARRAY:
- indentLevel+=10000L;
- break;
- case END_ARRAY:
- indentLevel-=10000L;
- break;
- }
- if (indentLevel == 1 && (t == JsonToken.VALUE_TRUE || t == JsonToken.VALUE_FALSE)) {
- try {
- if (CREATE_IF_NON_EXISTENT.equals(parser.getCurrentName())) {
- documentParseInfo.create = Optional.ofNullable(parser.getBooleanValue());
- continue;
- }
- } catch (IOException e) {
- throw new RuntimeException("Got IO exception while parsing document", e);
- }
- }
- if (indentLevel == 2L && t == JsonToken.START_OBJECT) {
-
- try {
- if (!FIELDS.equals(parser.getCurrentName())) {
- continue;
- }
- } catch (IOException e) {
- throw new RuntimeException("Got IO exception while parsing document", e);
- }
- bufferFields(documentParseInfo.fieldsBuffer, t);
- break;
- }
- }
- return documentParseInfo;
- }
-
private void verifyEndState(TokenBuffer buffer) {
Preconditions.checkState(buffer.nesting() == 0, "Nesting not zero at end of operation");
expectObjectEnd(buffer.currentToken());
@@ -304,168 +227,15 @@ public class JsonReader {
}
@SuppressWarnings("rawtypes")
- private ValueUpdate createMapUpdate(TokenBuffer buffer, Field field) {
+ public ValueUpdate createMapUpdate(TokenBuffer buffer, Field field) {
buffer.next();
- MapValueUpdate m = (MapValueUpdate) createMapUpdate(buffer, field.getDataType(), null, null);
+ MapValueUpdate m = (MapValueUpdate) MapReader.createMapUpdate(buffer, field.getDataType(), null, null);
buffer.next();
// must generate the field value in parallell with the actual
return m;
}
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private ValueUpdate createMapUpdate(TokenBuffer buffer, DataType currentLevel, FieldValue keyParent, FieldValue topLevelKey) {
- TokenBuffer.Token element = buffer.prefetchScalar(UPDATE_ELEMENT);
- if (UPDATE_ELEMENT.equals(buffer.currentName())) {
- buffer.next();
- }
-
- FieldValue key = keyTypeForMapUpdate(element, currentLevel);
- if (keyParent != null) {
- ((CollectionFieldValue) keyParent).add(key);
- }
- // structure is: [(match + element)*, (element + action)]
- // match will always have element, and either match or action
- if (!UPDATE_MATCH.equals(buffer.currentName())) {
- // we have reached an action...
- if (topLevelKey == null) {
- return ValueUpdate.createMap(key, readSingleUpdate(buffer, valueTypeForMapUpdate(currentLevel), buffer.currentName()));
- } else {
- return ValueUpdate.createMap(topLevelKey, readSingleUpdate(buffer, valueTypeForMapUpdate(currentLevel), buffer.currentName()));
- }
- } else {
- // next level of matching
- if (topLevelKey == null) {
- return createMapUpdate(buffer, valueTypeForMapUpdate(currentLevel), key, key);
- } else {
- return createMapUpdate(buffer, valueTypeForMapUpdate(currentLevel), key, topLevelKey);
- }
- }
- }
-
- private DataType valueTypeForMapUpdate(DataType parentType) {
- if (parentType instanceof WeightedSetDataType) {
- return DataType.INT;
- } else if (parentType instanceof CollectionDataType) {
- return ((CollectionDataType) parentType).getNestedType();
- } else if (parentType instanceof MapDataType) {
- return ((MapDataType) parentType).getValueType();
- } else {
- throw new UnsupportedOperationException("Unexpected parent type: " + parentType);
- }
- }
-
- private FieldValue keyTypeForMapUpdate(Token element, DataType expectedType) {
- FieldValue v;
- if (expectedType instanceof ArrayDataType) {
- v = new IntegerFieldValue(Integer.valueOf(element.text));
- } else if (expectedType instanceof WeightedSetDataType) {
- v = ((WeightedSetDataType) expectedType).getNestedType().createFieldValue(element.text);
- } else if (expectedType instanceof MapDataType) {
- v = ((MapDataType) expectedType).getKeyType().createFieldValue(element.text);
- } else {
- throw new IllegalArgumentException("Container type " + expectedType + " not supported for match update.");
- }
- return v;
- }
-
- @SuppressWarnings("rawtypes")
- private ValueUpdate readSingleUpdate(TokenBuffer buffer, DataType expectedType, String action) {
- ValueUpdate update;
-
- switch (action) {
- case UPDATE_ASSIGN:
- update = (buffer.currentToken() == JsonToken.VALUE_NULL)
- ? ValueUpdate.createClear()
- : ValueUpdate.createAssign(readSingleValue(buffer, buffer.currentToken(), expectedType));
- break;
- // double is silly, but it's what is used internally anyway
- case UPDATE_INCREMENT:
- update = ValueUpdate.createIncrement(Double.valueOf(buffer.currentText()));
- break;
- case UPDATE_DECREMENT:
- update = ValueUpdate.createDecrement(Double.valueOf(buffer.currentText()));
- break;
- case UPDATE_MULTIPLY:
- update = ValueUpdate.createMultiply(Double.valueOf(buffer.currentText()));
- break;
- case UPDATE_DIVIDE:
- update = ValueUpdate.createDivide(Double.valueOf(buffer.currentText()));
- break;
- default:
- throw new IllegalArgumentException("Operation \"" + buffer.currentName() + "\" not implemented.");
- }
- return update;
- }
-
- // yes, this suppresswarnings ugliness is by intention, the code relies on
- // the contracts in the builders
- @SuppressWarnings({ "cast", "rawtypes", "unchecked" })
- private void createAddsOrRemoves(TokenBuffer buffer, Field field, FieldUpdate update, FieldOperation op) {
- FieldValue container = field.getDataType().createFieldValue();
- FieldUpdate singleUpdate;
- int initNesting = buffer.nesting();
- JsonToken token;
-
- Preconditions.checkState(buffer.currentToken().isStructStart(), "Expected start of composite, got %s", buffer.currentToken());
- if (container instanceof CollectionFieldValue) {
- token = buffer.next();
- DataType valueType = ((CollectionFieldValue) container).getDataType().getNestedType();
- if (container instanceof WeightedSet) {
- // these are objects with string keys (which are the nested
- // types) and values which are the weight
- WeightedSet weightedSet = (WeightedSet) container;
- fillWeightedSetUpdate(buffer, initNesting, valueType, weightedSet);
- if (op == FieldOperation.REMOVE) {
- singleUpdate = FieldUpdate.createRemoveAll(field, weightedSet);
- } else {
- singleUpdate = FieldUpdate.createAddAll(field, weightedSet);
-
- }
- } else {
- List<FieldValue> arrayContents = new ArrayList<>();
- token = fillArrayUpdate(buffer, initNesting, token, valueType, arrayContents);
- if (token != JsonToken.END_ARRAY) {
- throw new IllegalStateException("Expected END_ARRAY. Got '" + token + "'.");
- }
- if (op == FieldOperation.REMOVE) {
- singleUpdate = FieldUpdate.createRemoveAll(field, arrayContents);
- } else {
- singleUpdate = FieldUpdate.createAddAll(field, arrayContents);
- }
- }
- } else {
- throw new UnsupportedOperationException(
- "Trying to add or remove from a field of a type the reader does not know how to handle: "
- + container.getClass().getName());
- }
- expectCompositeEnd(buffer.currentToken());
- update.addAll(singleUpdate);
- }
-
- private JsonToken fillArrayUpdate(TokenBuffer buffer, int initNesting, JsonToken initToken, DataType valueType, List<FieldValue> arrayContents) {
- JsonToken token = initToken;
- while (buffer.nesting() >= initNesting) {
- arrayContents.add(readSingleValue(buffer, token, valueType));
- token = buffer.next();
- }
- return token;
- }
-
- private static void fillWeightedSetUpdate(TokenBuffer buffer, int initNesting, DataType valueType, @SuppressWarnings("rawtypes") WeightedSet weightedSet) {
- iterateThroughWeightedSet(buffer, initNesting, valueType, weightedSet);
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- private static void iterateThroughWeightedSet(TokenBuffer buffer, int initNesting, DataType valueType, WeightedSet weightedSet) {
- while (buffer.nesting() >= initNesting) {
- // XXX the keys are defined in the spec to always be represented as strings
- FieldValue v = valueType.createFieldValue(buffer.currentName());
- weightedSet.put(v, Integer.valueOf(buffer.currentText()));
- buffer.next();
- }
- }
-
public static FieldValue NEWpopulateComposite(DataType dataType, JsonParser parser) throws IOException {
// bla
JsonToken t = parser.nextToken();
@@ -473,57 +243,11 @@ public class JsonReader {
}
-
- // TODO populateComposite is extremely similar to add/remove, refactor
- // yes, this suppresswarnings ugliness is by intention, the code relies on the contracts in the builders
- @SuppressWarnings({ "cast", "rawtypes" })
- private static void populateComposite(TokenBuffer buffer, FieldValue parent, JsonToken token) {
- if ((token != JsonToken.START_OBJECT) && (token != JsonToken.START_ARRAY)) {
- throw new IllegalArgumentException("Expected '[' or '{'. Got '" + token + "'.");
- }
- if (parent instanceof CollectionFieldValue) {
- DataType valueType = ((CollectionFieldValue) parent).getDataType().getNestedType();
- if (parent instanceof WeightedSet) {
- fillWeightedSet(buffer, valueType, (WeightedSet) parent);
- } else {
- fillArray(buffer, (CollectionFieldValue) parent, valueType);
- }
- } else if (parent instanceof MapFieldValue) {
- fillMap(buffer, (MapFieldValue) parent);
- } else if (parent instanceof StructuredFieldValue) {
- fillStruct(buffer, (StructuredFieldValue) parent);
- } else if (parent instanceof TensorFieldValue) {
- fillTensor(buffer, (TensorFieldValue) parent);
- } else {
- throw new IllegalStateException("Has created a composite field"
- + " value the reader does not know how to handle: "
- + parent.getClass().getName() + " This is a bug. token = " + token);
- }
- expectCompositeEnd(buffer.currentToken());
- }
-
- private static void expectCompositeEnd(JsonToken token) {
+ public static void expectCompositeEnd(JsonToken token) {
Preconditions.checkState(token.isStructEnd(), "Expected end of composite, got %s", token);
}
- private static void fillStruct(TokenBuffer buffer, StructuredFieldValue parent) {
- // do note the order of initializing initNesting and token is relevant for empty docs
- int initNesting = buffer.nesting();
- JsonToken token = buffer.next();
-
- while (buffer.nesting() >= initNesting) {
- Field f = getField(buffer, parent);
- try {
- FieldValue v = readSingleValue(buffer, token, f.getDataType());
- parent.setFieldValue(f, v);
- token = buffer.next();
- } catch (IllegalArgumentException e) {
- throw new JsonReaderException(f, e);
- }
- }
- }
-
- private static Field getField(TokenBuffer buffer, StructuredFieldValue parent) {
+ public static Field getField(TokenBuffer buffer, StructuredFieldValue parent) {
Field f = parent.getField(buffer.currentName());
if (f == null) {
throw new NullPointerException("Could not get field \"" + buffer.currentName() +
@@ -532,125 +256,19 @@ public class JsonReader {
return f;
}
- @SuppressWarnings({ "rawtypes", "cast", "unchecked" })
- private static void fillMap(TokenBuffer buffer, MapFieldValue parent) {
- JsonToken token = buffer.currentToken();
- int initNesting = buffer.nesting();
- expectArrayStart(token);
- token = buffer.next();
- DataType keyType = parent.getDataType().getKeyType();
- DataType valueType = parent.getDataType().getValueType();
- while (buffer.nesting() >= initNesting) {
- FieldValue key = null;
- FieldValue value = null;
- expectObjectStart(token);
- token = buffer.next();
- for (int i = 0; i < 2; ++i) {
- if (MAP_KEY.equals(buffer.currentName())) {
- key = readSingleValue(buffer, token, keyType);
- } else if (MAP_VALUE.equals(buffer.currentName())) {
- value = readSingleValue(buffer, token, valueType);
- }
- token = buffer.next();
- }
- Preconditions.checkState(key != null && value != null, "Missing key or value for map entry.");
- parent.put(key, value);
-
- expectObjectEnd(token);
- token = buffer.next(); // array end or next entry
- }
- }
-
- private static void expectArrayStart(JsonToken token) {
+ public static void expectArrayStart(JsonToken token) {
Preconditions.checkState(token == JsonToken.START_ARRAY, "Expected start of array, got %s", token);
}
- private static void expectObjectStart(JsonToken token) {
+ public static void expectObjectStart(JsonToken token) {
Preconditions.checkState(token == JsonToken.START_OBJECT, "Expected start of JSON object, got %s", token);
}
- private static void expectObjectEnd(JsonToken token) {
+ public static void expectObjectEnd(JsonToken token) {
Preconditions.checkState(token == JsonToken.END_OBJECT, "Expected end of JSON object, got %s", token);
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private static void fillArray(TokenBuffer buffer, CollectionFieldValue parent, DataType valueType) {
- int initNesting = buffer.nesting();
- expectArrayStart(buffer.currentToken());
- JsonToken token = buffer.next();
- while (buffer.nesting() >= initNesting) {
- parent.add(readSingleValue(buffer, token, valueType));
- token = buffer.next();
- }
- }
-
- private static void fillWeightedSet(TokenBuffer buffer, DataType valueType, @SuppressWarnings("rawtypes") WeightedSet weightedSet) {
- int initNesting = buffer.nesting();
- expectObjectStart(buffer.currentToken());
- buffer.next();
- iterateThroughWeightedSet(buffer, initNesting, valueType, weightedSet);
- }
-
- private static void fillTensor(TokenBuffer buffer, TensorFieldValue tensorFieldValue) {
- Tensor.Builder tensorBuilder = Tensor.Builder.of(tensorFieldValue.getDataType().getTensorType());
- expectObjectStart(buffer.currentToken());
- int initNesting = buffer.nesting();
- // read tensor cell fields and ignore everything else
- for (buffer.next(); buffer.nesting() >= initNesting; buffer.next()) {
- if (TENSOR_CELLS.equals(buffer.currentName()))
- readTensorCells(buffer, tensorBuilder);
- }
- expectObjectEnd(buffer.currentToken());
- tensorFieldValue.assign(tensorBuilder.build());
- }
-
- private static void readTensorCells(TokenBuffer buffer, Tensor.Builder tensorBuilder) {
- expectArrayStart(buffer.currentToken());
- int initNesting = buffer.nesting();
- for (buffer.next(); buffer.nesting() >= initNesting; buffer.next())
- readTensorCell(buffer, tensorBuilder);
- expectCompositeEnd(buffer.currentToken());
- }
-
- private static void readTensorCell(TokenBuffer buffer, Tensor.Builder tensorBuilder) {
- expectObjectStart(buffer.currentToken());
- int initNesting = buffer.nesting();
- double cellValue = 0.0;
- Tensor.Builder.CellBuilder cellBuilder = tensorBuilder.cell();
- for (buffer.next(); buffer.nesting() >= initNesting; buffer.next()) {
- String currentName = buffer.currentName();
- if (TENSOR_ADDRESS.equals(currentName)) {
- readTensorAddress(buffer, cellBuilder);
- } else if (TENSOR_VALUE.equals(currentName)) {
- cellValue = Double.valueOf(buffer.currentText());
- }
- }
- expectObjectEnd(buffer.currentToken());
- cellBuilder.value(cellValue);
- }
-
- private static void readTensorAddress(TokenBuffer buffer, MappedTensor.Builder.CellBuilder cellBuilder) {
- expectObjectStart(buffer.currentToken());
- int initNesting = buffer.nesting();
- for (buffer.next(); buffer.nesting() >= initNesting; buffer.next()) {
- String dimension = buffer.currentName();
- String label = buffer.currentText();
- cellBuilder.label(dimension, label);
- }
- expectObjectEnd(buffer.currentToken());
- }
-
- private static FieldValue readSingleValue(TokenBuffer buffer, JsonToken t, DataType expectedType) {
- if (t.isScalarValue()) {
- return readAtomic(buffer, expectedType);
- } else {
- FieldValue v = expectedType.createFieldValue();
- populateComposite(buffer, v, t);
- return v;
- }
- }
-
- private static FieldValue readAtomic(TokenBuffer buffer, DataType expectedType) {
+ public static FieldValue readAtomic(TokenBuffer buffer, DataType expectedType) {
if (expectedType.equals(DataType.RAW)) {
return expectedType.createFieldValue(new Base64().decode(buffer.currentText()));
} else if (expectedType.equals(PositionDataType.INSTANCE)) {
@@ -671,80 +289,11 @@ public class JsonReader {
return value;
}
- private void bufferFields(TokenBuffer buffer, JsonToken current) {
+ public static void bufferFields(JsonParser parser, TokenBuffer buffer, JsonToken current) {
buffer.bufferObject(current, parser);
}
- Optional<DocumentParseInfo> parseDocument() {
- // we should now be at the start of a feed operation or at the end of the feed
- JsonToken token = nextToken(parser);
- if (token == JsonToken.END_ARRAY) {
- return Optional.empty(); // end of feed
- }
- expectObjectStart(token);
-
- DocumentParseInfo documentParseInfo = new DocumentParseInfo();
-
- while (true) {
- try {
- token = nextToken(parser);
- if ((token == JsonToken.VALUE_TRUE || token == JsonToken.VALUE_FALSE) &&
- CREATE_IF_NON_EXISTENT.equals(parser.getCurrentName())) {
- documentParseInfo.create = Optional.of(token == JsonToken.VALUE_TRUE);
- continue;
- }
- if (token == JsonToken.VALUE_STRING && CONDITION.equals(parser.getCurrentName())) {
- documentParseInfo.condition = Optional.of(parser.getText());
- continue;
- }
- if (token == JsonToken.START_OBJECT) {
- try {
- if (!FIELDS.equals(parser.getCurrentName())) {
- throw new IllegalArgumentException("Unexpected object key: " + parser.getCurrentName());
- }
- } catch (IOException e) {
- // TODO more specific wrapping
- throw new RuntimeException(e);
- }
- bufferFields(documentParseInfo.fieldsBuffer, token);
- continue;
- }
- if (token == JsonToken.END_OBJECT) {
- if (documentParseInfo.documentId == null) {
- throw new RuntimeException("Did not find document operation");
- }
- return Optional.of(documentParseInfo);
- }
- if (token == JsonToken.VALUE_STRING) {
- documentParseInfo.operationType = operationNameToOperationType(parser.getCurrentName());
- documentParseInfo.documentId = new DocumentId(parser.getText());
- continue;
- }
- throw new RuntimeException("Expected document start or document operation.");
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
-
- }
- }
-
- private static SupportedOperation operationNameToOperationType(String operationName) {
- switch (operationName) {
- case PUT:
- case ID:
- return SupportedOperation.PUT;
- case REMOVE:
- return SupportedOperation.REMOVE;
- case UPDATE:
- return SupportedOperation.UPDATE;
- default:
- throw new IllegalArgumentException(
- "Got " + operationName + " as document operation, only \"put\", " +
- "\"remove\" and \"update\" are supported.");
- }
- }
-
- DocumentType readDocumentType(DocumentId docId) {
+ public DocumentType readDocumentType(DocumentId docId) {
return getDocumentTypeFromString(docId.getDocType(), typeManager);
}
@@ -756,7 +305,7 @@ public class JsonReader {
return docType;
}
- private static JsonToken nextToken(JsonParser parser) {
+ public static JsonToken nextToken(JsonParser parser) {
try {
return parser.nextValue();
} catch (IOException e) {
@@ -766,7 +315,4 @@ public class JsonReader {
throw new RuntimeException(e);
}
}
-
-
-
}
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 5fb8948649a..855fabc7a63 100644
--- a/document/src/main/java/com/yahoo/document/json/JsonSerializationHelper.java
+++ b/document/src/main/java/com/yahoo/document/json/JsonSerializationHelper.java
@@ -21,6 +21,7 @@ import com.yahoo.document.datatypes.Struct;
import com.yahoo.document.datatypes.StructuredFieldValue;
import com.yahoo.document.datatypes.TensorFieldValue;
import com.yahoo.document.datatypes.WeightedSet;
+import com.yahoo.document.json.readers.TensorReader;
import com.yahoo.document.serialization.FieldWriter;
import com.yahoo.tensor.Tensor;
import com.yahoo.tensor.TensorAddress;
@@ -34,6 +35,9 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import static com.yahoo.document.json.readers.MapReader.MAP_KEY;
+import static com.yahoo.document.json.readers.MapReader.MAP_VALUE;
+
/**
* @author Steinar Knutsen
* @author Vegard Sjonfjell
@@ -78,7 +82,7 @@ public class JsonSerializationHelper {
}
private static void serializeTensorDimensions(JsonGenerator generator, Set<String> dimensions) throws IOException {
- generator.writeArrayFieldStart(JsonReader.TENSOR_DIMENSIONS);
+ generator.writeArrayFieldStart(TensorReader.TENSOR_DIMENSIONS);
for (String dimension : dimensions) {
generator.writeString(dimension);
}
@@ -87,11 +91,11 @@ public class JsonSerializationHelper {
}
private static void serializeTensorCells(JsonGenerator generator, Tensor tensor) throws IOException {
- generator.writeArrayFieldStart(JsonReader.TENSOR_CELLS);
+ generator.writeArrayFieldStart(TensorReader.TENSOR_CELLS);
for (Map.Entry<TensorAddress, Double> cell : tensor.cells().entrySet()) {
generator.writeStartObject();
serializeTensorAddress(generator, cell.getKey(), tensor.type());
- generator.writeNumberField(JsonReader.TENSOR_VALUE, cell.getValue());
+ generator.writeNumberField(TensorReader.TENSOR_VALUE, cell.getValue());
generator.writeEndObject();
}
@@ -99,7 +103,7 @@ public class JsonSerializationHelper {
}
private static void serializeTensorAddress(JsonGenerator generator, TensorAddress address, TensorType type) throws IOException {
- generator.writeObjectFieldStart(JsonReader.TENSOR_ADDRESS);
+ generator.writeObjectFieldStart(TensorReader.TENSOR_ADDRESS);
for (int i = 0; i < type.dimensions().size(); i++)
generator.writeStringField(type.dimensions().get(i).name(), address.label(i));
@@ -186,9 +190,9 @@ public class JsonSerializationHelper {
for (Map.Entry<K, V> entry : map.entrySet()) {
generator.writeStartObject();
- generator.writeFieldName(JsonReader.MAP_KEY);
+ generator.writeFieldName(MAP_KEY);
entry.getKey().serialize(null, fieldWriter);
- generator.writeFieldName(JsonReader.MAP_VALUE);
+ generator.writeFieldName(MAP_VALUE);
entry.getValue().serialize(null, fieldWriter);
generator.writeEndObject();
}
diff --git a/document/src/main/java/com/yahoo/document/json/TokenBuffer.java b/document/src/main/java/com/yahoo/document/json/TokenBuffer.java
index 8f3395b989e..116de5acd04 100644
--- a/document/src/main/java/com/yahoo/document/json/TokenBuffer.java
+++ b/document/src/main/java/com/yahoo/document/json/TokenBuffer.java
@@ -15,11 +15,11 @@ import com.google.common.base.Preconditions;
*
* @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a>
*/
-class TokenBuffer {
- static final class Token {
- final JsonToken token;
- final String name;
- final String text;
+public class TokenBuffer {
+ public static final class Token {
+ public final JsonToken token;
+ public final String name;
+ public final String text;
Token(JsonToken token, String name, String text) {
this.token = token;
@@ -31,7 +31,7 @@ class TokenBuffer {
private Deque<Token> buffer;
private int nesting = 0;
- TokenBuffer() {
+ public TokenBuffer() {
this(new ArrayDeque<>());
}
@@ -42,7 +42,7 @@ class TokenBuffer {
}
}
- JsonToken next() {
+ public JsonToken next() {
buffer.removeFirst();
Token t = buffer.peekFirst();
if (t == null) {
@@ -52,15 +52,15 @@ class TokenBuffer {
return t.token;
}
- JsonToken currentToken() {
+ public JsonToken currentToken() {
return buffer.peekFirst().token;
}
- String currentName() {
+ public String currentName() {
return buffer.peekFirst().name;
}
- String currentText() {
+ public String currentText() {
return buffer.peekFirst().text;
}
@@ -72,7 +72,7 @@ class TokenBuffer {
buffer.addLast(new Token(token, name, text));
}
- void bufferObject(JsonToken first, JsonParser tokens) {
+ void bufferObject(JsonToken first, JsonParser tokens) {
int localNesting = 0;
JsonToken t = first;
@@ -146,7 +146,7 @@ class TokenBuffer {
}
}
- TokenBuffer prefetchCurrentElement() {
+ public TokenBuffer prefetchCurrentElement() {
Deque<Token> copy = new ArrayDeque<>();
if (currentToken().isScalarValue()) {
@@ -165,7 +165,7 @@ class TokenBuffer {
return new TokenBuffer(copy);
}
- Token prefetchScalar(String name) {
+ public Token prefetchScalar(String name) {
int localNesting = nesting();
int nestingBarrier = localNesting;
Token toReturn = null;
diff --git a/document/src/main/java/com/yahoo/document/json/document/DocumentParser.java b/document/src/main/java/com/yahoo/document/json/document/DocumentParser.java
new file mode 100644
index 00000000000..deac5498f5a
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/document/DocumentParser.java
@@ -0,0 +1,86 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.document;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.yahoo.document.DocumentId;
+import com.yahoo.document.json.readers.DocumentParseInfo;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import static com.yahoo.document.json.JsonReader.*;
+
+public class DocumentParser {
+ private static final String UPDATE = "update";
+ private static final String PUT = "put";
+ private static final String ID = "id";
+
+ public static Optional<DocumentParseInfo> parseDocument(JsonParser parser) {
+ // we should now be at the start of a feed operation or at the end of the feed
+ JsonToken token = nextToken(parser);
+ if (token == JsonToken.END_ARRAY) {
+ return Optional.empty(); // end of feed
+ }
+ expectObjectStart(token);
+
+ DocumentParseInfo documentParseInfo = new DocumentParseInfo();
+
+ while (true) {
+ try {
+ token = nextToken(parser);
+ if ((token == JsonToken.VALUE_TRUE || token == JsonToken.VALUE_FALSE) &&
+ CREATE_IF_NON_EXISTENT.equals(parser.getCurrentName())) {
+ documentParseInfo.create = Optional.of(token == JsonToken.VALUE_TRUE);
+ continue;
+ }
+ if (token == JsonToken.VALUE_STRING && CONDITION.equals(parser.getCurrentName())) {
+ documentParseInfo.condition = Optional.of(parser.getText());
+ continue;
+ }
+ if (token == JsonToken.START_OBJECT) {
+ try {
+ if (!FIELDS.equals(parser.getCurrentName())) {
+ throw new IllegalArgumentException("Unexpected object key: " + parser.getCurrentName());
+ }
+ } catch (IOException e) {
+ // TODO more specific wrapping
+ throw new RuntimeException(e);
+ }
+ bufferFields(parser, documentParseInfo.fieldsBuffer, token);
+ continue;
+ }
+ if (token == JsonToken.END_OBJECT) {
+ if (documentParseInfo.documentId == null) {
+ throw new RuntimeException("Did not find document operation");
+ }
+ return Optional.of(documentParseInfo);
+ }
+ if (token == JsonToken.VALUE_STRING) {
+ documentParseInfo.operationType = operationNameToOperationType(parser.getCurrentName());
+ documentParseInfo.documentId = new DocumentId(parser.getText());
+ continue;
+ }
+ throw new RuntimeException("Expected document start or document operation.");
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ private static SupportedOperation operationNameToOperationType(String operationName) {
+ switch (operationName) {
+ case PUT:
+ case ID:
+ return SupportedOperation.PUT;
+ case REMOVE:
+ return SupportedOperation.REMOVE;
+ case UPDATE:
+ return SupportedOperation.UPDATE;
+ default:
+ throw new IllegalArgumentException(
+ "Got " + operationName + " as document operation, only \"put\", " +
+ "\"remove\" and \"update\" are supported.");
+ }
+ }
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/AddRemoveCreator.java b/document/src/main/java/com/yahoo/document/json/readers/AddRemoveCreator.java
new file mode 100644
index 00000000000..e353da05ad1
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/AddRemoveCreator.java
@@ -0,0 +1,67 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.fasterxml.jackson.core.JsonToken;
+import com.google.common.base.Preconditions;
+import com.yahoo.document.DataType;
+import com.yahoo.document.Field;
+import com.yahoo.document.datatypes.CollectionFieldValue;
+import com.yahoo.document.datatypes.FieldValue;
+import com.yahoo.document.datatypes.WeightedSet;
+import com.yahoo.document.json.JsonReader;
+import com.yahoo.document.json.TokenBuffer;
+import com.yahoo.document.update.FieldUpdate;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.yahoo.document.json.JsonReader.expectCompositeEnd;
+import static com.yahoo.document.json.readers.WeightedSetReader.fillWeightedSetUpdate;
+
+public class AddRemoveCreator {
+
+ // yes, this suppresswarnings ugliness is by intention, the code relies on
+ // the contracts in the builders
+ @SuppressWarnings({ "cast", "rawtypes", "unchecked" })
+ public static void createAddsOrRemoves(TokenBuffer buffer, Field field, FieldUpdate update, JsonReader.FieldOperation op) {
+ FieldValue container = field.getDataType().createFieldValue();
+ FieldUpdate singleUpdate;
+ int initNesting = buffer.nesting();
+ JsonToken token;
+
+ Preconditions.checkState(buffer.currentToken().isStructStart(), "Expected start of composite, got %s", buffer.currentToken());
+ if (container instanceof CollectionFieldValue) {
+ token = buffer.next();
+ DataType valueType = ((CollectionFieldValue) container).getDataType().getNestedType();
+ if (container instanceof WeightedSet) {
+ // these are objects with string keys (which are the nested
+ // types) and values which are the weight
+ WeightedSet weightedSet = (WeightedSet) container;
+ fillWeightedSetUpdate(buffer, initNesting, valueType, weightedSet);
+ if (op == JsonReader.FieldOperation.REMOVE) {
+ singleUpdate = FieldUpdate.createRemoveAll(field, weightedSet);
+ } else {
+ singleUpdate = FieldUpdate.createAddAll(field, weightedSet);
+
+ }
+ } else {
+ List<FieldValue> arrayContents = new ArrayList<>();
+ token = ArrayReader.fillArrayUpdate(buffer, initNesting, token, valueType, arrayContents);
+ if (token != JsonToken.END_ARRAY) {
+ throw new IllegalStateException("Expected END_ARRAY. Got '" + token + "'.");
+ }
+ if (op == JsonReader.FieldOperation.REMOVE) {
+ singleUpdate = FieldUpdate.createRemoveAll(field, arrayContents);
+ } else {
+ singleUpdate = FieldUpdate.createAddAll(field, arrayContents);
+ }
+ }
+ } else {
+ throw new UnsupportedOperationException(
+ "Trying to add or remove from a field of a type the reader does not know how to handle: "
+ + container.getClass().getName());
+ }
+ expectCompositeEnd(buffer.currentToken());
+ update.addAll(singleUpdate);
+ }
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/ArrayReader.java b/document/src/main/java/com/yahoo/document/json/readers/ArrayReader.java
new file mode 100644
index 00000000000..6f216bbca53
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/ArrayReader.java
@@ -0,0 +1,35 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.fasterxml.jackson.core.JsonToken;
+import com.yahoo.document.DataType;
+import com.yahoo.document.datatypes.CollectionFieldValue;
+import com.yahoo.document.datatypes.FieldValue;
+import com.yahoo.document.json.TokenBuffer;
+
+import java.util.List;
+
+import static com.yahoo.document.json.JsonReader.expectArrayStart;
+import static com.yahoo.document.json.readers.SingleValueReader.readSingleValue;
+
+public class ArrayReader {
+ static public JsonToken fillArrayUpdate(TokenBuffer buffer, int initNesting, JsonToken initToken, DataType valueType, List<FieldValue> arrayContents) {
+ JsonToken token = initToken;
+ while (buffer.nesting() >= initNesting) {
+ arrayContents.add(readSingleValue(buffer, token, valueType));
+ token = buffer.next();
+ }
+ return token;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static void fillArray(TokenBuffer buffer, CollectionFieldValue parent, DataType valueType) {
+ int initNesting = buffer.nesting();
+ expectArrayStart(buffer.currentToken());
+ JsonToken token = buffer.next();
+ while (buffer.nesting() >= initNesting) {
+ parent.add(readSingleValue(buffer, token, valueType));
+ token = buffer.next();
+ }
+ }
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/CompositeReader.java b/document/src/main/java/com/yahoo/document/json/readers/CompositeReader.java
new file mode 100644
index 00000000000..efb491ac545
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/CompositeReader.java
@@ -0,0 +1,47 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.fasterxml.jackson.core.JsonToken;
+import com.yahoo.document.DataType;
+import com.yahoo.document.datatypes.CollectionFieldValue;
+import com.yahoo.document.datatypes.FieldValue;
+import com.yahoo.document.datatypes.MapFieldValue;
+import com.yahoo.document.datatypes.StructuredFieldValue;
+import com.yahoo.document.datatypes.TensorFieldValue;
+import com.yahoo.document.datatypes.WeightedSet;
+import com.yahoo.document.json.TokenBuffer;
+
+import static com.yahoo.document.json.JsonReader.expectCompositeEnd;
+import static com.yahoo.document.json.readers.ArrayReader.fillArray;
+import static com.yahoo.document.json.readers.WeightedSetReader.fillWeightedSet;
+
+public class CompositeReader {
+
+ // TODO populateComposite is extremely similar to add/remove, refactor
+ // yes, this suppresswarnings ugliness is by intention, the code relies on the contracts in the builders
+ @SuppressWarnings({ "cast", "rawtypes" })
+ public static void populateComposite(TokenBuffer buffer, FieldValue parent, JsonToken token) {
+ if ((token != JsonToken.START_OBJECT) && (token != JsonToken.START_ARRAY)) {
+ throw new IllegalArgumentException("Expected '[' or '{'. Got '" + token + "'.");
+ }
+ if (parent instanceof CollectionFieldValue) {
+ DataType valueType = ((CollectionFieldValue) parent).getDataType().getNestedType();
+ if (parent instanceof WeightedSet) {
+ fillWeightedSet(buffer, valueType, (WeightedSet) parent);
+ } else {
+ fillArray(buffer, (CollectionFieldValue) parent, valueType);
+ }
+ } else if (parent instanceof MapFieldValue) {
+ MapReader.fillMap(buffer, (MapFieldValue) parent);
+ } else if (parent instanceof StructuredFieldValue) {
+ StructReader.fillStruct(buffer, (StructuredFieldValue) parent);
+ } else if (parent instanceof TensorFieldValue) {
+ TensorReader.fillTensor(buffer, (TensorFieldValue) parent);
+ } else {
+ throw new IllegalStateException("Has created a composite field"
+ + " value the reader does not know how to handle: "
+ + parent.getClass().getName() + " This is a bug. token = " + token);
+ }
+ expectCompositeEnd(buffer.currentToken());
+ }
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/DocumentParseInfo.java b/document/src/main/java/com/yahoo/document/json/readers/DocumentParseInfo.java
new file mode 100644
index 00000000000..a5ea8fd0812
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/DocumentParseInfo.java
@@ -0,0 +1,16 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.yahoo.document.DocumentId;
+import com.yahoo.document.json.JsonReader;
+import com.yahoo.document.json.TokenBuffer;
+
+import java.util.Optional;
+
+public class DocumentParseInfo {
+ public DocumentId documentId;
+ public Optional<Boolean> create = Optional.empty();
+ public Optional<String> condition = Optional.empty();
+ public JsonReader.SupportedOperation operationType = null;
+ public TokenBuffer fieldsBuffer = new TokenBuffer();
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/DocumentToFields.java b/document/src/main/java/com/yahoo/document/json/readers/DocumentToFields.java
new file mode 100644
index 00000000000..fcebe510b5b
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/DocumentToFields.java
@@ -0,0 +1,65 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.yahoo.document.DocumentId;
+import com.yahoo.document.json.JsonReader;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import static com.yahoo.document.json.JsonReader.CREATE_IF_NON_EXISTENT;
+import static com.yahoo.document.json.JsonReader.FIELDS;
+
+public class DocumentToFields {
+ public static DocumentParseInfo parseToDocumentsFieldsAndInsertFieldsIntoBuffer(JsonParser parser, DocumentId documentId) {
+ long indentLevel = 0;
+ DocumentParseInfo documentParseInfo = new DocumentParseInfo();
+ documentParseInfo.documentId = documentId;
+ while (true) {
+ // we should now be at the start of a feed operation or at the end of the feed
+ JsonToken t = JsonReader.nextToken(parser);
+ if (t == null) {
+ throw new IllegalArgumentException("Could not read document, no document?");
+ }
+ switch (t) {
+ case START_OBJECT:
+ indentLevel++;
+ break;
+ case END_OBJECT:
+ indentLevel--;
+ break;
+ case START_ARRAY:
+ indentLevel+=10000L;
+ break;
+ case END_ARRAY:
+ indentLevel-=10000L;
+ break;
+ }
+ if (indentLevel == 1 && (t == JsonToken.VALUE_TRUE || t == JsonToken.VALUE_FALSE)) {
+ try {
+ if (CREATE_IF_NON_EXISTENT.equals(parser.getCurrentName())) {
+ documentParseInfo.create = Optional.ofNullable(parser.getBooleanValue());
+ continue;
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Got IO exception while parsing document", e);
+ }
+ }
+ if (indentLevel == 2L && t == JsonToken.START_OBJECT) {
+
+ try {
+ if (!FIELDS.equals(parser.getCurrentName())) {
+ continue;
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Got IO exception while parsing document", e);
+ }
+ JsonReader.bufferFields(parser, documentParseInfo.fieldsBuffer, t);
+ break;
+ }
+ }
+ return documentParseInfo;
+ }
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/MapReader.java b/document/src/main/java/com/yahoo/document/json/readers/MapReader.java
new file mode 100644
index 00000000000..ad510924b9a
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/MapReader.java
@@ -0,0 +1,110 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.fasterxml.jackson.core.JsonToken;
+import com.google.common.base.Preconditions;
+import com.yahoo.document.ArrayDataType;
+import com.yahoo.document.CollectionDataType;
+import com.yahoo.document.DataType;
+import com.yahoo.document.MapDataType;
+import com.yahoo.document.WeightedSetDataType;
+import com.yahoo.document.datatypes.CollectionFieldValue;
+import com.yahoo.document.datatypes.FieldValue;
+import com.yahoo.document.datatypes.IntegerFieldValue;
+import com.yahoo.document.datatypes.MapFieldValue;
+import com.yahoo.document.json.TokenBuffer;
+import com.yahoo.document.update.ValueUpdate;
+
+import static com.yahoo.document.json.JsonReader.*;
+import static com.yahoo.document.json.readers.SingleValueReader.readSingleUpdate;
+import static com.yahoo.document.json.readers.SingleValueReader.readSingleValue;
+
+public class MapReader {
+ public static final String MAP_KEY = "key";
+ public static final String MAP_VALUE = "value";
+
+ @SuppressWarnings({ "rawtypes", "cast", "unchecked" })
+ public static void fillMap(TokenBuffer buffer, MapFieldValue parent) {
+ JsonToken token = buffer.currentToken();
+ int initNesting = buffer.nesting();
+ expectArrayStart(token);
+ token = buffer.next();
+ DataType keyType = parent.getDataType().getKeyType();
+ DataType valueType = parent.getDataType().getValueType();
+ while (buffer.nesting() >= initNesting) {
+ FieldValue key = null;
+ FieldValue value = null;
+ expectObjectStart(token);
+ token = buffer.next();
+ for (int i = 0; i < 2; ++i) {
+ if (MAP_KEY.equals(buffer.currentName())) {
+ key = readSingleValue(buffer, token, keyType);
+ } else if (MAP_VALUE.equals(buffer.currentName())) {
+ value = readSingleValue(buffer, token, valueType);
+ }
+ token = buffer.next();
+ }
+ Preconditions.checkState(key != null && value != null, "Missing key or value for map entry.");
+ parent.put(key, value);
+
+ expectObjectEnd(token);
+ token = buffer.next(); // array end or next entry
+ }
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public static ValueUpdate createMapUpdate(TokenBuffer buffer, DataType currentLevel, FieldValue keyParent, FieldValue topLevelKey) {
+ TokenBuffer.Token element = buffer.prefetchScalar(UPDATE_ELEMENT);
+ if (UPDATE_ELEMENT.equals(buffer.currentName())) {
+ buffer.next();
+ }
+
+ FieldValue key = keyTypeForMapUpdate(element, currentLevel);
+ if (keyParent != null) {
+ ((CollectionFieldValue) keyParent).add(key);
+ }
+ // structure is: [(match + element)*, (element + action)]
+ // match will always have element, and either match or action
+ if (!UPDATE_MATCH.equals(buffer.currentName())) {
+ // we have reached an action...
+ if (topLevelKey == null) {
+ return ValueUpdate.createMap(key, readSingleUpdate(buffer, valueTypeForMapUpdate(currentLevel), buffer.currentName()));
+ } else {
+ return ValueUpdate.createMap(topLevelKey, readSingleUpdate(buffer, valueTypeForMapUpdate(currentLevel), buffer.currentName()));
+ }
+ } else {
+ // next level of matching
+ if (topLevelKey == null) {
+ return createMapUpdate(buffer, valueTypeForMapUpdate(currentLevel), key, key);
+ } else {
+ return createMapUpdate(buffer, valueTypeForMapUpdate(currentLevel), key, topLevelKey);
+ }
+ }
+ }
+
+ private static DataType valueTypeForMapUpdate(DataType parentType) {
+ if (parentType instanceof WeightedSetDataType) {
+ return DataType.INT;
+ } else if (parentType instanceof CollectionDataType) {
+ return ((CollectionDataType) parentType).getNestedType();
+ } else if (parentType instanceof MapDataType) {
+ return ((MapDataType) parentType).getValueType();
+ } else {
+ throw new UnsupportedOperationException("Unexpected parent type: " + parentType);
+ }
+ }
+
+ private static FieldValue keyTypeForMapUpdate(TokenBuffer.Token element, DataType expectedType) {
+ FieldValue v;
+ if (expectedType instanceof ArrayDataType) {
+ v = new IntegerFieldValue(Integer.valueOf(element.text));
+ } else if (expectedType instanceof WeightedSetDataType) {
+ v = ((WeightedSetDataType) expectedType).getNestedType().createFieldValue(element.text);
+ } else if (expectedType instanceof MapDataType) {
+ v = ((MapDataType) expectedType).getKeyType().createFieldValue(element.text);
+ } else {
+ throw new IllegalArgumentException("Container type " + expectedType + " not supported for match update.");
+ }
+ return v;
+ }
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/SingleValueReader.java b/document/src/main/java/com/yahoo/document/json/readers/SingleValueReader.java
new file mode 100644
index 00000000000..5c9f0e9516e
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/SingleValueReader.java
@@ -0,0 +1,59 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.fasterxml.jackson.core.JsonToken;
+import com.yahoo.document.DataType;
+import com.yahoo.document.datatypes.FieldValue;
+import com.yahoo.document.json.JsonReader;
+import com.yahoo.document.json.TokenBuffer;
+import com.yahoo.document.update.ValueUpdate;
+
+import static com.yahoo.document.json.readers.CompositeReader.populateComposite;
+
+public class SingleValueReader {
+ public static final String UPDATE_ASSIGN = "assign";
+ public static final String UPDATE_INCREMENT = "increment";
+ public static final String UPDATE_DECREMENT = "decrement";
+ public static final String UPDATE_MULTIPLY = "multiply";
+ public static final String UPDATE_DIVIDE = "divide";
+
+ public static FieldValue readSingleValue(TokenBuffer buffer, JsonToken t, DataType expectedType) {
+ if (t.isScalarValue()) {
+ return JsonReader.readAtomic(buffer, expectedType);
+ } else {
+ FieldValue v = expectedType.createFieldValue();
+ populateComposite(buffer, v, t);
+ return v;
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static ValueUpdate readSingleUpdate(TokenBuffer buffer, DataType expectedType, String action) {
+ ValueUpdate update;
+
+ switch (action) {
+ case UPDATE_ASSIGN:
+ update = (buffer.currentToken() == JsonToken.VALUE_NULL)
+ ? ValueUpdate.createClear()
+ : ValueUpdate.createAssign(readSingleValue(buffer, buffer.currentToken(), expectedType));
+ break;
+ // double is silly, but it's what is used internally anyway
+ case UPDATE_INCREMENT:
+ update = ValueUpdate.createIncrement(Double.valueOf(buffer.currentText()));
+ break;
+ case UPDATE_DECREMENT:
+ update = ValueUpdate.createDecrement(Double.valueOf(buffer.currentText()));
+ break;
+ case UPDATE_MULTIPLY:
+ update = ValueUpdate.createMultiply(Double.valueOf(buffer.currentText()));
+ break;
+ case UPDATE_DIVIDE:
+ update = ValueUpdate.createDivide(Double.valueOf(buffer.currentText()));
+ break;
+ default:
+ throw new IllegalArgumentException("Operation \"" + buffer.currentName() + "\" not implemented.");
+ }
+ return update;
+ }
+
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/StructReader.java b/document/src/main/java/com/yahoo/document/json/readers/StructReader.java
new file mode 100644
index 00000000000..30620fb19bb
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/StructReader.java
@@ -0,0 +1,31 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.fasterxml.jackson.core.JsonToken;
+import com.yahoo.document.Field;
+import com.yahoo.document.datatypes.FieldValue;
+import com.yahoo.document.datatypes.StructuredFieldValue;
+import com.yahoo.document.json.JsonReader;
+import com.yahoo.document.json.JsonReaderException;
+import com.yahoo.document.json.TokenBuffer;
+
+import static com.yahoo.document.json.readers.SingleValueReader.readSingleValue;
+
+public class StructReader {
+ public static void fillStruct(TokenBuffer buffer, StructuredFieldValue parent) {
+ // do note the order of initializing initNesting and token is relevant for empty docs
+ int initNesting = buffer.nesting();
+ JsonToken token = buffer.next();
+
+ while (buffer.nesting() >= initNesting) {
+ Field f = JsonReader.getField(buffer, parent);
+ try {
+ FieldValue v = readSingleValue(buffer, token, f.getDataType());
+ parent.setFieldValue(f, v);
+ token = buffer.next();
+ } catch (IllegalArgumentException e) {
+ throw new JsonReaderException(f, e);
+ }
+ }
+ }
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/TensorReader.java b/document/src/main/java/com/yahoo/document/json/readers/TensorReader.java
new file mode 100644
index 00000000000..e4fa676a150
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/TensorReader.java
@@ -0,0 +1,64 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.yahoo.document.datatypes.TensorFieldValue;
+import com.yahoo.document.json.JsonReader;
+import com.yahoo.document.json.TokenBuffer;
+import com.yahoo.tensor.MappedTensor;
+import com.yahoo.tensor.Tensor;
+
+public class TensorReader {
+ public static final String TENSOR_ADDRESS = "address";
+ public static final String TENSOR_DIMENSIONS = "dimensions";
+ public static final String TENSOR_CELLS = "cells";
+ public static final String TENSOR_VALUE = "value";
+
+ public static void fillTensor(TokenBuffer buffer, TensorFieldValue tensorFieldValue) {
+ Tensor.Builder tensorBuilder = Tensor.Builder.of(tensorFieldValue.getDataType().getTensorType());
+ JsonReader.expectObjectStart(buffer.currentToken());
+ int initNesting = buffer.nesting();
+ // read tensor cell fields and ignore everything else
+ for (buffer.next(); buffer.nesting() >= initNesting; buffer.next()) {
+ if (TensorReader.TENSOR_CELLS.equals(buffer.currentName()))
+ readTensorCells(buffer, tensorBuilder);
+ }
+ JsonReader.expectObjectEnd(buffer.currentToken());
+ tensorFieldValue.assign(tensorBuilder.build());
+ }
+
+ public static void readTensorCells(TokenBuffer buffer, Tensor.Builder tensorBuilder) {
+ JsonReader.expectArrayStart(buffer.currentToken());
+ int initNesting = buffer.nesting();
+ for (buffer.next(); buffer.nesting() >= initNesting; buffer.next())
+ readTensorCell(buffer, tensorBuilder);
+ JsonReader.expectCompositeEnd(buffer.currentToken());
+ }
+
+ public static void readTensorCell(TokenBuffer buffer, Tensor.Builder tensorBuilder) {
+ JsonReader.expectObjectStart(buffer.currentToken());
+ int initNesting = buffer.nesting();
+ double cellValue = 0.0;
+ Tensor.Builder.CellBuilder cellBuilder = tensorBuilder.cell();
+ for (buffer.next(); buffer.nesting() >= initNesting; buffer.next()) {
+ String currentName = buffer.currentName();
+ if (TensorReader.TENSOR_ADDRESS.equals(currentName)) {
+ readTensorAddress(buffer, cellBuilder);
+ } else if (TensorReader.TENSOR_VALUE.equals(currentName)) {
+ cellValue = Double.valueOf(buffer.currentText());
+ }
+ }
+ JsonReader.expectObjectEnd(buffer.currentToken());
+ cellBuilder.value(cellValue);
+ }
+
+ public static void readTensorAddress(TokenBuffer buffer, MappedTensor.Builder.CellBuilder cellBuilder) {
+ JsonReader.expectObjectStart(buffer.currentToken());
+ int initNesting = buffer.nesting();
+ for (buffer.next(); buffer.nesting() >= initNesting; buffer.next()) {
+ String dimension = buffer.currentName();
+ String label = buffer.currentText();
+ cellBuilder.label(dimension, label);
+ }
+ JsonReader.expectObjectEnd(buffer.currentToken());
+ }
+}
diff --git a/document/src/main/java/com/yahoo/document/json/readers/WeightedSetReader.java b/document/src/main/java/com/yahoo/document/json/readers/WeightedSetReader.java
new file mode 100644
index 00000000000..ad0aaa10bf5
--- /dev/null
+++ b/document/src/main/java/com/yahoo/document/json/readers/WeightedSetReader.java
@@ -0,0 +1,31 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.document.json.readers;
+
+import com.yahoo.document.DataType;
+import com.yahoo.document.datatypes.FieldValue;
+import com.yahoo.document.datatypes.WeightedSet;
+import com.yahoo.document.json.TokenBuffer;
+
+import static com.yahoo.document.json.JsonReader.expectObjectStart;
+
+public class WeightedSetReader {
+ public static void fillWeightedSet(TokenBuffer buffer, DataType valueType, @SuppressWarnings("rawtypes") WeightedSet weightedSet) {
+ int initNesting = buffer.nesting();
+ expectObjectStart(buffer.currentToken());
+ buffer.next();
+ iterateThroughWeightedSet(buffer, initNesting, valueType, weightedSet);
+ }
+ public static void fillWeightedSetUpdate(TokenBuffer buffer, int initNesting, DataType valueType, @SuppressWarnings("rawtypes") WeightedSet weightedSet) {
+ iterateThroughWeightedSet(buffer, initNesting, valueType, weightedSet);
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private static void iterateThroughWeightedSet(TokenBuffer buffer, int initNesting, DataType valueType, WeightedSet weightedSet) {
+ while (buffer.nesting() >= initNesting) {
+ // XXX the keys are defined in the spec to always be represented as strings
+ FieldValue v = valueType.createFieldValue(buffer.currentName());
+ weightedSet.put(v, Integer.valueOf(buffer.currentText()));
+ buffer.next();
+ }
+ }
+}
diff --git a/document/src/test/java/com/yahoo/document/json/JsonReaderTestCase.java b/document/src/test/java/com/yahoo/document/json/JsonReaderTestCase.java
index ef58692662b..127d2cb968a 100644
--- a/document/src/test/java/com/yahoo/document/json/JsonReaderTestCase.java
+++ b/document/src/test/java/com/yahoo/document/json/JsonReaderTestCase.java
@@ -30,6 +30,8 @@ import com.yahoo.document.datatypes.StringFieldValue;
import com.yahoo.document.datatypes.Struct;
import com.yahoo.document.datatypes.TensorFieldValue;
import com.yahoo.document.datatypes.WeightedSet;
+import com.yahoo.document.json.readers.DocumentParseInfo;
+import com.yahoo.document.json.readers.SingleValueReader;
import com.yahoo.document.update.AddValueUpdate;
import com.yahoo.document.update.ArithmeticValueUpdate;
import com.yahoo.document.update.ArithmeticValueUpdate.Operator;
@@ -63,6 +65,7 @@ import java.util.Map;
import java.util.Random;
import java.util.Set;
+import static com.yahoo.document.json.readers.SingleValueReader.*;
import static com.yahoo.test.json.JsonTestHelper.inputJson;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
@@ -209,7 +212,7 @@ public class JsonReaderTestCase {
+ " \"fields\": { \"something\": \"smoketest\","
+ " \"nalle\": \"bamse\"}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -225,7 +228,7 @@ public class JsonReaderTestCase {
+ "\"put\": \"id:unittest:smoke::whee\""
+ "}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -239,7 +242,7 @@ public class JsonReaderTestCase {
Utf8.toBytes("{\"put\": \"id:unittest:smoke::whee\","
+ " \"fields\": {}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -255,7 +258,7 @@ public class JsonReaderTestCase {
+ "\"sandra\": \"person\","
+ " \"cloud\": \"another person\"}}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -275,7 +278,7 @@ public class JsonReaderTestCase {
+ " \"person\","
+ " \"another person\"]}}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentUpdate doc = new DocumentUpdate(docType, parseInfo.documentId);
r.readUpdate(parseInfo.fieldsBuffer, doc);
@@ -291,7 +294,7 @@ public class JsonReaderTestCase {
+ " \"person\": 37,"
+ " \"another person\": 41}}}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentUpdate doc = new DocumentUpdate(docType, parseInfo.documentId);
r.readUpdate(parseInfo.fieldsBuffer, doc);
@@ -320,7 +323,7 @@ public class JsonReaderTestCase {
+ " \"element\": \"person\","
+ " \"increment\": 13}}}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentUpdate doc = new DocumentUpdate(docType, parseInfo.documentId);
@@ -346,13 +349,13 @@ public class JsonReaderTestCase {
@Test
public final void testArithmeticOperators() {
Tuple2[] operations = new Tuple2[] {
- new Tuple2<String, Operator>(JsonReader.UPDATE_DECREMENT,
+ new Tuple2<String, Operator>(UPDATE_DECREMENT,
ArithmeticValueUpdate.Operator.SUB),
- new Tuple2<String, Operator>(JsonReader.UPDATE_DIVIDE,
+ new Tuple2<String, Operator>(UPDATE_DIVIDE,
ArithmeticValueUpdate.Operator.DIV),
- new Tuple2<String, Operator>(JsonReader.UPDATE_INCREMENT,
+ new Tuple2<String, Operator>(UPDATE_INCREMENT,
ArithmeticValueUpdate.Operator.ADD),
- new Tuple2<String, Operator>(JsonReader.UPDATE_MULTIPLY,
+ new Tuple2<String, Operator>(UPDATE_MULTIPLY,
ArithmeticValueUpdate.Operator.MUL) };
for (Tuple2<String, Operator> operator : operations) {
InputStream rawDoc = new ByteArrayInputStream(
@@ -362,7 +365,7 @@ public class JsonReaderTestCase {
+ " \"" + (String) operator.first + "\": 13}}}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentUpdate doc = new DocumentUpdate(docType, parseInfo.documentId);
@@ -396,7 +399,7 @@ public class JsonReaderTestCase {
+ " \"element\": 3,"
+ " \"assign\": \"nalle\"}}}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentUpdate doc = new DocumentUpdate(docType, parseInfo.documentId);
@@ -434,7 +437,7 @@ public class JsonReaderTestCase {
+ " \"nalle\": 2,"
+ " \"tralle\": 7 }}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -455,7 +458,7 @@ public class JsonReaderTestCase {
+ " \"nalle\","
+ " \"tralle\"]}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -476,7 +479,7 @@ public class JsonReaderTestCase {
+ " { \"key\": \"nalle\", \"value\": \"kalle\"},"
+ " { \"key\": \"tralle\", \"value\": \"skalle\"} ]}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -495,7 +498,7 @@ public class JsonReaderTestCase {
Utf8.toBytes("{\"put\": \"id:unittest:testsinglepos::bamf\","
+ " \"fields\": { \"singlepos\": \"N63.429722;E10.393333\" }}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -512,7 +515,7 @@ public class JsonReaderTestCase {
Utf8.toBytes("{\"put\": \"id:unittest:testsinglepos::bamf\","
+ " \"fields\": { \"singlepos\": \"W46.63;S23.55\" }}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -533,7 +536,7 @@ public class JsonReaderTestCase {
+ "\""
+ " }}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -553,7 +556,7 @@ public class JsonReaderTestCase {
+ "{ \"key\": \"bamse\", \"value\": [1, 2, 3] }"
+ "]}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
@@ -575,7 +578,7 @@ public class JsonReaderTestCase {
+ " \"fields\": { \"something\": {"
+ " \"assign\": \"orOther\" }}" + " }"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentUpdate doc = new DocumentUpdate(docType, parseInfo.documentId);
r.readUpdate(parseInfo.fieldsBuffer, doc);
@@ -594,7 +597,7 @@ public class JsonReaderTestCase {
+ "{ \"key\": \"bamse\", \"value\": [1, 2, 3] }"
+ "]}}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentUpdate doc = new DocumentUpdate(docType, parseInfo.documentId);
r.readUpdate(parseInfo.fieldsBuffer, doc);
@@ -618,7 +621,7 @@ public class JsonReaderTestCase {
+ " \"person\": 37,"
+ " \"another person\": 41}}}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentUpdate doc = new DocumentUpdate(docType, parseInfo.documentId);
r.readUpdate(parseInfo.fieldsBuffer, doc);
@@ -819,7 +822,7 @@ public class JsonReaderTestCase {
+ " \"fields\": { \"smething\": \"smoketest\","
+ " \"nalle\": \"bamse\"}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
exception.expect(NullPointerException.class);
@@ -848,7 +851,7 @@ public class JsonReaderTestCase {
+ " \"fields\": { \"something\": \"smoketest\","
+ " \"nalle\": \"bamse\"}}"));
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo parseInfo = r.parseDocument().get();
+ DocumentParseInfo parseInfo = r.parseDocument().get();
DocumentType docType = r.readDocumentType(parseInfo.documentId);
DocumentPut put = new DocumentPut(new Document(docType, parseInfo.documentId));
r.readPut(parseInfo.fieldsBuffer, put);
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 3a209fb895b..2ef6fad965e 100644
--- a/document/src/test/java/com/yahoo/document/json/JsonWriterTestCase.java
+++ b/document/src/test/java/com/yahoo/document/json/JsonWriterTestCase.java
@@ -22,6 +22,7 @@ import com.yahoo.document.TensorDataType;
import com.yahoo.document.WeightedSetDataType;
import com.yahoo.document.datatypes.ReferenceFieldValue;
import com.yahoo.document.datatypes.TensorFieldValue;
+import com.yahoo.document.json.readers.DocumentParseInfo;
import com.yahoo.tensor.TensorType;
import com.yahoo.text.Utf8;
import org.apache.commons.codec.binary.Base64;
@@ -36,6 +37,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import static com.yahoo.document.json.readers.MapReader.MAP_KEY;
+import static com.yahoo.document.json.readers.MapReader.MAP_VALUE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
@@ -244,8 +247,8 @@ public class JsonWriterTestCase {
private Map<Object, Object> populateMap(List<?> actualMap) {
Map<Object, Object> m = new HashMap<>();
for (Object o : actualMap) {
- Object key = ((Map) o).get(JsonReader.MAP_KEY);
- Object value = ((Map) o).get(JsonReader.MAP_VALUE);
+ Object key = ((Map) o).get(MAP_KEY);
+ Object value = ((Map) o).get(MAP_VALUE);
m.put(key, value);
}
return m;
@@ -290,8 +293,10 @@ public class JsonWriterTestCase {
private Document readDocumentFromJson(String docId, String fields) {
InputStream rawDoc = new ByteArrayInputStream(asFeed(docId, fields));
+
+
JsonReader r = new JsonReader(types, rawDoc, parserFactory);
- JsonReader.DocumentParseInfo raw = r.parseDocument().get();
+ DocumentParseInfo raw = r.parseDocument().get();
DocumentType docType = r.readDocumentType(raw.documentId);
DocumentPut put = new DocumentPut(new Document(docType, raw.documentId));
r.readPut(raw.fieldsBuffer, put);