com.qwlabs.tree.TreeNode Maven / Gradle / Ivy
package com.qwlabs.tree;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.google.common.collect.Streams;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.stream.Stream;
@Getter
@Setter
@JsonPropertyOrder(alphabetic = true)
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public class TreeNode implements TreeNodeAble {
@JsonUnwrapped
private N node;
private TreeNodes children;
private TreeNodes safeChildren() {
return Optional.ofNullable(children).orElseGet(TreeNodes::empty);
}
@Override
public void forEach(BiConsumer>, TreeNode> consumer,
Location> parentLocation,
boolean parallel) {
consumer.accept(parentLocation, this);
var location = parentLocation.child(this);
safeChildren().forEach(consumer, location, parallel);
}
@Override
public Optional> find(List path,
BiPredicate, E> filter,
boolean parallel) {
if (path.isEmpty()) {
return Optional.of(this);
}
var findFor = path.get(0);
var found = filter.test(this, findFor);
if (!found) {
return Optional.empty();
}
if (path.size() == 1) {
return Optional.of(this);
}
var childPath = path.subList(1, path.size());
return children.find(childPath, filter, parallel);
}
@Override
public Optional>> find(BiPredicate>, TreeNode> filter,
Location> parentLocation,
boolean parallel) {
var location = parentLocation.child(this);
if (filter.test(parentLocation, this)) {
return Optional.of(location);
}
return safeChildren().find(filter, location, parallel);
}
@Override
public Stream all(BiFunction>, TreeNode, R> mapper, Location> parentLocation) {
var location = parentLocation.child(this);
Stream childStream = safeChildren().all(mapper, location);
return Streams.concat(childStream, Stream.of(mapper.apply(parentLocation, this)));
}
public TreeNode map(BiFunction>, TreeNode, R> mapper) {
return map(mapper, Location.root(), false);
}
public TreeNode mapParallel(BiFunction>, TreeNode, R> mapper) {
return map(mapper, Location.root(), true);
}
public TreeNode map(BiFunction>, TreeNode, R> mapper,
boolean parallel) {
return map(mapper, Location.root(), parallel);
}
public TreeNode map(BiFunction>, TreeNode, R> mapper, Location> parentLocation) {
return map(mapper, parentLocation, false);
}
public TreeNode mapParallel(BiFunction>, TreeNode, R> mapper, Location> parentLocation) {
return map(mapper, parentLocation, true);
}
public TreeNode map(BiFunction>, TreeNode, R> mapper,
Location> parentLocation,
boolean parallel) {
R newNode = mapper.apply(parentLocation, this);
var newTreeNode = new TreeNode();
var location = parentLocation.child(this);
newTreeNode.setNode(newNode);
newTreeNode.setChildren(safeChildren().map(mapper, location, parallel));
return newTreeNode;
}
public R map(TreeNodeFunction mapper) {
return map(mapper, Location.root(), false);
}
public R mapParallel(TreeNodeFunction mapper) {
return map(mapper, Location.root(), true);
}
public R map(TreeNodeFunction mapper, boolean parallel) {
return map(mapper, Location.root(), parallel);
}
public R map(TreeNodeFunction mapper,
Location> parentLocation) {
return map(mapper, parentLocation, false);
}
public R mapParallel(TreeNodeFunction mapper,
Location> parentLocation) {
return map(mapper, parentLocation, true);
}
public R map(TreeNodeFunction mapper,
Location> parentLocation,
boolean parallel) {
var location = parentLocation.child(this);
var children = safeChildren().map(mapper, location, parallel);
return mapper.apply(parentLocation, this, children);
}
public R map(Function mapper) {
return mapper.apply(node);
}
public TreeNode addChildren(TreeNode... addChildren) {
if (addChildren != null && addChildren.length > 0) {
TreeNodes children = Optional.ofNullable(getChildren())
.orElseGet(TreeNodes::of);
children.addAll(List.of(addChildren));
setChildren(children);
}
return this;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TreeNode> treeNode = (TreeNode>) o;
return Objects.equals(node, treeNode.node) && Objects.equals(children, treeNode.children);
}
@Override
public int hashCode() {
return Objects.hash(node, children);
}
public static TreeNode of(N node) {
var treeNode = new TreeNode();
treeNode.setNode(node);
return treeNode;
}
public static TreeNode of(N node, TreeNode... children) {
var treeNode = new TreeNode();
treeNode.setNode(node);
treeNode.addChildren(children);
return treeNode;
}
public static TreeNode of(N node, TreeNodes children) {
var treeNode = new TreeNode();
treeNode.setNode(node);
treeNode.setChildren(children);
return treeNode;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy