in oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentSerializer.java [147:251]
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;
// case #1: BDATA (blob) contains base data, DATA (string) contains
// update operations
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);
// start processing the VARCHAR data
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);
// OAK-7855: check and fix _sdType
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);
}
}