• e3.tree参考手册


    简介
    1. E3.Tree是E3平台下一个用于构造树型UI(menu,tree,outlookbar等)的的组件,
    E3.Tree 特色
     部署简单,只需要把相关jar放到WEB-INF/lib目录下即可
     构造树,菜单等树型UI的开发模式一致,
     提供了API和taglib 2种使用方式,使用简单,功能强大
     能够很容易把现有的树型UI集成进来,现在支持的有:xtree, ext tree 和yui menu
     功能丰富,现在支持的树有 普通树,radio树 ,checkbox树,动态树等



    系统要求
    JDK1.4X 或者以上版本
    E3.tree 有2种使用方式,一种是直接调用API,另外一种是使用taglib,第一种方式只要求jsp1.2,servlet2.3即可。第2种方式需要jsp2.0 servlet2.4
    新增功能
    提供了taglib的方式来构造树型UI
    升级说明
    替换E3-Tree.jar
    添加commons-beanutils-core.jar
    样例部署
    把e3.war 放到Tomcat's webapps 目录下,启动服务器,输入地址http://localhost:8080/e3 进入示例主页. 点级 E3.Tree 连接,即可看到示例程序.
    示例组图:

      
    使用
    Lib文件清单
    文件名 版本 说明
    E3-Tree.jar 1.0 E3平台的树
    E3-TemplateEngine.ja 1.0 E3平台的模板引擎Adapter
    commons-logging.jar 1.04 Apache的commons log,
    log4j-1.2.14.jar 1.2.14 Apache的log4j
    commons-collections-2.1.1.jar 2.1.1 Apache的collections
    velocity-1.4.jar 1.4 Apache的模板引擎
    commons-beanutils-core.jar 1.6 Apache的BeanUtils,使用里面的PropertyUtils类.



    使用taglib
    我们先来看看怎么使用taglib.把下面内容命名为E3Tree.jsp,放到例子web应用目录下去,输入地址http://localhost:8080/e3/E3Tree.jsp 看看效果,如果你看到2棵树,说明程序正常没问题,否则请到e3群(21523645)里面问.

    <%@ page contentType="text/html; charset=utf-8"%>

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="e3" uri="/e3/tree/E3Tree.tld" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <META http-equiv=Content-Type content="text/html; charset=utf-8">
    <script>

    function showSelectedNode(){
    var selectModel= tree.getSelectionModel();
    var selectNode = selectModel.getSelectedNode();
    alert(selectNode.text + selectNode.id );  
    }

    </script>
    </HEAD>
    <BODY>
    <%
      java.util.List datas  = new java.util.ArrayList();
      java.util.Map data = new java.util.HashMap();
      data.put("id","10");
      data.put("parentId", null );
      data.put("name","总部");

      datas.add( data );
     
      java.util.Map data1 = new java.util.HashMap();
      data1.put("id","1010");
      data1.put("parentId", "10" );
      data1.put("name","子公司1");
      datas.add( data1 );
     
          java.util.Map data2 = new java.util.HashMap();
      data2.put("id","1020");
      data2.put("parentId", "10" );
      data2.put("name","子公司2");
      datas.add( data2 ); 
       
      pageContext.setAttribute("orgs", datas);
     
    %>
    <table>
    <tr>
    <td>
    <c:url var="orgIcon" value="/e3/samples/tree/Org.gif"/>
    <c:url var="userIcon" value="/e3/samples/tree/User.gif"/>
    <e3:tree var="org" items="orgs" builder="extTree">
      <e3:node id="${org.id}" parentId="${org.parentId}" name="${org.name}"
               icon="${orgIcon}"
               openIcon="${userIcon}"
               action="javascript:showSelectedNode()"
      />
    </e3:tree>
    </td>
    <td>
    <e3:tree var="org" items="orgs"  builder="xTree">
      <e3:node id="B${org.id}" parentId="B${org.parentId}" name="${org.name}"
               icon="${orgIcon}"
               openIcon="${userIcon}"
               action="javascript:alert('test')"
      />
    </e3:tree>
    </td>
    </tr>
    </BODY>
    </HTML>



    使用taglib步骤
    1. 声明taglib
        <%@ taglib prefix="e3" uri="/e3/tree/E3Tree.tld" %>
    2. 准备业务数据
      java.util.List datas  = new java.util.ArrayList();
      java.util.Map data = new java.util.HashMap();
      data.put("id","10");
      data.put("parentId", null );
      data.put("name","总部");
      datas.add( data );
     
      java.util.Map data2 = new java.util.HashMap();
      data2.put("id","1020");
      data2.put("parentId", "10" );
      data2.put("name","子公司2");
      datas.add( data2 ); 
    业务数据可以保存在Map或者普通的JAVABEAN中.业务数据必须包含id,parentId,以及节点名称 信息。注意:并不要求他们的属性名是”id” “parented”,”name”,只需要包含了这些信息即可。Id代表节点主键,parentId代表父亲节点主键, name代表节点标题。 如你的业务对象属性名称是orgId, parentOrgId, orgName都可以.

    3. 保存业务数据
         pageContext.setAttribute("orgs", datas);
         可以保存到(pageContext,request, session或application里)
    4. 使用taglib显示树
    <e3:tree var="org" items="orgs" builder="extTree">
      <e3:node id="${org.id}" parentId="${org.parentId}" name="${org.name}"
               icon="${orgIcon}"
               openIcon="${userIcon}"
               action="javascript:showSelectedNode()"
      />
    </e3:tree>
    Tree标签属性
    属性名称 属性类型 备注
    var String 用于保存items元素
    items String 是业务数据列表对象的key
    builder String 用于构造树的builder对象(builder是什么下面会有介绍),可以选值有
    [XTree, XLoadTree, RadioXTree, RadioXLoadTree, CheckXTree, CheckXLoadTree, CompositeXTree, CompositeXLoadTree, ExtTree, ExtLoadTree]
    如果这些builder不能满足您的需求,你可以指定一个class,只要指定class实现了WebTreeBuilder接口即可.
    comparator java.util.Comparator 排序器,用来对树的节点排序. 节点类型为
    net.jcreate.e3.tree.support.WebTreeNode
    sortProperty String 排序属性名称,默认是按节点的名称来排序的,如果要使用别的属性排序,则需要设置该值.:如果你的业务对象有排序属性时,则需要指定,如sortProperty=”orgOrder”. 注意:如果设置了comparator属性,那么该值无效.
    reverse boolean 是否反向排序,默认false


     node标签负责将业务对象转换成树节点对象.node taglib包含的常规属性有
    属性名称 属性类型 备注
    id String 节点id
    parentId String 父亲节点id
    name  String 节点名称(标题)
    icon String 节点图标
    openIcon String 节点展开时的图标
    action String 是单节点时的动作,可以是一个url也可以是javascript函数.如果是函数,则必须以javascript:开头.如:action=”javascript: alert(‘demo’)”
    nodeProperty String 用于设置节点类型,有效值radio,checkbox和none,  nodeProperty的默认值是none,表示节点旁边没有其他控件,为radio时,节点旁边会有个单选按纽,为checkbox时,节点旁边会有个checkbox按纽.
    selected boolean 是否选种节点,只有当nodeProperty为radio或checkbox时才有效,默认值为false
    disabled boolean 是否禁用节点,默认值为false
    value String 节点帮定的值,只有当nodeProperty为radio或checkbox时才有效,默认值为空(长度为0的字符串)
    dragable boolean 节点是否允许拖动,默认值为false
    dropable boolean 是否允许停放拖动的节点,默认值为false
       
    添加JAR到classpath中
    现在来看调用API的使用方式.新建一个web项目,把Lib文件清单中的jar全部添加到classpath中

    业务数据对象
    package net.jcreate.e3.samples.tree;

    public class Org {
    private String id;
    private String parentId;
    private String name;
    private int viewOrder;

    public Org(){

    }

    public Org(String pId, String pParentId, String pName, int pViewOrder){
    this.id = pId;
    this.parentId = pParentId;
    this.name = pName;
    this.viewOrder = pViewOrder;
    }
    public int getViewOrder() {
    return viewOrder;
    }

    public void setViewOrder(int viewOrder) {
    this.viewOrder = viewOrder;
    }

    public String getId() {
    return id;
    }

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

    public String getName() {
    return name;
    }

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

    public String getParentId() {
    return parentId;
    }

    public void setParentId(String parentId) {
    this.parentId = parentId;
    }

    }

    控制器Servlet
    package net.jcreate.e3.samples.tree;

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import net.jcreate.e3.tree.Node;
    import net.jcreate.e3.tree.TreeDirector;
    import net.jcreate.e3.tree.TreeModel;
    import net.jcreate.e3.tree.UncodeException;
    import net.jcreate.e3.tree.UserDataUncoder;
    import net.jcreate.e3.tree.support.AbstractWebTreeModelCreator;
    import net.jcreate.e3.tree.support.DefaultTreeDirector;
    import net.jcreate.e3.tree.support.WebTreeBuilder;
    import net.jcreate.e3.tree.support.WebTreeNode;
    import net.jcreate.e3.tree.xtree.XTreeBuilder;

    public class TestServlet extends HttpServlet{

    protected void service(HttpServletRequest pRequest, HttpServletResponse pResponse) throws ServletException, IOException {

    //业务数据

    List orgs =  new ArrayList();
    Org jcjtOrg = new Org("001",null,"进创集团", 1);
    Org jcrjOrg = new Org("001001","001","进创软件", 1);
    Org xrjOrg = new Org("0010010011","001001","X软件公司", 1);
    Org yrjOrg = new Org("0010010012","001001","Y软件公司", 2);
    Org zrjOrg = new Org("0010010013","001001","Z软件公司", 3);
    orgs.add(jcjtOrg);
    orgs.add(jcrjOrg);
    orgs.add(xrjOrg);
    orgs.add(yrjOrg);
    orgs.add(zrjOrg);

    //业务数据解码器,从业务数据中分解出id和parentid
    UserDataUncoder orgUncoder = new UserDataUncoder(){
    public Object getID(Object pUserData) throws UncodeException {
    Org org = (Org)pUserData;
    return org.getId();
    }
    public Object getParentID(Object pUserData) throws UncodeException {
    Org org = (Org)pUserData;
    return org.getParentId();
    }
    };

    //Tree模型构造器,用于生成树模型
    AbstractWebTreeModelCreator treeModelCreator =
    new AbstractWebTreeModelCreator(){
    //该方法负责将业务数据映射到树型节点
    protected Node createNode(Object pUserData, UserDataUncoder pUncoder) {
    Org org = (Org)pUserData;
    WebTreeNode result = new WebTreeNode(org.getName(), "org" + org.getId());
    //action是点击按纽执行的方法.可以是url,或者javascript函数
    result.setAction("javascript:alert(' " + org.getName() + "')");
    return result;
    }
    };
    treeModelCreator.init(pRequest);

    TreeModel treeModel = treeModelCreator.create(orgs,orgUncoder);
    TreeDirector director = new DefaultTreeDirector();//构造树导向器
    WebTreeBuilder treeBuilder = new XTreeBuilder();//构造树Builder
    treeBuilder.init(pRequest);
    director.build(treeModel, treeBuilder);//执行构造
    String treeScript = treeBuilder.getTreeScript();//获取构造树的脚本
    pRequest.setAttribute("treeScript", treeScript);//保存到request,以便页面使用
            pRequest.getRequestDispatcher("XTree.jsp").forward(pRequest,pResponse);
    }


    }

    上面代码构造是普通树,如果要构造带checkbox/radiobox的树,只需要将
    WebTreeBuilder treeBuilder = new XTreeBuilder()
    这行代码换成
    WebTreeBuilder treeBuilder = new CheckXTreeBuilder ()

    WebTreeBuilder treeBuilder = new RadioXTreeBuilder ()
    即可
    JSP页面
    命名为XTree.jsp,放在web应用跟目录下(WEB-INF所在目录);
    %@ page contentType="text/html; charset=utf-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <META http-equiv=Content-Type content="text/html; charset=utf-8">
    </HEAD>
    <BODY>
    <%= request.getAttribute("treeScript") %>
    </BODY>
    </HTML>




    web.xml配置

    把下面配置添加到web.xml文件
        <listener>    <listener-class>net.jcreate.e3.tree.loader.LoadResourcesListener</listener-class>
        </listener>
         <filter>
        <filter-name>e3/characterEncodingFilter</filter-name>
        <filter-class>net.jcreate.e3.web.CharacterEncodingFilter</filter-class>
        <init-param>
          <param-name>encoding</param-name>
          <param-value>utf-8</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>e3/characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>   

      <servlet>
    <servlet-name>testServlet</servlet-name>
    <servlet-class>net.jcreate.e3.samples.tree.TestServlet</servlet-class>
    </servlet>

    <servlet-mapping>
    <servlet-name>testServlet</servlet-name>
    <url-pattern>/testServlet</url-pattern>
    </servlet-mapping>

    测试
    将web项目部署到Tomcat's webapps的test目录
    输入地址 http://localhost:8080/test/testServlet 如果看到树,恭喜你成功了!

    体系结构

    db


    xml

    ldap


    mem



     灰色大框图里的部件是E3.Tree的,框外是E3.Tree需要的输入和输出
     业务数据的来源会很多,常见的有db,xml,ldap和内存,所以对于数据如何获取,在E3.Tree里不做定义
     业务数据以Collection的形式提交给E3.Tree
     解码器:负责业务对象解码,分解出ID和parentID
     模型构造器:使用解码器对业务数据进行处理,生成树模型
     树模型:就是树的内存结构,可以有一个或者多个跟节点
     树构造器:负责对树模型中的节点进行处理,将内存节点翻译成用于与构造特定树型UI的脚本.
     导向器:负责树模型的节点遍历,驱动树构造器的处理.
     排序器:负责节点的排序
     访问器:负责节点过滤或者节点遍历.
    设计模型
    E3.Tree采用的核心设计模式是builder模式,如果您对builder还不大清楚,可以找gof设计模式树翻翻

    业务对象
    具有树型属性(构造树型结构需要的属性)的业务数据对象,从这类对象中可以分解出ID,和parentID.这类业务对象通常是会下面几种结构中的一种.
    如:
    A{
       Private String id;
       Private String parentId ;
    }

    B{
      Private String ID;  //ID的值是 0000_0001, 0000_0001_0001这种形式
    }
    E3.Tree对业务数据的唯一要求就是:从业务对象中要能分解出ID和父亲ID。ID和parentID可以是任何数据类型

     业务数据集
    业务对象的集合,该集合里的业务对象是线型关系。彼此之间没关系.
    由于业务数据的来源会很多,常见的有db,xml,ldap和内存,所以对于数据如何获取,在E3.Tree里不做定义.E3.Tree只要求以Collection的形式传递给TreeModelCreator即可.

     节点Node
    跟数据结构里的节点概念一致,包含的方法有
    public interface Node  {
    //获取父亲节点
    public Node getParent();
    //设置父亲节点
    public void setParent(Node pParent);
    //设置业务对象
    public void setUserData(Object pUserData);
        //获取业务对象
    public Object getUserData();
        //获取所有儿子
    public Iterator getChildren();
    //删除儿子
    public void detachNode(Node pNode);
        //添加儿子
    public void addNode(Node pNode);
         //是否是叶子节点
    public boolean isLeaf();
         //是否是根节点
    public boolean isRoot();
        //儿子节点个数
    public int getChildCount();
         //获取指定位置节点,序号从0开始
    public Node getChildAt(int pChildIndex);
         //获取儿子节点的序号
    public int getIndex(Node node);
    }


     树模型TreeModel
      TreeModel 跟数据结构里的树的概念对应. TreeModel可以有一个跟节点也可以有多个跟节点,所以可以是树有可以是森林.
    /**
    * 树,森林
    * @author new
    *
    */
    public interface TreeModel {

    /**
    * 获取跟节点,可以是多个跟节点.
    * @return
    */
    public Iterator getRootNodes();
    }

     解码器UserDataUncoder
    负责业务对象解码,分解出ID和parentID. 如果分解过程出错,抛UncodeException或它的派生类异常.TreeModelCreator会使用它对业务对象进行解码(我把从业务对象中分解出ID和parentID的过程叫做解码)处理.
    /**
    * 负责业务对象解码,分解出ID和parentID
    * @author new
    *
    */
    public interface UserDataUncoder {
      public Object getID(Object pUserData) throws UncodeException;
      public Object getParentID(Object pUserData) throws UncodeException;
    }

     树模型构造器TreeModelCreator
    负责创建TreeModel对象.注意,存在2个create方法,请看注释,理解2种方法的区别.
    /**
    * 将业务数据构造成TreeModel
    * @author new
    *
    */
    public interface TreeModelCreator {

    /**
    * 创建树模型
    * @param pUserDatas 业务数据,至少要存在一个跟节点(不存在父亲节点的节点)
    *                   要求集合元素读必须实现Uncodable接口                    
    * @return 返回根节点.
    * @throws CreateTreeModelException 如果集合元素没有实现Uncodable接口,会抛出
    *                                  ClassCastException异常
    */
       public TreeModel create(Collection pUserDatas) throws CreateTreeModelException;

    /**
    * 创建树模型
    * @param pUserDatas 业务数据,至少要存在一个跟节点(不存在父亲节点的节点)
    * @param pUncoder   解码器,对每个业务数据进行解码,返回主键对象和父亲主键对象.
    * @return 返回根节点.
    * @throws CreateTreeModelException
    */
      public TreeModel create(Collection pUserDatas, UserDataUncoder pUncoder) throws CreateTreeModelException;
    }

     树构造器TreeBuilder
    负责对树模型中的节点进行处理,将内存节点翻译成用于与构造特定树型UI的脚本.
    TreeBuilder包含一系列树型UI构造过程方法。请看注释,理解各方法的含义.

    public interface TreeBuilder {

    /**
    * 开始构造树

    * @throws BuildTreeException
    */
    public void buildTreeStart() throws BuildTreeException;
    /**
    * 结束构造树
    * @throws BuildTreeException
    */
    public void buildTreeEnd() throws BuildTreeException;

    /**
    * 开始构造普通节点(除跟节点之外的节点)
    * @param pNode 当前节点
    * @param pParentNode 父亲节点
    * @param pLevel 节点级别,根节点为0级,根节点直接儿子节点为1级,依次类推,2,3,....
    * @param pRow   在兄弟节点里的序号,第一个兄弟节点为0,第2个为1,第3个为2,依次类推.3,4....
    * @throws BuildTreeException
    */
    public void buildNodeStart(Node pNode, Node pParentNode, int pLevel, int pRow)
    throws BuildTreeException;

    /**
    * 结束构造普通节点(除跟节点之外的节点)
    * @param pNode 当前节点
    * @param pParentNode 父亲节点
    * @param pLevel 节点级别,根节点为0级,根节点直接儿子节点为1级,依次类推,2,3,....
    * @param pRow   在兄弟节点里的序号,第一个兄弟节点为0,第2个为1,第3个为2,依次类推.3,4....
    * @throws BuildTreeException
    */
    public void buildNodeEnd(Node pNode, Node pParentNode, int pLevel, int pRow)
    throws BuildTreeException;


    /**
    * 开始构造跟节点
    * @param pRootNode 跟节点,非空
    * @param pLevel 根节点级别
    * @param pRow   在兄弟节点里的序号,第一个兄弟节点为0,第2个为1,第3个为2,依次类推.3,4....
    * @throws BuildTreeException
    */
    public void buildRootNodeStart(Node pRootNode,int pLevel, int pRow) throws BuildTreeException;

    /**
    * 结束构造跟节点
    * @param pRootNode 跟节点,非空
    * @param pLevel 根节点级别
    * @param pRow   在兄弟节点里的序号,第一个兄弟节点为0,第2个为1,第3个为2,依次类推.3,4....
    * @throws BuildTreeException
    */
    public void buildRootNodeEnd(Node pRootNode, int pLevel, int pRow) throws BuildTreeException;

    }

     导向器TreeDirector
    负责树模型的节点遍历,驱动树构造器的处理.
       
    public interface TreeDirector {

    /**
    * 设置节点比较器
    * @param pComparator 节点比较器,用于进行兄弟节点比较
    */
    public void setComparator(Comparator pComparator);

       /**
        * 节点访问者
        * @param pVisitor
        */
       public void setNodeVisitor(NodeVisitor pVisitor);
      
    /**
    *  build树
    * @param pTree
    * @param pTreeBuilder Tree构造器(非空)
    * @throws BuildTreeException
    */
      public void build(TreeModel pTree, TreeBuilder pTreeBuilder) throws BuildTreeException; 
    }

     排序器Comparator
        负责节点的排序处理.排序器是使用jdk自带的java.util.Comparator


     访问器NodeVisitor
    负责节点过滤或者节点遍历.
    /**
    * 在使用TreeBuilder构造节点前进行访问.可以通过NodeVisitor
    * 设置Node的属性,过滤节点.当访问一个节点返回false时,
    * 该节点和他所有儿子节点不会传递个TreeBuilder
    * 节点访问.
    * @author 黄云辉
    *
    */
    public interface NodeVisitor {
      public boolean visit(Node pNode);
    }

    API代码片段
    排序

    节点默认是不排序,如果要排序,需要给导向器TreeDirector设置排序器.
    net.jcreate.e3.tree.support.DefaultNodeComparator是E3.Tree内置的排序器,根据节点名称排序.
    TreeDirector director = new DefaultTreeDirector();//构造树导向器
    director.setComparator(new DefaultNodeComparator());

    如果要根据特定属性排序,则需要自己实现排序器,通常只需要从
    net.jcreate.e3.tree.support.AbstractNodeComparator派生即可
    TreeDirector director = new DefaultTreeDirector();//构造树导向器
    director.setComparator(new AbstractNodeComparator(){
    protected Comparable getComparableProperty(Node pNode) {
    Object userData = pNode.getUserData();//获取业务对象
    Org org = (Org)userData;
    return new Integer( org.getViewOrder() );
    }
    });

    设置节点图标
    设置节点图标
    //Tree模型构造器,用于生成树模型
    AbstractWebTreeModelCreator treeModelCreator =
    new AbstractWebTreeModelCreator(){
    //该方法负责将业务数据映射到树型节点
    protected Node createNode(Object pUserData, UserDataUncoder pUncoder) {
    Org org = (Org)pUserData;
    WebTreeNode result = new WebTreeNode(org.getName(), "org" + org.getId());
    result.setIcon(this.getUrl("/e3/samples/tree/Org.gif"));
    result.setOpenIcon(this.getUrl("/e3/samples/tree/Org.gif"));
    //action是点击按纽执行的方法.可以是url,或者javascript函数
    result.setAction("javascript:alert(' " + org.getName() + "')");
    return result;
    }
    };

    类 net.jcreate.e3.tree.support. DefaultNode
    属性 名称 备注
    name 节点名称


    类 net.jcreate.e3.tree.support.WebTreeNode
    属性 名称 备注
    id 节点ID 注意:该ID要是合法标识符号,因为TreeBuilder可能使用该ID作为js变量
    icon 节点图标 收缩时图标
    openIcon 打开时的图标 展开时图标
    action 动作 单击节点时的动作,可以是javascript,也可以是超级连接 如: javascript:orgClick();
    /e3/a.jsp
    selected 是否被选种
    disabled 是否被禁用
    nodeProperty 节点属性 目前只有3种属性radio,checkbox和none
    这个属性需特别说明:一个树的最终形态是由TreeBuilder来决定的。所以如果采用CheckXTreeBuilder或RadioXTreeBuilder构造树时 ,该属性是没有用的。只有当一棵树中既有check节点又有radio节点或普通节点时,该属性才有效.

    类 net.jcreate.e3.tree.support. WebTreeDynamicNode
    属性 名称 备注
    subTreeURL 子树URL 负责导入子树的URL



    节点过滤
    过滤掉所有没有儿子节点的跟节点.返回false的节点以及他的儿子节点都会被过滤掉
    director.setNodeVisitor(new NodeVisitor(){
    public boolean visit(Node pNode) {
                    boolean noChildRoot = pNode.isRoot() && (pNode.getChildCount() == 0);
                    if (noChildRoot).{
                       return false;
                     } else { 
       return true;
                     }
    }

    });

    设置所有叶子节点图标

    director.setNodeVisitor(new NodeVisitor(){
    public boolean visit(Node pNode) {
                    if (pNode.isLeaf() ){
                    result.setIcon(RequestUtil.getUrl("/e3/samples/tree/Org.gif", pRequest));
    result.setOpenIcon(RequestUtil.getUrl("/e3/samples/tree/Org.gif", pRequest));

                   }
       return true;
    }

    });
    说明:RequestUtil的包名是net.jcreate.e3.tree.support
          pRequest是HttpServletRequest对象,因为是在匿名类里使用,所以pRequest必须是final 类型的.否则编译不能通过.
    构造混合节点树
    这棵树有机构节点和用户节点,用户节点挂在机构下.用户有个属性指向所属机构.
    混合节点的构造跟单节点的构造基本相同。就有一点要特别注意:因为是多节点,可能存在
    主键冲突的问题,所以构造节点ID和做节点分解的时候,需要带上前缀.

    public void showMixTree(final HttpServletRequest pRequest,
                final HttpServletResponse pResponse) throws Exception{
    //业务数据
    List orgs =  new ArrayList();
    Org jcjtOrg = new Org("001",null,"进创集团", 1);
    Org jcrjOrg = new Org("001001","001","进创软件", 1);
    orgs.add(jcjtOrg);
    orgs.add(jcrjOrg);

    User huangy = new User("huangyh", "黄云辉", "001");//直属集团
    User guohp = new User("guohp", "郭鸿鹏", "001");//直属集团

    User caogp = new User("caogp", "曹高平", "001001");//进创软件

    List users = new ArrayList();
    users.add(huangy);
    users.add(guohp);
    users.add(caogp);

    List allData = new ArrayList();
    allData.addAll(orgs);
    allData.addAll(users);



    //业务数据解码器,从业务数据中分解出id和parentid

    UserDataUncoder uncoder = new UserDataUncoder(){
    final String USERID_PREFIX = "USER_";//为了避免用户ID和机构ID出现相同的情况,所以构造树时
                //所有用户ID带个前缀.

    public Object getID(Object pUserData) throws UncodeException {
    if ( pUserData instanceof Org){
      Org org = (Org)pUserData;
      return org.getId();
    }
    if ( pUserData instanceof User ){
    User user = (User)pUserData;
    return USERID_PREFIX + user.getId();
    }
    throw new UncodeException("不支持的数据对象." + pUserData.getClass().getName());
    }
    public Object getParentID(Object pUserData) throws UncodeException {
    if ( pUserData instanceof Org){
      Org org = (Org)pUserData;
      return org.getParentId();
    }
    if ( pUserData instanceof User ){
    User user = (User)pUserData;
    return user.getOrgId();
    }
    throw new UncodeException("不支持的数据对象." + pUserData.getClass().getName());
    }
    };

    //Tree模型构造器,用于生成树模型
    AbstractWebTreeModelCreator treeModelCreator =
    new AbstractWebTreeModelCreator(){
    //该方法负责将业务数据映射到树型节点
    protected Node createNode(Object pUserData, UserDataUncoder pUncoder) {
    if ( pUserData instanceof Org ){
    Org org = (Org)pUserData;
    WebTreeNode result = new WebTreeNode(org.getName(), "org" + org.getId());
    result.setIcon(this.getUrl("/e3/samples/tree/Org.gif"));
    result.setOpenIcon(this.getUrl("/e3/samples/tree/Org.gif"));
    //action是点击按纽执行的方法.可以是url,或者javascript函数
    result.setAction("javascript:alert(' " + org.getName() + "')");
    return result;
    }

    if ( pUserData instanceof User ){
    User user = (User)pUserData;
    WebTreeNode result = new WebTreeNode(user.getName(), "user" + user.getId());
    result.setIcon(this.getUrl("/e3/samples/tree/User.gif"));
    result.setOpenIcon(this.getUrl("/e3/samples/tree/User.gif"));
    //action是点击按纽执行的方法.可以是url,或者javascript函数
    result.setAction("javascript:alert(' " + user.getName() + "')");
    return result;
    }
    throw new UncodeException("不支持的数据对象." + pUserData.getClass().getName());
    }
    };
    treeModelCreator.init(pRequest);

    TreeModel treeModel = treeModelCreator.create(allData,uncoder);
    TreeDirector director = new DefaultTreeDirector();//构造树导向器
    WebTreeBuilder treeBuilder = new XTreeBuilder();//构造树Builder
    treeBuilder.init(pRequest);
    director.build(treeModel, treeBuilder);//执行构造
    String treeScript = treeBuilder.getTreeScript();//获取构造树的脚本
    pRequest.setAttribute("treeScript", treeScript);//保存到request,以便页面使用
    pRequest.getRequestDispatcher("/e3/samples/tree/XTree.jsp").forward(pRequest,pResponse);
    }

    构造动态树
      动态树的构造分2个过程,第一个过程构造顶层静态节点(第一次要显示的节点),第2个过程负责导入特定节点的儿子节点数据.
    通常第一个过程只显示跟节点,下面的代码
    public void showLoadTree(final HttpServletRequest pRequest,
                     final HttpServletResponse pResponse) throws Exception{
    WebTreeDynamicNode rootNode = new WebTreeDynamicNode("进创集团", "org" + "001");
    rootNode.setSubTreeURL(
    RequestUtil.getUrl("/servlet/xtreeServlet?_actionType=" +
               "loadSubOrgs&parentID=" + "001", pRequest));
    DefaultTreeModel treeModel = new DefaultTreeModel();
    treeModel.addRootNode(rootNode);
    TreeDirector director = new DefaultTreeDirector();
    director.setComparator(new DefaultNodeComparator());
    WebTreeBuilder treeBuilder = new XLoadTreeBuilder();
    treeBuilder.init(pRequest);
    director.build(treeModel, treeBuilder);
    String treeScript = treeBuilder.getTreeScript();
    pRequest.setAttribute("treeScript", treeScript);
    pRequest.getRequestDispatcher("/e3/samples/tree/XTree.jsp").forward(pRequest,pResponse);

    }
    说明:
    1. 动态节点对象必须是WebTreeDynamicNode
    2. setSubTreeURL方法用于设置导入儿子节点数据的url

    下面这个方法用于生成儿子节点XML
    public void loadSubOrgs(final HttpServletRequest pRequest,
                final HttpServletResponse pResponse) throws Exception{
    final String parentID = pRequest.getParameter("parentID");
    TreeService treeService =  TreeBeanFactory.getTreeService();
    List subOrgs = treeService.getSubOrgs(parentID);
    UserDataUncoder orgUncoder = new OrgUncoder();
    AbstractWebTreeModelCreator treeModelCreator =
    new AbstractWebTreeModelCreator(){
    protected Node createNode(Object pUserData, UserDataUncoder pUncoder) {
    Org org = (Org)pUserData;
    WebTreeDynamicNode result = new WebTreeDynamicNode(org.getName(), "org" +org.getId());
    result.setSubTreeURL(
    getUrl("/servlet/xtreeServlet?_actionType=" +
               "loadSubOrgs&parentID=" + org.getId()));
    return result;
    }
    };
    treeModelCreator.init(pRequest);

    TreeModel treeModel = treeModelCreator.create(subOrgs,orgUncoder);
    TreeDirector director = new DefaultTreeDirector();
    director.setComparator(new DefaultNodeComparator());
    WebTreeBuilder treeBuilder = new XLoadSubTreeBuilder();
    treeBuilder.init(pRequest);
    director.build(treeModel, treeBuilder);
    String treeScript = treeBuilder.getTreeScript();
    pResponse.setBufferSize(1024*10);
    pResponse.setContentType("text/xml;charset=utf-8");
    pResponse.getWriter().write(treeScript);
    pResponse.flushBuffer();
    return;
    }

    自定义TreeBuilder
      Todo

    Taglib使用代码片段
    简单树
    <e3:tree var="org" items="orgs" >
      <e3:node id="${org.id}" parentId="${org.parentId}" name="${org.name}"/>
    </e3:tree>

    设置节点图标
    <c:url var="orgIcon" value="/e3/samples/tree/Org.gif"/>
    <c:url var="userIcon" value="/e3/samples/tree/User.gif"/>
    <e3:tree var="org" items="orgs" >
      <e3:node id="${org.id}" parentId="${org.parentId}" name="${org.name}"
               icon="${orgIcon}"
               openIcon="${userIcon}"  
      />
    </e3:tree>

    动态树
    <c:url var="orgIcon" value="/e3/samples/tree/Org.gif"/>
    <c:url var="userIcon" value="/e3/samples/tree/User.gif"/>
    <c:url var="subTree" value="/servlet/xtreeServlet?_actionType=loadExtSubOrgs&parentID=001"/>

    <e3:tree var="org" items="orgs" builder="ExtLoadTree" >
      <e3:node id="${org.id}" parentId="${org.parentId}" name="${org.name}"
               icon="${orgIcon}"
               openIcon="${userIcon}"  
               subTreeURL="${subTree}"
               cls="dynamic"
      />
    </e3:tree>


    节点排序
    <c:url var="orgIcon" value="/e3/samples/tree/Org.gif"/>
    <c:url var="userIcon" value="/e3/samples/tree/User.gif"/>
    <e3:tree var="org" items="orgs" sortProperty="viewOrder" >
      <e3:node id="${org.id}" parentId="${org.parentId}" name="${org.name}"
               icon="${orgIcon}"
               openIcon="${userIcon}"  
      />
    </e3:tree>

    反向排序
    <c:url var="orgIcon" value="/e3/samples/tree/Org.gif"/>
    <c:url var="userIcon" value="/e3/samples/tree/User.gif"/>
    <e3:tree var="org" items="orgs" sortProperty="viewOrder" reverse="true">
      <e3:node id="${org.id}" parentId="${org.parentId}" name="${org.name}"
               icon="${orgIcon}"
               openIcon="${userIcon}"  
      />
    </e3:tree>

    FAQ
    1. 我用的web框架是struts/jsf/webwork/,可以用E3.Tree吗?
    E3.Tree对Web 框架只有一个要求,就是能取到HttpServletRequest对象,只要满足这个要求,都可以使用.显然上面这几个框架都可以使用E3.Tree.

  • 相关阅读:
    Collection和Collections的区别
    Demo小细节-1
    一道关于String的面试题,新鲜出炉,刚被坑过,趁热!!
    System.gc()与Object.finalize()的区别
    释放对象所占用的内存
    Java接口中的成员变量默认为(public、static、final)、方法为(public、abstract)
    纸牌游戏——队列和栈的应用
    Vue过渡动画运用transition
    SpringBoot整合Redis注意的一些问题
    Spring的Bean的生命周期
  • 原文地址:https://www.cnblogs.com/moonfans/p/3341153.html
Copyright © 2020-2023  润新知