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

es.iti.wakamiti.api.model.TreeNode Maven / Gradle / Ivy

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */
package es.iti.wakamiti.api.model;


import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;


/**
 * Abstract class representing a tree node with a generic type.
 *
 * @param  The type of the tree node
 * @author Luis Iñesta Gelabert - [email protected]
 */
public abstract class TreeNode> {

    private final List children;

    protected TreeNode(List children) {
        this.children = Collections.unmodifiableList(children);
    }

    /**
     * Gets a stream of the children of this tree node.
     *
     * @return The stream of children
     */
    public Stream children() {
        return children.stream();
    }

    /**
     * Gets the number of children of this tree node.
     *
     * @return The number of children
     */
    public int numChildren() {
        return children.size();
    }

    /**
     * Checks if this tree node has children.
     *
     * @return {@code true} if this tree node has children,
     * {@code false} otherwise
     */
    public boolean hasChildren() {
        return !children.isEmpty();
    }

    /**
     * Gets a stream of descendants of this tree node.
     *
     * @return The stream of descendants
     */
    public Stream descendants() {
        return Stream.concat(children(), children().flatMap(S::descendants));
    }

    /**
     * Gets the number of descendants satisfying the given predicate.
     *
     * @param predicate The predicate to filter descendants
     * @return The number of descendants satisfying the predicate
     */
    public int numDescendants(Predicate predicate) {
        return (int) descendants().filter(predicate).count();
    }

    /**
     * Checks if this tree node has the given child.
     *
     * @param child The child to check
     * @return {@code true} if this tree node has the given child,
     * {@code false} otherwise
     */
    public boolean hasChild(S child) {
        return children.contains(child);
    }

    /**
     * Checks if this tree node has the given descendant.
     *
     * @param descendant The descendant to check
     * @return {@code true} if this tree node has the given descendant,
     * {@code false} otherwise
     */
    public boolean hasDescendant(S descendant) {
        return hasChild(descendant) ||
                children().anyMatch(child -> child.hasDescendant(descendant));
    }

}