void (@NotNull DefaultMutableTreeNode node, @NotNull TreeUpdatePass pass, @Nullable LoadedChildren preloadedChildren, boolean toSmartExpand, boolean wasExpanded, boolean forceUpdate) { if (isUpdatingChildrenNow(node)) return; if (!canInitiateNewActivity()) { throw new ProcessCanceledException(); } NodeDescriptor<?> descriptor = getDescriptorFrom(node); MutualMap<Object, Integer> elementToIndexMap = loadElementsFromStructure(descriptor, preloadedChildren); LoadedChildren loadedChildren = preloadedChildren != null ? preloadedChildren : new LoadedChildren(elementToIndexMap.getKeys().toArray()); addToUpdatingChildren(node); pass.setCurrentNode(node); boolean canSmartExpand = canSmartExpand(node, toSmartExpand); removeFromUnbuilt(node); //noinspection unchecked processExistingNodes(node, elementToIndexMap, pass, canSmartExpand(node, toSmartExpand), forceUpdate, wasExpanded, preloadedChildren) .onSuccess(new TreeConsumer("AbstractTreeUi.updateNodeChildrenNow: on done processExistingNodes") { @Override public void perform() { if (isDisposed(node)) { removeFromUpdatingChildren(node); return; } removeLoading(node, false); boolean expanded = isExpanded(node, wasExpanded); if (expanded) { myWillBeExpanded.add(node); } else { myWillBeExpanded.remove(node); } collectNodesToInsert(descriptor, elementToIndexMap, node, expanded, loadedChildren) .doWhenDone((Consumer<List<TreeNode>>)nodesToInsert -> { insertNodesInto(nodesToInsert, node); ActionCallback callback = updateNodesToInsert(nodesToInsert, pass, canSmartExpand, isChildNodeForceUpdate(node, forceUpdate, expanded)); callback.doWhenDone(new TreeRunnable("AbstractTreeUi.updateNodeChildrenNow: on done updateNodesToInsert") { @Override public void perform() { removeLoading(node, false); removeFromUpdatingChildren(node); if (node.getChildCount() > 0) { if (expanded) { expand(node, canSmartExpand); } } if (!canInitiateNewActivity()) { throw new ProcessCanceledException(); } Object element = getElementFor(node); addNodeAction(element, false, node1 -> removeLoading(node1, false)); processNodeActionsIfReady(node); } }); }).doWhenProcessed(new TreeRunnable("AbstractTreeUi.updateNodeChildrenNow: on processed collectNodesToInsert") { @Override public void perform() { myWillBeExpanded.remove(node); removeFromUpdatingChildren(node); processNodeActionsIfReady(node); } }); } }) .onError(new TreeConsumer<>("AbstractTreeUi.updateNodeChildrenNow: on reject processExistingNodes") { @Override public void perform() { removeFromUpdatingChildren(node); processNodeActionsIfReady(node); } }); }