package com.estate.expert.admin.utils.tree;
|
|
import com.estate.expert.admin.enums.BizResultCode;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModelProperty;
|
import lombok.Data;
|
|
import javax.persistence.Transient;
|
import java.util.*;
|
|
@ApiModel(value = "树节点")
|
@Data
|
public class TreeNode<T> {
|
|
@ApiModelProperty(value = "节点id,在同一层级下唯一")
|
private Integer id = 0;
|
|
@ApiModelProperty(value = "节点名称,同一层级下唯一")
|
private String name;
|
|
@ApiModelProperty(value = "子节点Id计数器,自增")
|
private int childIdCnt = 0;
|
|
@ApiModelProperty(value = "节点中的数据")
|
private T data;
|
|
@ApiModelProperty(value = "节点的路径,全局唯一")
|
private String path;
|
|
@Transient
|
@JsonIgnore
|
private TreeNode<T> parent;
|
|
@ApiModelProperty(value = "子节点")
|
public SortedMap<Integer, TreeNode<T>> children = new TreeMap<>();
|
|
public TreeNode(){
|
}
|
|
public TreeNode(String name) {
|
this.name = name;
|
this.id = 0;
|
}
|
|
public TreeNode(String name, T data) {
|
this.name = name;
|
this.data = data;
|
this.id = 0;
|
}
|
|
public TreeNode<T> ShadowNode() {
|
TreeNode<T> shadow = new TreeNode<>(this.getName(), this.getData());
|
shadow.setId(this.getId());
|
shadow.setPath(this.getPath());
|
shadow.setData(this.getData());
|
shadow.setName(this.getName());
|
return shadow;
|
}
|
|
public TreeNode<T> addChild(TreeNode<T> child) {
|
children.put(child.getId(), child);
|
return child;
|
}
|
|
public TreeNode<T> addChild(String name) {
|
return addChild(name, null);
|
}
|
|
public TreeNode<T> addChild(String name, T data) {
|
for(TreeNode<T> child : children.values()) {
|
BizResultCode.HIERARCHY_NODE_NAME_ALREADY_EXISTS.check(child.getName().equals(name));
|
}
|
|
TreeNode<T> child = new TreeNode<>(name, data);
|
child.setId(childIdCnt++);
|
child.setName(name);
|
child.setData(data);
|
child.setParent(this);
|
this.children.put(child.getId(), child);
|
return child;
|
}
|
|
public void removeChild(Integer id) {
|
children.remove(id);
|
}
|
|
/**
|
* 获取该节点下所有的路径
|
* 以及所在分支的路径
|
*/
|
public List<String> allPaths(){
|
var list = new ArrayList<String>();
|
for (var child : children.values()){
|
list.addAll(child.allPaths());
|
}
|
list.add(getPath());
|
|
var parent = getParent();
|
while (parent != null){
|
list.add(parent.getPath());
|
parent = parent.getParent();
|
}
|
return list;
|
}
|
|
/**
|
* 递归查找节点
|
* 这里,由于树的根节点是单一的
|
* 根节点的path= "/"
|
*/
|
public void buildPath() {
|
StringBuilder builder = new StringBuilder();
|
TreeNode<T> node = this;
|
while (true) {
|
var parent = node.getParent();
|
if(parent == null) {
|
break;
|
}
|
|
builder.insert(0, node.getId());
|
builder.insert(0, "/");
|
node = parent;
|
}
|
if(builder.isEmpty()) {
|
path = "/";
|
return;
|
}
|
path = builder.toString();
|
}
|
|
@JsonIgnore
|
public String getNamePath(){
|
StringBuilder builder = new StringBuilder();
|
TreeNode<T> node = this;
|
while (true) {
|
var parent = node.getParent();
|
if(parent == null)
|
break;
|
|
builder.insert(0, node.getName());
|
builder.insert(0, "/");
|
node = parent;
|
}
|
|
if(builder.isEmpty())
|
return "/";
|
return builder.toString();
|
}
|
|
@JsonIgnore
|
public List<String> getNames(){
|
List<String> names = new ArrayList<>();
|
TreeNode<T> node = this;
|
while (true) {
|
names.add(node.getName());
|
var parent = node.getParent();
|
if(parent == null)
|
break;
|
|
node = parent;
|
}
|
return names;
|
}
|
|
@JsonIgnore
|
public int getDepth(){
|
// 根节点的深度为0
|
int depth = 0;
|
TreeNode<T> node = this;
|
while (true) {
|
var parent = node.getParent();
|
if(parent == null)
|
break;
|
|
depth++;
|
node = parent;
|
}
|
return depth;
|
}
|
|
@JsonIgnore
|
public List<TreeNode<T>> getLeafNodes() {
|
List<TreeNode<T>> leafNodes = new ArrayList<>();
|
getLeafNodes(this, leafNodes);
|
return leafNodes;
|
}
|
|
private void getLeafNodes(TreeNode<T> node, List<TreeNode<T>> leafNodes) {
|
if (node.getChildren().isEmpty()) {
|
leafNodes.add(node);
|
} else {
|
for (TreeNode<T> child : node.getChildren().values()) {
|
getLeafNodes(child, leafNodes);
|
}
|
}
|
}
|
|
@Override
|
public String toString() {
|
return "TreeNode{" +
|
"path=" + path +
|
", name='" + name +
|
"', data=" + data + "}" ;
|
}
|
}
|