final List<FileNode> getChildren() {
      List<FileNode> oldList = children;
      if (valid) return oldList;
      checkCanceled(); // ProcessCanceledException if current task is interrupted
      List<FileNode> newList = getChildren(oldList);
      oldList.forEach(node -> node.parent = null);
      newList.forEach(node -> node.parent = this);
      // cleanup removed nodes recursively to facilitate garbage collection
      oldList.stream().filter(node -> node.parent == null).forEach(Node::cleanup);
      children = newList;
      valid = true;
      return newList;
    }
final List<FileNode> getChildren()