/** * Copies the given tree of T to CopyType, starting at the leaf nodes * of the tree and moving in to the root node, which allows CopyType to * be immutable (but does not require it). * * @param def defines the structure of the tree * @param root root of the tree * @param nodeMapper given an unmapped node, and a list of CopyType nodes which have already been mapped, return a mapped node. * @return a CopyType with the same contents as the source tree */ public static <T, CopyType> CopyType copyLeavesIn(TreeDef<T> def, T root, BiFunction<T, List<CopyType>, CopyType> nodeMapper) { List<CopyType> childrenMapped = def.childrenOf(root).stream() .map(child -> copyLeavesIn(def, child, nodeMapper)) .collect(Collectors.toList()); return nodeMapper.apply(root, childrenMapped); }