public static void collapseAll(@NotNull JTree tree, boolean strict, int keepSelectionLevel) {
    assert EventQueue.isDispatchThread();
    int row = tree.getRowCount();
    if (row <= 1) return; // nothing to collapse

    final TreePath leadSelectionPath = tree.getLeadSelectionPath();

    int minCount = 1; // allowed path count to collapse
    if (!tree.isRootVisible()) minCount++;
    if (!tree.getShowsRootHandles()) {
      minCount++;
      strict = true;
    }

    // use the parent path of the normalized selection path to prohibit its collapsing
    TreePath prohibited = leadSelectionPath == null ? null : normalize(leadSelectionPath, minCount, keepSelectionLevel).getParentPath();
    // Collapse all
    var paths = new ArrayList<TreePath>();
    while (0 < row--) {
      if (!strict && row == 0) break;
      TreePath path = tree.getPathForRow(row);
      assert path != null : "path is not found at row " + row;
      int pathCount = path.getPathCount();
      if (pathCount < minCount) continue;
      if (pathCount == minCount && row > 0) strict = true;
      if (!isAlwaysExpand(path) && !path.isDescendant(prohibited)) {
        paths.add(path);
      }
    }
    collapsePaths(tree, paths);
    if (leadSelectionPath == null) return; // no selection to restore
    if (!strict) minCount++; // top level node is not collapsed
    internalSelect(tree, normalize(leadSelectionPath, minCount, keepSelectionLevel));
  }
public static void collapseAll(@NotNull JTree tree, boolean strict, int keepSelectionLevel)