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

cn.hutool.core.lang.tree.TreeBuilder Maven / Gradle / Ivy

Go to download

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

There is a newer version: 5.8.34
Show newest version
package cn.hutool.core.lang.tree;

import cn.hutool.core.builder.Builder;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.tree.parser.NodeParser;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 树构建器
 *
 * @param  ID类型
 */
public class TreeBuilder implements Builder> {
	private static final long serialVersionUID = 1L;

	private final Tree root;
	private final Map> idTreeMap;
	private boolean isBuild;

	/**
	 * 创建Tree构建器
	 *
	 * @param rootId 根节点ID
	 * @param     ID类型
	 * @return TreeBuilder
	 */
	public static  TreeBuilder of(T rootId) {
		return of(rootId, null);
	}

	/**
	 * 创建Tree构建器
	 *
	 * @param rootId 根节点ID
	 * @param config 配置
	 * @param     ID类型
	 * @return TreeBuilder
	 */
	public static  TreeBuilder of(T rootId, TreeNodeConfig config) {
		return new TreeBuilder<>(rootId, config);
	}

	/**
	 * 构造
	 *
	 * @param rootId 根节点ID
	 * @param config 配置
	 */
	public TreeBuilder(E rootId, TreeNodeConfig config) {
		root = new Tree<>(config);
		root.setId(rootId);
		this.idTreeMap = new LinkedHashMap<>();
	}

	/**
	 * 设置ID
	 *
	 * @param id ID
	 * @return this
	 * @since 5.7.14
	 */
	public TreeBuilder setId(E id) {
		this.root.setId(id);
		return this;
	}

	/**
	 * 设置父节点ID
	 *
	 * @param parentId 父节点ID
	 * @return this
	 * @since 5.7.14
	 */
	public TreeBuilder setParentId(E parentId) {
		this.root.setParentId(parentId);
		return this;
	}

	/**
	 * 设置节点标签名称
	 *
	 * @param name 节点标签名称
	 * @return this
	 * @since 5.7.14
	 */
	public TreeBuilder setName(CharSequence name) {
		this.root.setName(name);
		return this;
	}

	/**
	 * 设置权重
	 *
	 * @param weight 权重
	 * @return this
	 * @since 5.7.14
	 */
	public TreeBuilder setWeight(Comparable weight) {
		this.root.setWeight(weight);
		return this;
	}

	/**
	 * 扩展属性
	 *
	 * @param key   键
	 * @param value 扩展值
	 * @return this
	 * @since 5.7.14
	 */
	public TreeBuilder putExtra(String key, Object value) {
		Assert.notEmpty(key, "Key must be not empty !");
		this.root.put(key, value);
		return this;
	}

	/**
	 * 增加节点列表,增加的节点是不带子节点的
	 *
	 * @param map 节点列表
	 * @return this
	 */
	public TreeBuilder append(Map> map) {
		checkBuilt();

		this.idTreeMap.putAll(map);
		return this;
	}

	/**
	 * 增加节点列表,增加的节点是不带子节点的
	 *
	 * @param trees 节点列表
	 * @return this
	 */
	public TreeBuilder append(Iterable> trees) {
		checkBuilt();

		for (Tree tree : trees) {
			this.idTreeMap.put(tree.getId(), tree);
		}
		return this;
	}

	/**
	 * 增加节点列表,增加的节点是不带子节点的
	 *
	 * @param list       Bean列表
	 * @param         Bean类型
	 * @param nodeParser 节点转换器,用于定义一个Bean如何转换为Tree节点
	 * @return this
	 */
	public  TreeBuilder append(List list, NodeParser nodeParser) {
		return append(list, null, nodeParser);
	}

	/**
	 * 增加节点列表,增加的节点是不带子节点的
	 *
	 * @param         Bean类型
	 * @param list       Bean列表
	 * @param rootId     根ID
	 * @param nodeParser 节点转换器,用于定义一个Bean如何转换为Tree节点
	 * @return this
	 * @since 5.8.6
	 */
	public  TreeBuilder append(List list, E rootId, NodeParser nodeParser) {
		checkBuilt();

		final TreeNodeConfig config = this.root.getConfig();
		final Map> map = new LinkedHashMap<>(list.size(), 1);
		Tree node;
		for (T t : list) {
			node = new Tree<>(config);
			nodeParser.parse(t, node);
			if (null != rootId && false == rootId.getClass().equals(node.getId().getClass())) {
				throw new IllegalArgumentException("rootId type is node.getId().getClass()!");
			}
			map.put(node.getId(), node);
		}
		return append(map);
	}

	/**
	 * 重置Builder,实现复用
	 *
	 * @return this
	 */
	public TreeBuilder reset() {
		this.idTreeMap.clear();
		this.root.setChildren(null);
		this.isBuild = false;
		return this;
	}

	@Override
	public Tree build() {
		checkBuilt();

		buildFromMap();
		cutTree();

		this.isBuild = true;
		this.idTreeMap.clear();

		return root;
	}

	/**
	 * 构建树列表,没有顶层节点,例如:
	 *
	 * 
	 * -用户管理
	 *  -用户管理
	 *    +用户添加
	 * - 部门管理
	 *  -部门管理
	 *    +部门添加
	 * 
* * @return 树列表 */ public List> buildList() { if (isBuild) { // 已经构建过了 return this.root.getChildren(); } return build().getChildren(); } /** * 开始构建 */ private void buildFromMap() { if (MapUtil.isEmpty(this.idTreeMap)) { return; } final Map> eTreeMap = MapUtil.sortByValue(this.idTreeMap, false); E parentId; for (Tree node : eTreeMap.values()) { if (null == node) { continue; } parentId = node.getParentId(); if (ObjectUtil.equals(this.root.getId(), parentId)) { this.root.addChildren(node); continue; } final Tree parentNode = eTreeMap.get(parentId); if (null != parentNode) { parentNode.addChildren(node); } } } /** * 树剪枝 */ private void cutTree() { final TreeNodeConfig config = this.root.getConfig(); final Integer deep = config.getDeep(); if (null == deep || deep < 0) { return; } cutTree(this.root, 0, deep); } /** * 树剪枝叶 * * @param tree 节点 * @param currentDepp 当前层级 * @param maxDeep 最大层级 */ private void cutTree(Tree tree, int currentDepp, int maxDeep) { if (null == tree) { return; } if (currentDepp == maxDeep) { // 剪枝 tree.setChildren(null); return; } final List> children = tree.getChildren(); if (CollUtil.isNotEmpty(children)) { for (Tree child : children) { cutTree(child, currentDepp + 1, maxDeep); } } } /** * 检查是否已经构建 */ private void checkBuilt() { Assert.isFalse(isBuild, "Current tree has been built."); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy