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

net.kemitix.mon.tree.MutableTree Maven / Gradle / Ivy

There is a newer version: 3.2.0
Show newest version
/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2018 Paul Campbell
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package net.kemitix.mon.tree;

import lombok.EqualsAndHashCode;
import net.kemitix.mon.maybe.Maybe;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * A mutable {@link Tree}.
 *
 * @param  the type of the objects help in the tree
 *
 * @author Paul Campbell ([email protected])
 */
@EqualsAndHashCode
@SuppressWarnings("methodcount")
class MutableTree implements Tree, TreeMapper {

    private final List> mySubTrees = new ArrayList<>();

    private T item;

    /**
     * Create a new {@link MutableTree}.
     *
     * @param  the type of the {@link Tree}.
     *
     * @return the MutableTree
     */
    static  MutableTree create() {
        return new MutableTree<>();
    }

    /**
     * Create a new mutable tree to hold object of a type.
     *
     * @param item the item for the leaf node
     * @param  the type of the object to be held in the tree
     *
     * @return a empty mutable tree
     */
    static  MutableTree leaf(final B item) {
        return MutableTree.create().set(item);
    }

    /**
     * Create a new mutable tree to hold the single item.
     *
     * @param item the item for the tree node
     * @param subtrees the subtrees of the tree node
     * @param  the type of the item
     * @return a leaf node of a generalised tree
     */
    static  MutableTree of(final B item, final Collection> subtrees) {
        return MutableTree.create().set(item).subTrees(subtrees);
    }

    /**
     * Duplicate, or cast if possible, an existing Tree as a {@link MutableTree}.
     * @param tree the tree to duplicate/cast
     * @param  the type of the tree
     * @return the mutable tree
     */
    static  MutableTree of(final Tree tree) {
        if (tree instanceof MutableTree) {
            return (MutableTree) tree;
        }
        final T item = tree.item().orElse(null);
        final List> subtrees = tree.subTrees()
                .stream().map(MutableTree::of).collect(Collectors.toList());
        return MutableTree.of(item, subtrees);
    }

    @Override
    public  MutableTree map(final Function f) {
        final MutableTree mutableTree = MutableTree.create();
        final List> trees = subTreesAsMutable().stream()
                .map(subTree -> subTree.map(f))
                .collect(Collectors.toList());
        return mutableTree
                .set(f.apply(item))
                .subTrees(trees);
    }

    @Override
    public Maybe item() {
        return Maybe.maybe(item);
    }

    /**
     * Sets the item of the tree.
     *
     * @param newItem the new item
     *
     * @return the tree
     */
    MutableTree set(final T newItem) {
        this.item = newItem;
        return this;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List> subTrees() {
        final Stream> mutableTreeStream = mySubTrees.stream();
        final Stream> treeStream = mutableTreeStream.map(Tree.class::cast);
        final List> treeList = treeStream.collect(Collectors.toList());
        return treeList;
    }

    /**
     * Sets the subTrees of the tree.
     *
     * @param subTrees the subtrees
     * @return the tree
     */
    MutableTree subTrees(final Collection> subTrees) {
        this.mySubTrees.clear();
        this.mySubTrees.addAll(subTrees);
        return this;
    }

    /**
     * Adds the subtree to the existing subtrees.
     *
     * @param subtree the subtree
     * @return the current tree
     */
    MutableTree add(final Tree subtree) {
        mySubTrees.add(MutableTree.of(subtree));
        return this;
    }

    /**
     * The mutable subtrees of the tree.
     *
     * @return a list of Trees
     */
    List> subTreesAsMutable() {
        return mySubTrees;
    }
}