📄 confignodeimpl.java
字号:
package de.spieleck.config;import java.io.PrintWriter;import java.io.IOException;import java.util.List;import java.util.LinkedList;import java.util.Iterator;import de.spieleck.util.EmptyIterator;/** * Basic Data container in a Config environment. * <P> * Not that most enhanced classes will be subnodes of this or * otherwise have to do a reimplementation of many methods * @author fsn * @version ? */public class ConfigNodeImpl implements ConfigNode{ /** Separator for path strings used in the Config-System */ public final static char PATHSEP = '/'; /** Remember your parent(s), boy */ protected ConfigNode parent; /** And cound your children! */ protected List children; /** Node name */ protected String name; /** Node value */ protected String value; /** A Parameter-Mapping class */ protected ConfigParamMap pm; /** Source line for this node */ protected int sourceLine = -1; /** * Create a ConfigNodeImplementation. * @param name Name of the node * @param value Value of the node * @param pm Parameter map used to expand parameter values. */ public ConfigNodeImpl(String name, String value, ConfigParamMap pm) { this.name = name == null ? null : name.intern(); // Names are supposed to repeat more than values, // therefore we intern only names. setValue(value); this.pm = pm; } /** * Create a ConfigNodeImplementation. * @param name Name of the node * @param value Value of the node * @param pm Parameter map used to expand parameter values. * @param line The source line where the node was generated */ public ConfigNodeImpl(String name, String value, ConfigParamMap pm, int line) { this(name, value, pm); sourceLine = line; } /** * @return the SourceLine */ public int getSourceLine() { return sourceLine; } /** * @return the name of the XML source where this node comes from. */ public String getSourceFileName() { ConfigFileNode srn = getBranchNode(); if (srn == null) return null; else return srn.getSourceFileName(); } /** * */ public String getSourceDescription() { return getSourceFileName()+":"+getSourceLine(); } /** * Getting the node responsible for reading the file. * This API is used so rarely that we do not keep a member to hold * that node any more. We search the node every time we need it. * @return the node responsible for reading the file. */ public ConfigFileNode getBranchNode() { ConfigFileNode branchNode = null; while (branchNode == null) { ConfigNode n = getParent(); if (n != null) branchNode = n.getBranchNode(); } return branchNode; } /** * @return the (interned) name of this node */ public String getName() { return name; } /** * @return the full path of this path with in the root config. */ public String getPath() { if (getParent() == null) return ""; // getName(); else return getParent().getPath() + PATHSEP + getName(); } /** * @return the unexpanded value of the node. */ public String getUnexpanded() { return value; } /** * @param v the new Value of this node. */ /* package */ void setValue(String v) { value = v; } protected String getValue() { return pm.expand(value); } // XXX: The interface only need ConfigNode, but we need ConfigNodeImpl // somewhere else, this is a modelation problem! public ConfigNode getParent() { return parent; } protected void setParent(ConfigNode p) { parent = p; } /** * * */ public boolean getBoolean() { return ConvertHelp.getBoolean(getValue()); } public boolean getBoolean(String path, boolean deflt) { return ConvertHelp.getBoolean(node(path), deflt); } public boolean getInhBoolean(String path, boolean deflt) { return ConvertHelp.getBoolean(nodeInh(path), deflt); } public int getInt() { return ConvertHelp.getInt(getValue()); } public int getInt(String path, int deflt) { return ConvertHelp.getInt(node(path), deflt); } public int getInhInt(String path, int deflt) { return ConvertHelp.getInt(nodeInh(path), deflt); } public double getDouble() { return ConvertHelp.getDouble(getValue()); } public double getDouble(String path, double deflt) { return ConvertHelp.getDouble(node(path), deflt); } public double getInhDouble(String path, double deflt) { return ConvertHelp.getDouble(nodeInh(path), deflt); } public String getString() { return getValue(); } public String getString(String path, String deflt) { return ConvertHelp.getString(node(path), deflt); } public String getInhString(String path, String deflt) { return ConvertHelp.getString(nodeInh(path), deflt); } /** * Find the very first child, grandchild, ... that matches a path! * Node this is fairly involved and not at all fast! But appropriate * for setup files in general. */ public ConfigNode node(String path) { if (path == null) return this; return node(path, 0, path.length()); } private ConfigNodeImpl node(String path, int begindex, int endIndex) { // Internal API, path != null here! int head = begindex; while (head < endIndex && path.charAt(head) == PATHSEP) head++; if (head == endIndex) return this; if (children == null) // children.size() == 0 impossible! return null; int tail = head + 1; while (tail < endIndex && path.charAt(tail) != PATHSEP) tail++; String match = path.substring(head, tail); for(Iterator it = childrenNamed(match); it.hasNext(); ) { ConfigNodeImpl child = (ConfigNodeImpl)it.next(); ConfigNodeImpl node = child.node(path, tail, endIndex); if (node != null) return node; } return null; } /** * Find the very first child of this node or a parent * fullfilling the path. */ public ConfigNode nodeInh(String path) { ConfigNode snr = node(path); if (snr != null) return snr; ConfigNode current = this; while (snr == null && (current = current.getParent()) != null) snr = current.node(path); return snr; } /** * @return the number children of this node. */ public int countChildren() { return children == null ? 0 : children.size(); } /** * @return an Iterator over all children of this node. */ public Iterator children() { if ( children == null ) return EmptyIterator.getInstance(); return new ConfigIterator(null); } public Iterator childrenNamed(String key) { if ( children == null ) return EmptyIterator.getInstance(); return new ConfigIterator(key); } public int countChildrenNamed(String key) { if ( children == null ) return 0; Iterator it = childrenNamed(key); int count = 0; while ( it.hasNext() ) count++; return count; } public void copyChildren(ConfigNode next) { Iterator e = next.children(); while (e.hasNext()) { ConfigNodeImpl n = (ConfigNodeImpl)e.next(); addChild(n); } } /** * create a new child add it to this node and * @return the new node. */ public ConfigNodeImpl addChild(String name, String value, int line) { ConfigNodeImpl child = new ConfigNodeImpl(name, value, pm, line); return addChild(child); } /** * create a new child add it to this node and * @return the new node. */ public ConfigNodeImpl addChild(String name, String value) { ConfigNodeImpl child = new ConfigNodeImpl(name, value, pm); return addChild(child); } /** * add a child to this node and * @return the new node. */ public ConfigNodeImpl addChild(ConfigNodeImpl child) { if (children == null) children = new LinkedList(); children.add(child); child.setParent(this); return child; } /** * Print a XML represenation of this node. * Caution: Encoding is not properly used, as is quoting of attributes. */ public void printXML(PrintWriter os) throws IOException { print(os, 0); } private void print(PrintWriter os, int depth) throws IOException { indent(os, depth, "<" + getName()); if (getValue() != null) os.print(" "+ConfigBuilder.THISATTR+"=\"" + getValue() + "\""); boolean hasDeepChildren = false; for ( Iterator it = children(); it.hasNext(); ) { ConfigNodeImpl child = (ConfigNodeImpl)it.next(); if (!hasDeepChildren && child.countChildren() == 0 ) os.print(" " + child.getName() + "=\"" + child.getValue() + "\""); else { if (!hasDeepChildren) os.println(">"); hasDeepChildren = true; child.print(os, depth + 2); } } if (!hasDeepChildren) os.println("/>"); else { indent(os, depth, "</" + getName() + ">"); os.println(); } } private static void indent(PrintWriter os, int depth, String msg) throws IOException { for (int i = 0; i < depth; i++) os.print(' '); os.print(msg); } public String toString() { return "["+super.toString()+"(" + getPath() + ", " + getValue() + "), (" + getSourceFileName() + ")" + ", " + countChildren() + "]"; } /** * */ protected class ConfigIterator implements Iterator { private Iterator it; private String key = null; private ConfigNodeImpl ci; public ConfigIterator(String key) { if ( key != null ) this.key = key; if ( children == null ) it = EmptyIterator.getInstance(); else it = children.iterator(); skip(); } private void skip() { ci = null; while ( ci == null && it.hasNext() ) { ci = (ConfigNodeImpl) it.next(); if ( key != null && key != ci.getName() && !key.equals(ci.getName()) ) ci = null; } } public boolean hasNext() { return ci != null; } public Object next() { ConfigNodeImpl c2 = ci; skip(); return c2; } public void remove() throws UnsupportedOperationException { throw new UnsupportedOperationException("Config is immutable."); } }}//// Jacson - Text Filtering with Java.// Copyright (C) 2002 Frank S. Nestel (nestefan -at- users.sourceforge.net)//// This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.//// This library 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// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -