void (@NotNull TreeModelEvent event, @NotNull EventType type) { TreePath path = event.getTreePath(); if (path == null) { // request a new root from model according to the specification submit(new CmdGetRoot("Reload root", null)); return; } Object object = path.getLastPathComponent(); if (object == null) { LOG.warn("unsupported path: " + path); return; } if (path.getParentPath() == null && type == EventType.StructureChanged) { // set a new root object according to the specification submit(new CmdGetRoot("Update root", object)); return; } onValidThread(() -> { Node node = tree.map.get(object); if (node == null) { if (LOG.isTraceEnabled()) LOG.debug("ignore updating of nonexistent node: ", object); } else if (type == EventType.NodesChanged) { // the object is already updated, so we should not start additional command to update AsyncTreeModel.this.treeNodesChanged(event.getTreePath(), event.getChildIndices(), event.getChildren()); } else if (node.isLoadingRequired()) { // update the object presentation only, if its children are not requested yet AsyncTreeModel.this.treeNodesChanged(event.getTreePath(), null, null); } else if (type == EventType.NodesInserted) { submit(new CmdGetChildren("Insert children", node, false)); } else if (type == EventType.NodesRemoved) { submit(new CmdGetChildren("Remove children", node, false)); } else { submit(new CmdGetChildren("Update children", node, true)); } }); }