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

com.moon.core.model.TreeElement Maven / Gradle / Ivy

package com.moon.core.model;

import com.moon.core.lang.ArrayUtil;
import com.moon.core.model.getter.*;

import java.util.*;
import java.util.function.Function;

/**
 * 树形元素模板
 *
 * @author moonsky
 */
public class TreeElement implements IdGetter, NameGetter {

    private String id;

    private String name;

    private List> children;
    /**
     * 携带的扩展数据
     */
    private T data;

    public TreeElement() { }

    public TreeElement(String id, String name) {
        this.name = name;
        this.id = id;
    }

    public TreeElement(String id, String name, List> children) {
        this(id, name);
        this.children = children;
    }

    @SafeVarargs
    public static  List> fromKeyValueList(
        Iterable data, Function... reGroupers
    ) { return fromKeyValueList(data, KeyGetter::getKey, reGroupers); }

    @SafeVarargs
    public static  List> fromIdNameList(
        Iterable data, Function... reGroupers
    ) { return fromIdNameList(data, IdGetter::getId, reGroupers); }

    @SafeVarargs
    public static  List> fromKeyValueList(
        Iterable data, Function grouper, Function... reGroupers
    ) { return fromList(data, grouper, KeyGetter::getKey, ValueGetter::getValue, reGroupers); }

    @SafeVarargs
    public static  List> fromIdNameList(
        Iterable data, Function grouper, Function... reGroupers
    ) { return fromList(data, grouper, IdGetter::getId, NameGetter::getName, reGroupers); }

    /**
     * 从数据列表中解析树形结构,注意参数{@code grouper}的返回值说明
     *
     * @param data       原数据
     * @param grouper    分组函数;
     *                   返回值为父节点的 id;
     *                   若返回值为 null 代表没有父节点,可用来标记顶级节点
     * @param idGetter   当前节点的 id,{@link #id}
     * @param nameGetter 当前节点的 name,{@link #name}
     * @param         数据类型
     *
     * @return 返回树形化后的每个顶级节点列表
     */
    public static  List> fromList(
        Iterable data, Function grouper,

        Function idGetter, Function nameGetter
    ) { return fromList(data, grouper, idGetter, nameGetter, (Function) null); }

    /**
     * 从数据列表中解析树形结构,注意参数{@code grouper}的返回值,null 值是有特殊意义的
     *
     * @param data       原数据
     * @param grouper    分组函数;
     *                   返回值为父节点的 id;
     *                   若返回值为 null 代表没有父节点,可用来标记顶级节点
     * @param idGetter   当前节点的 id,{@link #id}
     * @param nameGetter 当前节点的 name,{@link #name}
     * @param reGroupers 再分组函数(第一次【前一次】分组以及树形化之后,可能还剩余有数据,可以重新分组)
     * @param         数据类型
     *
     * @return 返回树形化后的每个顶级节点列表
     */
    @SafeVarargs
    public static  List> fromList(
        Iterable data,
        Function grouper,
        Function idGetter,
        Function nameGetter,
        Function... reGroupers
    ) {
        List> topParents = new ArrayList<>();
        Map>> grouped = new HashMap<>();
        for (T item : data) {
            String key = grouper.apply(item);
            if (key == null) {
                TreeElement element = new TreeElement<>(idGetter.apply(item), nameGetter.apply(item));
                element.setData(item);
                topParents.add(element);
            } else {
                List> list = grouped.computeIfAbsent(key, k -> new ArrayList<>());
                TreeElement element = new TreeElement<>(idGetter.apply(item), nameGetter.apply(item));
                element.setData(item);
                list.add(element);
            }
        }
        doGroup(topParents, grouped);
        // 再分组
        if (!grouped.isEmpty() && ArrayUtil.isNotEmpty(reGroupers)) {
            Map>> restGrouped = grouped;
            for (Function groupFn : reGroupers) {
                Map>> reGrouped = new HashMap<>();
                for (Map.Entry>> listEntry : restGrouped.entrySet()) {
                    String reGroupKey = groupFn.apply(listEntry.getKey());
                    List> reGroupArr = reGrouped.get(reGroupKey);
                    if (reGroupArr == null) {
                        reGrouped.put(reGroupKey, listEntry.getValue());
                    } else {
                        reGroupArr.addAll(listEntry.getValue());
                    }
                }
                redoGroup(topParents, reGrouped);
                if (reGrouped.isEmpty()) {
                    break;
                } else {
                    restGrouped = reGrouped;
                }
            }
        }
        return topParents;
    }

    @Override
    public String getId() { return id; }

    public void setId(String id) { this.id = id; }

    @Override
    public String getName() { return name; }

    public void setName(String name) { this.name = name; }

    public List> getChildren() { return children; }

    public void setChildren(List> children) {
        this.children = children;
    }

    public T getData() { return data; }

    public void setData(T data) { this.data = data; }

    /**
     * 清空携带的扩展数据
     *
     * @return 当前对象
     */
    public TreeElement clearExpandData() {
        setData(null);
        return this;
    }

    /**
     * 清空当前以及子项所携带的扩展数据
     *
     * @return 当前对象
     */
    public TreeElement clearAllExpandData() {
        List> children = getChildren();
        if (children != null) {
            for (TreeElement child : children) {
                if (child != null) {
                    child.clearAllExpandData();
                }
            }
        }
        return clearExpandData();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }
        TreeElement that = (TreeElement) o;
        return Objects.equals(id, that.id);
    }

    @Override
    public int hashCode() { return Objects.hash(id); }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("TreeElement{");
        sb.append("id='").append(id).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", children=").append(children);
        sb.append(", data=").append(data);
        sb.append('}');
        return sb.toString();
    }

    /*
    supports
     */

    private static  void redoGroup(List> parents, Map>> grouped) {
        for (TreeElement parent : parents) {
            String parentId = parent.getId();
            List list = grouped.remove(parentId);
            if (list != null) {
                List> children = parent.getChildren();
                if (children == null) {
                    parent.setChildren(list);
                } else {
                    children.addAll(list);
                }
                redoGroup(list, grouped);
            }
        }
    }

    private static  void doGroup(List> parents, Map>> grouped) {
        for (TreeElement parent : parents) {
            String parentId = parent.getId();
            List list = grouped.remove(parentId);
            if (list != null) {
                parent.setChildren(list);
                doGroup(list, grouped);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy