code: 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 -> {
  			return copyLeavesIn(def, child, nodeMapper);
  		}).collect(Collectors.toList());
  		return nodeMapper.apply(root, childrenMapped);
  	}
docs: 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