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

api.Tree Maven / Gradle / Ivy

The newest version!
package api;

import api.utils.NodePath;
import exception.NodeNotFoundException;
import impl.treelinearizers.CompactTreeLinearizer;

import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Represents a hierarchical collection of nodes
 */
public interface Tree extends TreeModel{

    Node getTreeRoot();
    Collection getListeners();
    default void fireTreeModelListenersForChange(Node node) throws NodeNotFoundException {
        TreeModelEvent treeModelEvent = new TreeModelEvent(node, node.getNodePath().toTreePath());
        getListeners().stream().forEach(treeModelListener -> treeModelListener.treeNodesChanged(treeModelEvent));
    }

    @SuppressWarnings("SimplifyStreamApiCallChains")
    default void fireTreeModelListenersForInsertion(Node node) throws NodeNotFoundException {
        TreeModelEvent treeModelEvent = new TreeModelEvent(node, node.getNodePath().toTreePath());
        getListeners().stream().forEach(treeModelListener -> treeModelListener.treeNodesInserted(treeModelEvent));
    }

    @SuppressWarnings("SimplifyStreamApiCallChains")
    default void fireTreeModelListenersForRemoval(Node node) throws NodeNotFoundException {
        TreeModelEvent treeModelEvent = new TreeModelEvent(node, node.getNodePath().toTreePath());
        getListeners().stream().forEach(treeModelListener -> treeModelListener.treeNodesRemoved(treeModelEvent));
    }

    default Collection> linearizeTree(){
        return new CompactTreeLinearizer().linearize(this);
    }

    default TreeValue getChildFromNode(Node parent, int index) throws NodeNotFoundException {
        assert parent != null;
        assert index >= 0;

        List> children = parent.getChildTree().getNodes();
        if (children.isEmpty() || index >= children.size()){
            throw new NodeNotFoundException(String.format("Child node index %s is invalid for parent node '%s'",
                    String.valueOf(index), parent.getValue().toString()));
        }
        return children.get(index).getValue();
    }

    default int getIndexOfChildNode(Node parent, Node child) throws NodeNotFoundException {
        assert parent != null;
        assert child != null;

        List> children = parent.getChildTree().getNodes();
        if (!children.contains(child)){
            throw new NodeNotFoundException(String.format("Node '%s' not found in parent node '%s'",
                    child.getValue().toString(), parent.getValue().toString()));
        }
        return children.indexOf(child);
    }

    default boolean isEqual(Object o){
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Tree that = (Tree) o;
        return getTreeRoot().isEqual(that);
    }

    default int getHashCode(){
        return Objects.hash(getTreeRoot().getHashCode());
    }

    @SuppressWarnings("unchecked")
    @Override
    default void valueForPathChanged(TreePath treePath, Object newValue){
        assert treePath != null;
        assert newValue != null;

        Object node = treePath.getLastPathComponent();
        if (!(node instanceof Node)){
            throw new IllegalArgumentException(String.format("Expected '%s', but found '%s'", Node.class.getSimpleName(), node.getClass().getSimpleName()));
        }
        try {
            fireTreeModelListenersForChange((Node) node);
        } catch (NodeNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    default Object getRoot(){
        return getTreeRoot().getValue();
    }

    @SuppressWarnings("unchecked")
    @Override
    default Object getChild(Object parent, int index){
        assert parent != null;
        assert index >= 0;

        try {
            return getChildFromNode((Node) parent, index);
        } catch (NodeNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    default int getChildCount(Object o){
        assert o != null;
        return getTreeRoot().getChildCount();
    }

    @SuppressWarnings("unchecked")
    @Override
    default int getIndexOfChild(Object parent, Object child){
        assert parent != null;
        assert child != null;

        if (!(parent instanceof Node)){
            throw new IllegalArgumentException("Parent have to be an instance of Node");
        }
        if (!(child instanceof Node)){
            throw new IllegalArgumentException("Child have to be an instance of Node");
        }
        try {
            return getIndexOfChildNode((Node) parent, (Node) child);
        } catch (NodeNotFoundException e) {
            return -1;
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    default boolean isLeaf(Object object){
        if (!(object instanceof TreeValue)){
            throw new IllegalArgumentException(String.format("Parent have to be an instance of %s", TreeValue.class.getSimpleName()));
        }
        TreeValue node = (TreeValue) object;
        if (!node.getOwnerNode().isLeaf()) return false;
        Map>, ChildTree> nodePaths = new CompactTreeLinearizer().buildNodePaths(this);
        return nodePaths.keySet().parallelStream().anyMatch(path -> path.getLastNode().isEqual(node));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy