in xstream/src/java/com/thoughtworks/xstream/io/xml/xppdom/XppDomComparator.java [63:155]
private int compareInternal(final XppDom dom1, final XppDom dom2, final StringBuilder xpath, final int count) {
final int pathlen = xpath.length();
final String name = dom1.getName();
int s = name.compareTo(dom2.getName());
xpath.append(name);
if (count >= 0) {
xpath.append('[').append(count).append(']');
}
if (s != 0) {
xpath.append('?');
return s;
}
final String[] attributes = dom1.getAttributeNames();
final String[] attributes2 = dom2.getAttributeNames();
final int len = attributes.length;
s = attributes2.length - len;
if (s != 0) {
xpath.append("::count(@*)");
return s < 0 ? 1 : -1;
}
Arrays.sort(attributes);
Arrays.sort(attributes2);
for (int i = 0; i < len; ++i) {
final String attribute = attributes[i];
s = attribute.compareTo(attributes2[i]);
if (s != 0) {
xpath.append("[@").append(attribute).append("?]");
return s;
}
s = dom1.getAttribute(attribute).compareTo(dom2.getAttribute(attribute));
if (s != 0) {
xpath.append("[@").append(attribute).append(']');
return s;
}
}
final int children = dom1.getChildCount();
s = dom2.getChildCount() - children;
if (s != 0) {
xpath.append("::count(*)");
return s < 0 ? 1 : -1;
}
if (children > 0) {
if (dom1.getValue() != null || dom2.getValue() != null) {
throw new IllegalArgumentException("XppDom cannot handle mixed mode at " + xpath + "::text()");
}
xpath.append('/');
final Map<String, int[]> names = new HashMap<>();
for (int i = 0; i < children; ++i) {
final XppDom child1 = dom1.getChild(i);
final XppDom child2 = dom2.getChild(i);
final String child = child1.getName();
if (!names.containsKey(child)) {
names.put(child, new int[1]);
}
s = compareInternal(child1, child2, xpath, names.get(child)[0]++);
if (s != 0) {
return s;
}
}
} else {
final String value2 = dom2.getValue();
final String value1 = dom1.getValue();
if (value1 == null) {
s = value2 == null ? 0 : -1;
} else {
s = value2 == null ? 1 : value1.compareTo(value2);
}
if (s != 0) {
xpath.append("::text()");
return s;
}
}
xpath.setLength(pathlen);
return s;
}