/** * Removes all children of an item identified by a given id. Items removed * by this method as well as the original item are all marked to be * collapsed. May be overridden in subclasses for removing obsolete data to * avoid memory leaks. * * @param id * the item id */ protected void removeChildren(Object id) { // Clean up removed nodes from child map Iterator<Entry<T, Set<T>>> iterator = childMap.entrySet().iterator(); Set<T> invalidatedChildren = new HashSet<>(); while (iterator.hasNext()) { Entry<T, Set<T>> entry = iterator.next(); T key = entry.getKey(); if (key != null && getDataProvider().getId(key).equals(id)) { invalidatedChildren.addAll(entry.getValue()); iterator.remove(); } } expandedItemIds.remove(id); invalidatedChildren.stream().map(getDataProvider()::getId) .forEach(x -> { removeChildren(x); parentIdMap.remove(x); }); }
/** * The method to recursively fetch the children of given parent. Used with * {@link Stream#flatMap} to expand a stream of parent nodes into a * flattened hierarchy. * * @param parent * the parent node * @param includeParent * {@code true} to include the parent in the stream; * {@code false} if not * @return the stream of all children under the parent */ private Stream<T> getChildrenStream(T parent, boolean includeParent) { List<T> childList = Collections.emptyList(); if (isExpanded(parent)) { childList = getDirectChildren(parent).collect(Collectors.toList()); if (childList.isEmpty()) { removeChildren(parent == null ? null : getDataProvider().getId(parent)); } else { registerChildren(parent, childList); } } return combineParentAndChildStreams(parent, childList.stream().flatMap(this::getChildrenStream), includeParent); }