buff.tag('-');
buff.value(path);
return buff.newline().toString();
}
TraversingNodeDiffHandler diffHandler = new TraversingNodeDiffHandler() {
@Override
public void propertyAdded(PropertyState after) {
buff.tag('+').
key(PathUtils.concat(getCurrentPath(), after.getName())).
encodedValue(after.getEncodedValue()).
newline();
}
@Override
public void propertyChanged(PropertyState before, PropertyState after) {
buff.tag('^').
key(PathUtils.concat(getCurrentPath(), after.getName())).
encodedValue(after.getEncodedValue()).
newline();
}
@Override
public void propertyDeleted(PropertyState before) {
// since property and node deletions can't be distinguished
// using the "- <path>" notation we're representing
// property deletions as "^ <path>:null"
buff.tag('^').
key(PathUtils.concat(getCurrentPath(), before.getName())).
value(null).
newline();
}
@Override
public void childNodeAdded(String name, NodeState after) {
addedNodes.put(rp.getId(after), PathUtils.concat(getCurrentPath(), name));
buff.tag('+').
key(PathUtils.concat(getCurrentPath(), name)).object();
toJson(buff, after, Integer.MAX_VALUE, 0, -1, false);
buff.endObject().newline();
}
@Override
public void childNodeDeleted(String name, NodeState before) {
removedNodes.put(rp.getId(before), PathUtils.concat(getCurrentPath(), name));
buff.tag('-');
buff.value(PathUtils.concat(getCurrentPath(), name));
buff.newline();
}
};
diffHandler.start(node1, node2, path);
// check if this commit includes 'move' operations
// by building intersection of added and removed nodes
addedNodes.keySet().retainAll(removedNodes.keySet());
if (!addedNodes.isEmpty()) {
// this commit includes 'move' operations
removedNodes.keySet().retainAll(addedNodes.keySet());
// addedNodes & removedNodes now only contain information about moved nodes
// re-build the diff in a 2nd pass, this time representing moves correctly
buff.resetWriter();
// TODO refactor code, avoid duplication
diffHandler = new TraversingNodeDiffHandler() {
@Override
public void propertyAdded(PropertyState after) {
buff.tag('+').
key(PathUtils.concat(getCurrentPath(), after.getName())).
encodedValue(after.getEncodedValue()).
newline();
}
@Override
public void propertyChanged(PropertyState before, PropertyState after) {
buff.tag('^').
key(PathUtils.concat(getCurrentPath(), after.getName())).
encodedValue(after.getEncodedValue()).
newline();
}
@Override
public void propertyDeleted(PropertyState before) {
// since property and node deletions can't be distinguished
// using the "- <path>" notation we're representing
// property deletions as "^ <path>:null"
buff.tag('^').
key(PathUtils.concat(getCurrentPath(), before.getName())).
value(null).
newline();
}
@Override
public void childNodeAdded(String name, NodeState after) {
if (addedNodes.containsKey(rp.getId(after))) {
// moved node, will be processed separately
return;
}
buff.tag('+').
key(PathUtils.concat(getCurrentPath(), name)).object();
toJson(buff, after, Integer.MAX_VALUE, 0, -1, false);
buff.endObject().newline();
}
@Override
public void childNodeDeleted(String name, NodeState before) {
if (addedNodes.containsKey(rp.getId(before))) {
// moved node, will be processed separately
return;
}
buff.tag('-');
buff.value(PathUtils.concat(getCurrentPath(), name));
buff.newline();
}
};
diffHandler.start(node1, node2, path);
// finally process moved nodes
for (Map.Entry<Id, String> entry : addedNodes.entrySet()) {
buff.tag('>').
// path/to/deleted/node