RDBDocumentSerializer { @NotNull public <T extends Document> T fromRow(@NotNull Collection<T> collection, @NotNull RDBRow row) throws DocumentStoreException { final String charData = row.getData(); checkNotNull(charData, "RDBRow.getData() is null for collection " + collection + ", id: " + row.getId()); T doc = collection.newDocument(store); doc.put(ID, row.getId()); if (row.getModified() != RDBRow.LONG_UNSET) { doc.put(MODIFIED, row.getModified()); } if (row.getModcount() != RDBRow.LONG_UNSET) { doc.put(MODCOUNT, row.getModcount()); } if (RDBDocumentStore.USECMODCOUNT && row.getCollisionsModcount() != RDBRow.LONG_UNSET) { doc.put(CMODCOUNT, row.getCollisionsModcount()); } if (row.hasBinaryProperties() != null) { doc.put(HASBINARY, row.hasBinaryProperties().longValue()); } if (row.deletedOnce() != null) { doc.put(DELETEDONCE, row.deletedOnce().booleanValue()); } if (row.getSchemaVersion() >= 2) { if (row.getSdType() != RDBRow.LONG_UNSET) { doc.put(SDTYPE, row.getSdType()); } if (row.getSdMaxRevTime() != RDBRow.LONG_UNSET) { doc.put(SDMAXREVTIME, row.getSdMaxRevTime()); } } byte[] bdata = row.getBdata(); boolean blobInUse = false; JsopTokenizer json; try { if (bdata != null && bdata.length != 0) { String s = fromBlobData(bdata); json = new JsopTokenizer(s); json.read('{'); readDocumentFromJson(json, doc); json.read(JsopReader.END); blobInUse = true; } } catch (Exception ex) { throw asDocumentStoreException(ex, "parsing blob data as JSON"); } json = new JsopTokenizer(charData); try { int next = json.read(); if (next == '{') { if (blobInUse) { throw new DocumentStoreException("expected literal \"blob\" but found: " + row.getData()); } readDocumentFromJson(json, doc); } else if (next == JsopReader.STRING) { if (!blobInUse) { throw new DocumentStoreException("did not expect \"blob\" here: " + row.getData()); } if (!"blob".equals(json.getToken())) { throw new DocumentStoreException("expected string literal \"blob\""); } } else { throw new DocumentStoreException("unexpected token " + next + " in " + row.getData()); } next = json.read(); if (next == ',') { do { Object ob = JSON.parse(json); if (!(ob instanceof List)) { throw new DocumentStoreException("expected array but got: " + ob); } List<List<Object>> update = (List<List<Object>>) ob; for (List<Object> op : update) { applyUpdate(doc, update, op); } } while (json.matches(',')); } json.read(JsopReader.END); checkSdType(doc); return doc; } catch (Exception ex) { String message = String.format("Error processing persisted data for document '%s'", row.getId()); if (charData.length() > 0) { int last = charData.charAt(charData.length() - 1); if (last != '}' && last != '"' && last != ']') { message += " (DATA column might be truncated)"; } } LOG.error(message, ex); throw asDocumentStoreException(ex, message); } } RDBDocumentSerializer(DocumentStore store); String asString(@NotNull Document doc, Set<String> columnProperties); String asString(UpdateOp update, Set<String> columnProperties); @NotNull T fromRow(@NotNull Collection<T> collection, @NotNull RDBRow row);  }
@Test public void testSimpleString() { RDBRow row = new RDBRow("_foo", 1L, true, 1l, 2l, 3l, 0L, 0L, 0L, "{}", null); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals(true, doc.hasBinary()); assertEquals(true, doc.get(NodeDocument.DELETED_ONCE)); assertEquals(2L, doc.getModCount().longValue()); }
@Test public void testNoSysprops() { RDBRow row = new RDBRow("_foo", null, null, 1l, 2l, 3l, 0L, 0L, 0L, "{}", null); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals(false, doc.hasBinary()); assertNull(null, doc.get(NodeDocument.HAS_BINARY_FLAG)); assertEquals(false, doc.wasDeletedOnce()); assertNull(null, doc.get(NodeDocument.DELETED_ONCE)); assertEquals(2L, doc.getModCount().longValue()); }
@Test public void testSimpleBlob() throws UnsupportedEncodingException { RDBRow row = new RDBRow("_foo", 0L, false, 1l, 2l, 3l, 0L, 0L, 0L, "\"blob\"", "{}".getBytes("UTF-8")); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals(false, doc.hasBinary()); assertEquals(2L, doc.getModCount().longValue()); }
@Test public void testSimpleBlobGzipped() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); GZIPOutputStream gos = new GZIPOutputStream(bos); gos.write("{}".getBytes("UTF-8")); gos.close(); RDBRow row = new RDBRow("_foo", 0L, false, 1l, 2l, 3l, 0L, 0L, 0L, "\"blob\"", bos.toByteArray()); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals(false, doc.hasBinary()); assertEquals(2L, doc.getModCount().longValue()); }
@Test public void testSimpleBlob2() throws UnsupportedEncodingException { RDBRow row = new RDBRow("_foo", 0L, false, 1l, 2l, 3l, 0L, 0L, 0L, "\"blob\"", "{\"s\":\"string\", \"b\":true, \"i\":1}".getBytes("UTF-8")); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals(false, doc.hasBinary()); assertEquals(2L, doc.getModCount().longValue()); assertEquals("string", doc.get("s")); assertEquals(Boolean.TRUE, doc.get("b")); assertEquals(1L, doc.get("i")); }
@Test public void testSimpleBoth() throws UnsupportedEncodingException { try { RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, 0L, 0L, "{}", "{}".getBytes("UTF-8")); this.ser.fromRow(Collection.NODES, row); fail("should fail"); } catch (DocumentStoreException expected) { } }
@Test public void testBlobAndDiff() throws UnsupportedEncodingException { RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, 0L, 0L, "\"blob\", [[\"=\", \"foo\", \"bar\"],[\"M\", \"m1\", 1],[\"M\", \"m2\", 3]]", "{\"m1\":2, \"m2\":2}".getBytes("UTF-8")); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("bar", doc.get("foo")); assertEquals(2L, doc.get("m1")); assertEquals(3L, doc.get("m2")); }
@Test public void testBlobAndDiffBorked() throws UnsupportedEncodingException { try { RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, 0L, 0L, "[[\"\", \"\", \"\"]]", "{}".getBytes("UTF-8")); this.ser.fromRow(Collection.NODES, row); fail("should fail"); } catch (DocumentStoreException expected) { } }
@Test public void testNullModified() throws UnsupportedEncodingException { RDBRow row = new RDBRow("_foo", 1L, true, null, 2l, 3l, 0L, 0L, 0L, "{}", null); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertNull(doc.getModified()); }
@Test public void testBrokenJSONTrailingComma() throws UnsupportedEncodingException { try { RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, 0L, 0L, "{ \"x\" : 1, }", null); this.ser.fromRow(Collection.NODES, row); fail("should fail"); } catch (DocumentStoreException expected) { } }
@Test public void testBrokenJSONUnquotedIdentifier() throws UnsupportedEncodingException { try { RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, 0L, 0L, "{ x : 1, }", null); this.ser.fromRow(Collection.NODES, row); fail("should fail"); } catch (DocumentStoreException expected) { } }
@Test public void testSimpleStringNonAscii() { RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, 0L, 0L, "{\"x\":\"\u20ac\uD834\uDD1E\"}", null); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals("\u20ac\uD834\uDD1E", doc.get("x")); }
@Test public void testInvalidGzip() { try { byte[] bytes = { 31, -117, 1, 2, 3, 4 }; RDBRow row = new RDBRow("_foo", 0L, false, 1l, 2l, 3l, 0L, 0L, 0L, "\"blob\"", bytes); this.ser.fromRow(Collection.NODES, row); fail("should fail"); } catch (DocumentStoreException expected) { } }