All Downloads are FREE. Search and download functionalities are using the official Maven repository.

api.utils.TreeLinearizer Maven / Gradle / Ivy

The newest version!
package api.utils;

import api.ChildTree;
import api.Node;
import api.Tree;
import impl.nodepaths.ImmutableNodePath;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.function.*;
import java.util.stream.Collector;
import java.util.stream.Stream;

/**
 * Transforms a tree into a collection of paths of its children
 */
public interface TreeLinearizer {
    interface NodeConverter {
        NodePath convert(Map.Entry>, ChildTree> nodePath);
    }

    Predicate>, ChildTree>> getFilter();
    NodeConverter getConverter();

    default Collection> linearize(Tree tree){
        assert tree != null;
        assert getConverter() != null;

        Map>, ChildTree> pathsFound = buildNodePaths(tree);
        final Collection> nodePaths = new ConcurrentSkipListSet<>();
        Set>, ChildTree>> entries = pathsFound.entrySet();
        entries.parallelStream().forEach(nodePathTreeEntry -> {
            nodePaths.add(getConverter().convert(nodePathTreeEntry));
        });
        return nodePaths;
    }

    default Map>, ChildTree> buildNodePaths(Tree tree) {
        assert tree != null;
        assert getFilter() != null;

        Map>, ChildTree> pathsFound = new ConcurrentHashMap<>();
        Map>, ChildTree> currentNodePaths = new ConcurrentHashMap<>();
        Map>, ChildTree> nextNodePaths = currentNodePaths;
        ImmutableNodePath> nodePath = new ImmutableNodePath<>(tree.getTreeRoot());
        ChildTree childTree = tree.getTreeRoot().getChildTree();
        currentNodePaths.put(nodePath, childTree);
        pathsFound.put(nodePath, childTree);

        while (!nextNodePaths.isEmpty()) {
            Set>, ChildTree>> entries = currentNodePaths.entrySet();
            Stream>, ChildTree>> entryStream = entries.parallelStream();
            nextNodePaths = entryStream.collect(new Collector>,ChildTree>, ConcurrentHashMap>, ChildTree>, Map>,ChildTree>>() {
                final ConcurrentHashMap>, ChildTree> map = new ConcurrentHashMap<>();

                @Override
                public Supplier>, ChildTree>> supplier() {
                    return () -> map;
                }

                @Override
                public BiConsumer>, ChildTree>, Map.Entry>, ChildTree>> accumulator() {
                    return (path, treeEntry) -> {
                        List> nodeList = treeEntry.getKey().getNodes();
                        ChildTree childTree = treeEntry.getValue();
                        List> nodes = childTree.getNodes();
                        Stream> nodeStream = nodes.parallelStream();
                        nodeStream.forEach(node -> {
                            ChildTree childTree1 = node.getChildTree();
                            path.put(new ImmutableNodePath<>(nodeList, node), childTree1);
                        });
                    };
                }

                @Override
                public BinaryOperator>, ChildTree>> combiner() {
                    return (path1, path2) -> {
                        path1.putAll(path2);
                        return path1;
                    };
                }

                @Override
                public Function>, ChildTree>, Map>, ChildTree>> finisher() {
                    return map -> map;
                }

                @Override
                public Set characteristics() {
                    return new HashSet<>(Arrays.asList(
                            Characteristics.UNORDERED,
                            Characteristics.IDENTITY_FINISH,
                            Characteristics.CONCURRENT
                    ));
                }
            });

            pathsFound.putAll(nextNodePaths);
            currentNodePaths = nextNodePaths;
        }
        Map>, ChildTree> result = new ConcurrentHashMap<>();
        pathsFound.entrySet().parallelStream().filter(getFilter()).forEach(treeEntry -> result.put(treeEntry.getKey(), treeEntry.getValue()));
        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy