public static Collection<String> printAsList(
     JTree tree, boolean withSelection, @Nullable Condition<String> nodePrintCondition) {
   Collection<String> strings = new ArrayList<String>();
   Object root = tree.getModel().getRoot();
   printImpl(tree, root, strings, 0, withSelection, nodePrintCondition);
   return strings;
 }
  private static void printImpl(
      JTree tree,
      Object root,
      Collection<String> strings,
      int level,
      boolean withSelection,
      @Nullable Condition<String> nodePrintCondition) {
    DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode) root;

    final Object userObject = defaultMutableTreeNode.getUserObject();
    String nodeText;
    if (userObject != null) {
      nodeText = toString(userObject, null);
    } else {
      nodeText = "null";
    }

    if (nodePrintCondition != null && !nodePrintCondition.value(nodeText)) return;

    final StringBuilder buff = new StringBuilder();
    StringUtil.repeatSymbol(buff, ' ', level);

    final boolean expanded = tree.isExpanded(new TreePath(defaultMutableTreeNode.getPath()));
    if (!defaultMutableTreeNode.isLeaf()) {
      buff.append(expanded ? "-" : "+");
    }

    final boolean selected =
        tree.getSelectionModel().isPathSelected(new TreePath(defaultMutableTreeNode.getPath()));
    if (withSelection && selected) {
      buff.append("[");
    }

    buff.append(nodeText);

    if (withSelection && selected) {
      buff.append("]");
    }

    strings.add(buff.toString());

    int childCount = tree.getModel().getChildCount(root);
    if (expanded) {
      for (int i = 0; i < childCount; i++) {
        printImpl(
            tree,
            tree.getModel().getChild(root, i),
            strings,
            level + 1,
            withSelection,
            nodePrintCondition);
      }
    }
  }