//------------------------------< internal >--------------------------------
private void parseJsonDiff(Commit commit, String json, String rootPath) {
Revision baseRev = commit.getBaseRevision();
String baseRevId = baseRev != null ? baseRev.toString() : null;
JsopReader t = new JsopTokenizer(json);
while (true) {
int r = t.read();
if (r == JsopReader.END) {
break;
}
String path = PathUtils.concat(rootPath, t.readString());
switch (r) {
case '+':
t.read(':');
t.read('{');
parseAddNode(commit, t, path);
break;
case '-':
DocumentNodeState toRemove = nodeStore.getNode(path, commit.getBaseRevision());
if (toRemove == null) {
throw new MicroKernelException("Node not found: " + path + " in revision " + baseRevId);
}
commit.removeNode(path);
nodeStore.markAsDeleted(toRemove, commit, true);
commit.removeNodeDiff(path);
break;
case '^':
t.read(':');
String value;
if (t.matches(JsopReader.NULL)) {
value = null;
} else {
value = t.readRawValue().trim();
}
String p = PathUtils.getParentPath(path);
String propertyName = PathUtils.getName(path);
commit.updateProperty(p, propertyName, value);
commit.updatePropertyDiff(p, propertyName, value);
break;
case '>': {
// TODO support moving nodes that were modified within this commit
t.read(':');
String targetPath = t.readString();
if (!PathUtils.isAbsolute(targetPath)) {
targetPath = PathUtils.concat(rootPath, targetPath);
}
DocumentNodeState source = nodeStore.getNode(path, baseRev);
if (source == null) {
throw new MicroKernelException("Node not found: " + path + " in revision " + baseRevId);
} else if (nodeExists(targetPath, baseRevId)) {
throw new MicroKernelException("Node already exists: " + targetPath + " in revision " + baseRevId);
}
commit.moveNode(path, targetPath);
nodeStore.moveNode(source, targetPath, commit);
break;
}
case '*': {
// TODO support copying nodes that were modified within this commit
t.read(':');
String targetPath = t.readString();
if (!PathUtils.isAbsolute(targetPath)) {
targetPath = PathUtils.concat(rootPath, targetPath);
}
DocumentNodeState source = nodeStore.getNode(path, baseRev);
if (source == null) {
throw new MicroKernelException("Node not found: " + path + " in revision " + baseRevId);
} else if (nodeExists(targetPath, baseRevId)) {
throw new MicroKernelException("Node already exists: " + targetPath + " in revision " + baseRevId);
}
commit.copyNode(path, targetPath);
nodeStore.copyNode(source, targetPath, commit);
break;
}
default:
throw new MicroKernelException("token: " + (char) t.getTokenType());
}
}
}