自个儿写的一个动态从后台数据库加载Ext.tree的json数据工具类

自己写的一个动态从后台数据库加载Ext.tree的json数据工具类
总共两个class(TreeLoader.java,TreeNode.java)一个接口(TreeNodeConfig.java),使用时是:比如Action中调用TreeLoader.loadTree(..),TreeLoader再回调接口TreeNodeConfig的实现,具体看代码:
1、TreeNode.java 这是一个Ext.tree.TreeNode的配置信息的bean

package com.test.util;

import java.io.Serializable;

public class TreeNode implements Serializable {

	private static final long serialVersionUID = 3932457248824817931L;

	private boolean allowChildren;
	
	private boolean allowDrag;
	
	private boolean allowDrop;
	
	private boolean checked;
	
	private String cls;
	
	private boolean disabled;
	
	private boolean draggable;
	
	private boolean editable;
	
	private boolean expandable;
	
	private boolean expanded;
	
	private boolean hidden;
	
	private String href;
	
	private String hrefTarget;
	
	private String icon;
	
	private String iconCls;
	
	private String id;//not null
	
	private boolean isTarget;
	
	private boolean leaf;//not null
	
	private String listeners;
	
	private String qtip;
	
	private String qtipCfg;
	
	private boolean singleClickExpand;
	
	private String text;
	
	private String uiProvider;
	
	private String superId;//not null

	public String getSuperId() {
		return superId;
	}

	public void setSuperId(String superId) {
		this.superId = superId;
	}

	public boolean isAllowChildren() {
		return allowChildren;
	}

	public void setAllowChildren(boolean allowChildren) {
		this.allowChildren = allowChildren;
	}

	public boolean isAllowDrag() {
		return allowDrag;
	}

	public void setAllowDrag(boolean allowDrag) {
		this.allowDrag = allowDrag;
	}

	public boolean isAllowDrop() {
		return allowDrop;
	}

	public void setAllowDrop(boolean allowDrop) {
		this.allowDrop = allowDrop;
	}

	public boolean isChecked() {
		return checked;
	}

	public void setChecked(boolean checked) {
		this.checked = checked;
	}

	public String getCls() {
		return cls;
	}

	public void setCls(String cls) {
		this.cls = cls;
	}

	public boolean isDisabled() {
		return disabled;
	}

	public void setDisabled(boolean disabled) {
		this.disabled = disabled;
	}

	public boolean isDraggable() {
		return draggable;
	}

	public void setDraggable(boolean draggable) {
		this.draggable = draggable;
	}

	public boolean isEditable() {
		return editable;
	}

	public void setEditable(boolean editable) {
		this.editable = editable;
	}

	public boolean isExpandable() {
		return expandable;
	}

	public void setExpandable(boolean expandable) {
		this.expandable = expandable;
	}

	public boolean isExpanded() {
		return expanded;
	}

	public void setExpanded(boolean expanded) {
		this.expanded = expanded;
	}

	public boolean isHidden() {
		return hidden;
	}

	public void setHidden(boolean hidden) {
		this.hidden = hidden;
	}

	public String getHref() {
		return href;
	}

	public void setHref(String href) {
		this.href = href;
	}

	public String getHrefTarget() {
		return hrefTarget;
	}

	public void setHrefTarget(String hrefTarget) {
		this.hrefTarget = hrefTarget;
	}

	public String getIcon() {
		return icon;
	}

	public void setIcon(String icon) {
		this.icon = icon;
	}

	public String getIconCls() {
		return iconCls;
	}

	public void setIconCls(String iconCls) {
		this.iconCls = iconCls;
	}

	public String getId() {
		return id;
	}

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

	public boolean isTarget() {
		return isTarget;
	}

	public void setTarget(boolean isTarget) {
		this.isTarget = isTarget;
	}

	public boolean isLeaf() {
		return leaf;
	}

	public void setLeaf(boolean leaf) {
		this.leaf = leaf;
	}

	public String getListeners() {
		return listeners;
	}

	public void setListeners(String listeners) {
		this.listeners = listeners;
	}

	public String getQtip() {
		return qtip;
	}

	public void setQtip(String qtip) {
		this.qtip = qtip;
	}

	public String getQtipCfg() {
		return qtipCfg;
	}

	public void setQtipCfg(String qtipCfg) {
		this.qtipCfg = qtipCfg;
	}

	public boolean isSingleClickExpand() {
		return singleClickExpand;
	}

	public void setSingleClickExpand(boolean singleClickExpand) {
		this.singleClickExpand = singleClickExpand;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public String getUiProvider() {
		return uiProvider;
	}

	public void setUiProvider(String uiProvider) {
		this.uiProvider = uiProvider;
	}
	
	public String toString(){
		return "(id:'"+id+"',text:'"+text+"',href:'"+href+"',leaf:"+leaf+")";
	}
}



2、TreeLoader.java 核心工具类

package com.test.util;

import java.util.ArrayList;
import java.util.List;
/**
 * 动态加载树结构的并得到Ext.tree形式的json数据
 */
public class TreeLoader {

	private String json;
	
	public String getJson() {
		return json;
	}

	public void setJson(String json) {
		this.json = json;
	}

	private TreeNodeConfig nodeConfig;//节点配置
	

	public TreeNodeConfig getNodeConfig() {
		return nodeConfig;
	}

	public void setNodeConfig(TreeNodeConfig nodeConfig) {
		this.nodeConfig = nodeConfig;
	}
	
	public TreeLoader(TreeNodeConfig treeNodeConfig) {
		this.nodeConfig = treeNodeConfig;
	}
	
	/**
	 * 加载树结构
	 * 典型的例子就是管理性质的系统中根据登陆者的角色动态加载出相应权限的节点菜单.
	 * (如果想要加载出来的树结构具有序,则allTreeNodes的内容应该是oracle树查询返回的结果集,像这样:
	 * 		 select * from tree_menu tm
	 *		connect by prior tm.node_id = tm.super_node_id
	 *	 	 start with tm.super_node_id = 0
	 *	 	 order siblings by tm.node_order asc;
	 * )
	 * @param superNodeId - 所加载的树结构的根节点id
	 * @param subTreeNodes - 完整树结构中的想要 加载出来的节点
	 * @param allTreeNodes - 完整树结构中的所有节点
	 * @param includeSuperNode - 是否包含superNodeId对应的节点
	 * @return
	 */
	public String loadTree(String superNodeId,List<TreeNode> subTreeNodes,
			List<TreeNode> allTreeNodes,boolean includeSuperNode) {
		
		String json = "";
		
		if(includeSuperNode){//include super node
			StringBuilder sb = new StringBuilder();
			this.loadChild(superNodeId, subTreeNodes, allTreeNodes, sb);
			json = sb.toString();
		}else{
			List<TreeNode> directChildNodes = this.getDirectedChilds(superNodeId, allTreeNodes);
			for(int i = 0; i < directChildNodes.size(); i++){
				StringBuilder sb = new StringBuilder();
				if(directChildNodes.get(i) != null && directChildNodes.get(i).getId() != null &&!"".equals(directChildNodes.get(i).getId())){
					this.loadChild(directChildNodes.get(i).getId(), subTreeNodes, allTreeNodes, sb);
					json = json + sb.toString();
				}
			}
		}
		
		json = "[" + json + "]";
		json = json.replace("},]", "}]");//trim ','
		this.setJson(json);
		return json;
	}
	/**
	 * 递归加载节点
	 * @param nodeId
	 * @param subTreeNodes
	 * @param allTreeNodes
	 * @param sb
	 */
	public void loadChild(String nodeId, List<TreeNode> subTreeNodes,
			List<TreeNode> allTreeNodes,StringBuilder sb){
		TreeNode currentNode = this.getTreeNode(nodeId, allTreeNodes);
		
		if(allTreeNodes == null || allTreeNodes.isEmpty()){
			return;
		}
		
		List<TreeNode> leafChildNodes = new ArrayList<TreeNode>();
		this.findLeafChild(nodeId, allTreeNodes, leafChildNodes);
		
		leafChildNodes.add(currentNode);
		//如果当前节点及其子节点组成的集合与视野节点subTreeNodes存在交集则加载当前节点
		if(!this.existCommons(leafChildNodes, subTreeNodes)){
			return;
		}
		
		if(currentNode != null){
			sb.append("{");
			if(currentNode.isLeaf()){//子节点,即叶子节点
				this.getNodeConfig().config4Leaf(sb, currentNode);
			}else{//含有子节点的节点
				this.getNodeConfig().config4Folder(sb, currentNode);
			}
			
			List<TreeNode> childNodes = this.getDirectedChilds(nodeId, allTreeNodes);
			if(!currentNode.isLeaf() || childNodes.size() != 0){
				sb.append(",children :[");
				for(int i = 0; i < childNodes.size(); i++){
					if(childNodes.get(i) != null && childNodes.get(i).getId() != null && !"".equals(childNodes.get(i).getId())){
						loadChild(childNodes.get(i).getId(),subTreeNodes,allTreeNodes,sb);
					}
				}
				sb.append("]");
			}
			sb.append("},");
		}
	}
	/**
	 * 递归查找叶子(leaf)节点,并保存在leafChildNodes中
	 * @param nodeId
	 * @param allTreeNodes
	 * @param leafChildNodes
	 */
	public void findLeafChild(String nodeId,List<TreeNode> allTreeNodes,List<TreeNode> leafChildNodes){
		List<TreeNode> directChilds = this.getDirectedChilds(nodeId, allTreeNodes);
		if(directChilds.size() == 0){
			return;
		}
		for(int i = 0; i < directChilds.size(); i++){
			if(!directChilds.get(i).isLeaf()){
				this.findLeafChild(directChilds.get(i).getId(),allTreeNodes,leafChildNodes);//递归查找
			}else{
				leafChildNodes.add(directChilds.get(i));
			}
		}
	}
	/**
	 * 获取nodeId对应节点的直接子节点
	 * @param nodeId
	 * @param allTreeNodes
	 * @return
	 */
	public List<TreeNode> getDirectedChilds(String nodeId,List<TreeNode> allTreeNodes){
		List<TreeNode> list = new ArrayList<TreeNode>();
		if(allTreeNodes == null || allTreeNodes.isEmpty()){
			return list;
		}
		for(int i = 0; i < allTreeNodes.size(); i++){
			if(nodeId.equals(allTreeNodes.get(i).getSuperId())){
				list.add(allTreeNodes.get(i));
			}
		}
		return list;
	}
	
	/**
	 * nodes1与 nodes2是否存在节点id相同的TreeNode
	 * @param nodes1
	 * @param nodes2
	 * @return
	 */
	public boolean existCommons(List<TreeNode> nodes1,List<TreeNode> nodes2){
		if(nodes1 == null || nodes1.isEmpty() || nodes2 == null || nodes1.isEmpty()){
			return false;
		}
		for(int i = 0; i < nodes1.size(); i++){
			if(nodes1.get(i) == null || nodes1.get(i).getId() == null || "".equals(nodes1.get(i).getId())){
				continue;
			}
			for(int j = 0; j < nodes2.size(); j++){
				if(nodes1.get(i).getId().equals(nodes2.get(j).getId())){
					return true;
				}
			}
		}
		return false;
	}
	/**
	 * 根据节点id获取节点
	 * @param nodeId
	 * @param list
	 * @return
	 */
	public TreeNode getTreeNode(String nodeId,List<TreeNode> list){
		TreeNode node = null;
		for(int i = 0; i < list.size(); i++){
			node = list.get(i);
			if(node == null) continue;
			if(nodeId.equals(node.getId())){
				break;
			}
		}
		return node;
	}
}



3、TreeNodeConfig.java  回调接口

package com.test.util;
/**
 * 具体加载Ext.tree.TreeNode的信息配置,由用户配置,比较灵活,该接口方法由TreeLoader在加载节点时回调
 */
public interface TreeNodeConfig {
	/*
	 * 针对leaf-叶子型节点的配置
	 */
	public void config4Leaf(StringBuilder sb,TreeNode treeNode);
	/*
	 * 针对folder-文件夹型节点的配置
	 */
	public void config4Folder(StringBuilder sb,TreeNode treeNode);
}



4、现在来看看如何应用。

String[] configLocations = {"applicationContext.xml"};
		ApplicationContext context = new ClassPathXmlApplicationContext(configLocations);
		EmployeeDao employeeDao = (EmployeeDao) context.getBean("employeeDao");
		
		List<TreeNode> all = employeeDao.getTreeStructure();
		List<TreeNode> sub = employeeDao.getAuthorizedTreeNode(911);
		System.out.println(">>>>>> all : " + all);
		System.out.println(">>>>>> sub : " + sub);
		TreeLoader loader = new TreeLoader(new TreeNodeConfig(){
			public void config4Leaf(StringBuilder sb, TreeNode treeNode) {
				sb.append("id:'" + treeNode.getId() + "',text:'" + treeNode.getText()
						+ "',leaf:" + treeNode.isLeaf() + ",href:'"
						+ treeNode.getHref() + "',hrefTarget:'target-"
						+ treeNode.getId() + "',listeners:{" + treeNode.getListeners() + "}");
			}
			public void config4Folder(StringBuilder sb, TreeNode treeNode) {
				sb.append("id:'" + treeNode.getId() + "',text:'" + treeNode.getText()
						+ "',leaf:" + treeNode.isLeaf() + ",cls:'folder',listeners:{" + treeNode.getListeners() + "}");
			}
		});
		String json = loader.loadTree("1011", sub, all,false);
		System.out.println(">>>>>>>> json : " + json);