/***************************************************************************** * * * This file is part of the tna framework distribution. * * Documentation and updates may be get from biaoping.yin the author of * * this framework * * * * Sun Public License Notice: * * * * The contents of this file are subject to the Sun Public License Version * * 1.0 (the "License"); you may not use this file except in compliance with * * the License. A copy of the License is available at http://www.sun.com * * * * The Original Code is tag. The Initial Developer of the Original * * Code is biaoping yin. Portions created by biaoping yin are Copyright * * (C) 2000. All Rights Reserved. * * * * GNU Public License Notice: * * * * Alternatively, the contents of this file may be used under the terms of * * the GNU Lesser General Public License (the "LGPL"), in which case the * * provisions of LGPL are applicable instead of those above. If you wish to * * allow use of your version of this file only under the terms of the LGPL * * and not to allow others to use your version of this file under the SPL, * * indicate your decision by deleting the provisions above and replace * * them with the notice and other provisions required by the LGPL. If you * * do not delete the provisions above, a recipient may use your version of * * this file under either the SPL or the LGPL. * * * * biaoping.yin (yin-bp@163.com) * * Author of Learning Java * * * *****************************************************************************/ package com.frameworkset.common.tag.tree.impl; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TreeSet; import javax.servlet.http.HttpServletRequest; import com.frameworkset.common.tag.contextmenu.ContextMenuImpl; import com.frameworkset.common.tag.tree.itf.ICollapseListener; import com.frameworkset.common.tag.tree.itf.IExpandListener; import com.frameworkset.common.tag.tree.itf.ISelectListener; import com.frameworkset.common.tag.tree.itf.ITree; import com.frameworkset.common.tag.tree.itf.ITreeNode; import com.frameworkset.common.tag.tree.itf.IUnselectListener; /** * 定义树结构的抽象类 * @author biaoping.yin * created on 2005-3-25 * version 1.0 */ public abstract class Tree extends ContextMenuImpl implements ITree,java.io.Serializable { /** * level:定义默认展开层级 */ protected int level = -1; protected boolean singleSelectionMode = false; protected Set expanded = new TreeSet(); protected Set selected = new TreeSet(); protected ITreeNode root = null; protected List expandListeners = new ArrayList(); protected List collapseListeners = new ArrayList(); protected List selectListeners = new ArrayList(); protected List unselectListeners = new ArrayList(); protected List nodeListeners = new ArrayList(); /**标识当前展开得节点*/ protected ITreeNode curExpanded; protected boolean dynamic = true; protected boolean needObservable = false; // added this attribute by biaoping.yin on 2005-02-04 /**更新结点得信息*/ protected boolean refreshNode = true; protected boolean uprecursive = false; protected boolean recursive = false; public static final String mode_static = "static"; public static final String mode_static_dynamic = "static-dynamic"; public static final String mode_dynamic = "dynamic"; /** * 指定是否对树节点进行排序,缺省为true */ private boolean sortable = false; public void setNeedObservable(boolean needObservable) { this.needObservable = needObservable; } /** * 判断是否需要注册到观察器中 * @return boolean */ protected boolean isNeedObservable() { return this.needObservable; } public ITreeNode getRoot() { return this.root; } public void setRoot(ITreeNode node) { this.root = node; this.root.setTree(this); } public ITreeNode findNode(String treeNodeId) { return findNode(getRoot(), treeNodeId); } protected ITreeNode findNode(ITreeNode treeNode, String treeNodeId){ if(treeNode.getId().equals(treeNodeId)){ return treeNode; } Iterator children = treeNode.getChildren().iterator(); while(children.hasNext()){ ITreeNode child = (ITreeNode) children.next(); ITreeNode match = findNode(child, treeNodeId); if( match != null){ return match; } } return null; } public Set findNodes(Set treeNodeIds) { Set treeNodes = new HashSet(); findNodes(getRoot(), treeNodeIds, treeNodes); return treeNodes; } protected void findNodes(ITreeNode treeNode, Set treeNodeIds, Set treeNodes){ if(treeNodeIds.contains(treeNode.getId())){ treeNodes.add(treeNode); } Iterator children = treeNode.getChildren().iterator(); while(children.hasNext()){ findNodes((ITreeNode) children.next(), treeNodeIds, treeNodes); } } public boolean isExpanded(String treeNodeId){ return this.expanded.contains(treeNodeId); } // /** // * 展开节点treeNodeId,curLevel为当前层级 // */ // // public void expand(String treeNodeId,int curLevel) { // this.expanded.add(treeNodeId); // ITreeNode expandedNode = findNode(treeNodeId); // /** // * 如果需要实时刷新所有节点的信息,则调用notifyObservers方法通知所有的其他的节点 // * 及时刷新信息 // */ // System.out.println("expand treenodeID 2:" + treeNodeId); // if (needObservable) // { // notifyObservers(expandedNode); // } // if(this.expandListeners.size() > 0){ // // // /** // if(expandedNode == null) // { // System.out.println("expandedNode:null"); // expanded.remove(treeNodeId); // return; // } // */ // // Iterator iterator = this.expandListeners.iterator(); // while(iterator.hasNext()){ // ((IExpandListener) iterator.next()).nodeExpanded(expandedNode, this,curLevel,needObservable); // } // } // } /** * * Description: * @param expandedNode * @param curLevel * @see com.frameworkset.common.tag.tree.itf.ITree#expand(com.frameworkset.common.tag.tree.itf.ITreeNode, int) */ public void expand(ITreeNode expandedNode,int curLevel) { this.expanded.add(expandedNode.getId()); //当展开事件是由于手动即点击页面的展开图标触发时,广播该事件 if (needObservable && curLevel > level) { notifyObservers(expandedNode); } if(this.expandListeners.size() > 0){ Iterator iterator = this.expandListeners.iterator(); while(iterator.hasNext()){ ((IExpandListener) iterator.next()).nodeExpanded(expandedNode, this,curLevel,needObservable); } } } /** * 静态模式时使用 * Description: * @param expandedNode * @param curLevel * @see com.frameworkset.common.tag.tree.itf.ITree#expand(com.frameworkset.common.tag.tree.itf.ITreeNode, int) */ public void impactExpand(ITreeNode expandedNode,int curLevel) { // this.expanded.add(expandedNode.getId()); //当展开事件是由于手动即点击页面的展开图标触发时,广播该事件 if (needObservable && curLevel > level) { notifyObservers(expandedNode); } if(this.expandListeners.size() > 0){ Iterator iterator = this.expandListeners.iterator(); while(iterator.hasNext()){ ((IExpandListener) iterator.next()).impactExpandNode(expandedNode, this,curLevel,needObservable); } } } /** * 页面上点击展开图标时,调用本方法展开点击的节点 * Description: * @param treeNodeId * @see com.frameworkset.common.tag.tree.itf.ITree#expand(java.lang.String) */ public void expand(String treeNodeId, String mode, String scope, HttpServletRequest request) { //modified by biaoping.yin on 2005-02-05 // this.expanded.add(treeNodeId); // ITreeNode expandedNode = findNode(treeNodeId); // if (needObservable) // { // notifyObservers(expandedNode); // } // if(this.expandListeners.size() > 0){ // Iterator iterator = this.expandListeners.iterator(); // while(iterator.hasNext()){ // ((IExpandListener) iterator.next()).nodeExpanded(expandedNode, this,needObservable); // } // } // System.out.println("expand treenodeID 0:" + treeNodeId); // if(mode == null || mode.equals("")) // { // ITreeNode expandedNode = findNode(treeNodeId); // this.curExpanded = expandedNode; // expand(expandedNode,this.getUnknownLevel()); // } if(mode.equals(Tree.mode_static_dynamic)) { // linkUrl += "__nodename=" + name; // linkUrl += "__nodetype=" + nodetype; // linkUrl += "__nodepath=" + nodepath; String treeName = request.getParameter("__nodename"); String type = request.getParameter("__nodetype"); String path = request.getParameter("__nodepath"); String isfirstChild = request.getParameter("__nodefirst"); String islastChild = request.getParameter("__nodelast"); ITreeNode expandedNode = new TreeNode( treeNodeId, treeName, type, true, null, null, null, null, path, null); if(isfirstChild != null && !isfirstChild.equals("true")) { ITreeNode leftNode = new TreeNode(); expandedNode.setLeftNode(leftNode); } if(islastChild != null && !islastChild.equals("true")) { ITreeNode lastNode = new TreeNode(); expandedNode.setRightNode(lastNode); } // else // node = // new TreeNode( // treeid, // treeName, // type, // showHref, // this, // memo, // radioValue, // checkboxValue); /** * mark hasSon; */ expandedNode.setHasChildren(true); expandedNode.setTree(this); this.curExpanded = expandedNode; expand(expandedNode,this.getUnknownLevel()); } else { ITreeNode expandedNode = findNode(treeNodeId); this.curExpanded = expandedNode; expand(expandedNode,this.getUnknownLevel()); } } /** * * Description:点击节点的折叠图标时调用本方法 * @param treeNodeId * @see com.frameworkset.common.tag.tree.itf.ITree#collapse(java.lang.String) */ public void collapse(String treeNodeId) { this.expanded.remove(treeNodeId); // System.out.println("collapse treenodeID:" + treeNodeId); // System.out.println("treenodeID 4050 is expanded:" + this.isExpanded("4050")); // System.out.println("tree:" + this); ITreeNode collapsedNode = findNode(treeNodeId); if (needObservable) { notifyObservers(collapsedNode); } if(this.collapseListeners.size() > 0){ Iterator iterator = this.collapseListeners.iterator(); while(iterator.hasNext()){ ((ICollapseListener) iterator.next()).nodeCollapsed(collapsedNode, this,needObservable); } } //System.out.println("treenodeID 4050 is expanded:" + this.isExpanded("4050")); } // public void collapse(ITreeNode collapsedNode) { // this.expanded.remove(collapsedNode.getId()); // if (needObservable) // { // notifyObservers(collapsedNode); // } // if(this.collapseListeners.size() > 0){ // //ITreeNode collapsedNode = findNode(treeNodeId); // Iterator iterator = this.collapseListeners.iterator(); // while(iterator.hasNext()){ // ((ICollapseListener) iterator.next()).nodeCollapsed(collapsedNode, this,needObservable); // } // } // // } public Set getExpandedNodes() { return findNodes(this.expanded); } public void addExpandListener(IExpandListener expandListener) { this.expandListeners.add(expandListener); } public void removeExpandListener(IExpandListener expandListener) { this.expandListeners.remove(expandListener); } public void addCollapseListener(ICollapseListener collapseListener) { this.collapseListeners.add(collapseListener); } public void removeCollapseListener(ICollapseListener collapseListener) { this.collapseListeners.remove(collapseListener); } public boolean isSelected(String treeNodeId) { return this.selected.contains(treeNodeId); } public void select(String treeNodeId) { if(isSingleSelectionMode()){ unSelectAll(); } ITreeNode selectedNode = findNode(treeNodeId); this.selected.add(treeNodeId); if (needObservable) { notifyObservers(selectedNode); } if(this.selectListeners.size() > 0){ Iterator iterator = this.selectListeners.iterator(); while(iterator.hasNext()){ ((ISelectListener) iterator.next()).nodeSelected(selectedNode, this,needObservable); } } } public void unSelect(String treeNodeId) { this.selected.remove(treeNodeId); ITreeNode unselectedNode = findNode(treeNodeId); if (needObservable) { notifyObservers(unselectedNode); } if(this.unselectListeners.size() > 0){ Iterator iterator = this.unselectListeners.iterator(); while(iterator.hasNext()){ ((IUnselectListener) iterator.next()).nodeUnselected(unselectedNode, this,needObservable); } } } public void unSelect(ITreeNode unselectedNode) { this.selected.remove(unselectedNode.getId()); if (needObservable) { notifyObservers(unselectedNode); } if(this.unselectListeners.size() > 0){ //ITreeNode unselectedNode = findNode(treeNodeId); Iterator iterator = this.unselectListeners.iterator(); while(iterator.hasNext()){ ((IUnselectListener) iterator.next()).nodeUnselected(unselectedNode, this,needObservable); } } } public void unSelectAll() { Iterator iterator = this.selected.iterator(); while(iterator.hasNext()){ unSelect((String) iterator.next()); } } public Set getSelectedNodes() { return findNodes(this.selected); } public void setSingleSelectionMode(boolean mode) { this.singleSelectionMode = mode; } public boolean isSingleSelectionMode(){ return this.singleSelectionMode; } public void addSelectListener(ISelectListener selectListener) { this.selectListeners.add(selectListener); } public void removeSelectListener(ISelectListener selectListener) { this.selectListeners.remove(selectListener); } public void addUnselectListener(IUnselectListener unselectListener) { this.unselectListeners.add(unselectListener); } public void removeUnselectListener(IUnselectListener unselectListener) { this.unselectListeners.remove(unselectListener); } public TreeIterator iterator(boolean includeRootNode) { return new TreeIterator(this, includeRootNode); } public TreeIterator iterator(String parentIndent) { return new TreeIterator(this, parentIndent); } /** * added by yinbiaoping on 2004/03/23 * 重载方法java.util.Observable#notifyObservers(Object o) */ public void notifyObservers(Object o) { setChanged(); super.notifyObservers(o); } /** * Description: * @return * boolean */ public boolean isRefreshNode() { return refreshNode; } /** * Description: * @param b * void */ public void setRefreshNode(boolean b) { refreshNode = b; } /** * 不知道当前层级时,调用本方法获取当前层级 * 没有指定节点所处的当前层级,为了避免与其他已有层级发生冲突,指定当前层级比默认层级大1, * 这样setSon方法调用addNode方法不至于因为当前所处的层级 * 比默认展开层级小而展开其下级的情况出现 * Description: * @return * int */ protected int getUnknownLevel() { return level + 1; } public void setSortable(boolean b) { this.sortable = b; } public boolean isSortable() { return sortable; } /** * 获取当前展开的节点信息, * 主要在动静态方式生成树时当太地返回当前的树节点的html信息 */ public ITreeNode getCurExpanded() { // return curExpanded == null ? this.root : curExpanded; return curExpanded ; } public boolean isDynamic() { // if(this.newmode) return this.mode.equals("dynamic"); // return dynamic; } public boolean isStatic() { // if(this.newmode) return this.mode.equals("static"); // else // { // return false; // } } public boolean isStaticDynamic() { // if(this.newmode) return this.mode.equals("static-dynamic"); // else // { // return !this.dynamic; // } } public void setDynamic(boolean dynamic) { this.dynamic = dynamic; } // private boolean newmode = false; private String mode; private boolean partuprecursive = false; public void setMode(String mode) { this.mode = mode; // if(mode != null && !mode.trim().equals("")) // this.newmode = true; } public boolean isRecursive() { return recursive; } public void setRecursive(boolean recursive) { this.recursive = recursive; } public boolean isUprecursive() { return uprecursive; } public void setUprecursive(boolean uprecursive) { this.uprecursive = uprecursive; } public void setPartuprecursive(boolean partuprecursive) { this.partuprecursive = partuprecursive; } public boolean isPartuprecursive() { return partuprecursive; } }