io.github.astrapi69.gen.tree.handler.SimpleTreeNodeHandlerExtensions Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gen-tree Show documentation
Show all versions of gen-tree Show documentation
Project that holds a generic model for tree objects
/**
* The MIT License
*
* Copyright (C) 2015 Asterios Raptis
*
* 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 io.github.astrapi69.gen.tree.handler;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import io.github.astrapi69.design.pattern.visitor.Visitor;
import io.github.astrapi69.gen.tree.SimpleTreeNode;
import lombok.NonNull;
/**
* The class {@link SimpleTreeNodeHandlerExtensions} provides handler methods for the class
* {@link SimpleTreeNode}
*/
public class SimpleTreeNodeHandlerExtensions
{
/**
* Gets the children from the given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
*
* @return the children from the given {@link SimpleTreeNode} object
*/
public static Collection> getChildren(
final @NonNull SimpleTreeNode treeNode)
{
Collection> children = new LinkedHashSet<>();
if (!treeNode.hasLeftMostChild())
{
return children;
}
SimpleTreeNode leftMostChild = treeNode.getLeftMostChild();
children.add(leftMostChild);
if (leftMostChild.hasRightSibling())
{
SimpleTreeNode currentRightSibling = leftMostChild.getRightSibling();
children.add(currentRightSibling);
do
{
currentRightSibling = currentRightSibling.getRightSibling();
children.add(currentRightSibling);
}
while (currentRightSibling.hasRightSibling());
}
return children;
}
/**
* Returns all siblings of the given {@link SimpleTreeNode} object in the parent's children list
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @return Returns all siblings of the given {@link SimpleTreeNode} object
*/
public static Collection> getAllSiblings(
final @NonNull SimpleTreeNode treeNode)
{
Collection> allSiblings = new LinkedHashSet<>();
if (treeNode.hasParent())
{
allSiblings = getChildren(treeNode.getParent());
}
return allSiblings;
}
/**
* Gets the root from the given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @return the root from the given {@link SimpleTreeNode} object
*/
public static SimpleTreeNode getRoot(final @NonNull SimpleTreeNode treeNode)
{
SimpleTreeNode root = treeNode;
if (root.isRoot())
{
return root;
}
do
{
root = root.getParent();
}
while (root != null && !root.isRoot());
return root;
}
/**
* Returns the next sibling of the given {@link SimpleTreeNode} object in the parent's children
* list. Returns null if the given {@link SimpleTreeNode} object is the root or is the parent's
* last child
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param currentTreeNode
* the tree node
* @return the next sibling of the given {@link SimpleTreeNode} object or null if the given
* {@link SimpleTreeNode} object is the root or is the parent's last child
*/
public static SimpleTreeNode getNextSibling(
final @NonNull SimpleTreeNode currentTreeNode)
{
return currentTreeNode.getRightSibling();
}
/**
* Returns the previous sibling of the given {@link SimpleTreeNode} object in the parent's
* children list. Returns null if the given {@link SimpleTreeNode} object is the root or is the
* parent's first child.
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
*
* @param currentTreeNode
* the tree node
* @return the next sibling of the given {@link SimpleTreeNode} object or null if the given
* {@link SimpleTreeNode} object is the root or is the parent's last child.
*/
public static SimpleTreeNode getPreviousSibling(
final @NonNull SimpleTreeNode currentTreeNode)
{
SimpleTreeNode previous = null;
if (currentTreeNode.getParent() == null)
{
return previous;
}
for (SimpleTreeNode treeNode : currentTreeNode.getParent().getChildren())
{
if (treeNode.equals(currentTreeNode))
{
break;
}
previous = treeNode;
}
return previous;
}
/**
* Returns the distance from the root to the given {@link SimpleTreeNode} object. Returns 0 if
* the given {@link SimpleTreeNode} object is the root {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
*
* @param treeNode
* the tree node
* @return the level from the given {@link SimpleTreeNode} object
*/
public static int getLevel(final @NonNull SimpleTreeNode treeNode)
{
SimpleTreeNode currentTreeNode = treeNode;
int count = 0;
while ((currentTreeNode = currentTreeNode.getParent()) != null)
{
count++;
}
return count;
}
/**
* Removes the given child from the given first {@link SimpleTreeNode}
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param parentTreeNode
* the parent tree node
* @param child
* the child tree node
*/
public static void removeChild(final @NonNull SimpleTreeNode parentTreeNode,
final SimpleTreeNode child)
{
if (child != null)
{
if (isChildOf(parentTreeNode, child))
{
parentTreeNode.getChildren().remove(child);
child.setParent(null);
child.setLeftMostChild(null);
}
}
}
/**
* Checks if the second given {@link SimpleTreeNode} object is a child of the first
* {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param parentTreeNode
* the parent tree node
* @param child
* the child
* @return true, if the second given {@link SimpleTreeNode} object is a child of the first
* {@link SimpleTreeNode} object otherwise false
*/
public static boolean isChildOf(final @NonNull SimpleTreeNode parentTreeNode,
final @NonNull SimpleTreeNode child)
{
return parentTreeNode.getChildren().contains(child);
}
/**
* Checks if the first given {@link SimpleTreeNode} object is the parent of the second
* {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param parentTreeNode
* the parent tree node
* @param child
* the child
* @return true, if the first given {@link SimpleTreeNode} object is the parent of the second
* given {@link SimpleTreeNode} object otherwise false
*/
public static boolean isParentOf(final @NonNull SimpleTreeNode parentTreeNode,
final @NonNull SimpleTreeNode child)
{
return child.getParent().equals(parentTreeNode);
}
/**
* Removes all the given children from the first given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param parentTreeNode
* the parent tree node
* @param children
* the children to remove
*/
public static void removeChildren(final @NonNull SimpleTreeNode parentTreeNode,
final @NonNull Collection> children)
{
children
.forEach(child -> SimpleTreeNodeHandlerExtensions.removeChild(parentTreeNode, child));
}
/**
* Removes all children from the given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param parentTreeNode
* the parent tree node
*/
public static void removeChildren(final @NonNull SimpleTreeNode parentTreeNode)
{
SimpleTreeNodeHandlerExtensions.removeChildren(parentTreeNode,
new ArrayList<>(parentTreeNode.getChildren()));
}
/**
* Checks if the given {@link SimpleTreeNode} is the root {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @return true, if the given {@link SimpleTreeNode} is the root {@link SimpleTreeNode} object
*/
public static boolean isRoot(final @NonNull SimpleTreeNode treeNode)
{
return !treeNode.hasParent();
}
/**
* Checks if the given {@link SimpleTreeNode} object has a parent {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @return true, if the given {@link SimpleTreeNode} object has a parent {@link SimpleTreeNode}
* object otherwise false
*/
public static boolean hasParent(final @NonNull SimpleTreeNode treeNode)
{
return treeNode.getParent() != null;
}
/**
* Checks if the given {@link SimpleTreeNode} object is a node
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @return true, if the given {@link SimpleTreeNode} object is a node otherwise false
*/
public static boolean isNode(final @NonNull SimpleTreeNode treeNode)
{
return !treeNode.isLeaf();
}
/**
* Removes all the descendants from the given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
*/
public static void clearAll(final @NonNull SimpleTreeNode treeNode)
{
treeNode.accept(currentTreeNode -> currentTreeNode.setLeftMostChild(null));
}
/**
* Removes all the children from the given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
*/
public static void clearChildren(final @NonNull SimpleTreeNode treeNode)
{
SimpleTreeNodeHandlerExtensions.removeChildren(treeNode,
new ArrayList<>(treeNode.getChildren()));
}
/**
* Adds the given child {@link SimpleTreeNode} object to the first given parent
* {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param parentTreeNode
* the parent tree node
* @param child
* the child
*/
public static void addChild(final @NonNull SimpleTreeNode parentTreeNode,
final SimpleTreeNode child)
{
if (child != null && parentTreeNode.isNode())
{
child.setParent(parentTreeNode);
parentTreeNode.getChildren().add(child);
}
}
/**
* Adds all the given children from the first given parent {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param parentTreeNode
* the parent tree node
* @param children
* the children to add
*/
public static void addChildren(final @NonNull SimpleTreeNode parentTreeNode,
final @NonNull Collection> children)
{
if (parentTreeNode.isNode())
{
children
.forEach(child -> SimpleTreeNodeHandlerExtensions.addChild(parentTreeNode, child));
}
}
/**
* Gets the child count from the given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @return the child count
*/
public static int getChildCount(final @NonNull SimpleTreeNode treeNode)
{
return treeNode.getChildren().size();
}
/**
* Checks if the given {@link SimpleTreeNode} object has children
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @return true, if the given {@link SimpleTreeNode} object has children otherwise false
*/
public static boolean hasChildren(final @NonNull SimpleTreeNode treeNode)
{
return treeNode.getChildren() != null && !treeNode.getChildren().isEmpty();
}
/**
* Traverse the given {@link SimpleTreeNode} object and add all descendants with the given
* {@link SimpleTreeNode} object included in to the returned {@link Collection} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
*
* @return a {@link Collection} object with the given {@link SimpleTreeNode} object and add all
* descendants
*/
public static Collection> traverse(
final @NonNull SimpleTreeNode treeNode)
{
final Collection> allTreeNodes = new LinkedHashSet<>();
treeNode.accept(allTreeNodes::add);
return allTreeNodes;
}
/**
* Accepts the given visitor that provides a custom algorithm for processing all elements
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @param visitor
* the visitor
*/
public static void accept(final @NonNull SimpleTreeNode treeNode,
final @NonNull Visitor> visitor)
{
SimpleTreeNodeHandlerExtensions.accept(treeNode, visitor, true);
}
/**
* Accepts the given visitor that provides a custom algorithm for processing all elements
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @param visitor
* the visitor
* @param visitBefore
* the flag if this flag is true the visit of the given {@link SimpleTreeNode} object
* is before visit the children otherwise the visit is after visit the children
*/
public static void accept(final @NonNull SimpleTreeNode treeNode,
final @NonNull Visitor> visitor, final boolean visitBefore)
{
boolean visitAfter = !visitBefore;
if (visitBefore)
{
visitor.visit(treeNode);
}
if (treeNode.hasLeftMostChild())
{
treeNode.getLeftMostChild().accept(visitor);
}
if (treeNode.hasRightSibling())
{
treeNode.getRightSibling().accept(visitor);
}
if (visitAfter)
{
visitor.visit(treeNode);
}
}
/**
* Find all {@link SimpleTreeNode} objects from the first given {@link SimpleTreeNode} object
* that serves as the search target, that have the same value as the given value
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @param value
* the value for the search process
* @return a {@link Collection} object with all found occurrences that have the same value as
* the given value
*/
public static Collection> findAllByValue(
final @NonNull SimpleTreeNode treeNode, final T value)
{
AtomicReference>> foundTreeNodes = new AtomicReference<>(
new LinkedHashSet<>());
treeNode.accept(currentTreeNode -> {
if (value == null)
{
if (currentTreeNode != null && currentTreeNode.getValue() == null)
{
foundTreeNodes.get().add(currentTreeNode);
}
}
else
{
if (value.equals(currentTreeNode.getValue()))
{
foundTreeNodes.get().add(currentTreeNode);
}
}
});
return foundTreeNodes.get();
}
/**
* Find the first occurrence of {@link SimpleTreeNode} object from the first given
* {@link SimpleTreeNode} object that serves as the search target, that have the same value as
* the given value
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @param value
* the value for the search process
* @return the first occurrence of {@link SimpleTreeNode} object that have the same value as the
* given value
*/
public static SimpleTreeNode findByValue(
final @NonNull SimpleTreeNode treeNode, final T value)
{
final AtomicReference> found = new AtomicReference<>();
SimpleTreeNodeHandlerExtensions.findAllByValue(treeNode, value).stream().findFirst()
.ifPresent(currentTreeNode -> {
found.set(currentTreeNode);
});
return found.get();
}
/**
* Checks if the second given {@link SimpleTreeNode} object is a descendant of the first given
* {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @param descendantCandidate
* the tree node to check
* @return true if the given {@link SimpleTreeNode} object is a descendant of the first given
* {@link SimpleTreeNode} object otherwise false
*/
public static boolean contains(final @NonNull SimpleTreeNode treeNode,
final SimpleTreeNode descendantCandidate)
{
if (descendantCandidate == null)
{
return false;
}
return SimpleTreeNodeHandlerExtensions.traverse(treeNode).contains(descendantCandidate);
}
/**
* Checks if the given {@link Collection} object of {@link SimpleTreeNode} objects are
* descendants of the first given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @param treeNodes
* the collection of the tree nodes to check
* @return true if the given {@link Collection} object of {@link SimpleTreeNode} objects are
* descendants of the first given {@link SimpleTreeNode} object otherwise false
*/
public static boolean containsAll(final @NonNull SimpleTreeNode treeNode,
final @NonNull Collection> treeNodes)
{
return SimpleTreeNodeHandlerExtensions.traverse(treeNode).containsAll(treeNodes);
}
/**
* Traverse the given {@link SimpleTreeNode} object and adds all descendant with it
* self-included in to a {@link List} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
*
* @return a {@link List} object with the given {@link SimpleTreeNode} object and all
* descendants
*/
public static List> toList(
final @NonNull SimpleTreeNode treeNode)
{
return new ArrayList<>(SimpleTreeNodeHandlerExtensions.traverse(treeNode));
}
/**
* Gets all the right siblings from the given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @return all the right siblings from the given {@link SimpleTreeNode} object
*/
public static Collection> getAllRightSiblings(
final @NonNull SimpleTreeNode treeNode)
{
Collection> allRightSiblings = new LinkedHashSet<>();
if (treeNode.hasRightSibling())
{
SimpleTreeNode currentRightSibling;
do
{
currentRightSibling = treeNode.getRightSibling();
allRightSiblings.add(currentRightSibling);
}
while (currentRightSibling.hasRightSibling());
}
return allRightSiblings;
}
/**
* Gets all the left siblings from the given {@link SimpleTreeNode} object
*
* @param
* the generic type of the value
* @param
* the generic type of the id of the node
* @param treeNode
* the tree node
* @return all the left siblings from the given {@link SimpleTreeNode} object
*/
public static Collection> getAllLeftSiblings(
final @NonNull SimpleTreeNode treeNode)
{
Collection> allSiblings = new LinkedHashSet<>();
if (treeNode.hasParent())
{
SimpleTreeNode parent = treeNode.getParent();
SimpleTreeNode leftMostChild = parent.getLeftMostChild();
if (leftMostChild.equals(treeNode))
{
return allSiblings;
}
allSiblings.add(leftMostChild);
if (leftMostChild.hasRightSibling())
{
SimpleTreeNode currentRightSibling = leftMostChild.getRightSibling();
if (currentRightSibling.equals(treeNode))
{
return allSiblings;
}
allSiblings.add(currentRightSibling);
do
{
currentRightSibling = currentRightSibling.getRightSibling();
if (currentRightSibling.equals(treeNode))
{
return allSiblings;
}
allSiblings.add(currentRightSibling);
}
while (currentRightSibling.hasRightSibling());
}
}
return allSiblings;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy