public void decorate(final BiFunction<K, ExplorerNode, ExplorerNode> nodeDecorator) {
        final K nullKey = null;
        final Set<ExplorerNode> childNodes = parentKeyToChildNodesMap.get(nullKey);

        // All the root nodes
        if (NullSafe.hasItems(childNodes)) {
            final Set<ExplorerNode> newChildNodes = new HashSet<>(childNodes.size());
            boolean hasChildNodeChanged = false;
            for (final ExplorerNode childNode : NullSafe.set(childNodes)) {
                final K childNodeKey = getNodeKey(childNode);
                final ExplorerNode newChildNode = decorate(childNodeKey, childNode, nodeDecorator);
                newChildNodes.add(newChildNode);
                if (newChildNode != childNode) {
                    hasChildNodeChanged = true;
                    keyToNodeMap.put(nullKey, newChildNode);
                }
            }

            if (hasChildNodeChanged) {
                parentKeyToChildNodesMap.put(nullKey, newChildNodes);
            }
        }
    }
@param nodeDecorator Returns a decorated copy of the node passed to it. It MUST have the
                     same node key as the node passed in. Will be called for each node in
                     a depth first way, with siblings processed in no specific order.
stroom-explorer/stroom-explorer-impl/src/main/java/stroom/explorer/impl/AbstractTreeModel.java