private int visit(final Node<T> n, final Node<T> parent, final long nameLength, final int depth, ObjectOpenHashSet<Node<T>> nodes, ObjectOpenHashSet<Leaf<T>> leaves, ObjectOpenHashSet<T> references) {
if (n == null) return 0;
if (DEBUG) {
for(int i = depth; i-- != 0;) System.err.print('\t');
System.err.println("Node " + n + " (name length: " + nameLength + ")" + (n.isInternal() ? " Jump left: " + ((InternalNode<T>)n).jumpLeft + " Jump right: " + ((InternalNode<T>)n).jumpRight : ""));
}
assert parent == null || parent.extent(transform).equals(n.extent(transform).subVector(0, ((InternalNode<T>)parent).extentLength));
assert nameLength <= n.extentLength(transform);
assert n.nameLength == nameLength : n.nameLength + " != " + nameLength + " " + n;
if (n.isInternal()) {
assert references.add(((InternalNode<T>)n).reference.key);
assert nodes.remove(n) : n;
assert handle2Node.keySet().contains(n.handle(transform)) : n;
final long jumpLength = ((InternalNode<T>)n).jumpLength();
Node<T> jumpLeft = ((InternalNode<T>)n).left;
while(jumpLeft.isInternal() && jumpLength > ((InternalNode<T>)jumpLeft).extentLength) jumpLeft = ((InternalNode<T>)jumpLeft).left;
assert jumpLeft == ((InternalNode<T>)n).jumpLeft : jumpLeft + " != " + ((InternalNode<T>)n).jumpLeft + " (node: " + n + ")";
Node<T> jumpRight = ((InternalNode<T>)n).right;
while(jumpRight.isInternal() && jumpLength > ((InternalNode<T>)jumpRight).extentLength) jumpRight = ((InternalNode<T>)jumpRight).right;
assert jumpRight == ((InternalNode<T>)n).jumpRight : jumpRight + " != " + ((InternalNode<T>)n).jumpRight + " (node: " + n + ")";
return 1 + visit(((InternalNode<T>)n).left, n, ((InternalNode<T>)n).extentLength + 1, depth + 1, nodes, leaves, references) + visit(((InternalNode<T>)n).right, n, n.extentLength(transform) + 1, depth + 1, nodes, leaves, references);
}
else {
assert leaves.add((Leaf<T>)n);
assert n.extentLength(transform) == n.key(transform).length();
return 1;
}
}