📄 hierarchypropertyparser.java
字号:
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* HierarchyPropertyParser.java
* Copyright (C) 2001 Xin Xu
*
*/
package weka.gui;
import java.io.Serializable;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* This class implements a parser to read properties that have
* a hierarchy(i.e. tree) structure. Conceptually it's similar to
* the XML DOM/SAX parser but of course is much simpler and
* uses dot as the seperator of levels instead of back-slash.<br>
* It provides interfaces to both build a parser tree and traverse
* the tree. <br>
* Note that this implementation does not lock the tree when different
* threads are traversing it simultaneously, i.e. it's NOT synchronized
* and multi-thread safe. It is recommended that later implementation
* extending this class provide a locking scheme and override the
* functions with the "synchronized" modifier (most of them are
* goToXXX() and information accessing functions).<p>
*
* @author Xin Xu (xx5@cs.waikato.ac.nz)
* @version $Revision$
*/
public class HierarchyPropertyParser implements Serializable{
/** Keep track of the root of the tree */
private TreeNode m_Root;
/** Keep track of the current node when traversing the tree */
private TreeNode m_Current;
/** The level separate in the path */
private String m_Seperator = ".";
/** The depth of the tree */
private int m_Depth = 0;
/**
* The inner class implementing a single tree node.
* All fields are made public simply for convenient access,
* Although a severe violation of OO Design principle.
*/
private class TreeNode{
/** The parent of this node */
public TreeNode parent = null;
/** The value of this node. Always String */
public String value = null;
/** The children of this node */
public Vector children = null;
/** The level of this node */
public int level = 0;
/** The context of this node */
public String context = null;
}
/** Default constructor */
public HierarchyPropertyParser(){
m_Root = new TreeNode();
m_Root.parent = null;
m_Root.children = new Vector();
goToRoot();
}
/**
* Constructor that builds a tree from the given property with
* the given delimitor
*
* @param p the given property string
* @param delim the given dilimitor
*/
public HierarchyPropertyParser(String p, String delim) throws Exception {
this();
build(p, delim);
}
/**
* Set the seperator between levels. Default is dot.
*
* @param s the seperator symbol
*/
public void setSeperator(String s){
m_Seperator = s;
}
/**
* Get the seperator between levels. Default is dot.
*
* @return the seperator symbol
*/
public String getSeperator(){ return m_Seperator; }
/**
* Build a tree from the given property with the given delimitor
*
* @param p the given property
* @param delim the given delimitor
*/
public void build(String p, String delim) throws Exception {
StringTokenizer st = new StringTokenizer(p, delim);
//System.err.println("delim: "+delim);
while(st.hasMoreTokens()){
String property = st.nextToken().trim();
if(!isHierachic(property))
throw new Exception("The given property is not in"+
"hierachy structure with seperators!");
add(property);
}
goToRoot();
}
/**
* Add the given item of property to the tree
*
* @param property the given item
*/
public synchronized void add(String property){
String[] values = tokenize(property);
if(m_Root.value == null)
m_Root.value = values[0];
buildBranch(m_Root, values, 1);
}
/**
* Private function to build one branch of the tree
* based on one property
*
* @param parent the parent of the node to be built
* @param values the value of one property
* @param lvl the level of the node to be built in the tree
*/
private void buildBranch(TreeNode parent, String[] values, int lvl){
// Precondition: children is not null
if(lvl == values.length){ // Parent is leaf
parent.children = null;
return;
}
if(lvl > (m_Depth-1))
m_Depth = lvl+1; // Depth starts from 1
Vector kids = parent.children;
int index = search(kids, values[lvl]);
if(index != -1){
TreeNode newParent = (TreeNode)kids.elementAt(index);
if(newParent.children == null)
newParent.children = new Vector();
buildBranch(newParent, values, lvl+1);
}
else{
TreeNode added = new TreeNode();
added.parent = parent;
added.value = values[lvl];
added.children = new Vector();
added.level = lvl;
if(parent != m_Root)
added.context = parent.context + m_Seperator + parent.value;
else
added.context = parent.value;
kids.addElement(added);
buildBranch(added, values, lvl+1);
}
}
/**
* Tokenize the given string based on the seperator and
* put the tokens into an array of strings
*
* @param rawString the given string
* @return an array of strings
*/
public String[] tokenize(String rawString){
Vector result = new Vector();
StringTokenizer tk = new StringTokenizer(rawString, m_Seperator);
while(tk.hasMoreTokens())
result.addElement(tk.nextToken());
String[] newStrings = new String[result.size()];
for(int i=0; i < result.size(); i++)
newStrings[i] = (String)result.elementAt(i);
return newStrings;
}
/**
* Whether the HierarchyPropertyParser contains the given
* string
*
* @param string the given string
* @return whether contains
*/
public boolean contains(String string){
String[] item = tokenize(string);
if(!item[0].equals(m_Root.value))
return false;
return isContained(m_Root, item, 1);
}
/**
* Private function to decide whether one level of one branch
* contains the relevant values
*
* @param parent the parent of the node to be searched
* @param values the value of one property
* @param lvl the level of the node in question
* @return whether this branch contains the corresponding values
*/
private boolean isContained(TreeNode parent, String[] values, int lvl){
if(lvl == values.length) // Parent is leaf
return true;
else if(lvl > values.length)
return false;
else{
Vector kids = parent.children;
int index = search(kids, values[lvl]);
if(index != -1){
TreeNode newParent = (TreeNode)kids.elementAt(index);
return isContained(newParent, values, lvl+1);
}
else
return false;
}
}
/**
* Whether the given string has a hierachy structure with
* the seperators
*
* @param string the given string
*/
public boolean isHierachic(String string){
int index = string.indexOf(m_Seperator);
// Seperator not occur or first occurance at the end
if((index == (string.length()-1)) || (index == -1))
return false;
return true;
}
/**
* Helper function to search for the given target string in a
* given vector in which the elements' value may hopefully is equal
* to the target. If such elements are found the first index
* is returned, otherwise -1
*
* @param vct the given vector
* @param target the given target string
* @return the index of the found element, -1 if not found
*/
public int search(Vector vct, String target){
if(vct == null)
return -1;
for(int i=0; i < vct.size(); i++)
if(target.equals(((TreeNode)vct.elementAt(i)).value))
return i;
return -1;
}
/**
* Go to a certain node of the tree according to the specified path
* Note that the path must be absolute path from the root. <br>
* For relative path, see goDown(String path).
*
* @param path the given absolute path
* @return whether the path exists, if false the current position does
* not move
*/
public synchronized boolean goTo(String path){
if(!isHierachic(path)){
if(m_Root.value.equals(path)){
goToRoot();
return true;
}
else
return false;
}
TreeNode old = m_Current;
m_Current = new TreeNode();
goToRoot();
String[] nodes = tokenize(path);
if(!m_Current.value.equals(nodes[0]))
return false;
for(int i=1; i < nodes.length; i++){
int pos = search(m_Current.children, nodes[i]);
if(pos == -1){
m_Current = old;
return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -