树的动态生成

来源:互联网 发布:异色眼灵摆龙淘宝 编辑:程序博客网 时间:2024/05/21 08:52

 
树的动态生成和一般的静态书是不一样的。因为动态树中所有的结点或者部分节点不是固定的,可能会随时随着数据库中或者文件中的数据而动态的变动。对于一般的静态树,我们只需要在jsp页面中包含js代码就可以了。那么动态树就需要javabean的支持了。
 
主要文件
TreeNote.java :树的结点类。
TreeBuilder.java :树的构造器。
ShowTree.java :为了减少页面中的java语句,我们在这里构造生成树需要的html代码。
BuildyourTree.java :在这里构造你的树。你也可以写自己的方法,这里只是个例子。
 
下面一个一个文件的来看:
TreeNote.java

package cn.edu.ouc.jwc.zysb.tree;

import java.util.*;

import cn.edu.ouc.jwc.util.*;

/**
 *


  /**
   * 节点的Id,生成对象时此Id会被自动生成.
   */
  private String Id = null;

  /**
   * 描述节点在树中的位置.必须准许一定的格式.其格式规则如下:
   * 1.根节点值为"root";
   * 2.其他节点的值为"root secondLevelparameter thirdLevelParameter ... thisLevelParameter".
   * 举例我要添加专业节点其location内容如下: "root yh zhuanye",其中yh为这个专业所属院的parameter,zhuanye为本专业的parameter.
   */
  private String location = null;

  /**
   * 节点名字.要显示在页面上的东东.就是每个节点上显示的名字.
   */
  private String name = null;

  /**
   * 每个节点对应的URL.
   */
  private String URL = null;

  /**
   * 也就是本层的参数,代表本层,将要添加到location的末尾中.
   */
  private String parameter = null;

  /**
   * 容器包装其所有的孩子节点.
   */
  private ArrayList children = new ArrayList();

  public TreeNote() {
    Id = IDGenerator.getID();
  }

  public TreeNote(int seed) {
    Id = IDGenerator.getID(seed);
  }

  public TreeNote(String name) {
    Id = IDGenerator.getID();
    this.name = name;
  }

  public TreeNote(String name, int seed) {
    Id = IDGenerator.getID(seed);
    this.name = name;
  }

  public String getId() {
    return Id;
  }

  public String getName() {
    return name;
  }

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

  public String getURL() {
    return URL;
  }

  public void setURL(String URL) {
    this.URL = URL;
  }

  public void setLocation(String location) {
    this.location = location;
  }

  public String getLocation() {
    return location;
  }

  public ArrayList getChildren() {
    return children;
  }

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

  public String getParameter() {
    return parameter;
  }

  public void setParameter(String parameter) {
    this.parameter = parameter;
  }

  /**
   * 返回孩子的数目.
   *
   * @return 孩子的数目,无孩子为"0".
   */
  public int getChildNum() {
    return children.size();
  }

  /**
   * 增加一个孩子.
   *
   * @param child TreeNote.
   */
  public void addChild(TreeNote child) {
    children.add(child);
  }

  /**
   * 根据索引得到一个孩子.
   *
   * @param index 从"0"开始的索引."0"代表第一个孩子.
   * @return TreeNote
   */
  public TreeNote getChild(int index) {
    return (TreeNote) children.get(index);
  }

}

 

Title: 教务处工程-专业识别


 *
 *
Description:树的节点对象


 *
 *
Copyright: Copyright (c) 2004


 *
 *
Company: 中国海洋大学教务处


 *
 *
创建日期: 2004.4.17


 *
 *
修改日期: 2004.4.17


 * @author  IPlinger
 * @version 1.0
 */
public class TreeNote {

 
注释我应该已经写的很清楚了,自己看吧。其中需要一个IDGenerator.getID()的辅助方法ID产生器,这里我给出这个源码,当然你也可以自己写呀
 

IDGenerator.java

package cn.edu.ouc.jwc.util;

import java.net.*;

/**
 *


  /**
   * a single static metod which generates a unique id based on hostname and
   * time.Id=hostname+time.
   *


    return Id;
  }

  /**
   * a single static metod which generates a unique id based on hostname and
   * time and seed.Id=hostname+time+seed.
   *

 

此方法的引入无非是为了避免上一方法的缺点,但注意传入的seed在生成一系列id时务必是不同的;比如可以传入循环中的"i".


   * @param seed
   * @return String 一般为主机名+当前时间(毫秒)+seed;如果找不到主机明就为UnknownHost加当前时间+seed;
   */
  public static String getID(int seed) {
    String Id = null;
    try {
      Id = InetAddress.getLocalHost().getHostName();
    }
    catch (UnknownHostException ue) {
      Id = "UnknownHost";
    }
    Id = Id + System.currentTimeMillis() + String.valueOf(seed);
    return Id;
  }
}
 
 

注意 如果id连续产生可能会产生相同的Id,务必谨慎!


   * @return String 一般为主机名加当前时间(毫秒);如果找不到主机明就为UnknownHost加当前时间;
   */
  public static String getID() {
    String Id = null;
    try {
      Id = InetAddress.getLocalHost().getHostName();
    }
    catch (UnknownHostException ue) {
      Id = "UnknownHost";
    }
    Id = Id + System.currentTimeMillis();
 

名称: 教务处工程-专业识别


 *
 *
描述: This class has a single static metod which generates a unique id based on hostname and time.


 *
 *
版权: Copyright (c) 2004


 *
 *
单位: 中国海洋大学教务处


 *
创建日期: 2004.4.8


 * 
修改日期: 2004.4.8


 * @author IPlinger
 * @version 1.0
 */
public class IDGenerator {

下面是TreeBuilder类

 TreeBuilder.java

package cn.edu.ouc.jwc.zysb.tree;

import java.util.*;

import org.apache.log4j.*;

/**
 *


  /**
   * 给定一个parent节点和一个child节点,判断这个child节点是否属于这个parent.
   *
   * @param parent parent节点.
   * @param child child节点.
   * @return true 所给的两个节点父子关系正确.
   *   false 所给的两个节点不存在指定的父子关系.
   */
  private boolean isChild(TreeNote parent, TreeNote child) {
    if (parent == null) {
      //logger.error("treeNote parent null!!!");
      throw new NullPointerException();
    }
    if (child != null &&
        findNoteByParam(parent.getChildren(), child.getParameter()) != null) {
      return true;
    }
    return false;
  }

  /**
   * 在树中找出所给节点的双亲节点.
   *
   * @param treeNote
   * @return TreeNote 如果没有找到返回null.
   */
  private TreeNote locateParentNote(TreeNote treeNote) {
    String location = treeNote.getLocation();
    if (location != null) {
      TreeNote locatedNote = root; //当前定位到的节点;初始时为根节点;
      StringTokenizer loc = new StringTokenizer(location);
      int locNum = loc.countTokens();
      if (loc.nextToken().equals("root") && locNum > 1) {
        //第一层为"root",最后一层为自己,所以i从0开始,循环locNum-2遍;
        for (int i = 0; i < locNum - 2; i++) {
          locatedNote = findNoteByParam(locatedNote.getChildren(),
                                        loc.nextToken());
          if (locatedNote == null) {
            break;
          }
        }
        if (locatedNote != null) {
          return locatedNote;
        }
      }
    }
    return null;
  }

  /**
   * 向树中添加一个节点.
   *
   * @param treeNote 待添加节点对象.
   * @return ture 添加成功.
   *   false
   *   添加失败.可能是找不到这个节点的parent节点或着这个节点已经存在!
   */
  public boolean treeNoteAdd(TreeNote treeNote) {
    if (treeNote == null) {
      //logger.error("the size of treeNote is null!!!");
      throw new NullPointerException();
    }
    TreeNote parentNote = locateParentNote(treeNote);
    if (parentNote != null && !isChild(parentNote, treeNote)) {
      parentNote.getChildren().add(treeNote);
      return true;
    }
    //logger.error("treeNote " + treeNote.getName() + "have not parents or is existent! can't be added!!");
    return false;
  }

  /**
   * 把以ArrayList容器装载的一系列节点添加到树.
   *
   * @param treeNoteList 装入一系列TreeNote的ArrayList.
   */
  public void ArrayListAdd(ArrayList treeNoteList) {
    int noteNum = treeNoteList.size();
    if (noteNum == 0) {
      //logger.error("the size of treeNoteList is zero!!!");
      throw new NullPointerException();
    }
    for (int i = 0; i < noteNum; i++) {
      treeNoteAdd( (TreeNote) treeNoteList.get(i));
    }
  }

  /**
   * 从所给的存放TreeNote的容器中找到一个其parameter为所给值的节点.
   *
   * @param locNote ArrayList.
   * @param parameter String.
   * @return 如果能找到多个则只返回一个TreeNote,其位置在容器中最靠前.找不到则返回null.
   */
  private TreeNote findNoteByParam(ArrayList locNote, String parameter) {
    if (parameter == null) {
      //logger.error("the parameter is null!!!");
      throw new NullPointerException();
    }
    TreeNote noteTemp = null;
    int num = locNote.size();
    for (int i = 0; i < num; i++) {
      noteTemp = (TreeNote) locNote.get(i);
      if (noteTemp.getParameter().equals(parameter)) {
        return noteTemp;
      }
    }
    return null;
  }

  //测试用
  public static void main(String[] args) {
    TreeBuilder myTree = new TreeBuilder();
    TreeNote testson = new TreeNote("son");
    testson.setLocation("root test");
    testson.setParameter("test");
    myTree.root.addChild(testson);
    TreeNote test = new TreeNote("son");
    test.setLocation("root test");
    System.out.println(myTree.isChild(myTree.root, test));
  }
}

 

 

 

Title: 教务处工程-专业识别


 *
 *
Description: 树构建器对象.自动生成root节点.包含构建树用的一切方法.


 *
 *
Copyright: Copyright (c) 2004


 *
 *
Company: 中国海洋大学教务处


 * @author  IPlinger
 * @version 1.0  2004.4.17
 */
public class TreeBuilder {
  public TreeNote root = new TreeNote("root");
  //public static Logger logger = Logger.getLogger(TreeBuilder.class); //生成记录器;
  public TreeBuilder() {
    root.setLocation("root");
    root.setParameter("root");
  }


不知道你们主要了吗?添加节点要根据location来添加,它就相当于这里节点的地址,指明它在整棵树的那个位置。location其他解释看TreeNote.java中的注释。

ShowTree.java

package cn.edu.ouc.jwc.zysb.tree;

import java.util.*;

import org.apache.log4j.*;

public class ShowTree {
  //public static Logger logger = Logger.getLogger(ShowTree.class);
  private TreeNote temp = null;
  private StringBuffer buf = new StringBuffer();

  /**
   * 包装treeHTMLGenerator(ArrayList chiildren)方法
   *
   * @param children children 开始传入root节点的孩子
   * @return String 生成的HTML代码
   */
  public String HTMLGenerator(TreeNote root) {
    return treeHTMLGenerator(root.getChildren());
  }

  /**
   * 产生树的HTML代码,为递归程序.
   *
   * @param children 开始传入root节点的孩子
   * @return 生成的HTML代码
   */
  private String treeHTMLGenerator(ArrayList children) {
    buf.append(" <>/n");
    int size = children.size();
    for (int i = 0; i < size; i++) {
      temp = (TreeNote) children.get(i);
      if (temp.getChildNum() != 0) { //如果这个节点有孩子..
        buf.append("  <>/n");
        if (temp.getURL() != null) {
          buf.append(
              "                temp.getId() + "').style){display=display=='none'?'':'none';this.style.backgroundImage=display!='none'?'url(image/e.gif)':'url(image/c.gif)'}/">
              temp.getURL() + //通过URL管理器得到URL
              "?location=" + temp.getLocation() + "/" target=/"mainFrame/">" +
              temp.getName() + " <>/n"); //页面上显示节点的名字
        }
        else {
          buf.append(
              "                temp.getId() + "').style){display=display=='none'?'':'none';this.style.backgroundImage=display!='none'?'url(image/e.gif)':'url(image/c.gif)'}/">
" +
              temp.getName() + " <>/n");
        }
        buf.append("
<>/n");
        buf.append("  <>/n");
        buf.append("                     "/" style=/"display:none/">/n");
        treeHTMLGenerator(temp.getChildren());
        buf.append(" <>/n");
        buf.append("
<>/n");
      }
      else { //这个节点没有孩子...
        buf.append("  <>/n");
        if (temp.getURL() != null) {
          buf.append(
              "                temp.getURL() +
              "?location=" + temp.getLocation() + "/" target=/"mainFrame/">" +
              temp.getName() + " <>/n");
        }
        else {
          buf.append("  " +
                     temp.getName() + " <>/n");
        }
        buf.append("
<>/n");
      }
    }
    buf.append(" /n");
    return buf.toString();
  }
}

 


这个类避免了在页面中嵌入过多的java代码,我们用递归来生成树的html代码。所以你要对树的显示效果的修改就要修改这里的代码。当然css用的好的人可以用css解决。不是很方便,可是我也找不到好的方法了:)。也希望大家能多提意见呀。

下面给出要显示树的jsp页面中需要的js和css代码。

 function findObj(theObj, theDoc)
{
  var p, i, foundObj;

  if(!theDoc) theDoc = document;
  if( (p = theObj.indexOf("?")) > 0 && parent.frames.length)
  {
 theDoc = parent.frames[theObj.substring(p+1)].document;
 theObj = theObj.substring(0,p);
  }
  if(!(foundObj = theDoc[theObj]) && theDoc.all) foundObj = theDoc.all[theObj];
  for (i=0; !foundObj && i < theDoc.forms.length; i++)
 foundObj = theDoc.forms[i][theObj];
  for(i=0; !foundObj && theDoc.layers && i < theDoc.layers.length; i++)
 foundObj = findObj(theObj,theDoc.layers[i].document);
  if(!foundObj && document.getElementById) foundObj = document.getElementById(theObj);

  return foundObj;
}

.folder { BACKGROUND-POSITION: left 50%; PADDING-LEFT: 20px; FONT-SIZE: 12px; BACKGROUND-IMAGE: url(image/e.gif); CURSOR: hand; BACKGROUND-REPEAT: no-repeat; FONT-FAMILY: "Verdana", "Arial", "Helvetica", "sans-serif" } .collapsedFolder { BACKGROUND-POSITION: left 50%; PADDING-LEFT: 20px; FONT-SIZE: 12px; BACKGROUND-IMAGE: url(image/c.gif); CURSOR: hand; BACKGROUND-REPEAT: no-repeat; FONT-FAMILY: "Verdana", "Arial", "Helvetica", "sans-serif" } .submenu { PADDING-LEFT: 18px } .iefile { BACKGROUND-POSITION: left 50%; PADDING-LEFT: 20px; FONT-SIZE: 12px; BACKGROUND-IMAGE: url(image/f.gif); BACKGROUND-REPEAT: no-repeat; FONT-FAMILY: "Verdana", "Arial", "Helvetica", "sans-serif" }
 


这些css你都需要根据你的需求来订制。也可以自己加入新的。

下面我们用BuildYourTree.java这个类,来建造我们的树。

BuildYourTree.java

package cn.edu.ouc.jwc.zysb.tree;

import cn.edu.ouc.jwc.zysb.data.*;

/**
 *


  /**
   * 建造你自己的树.用于教学计划的维护.
   *
   * @return 你所建造树的根节点.
   */
  public TreeNote buildMaintaiTree() {

    YearPlanData yearplan = new YearPlanData(); //加入第一层"计划学年".
    myTree.ArrayListAdd(yearplan.buildTreeNotes());

    InstituteData institute = new InstituteData(); //第二层"学院".
    myTree.ArrayListAdd(institute.buildTreeNotes());

    SpecialityData speciality = new SpecialityData(); //第三层"专业".
    myTree.ArrayListAdd(speciality.buildTreeNotes("Speciality.jsp"));

    LevelData level = new LevelData(); //第四层"层次".
    myTree.ArrayListAdd(level.buildTreeNotes("Level.jsp"));

    return myTree.root;
  }

  /**
   * 建造你自己的树.用于教学计划的察看.
   *
   * @return 你所建造树的根节点.
   */
  public TreeNote buildViewTree() {

    YearPlanData yearplan = new YearPlanData(); //加入第一层"计划学年".
    myTree.ArrayListAdd(yearplan.buildTreeNotes());

    InstituteData institute = new InstituteData(); //第二层"学院".
    myTree.ArrayListAdd(institute.buildTreeNotes());

    SpecialityData speciality = new SpecialityData(); //第三层"专业".
    myTree.ArrayListAdd(speciality.buildTreeNotes("SpecialityView.jsp"));

    LevelData level = new LevelData(); //第四层"层次".
    myTree.ArrayListAdd(level.buildTreeNotes("LevelView.jsp"));

    return myTree.root;
  }

}


 

Title: 教务处工程-专业识别


 *
 *
Description: 在这里用TreeBuilder对象建造你自己的树


 *
 *
Copyright: Copyright (c) 2004


 *
 *
Company:


 * @author  IPlinger
 * @version 1.0
 */
public class BuildYourTree {
  TreeBuilder myTree = new TreeBuilder();

这里只是我的实现,我用两个方法生成了我需要的两棵树。这里可以写你自己的方法。我们在构造树的时候是一层一层的往树中添加的。而每层中的节点的位置时根据每个节点location 这个参数决定的。关于buildTreeNotes()方法,你们可以有自己的实现。下面给出我的一个实现。我的这些节点信息是在数据库中得到的。

  /**
   * 先调用getAllSpecialityData()得到含所有专业对象的容器,再把所有Speciality对象转换成
   * TreeNote对象,并装入ArrayList容器
   *
   * @return 生成的TreeNote容器,如果没有则返回空容器。
   */
  public ArrayList buildTreeNotes(String noteURL) {
    ArrayList allSpecialityData = getAllSpecialityData();
    ArrayList result = new ArrayList();
    for (int i = 0, n = allSpecialityData.size(); i < n; i++) {
      Speciality temp = (Speciality) allSpecialityData.get(i);
      TreeNote note = new TreeNote(temp.getSpecialityName(), i);
      note.setURL(URLManager.makeDocumentURL(noteURL)); //加入连接
      note.setParameter(temp.getSpecialityId()); //加入本节点的属性
      note.setLocation("root " + temp.getYearPlan() + " " + temp.getInstituteId() + " " +
                       temp.getSpecialityId()); //节点位置
      result.add(note); //加入容器
    }
    return result;
  }

/**
   * 从数据库中得到所有的专业信息.
   *
   * @return ArrayList 包含所有Speciality对象的容器,如果没有返回空容器;
   */
  public ArrayList getAllSpecialityData() {...}
 

 

原创粉丝点击