void (ExternalSystemNode<?> currentNode, DataNode<?> newDataNode, ExternalSystemNode newNode) { final ExternalSystemNode<?>[] cached = currentNode.getCached(); if (cached == null) { //noinspection unchecked currentNode.mergeWith(newNode); } else { final List<Object> duplicates = new ArrayList<>(); final Map<Object, ExternalSystemNode<?>> oldDataMap = new LinkedHashMap<>(); for (ExternalSystemNode<?> node : cached) { Object key = node.getData() != null ? node.getData() : node.getName(); final Object systemNode = oldDataMap.put(key, node); if(systemNode != null) { duplicates.add(key); } } Map<Object, ExternalSystemNode<?>> newDataMap = new LinkedHashMap<>(); Map<Object, ExternalSystemNode<?>> unchangedNewDataMap = new LinkedHashMap<>(); for (ExternalSystemNode<?> node : newNode.getChildren()) { Object key = node.getData() != null ? node.getData() : node.getName(); if (oldDataMap.remove(key) == null) { newDataMap.put(key, node); } else { unchangedNewDataMap.put(key, node); } } for (Object duplicate : duplicates) { newDataMap.remove(duplicate); } currentNode.removeAll(oldDataMap.values()); for (ExternalSystemNode<?> node : currentNode.getChildren()) { Object key = node.getData() != null ? node.getData() : node.getName(); final ExternalSystemNode<?> unchangedNewNode = unchangedNewDataMap.get(key); if (unchangedNewNode != null) { doMergeChildrenChanges(node, unchangedNewNode.myDataNode, unchangedNewNode); } } updateFrom(currentNode); //noinspection unchecked currentNode.mergeWith(newNode); currentNode.addAll(newDataMap.values()); } }