package com.bgy.bpc.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Slf4j
public class TreeUtil {
private static final String PARENT_ID = "parentId";
private static final String ID = "id";
private static final String CHILDREN = "children";
private static final String LEVEL_NAME = "treeLevel";
public static <T> List<T> getAllChild(List<T> list, Object currNodeId) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
if (CollectionUtils.isEmpty(list)) {
return null;
}
List<T> allChildNode = new ArrayList<>();
try {
Class<?> tClass = list.get(0).getClass();
Field parentIdField = tClass.getDeclaredField(PARENT_ID);
Field idField = tClass.getDeclaredField(ID);
idField.setAccessible(true);
parentIdField.setAccessible(true);
MultiValueMap<String, T> parentMap = new LinkedMultiValueMap<>(list.size());
list.forEach(item -> {
Object parentIdValue = ReflectionUtils.getField(parentIdField, item);
if (Objects.isNull(parentIdValue)) {
parentIdValue = "0";
}
parentMap.add(String.valueOf(parentIdValue), item);
});
list.forEach(item -> {
Object idValue = ReflectionUtils.getField(idField, item);
if (Objects.equals(idValue, currNodeId)) {
List<T> allCurrChild = parentMap.get(currNodeId);
getAllChild(parentMap, allChildNode, allCurrChild, idField);
allChildNode.add(item);
}
});
} catch (Exception e) {
log.error("获取子节点异常");
}
stopWatch.stop();
log.info("查询所有子孙节点耗时:{}ms", stopWatch.getTotalTimeMillis());
return allChildNode;
}
private static <T> void getAllChild(MultiValueMap<String, T> parentMap, List<T> allChildNode, List<T> allCurrChild, Field idField) {
if (CollectionUtils.isEmpty(allCurrChild)) {
return;
}
allChildNode.addAll(allCurrChild);
allCurrChild.forEach(item -> {
Object idValue = ReflectionUtils.getField(idField, item);
List<T> allCurrChild2 = parentMap.get(idValue);
getAllChild(parentMap, allChildNode, allCurrChild2, idField);
});
}
public static <T> List<T> parseTree(List<T> list) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
List<T> ts = parseTree(list, PARENT_ID, ID, CHILDREN, null);
stopWatch.stop();
log.info("组建树耗时:{}ms", stopWatch.getTotalTimeMillis());
return ts;
}
public static <T> List<T> parseTreeHasLevel(List<T> list, String levelName) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
if (StringUtils.isEmpty(levelName)) {
levelName = LEVEL_NAME;
}
List<T> ts = parseTree(list, PARENT_ID, ID, CHILDREN, levelName);
stopWatch.stop();
log.info("组建树耗时:{}ms", stopWatch.getTotalTimeMillis());
return ts;
}
public static <T> List<T> parseTree(List<T> list, String parentIdName, String idName, String childName, String levelName) {
List<T> result = new ArrayList<>();
if (Objects.isNull(list) || list.isEmpty()) {
return result;
}
try {
Class<?> tClass = list.get(0).getClass();
Field parentIdField = tClass.getDeclaredField(parentIdName);
Field idField = tClass.getDeclaredField(idName);
Field childrenField = tClass.getDeclaredField(childName);
Field levelNameField = StringUtils.isEmpty(levelName) ? null : tClass.getDeclaredField(levelName);
parentIdField.setAccessible(true);
idField.setAccessible(true);
childrenField.setAccessible(true);
if (levelNameField != null) {
levelNameField.setAccessible(true);
}
MultiValueMap<String, T> parentMap = new LinkedMultiValueMap<>(list.size());
list.forEach(t -> {
Object idValue = ReflectionUtils.getField(idField, t);
if (Objects.isNull(idValue)) {
return;
}
Object parentIdValue = ReflectionUtils.getField(parentIdField, t);
if (Objects.isNull(parentIdValue) || StringUtils.isEmpty(parentIdValue.toString()) || Objects.equals("0", parentIdValue.toString())) {
if (levelNameField != null) {
ReflectionUtils.setField(levelNameField, t, 1);
}
result.add(t);
} else {
parentMap.add(parentIdValue.toString(), t);
}
});
if (levelNameField != null) {
result.forEach(r -> setChildren(r, parentMap, idField, childrenField, levelNameField));
} else {
result.forEach(r -> setChildren(r, parentMap, idField, childrenField));
}
} catch (Exception e) {
log.error("转换Tree报错", e);
return result;
}
return result;
}
private static <T> void setChildren(T parent, MultiValueMap<String, T> parentMap, Field idField, Field childrenField, Field levelNameField) {
String idValue = ReflectionUtils.getField(idField, parent).toString();
int levelValue = Integer.valueOf(ReflectionUtils.getField(levelNameField, parent).toString());
List<T> ts = parentMap.get(idValue);
if (Objects.isNull(ts) || ts.isEmpty()) {
return;
}
ReflectionUtils.setField(childrenField, parent, ts);
for (T t : ts) {
ReflectionUtils.setField(levelNameField, t, levelValue + 1);
setChildren(t, parentMap, idField, childrenField, levelNameField);
}
}
private static <T> void setChildren(T parent, MultiValueMap<String, T> parentMap, Field idField, Field childrenField) {
String idValue = ReflectionUtils.getField(idField, parent).toString();
List<T> ts = parentMap.get(idValue);
if (Objects.isNull(ts) || ts.isEmpty()) {
return;
}
ReflectionUtils.setField(childrenField, parent, ts);
ts.forEach(t -> {
setChildren(t, parentMap, idField, childrenField);
});
}
}