📄 flatconfigdata.java
字号:
/* * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved * * 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 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 Lesser General Public License for more details * (http://www.gnu.org/copyleft/lesser.html). * * 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 */package jcckit.util;/** * An implementation of <tt>ConfigData</tt> based on a flat * representation of the hierachically organized key-value pairs. * Concrete subclasses must implement the methods * {@link #getValue} and {@link #createConfigData} in accordance * with the Template Method pattern and Factory Method pattern, * respectively. * <p> * In a flat representation of hierachically organized key-value * pairs all key-value pairs are stored in a single <tt>Hashtable</tt>. * Its key is the <em>full key</em> of the configuration data (i.e. the key * including its path). * <p> * Example (using the notation for a <tt>.properties</tt> file): * <pre> * title = example * symbolAttributes/className = jcckit.graphic.BasicDrawingAttributes * symbolAttributes/fillColor = 0xcaffee * symbolAttributes/lineColor = 0xff0000 * </pre> * The following table shows the result of some method calls at a * <tt>FlatConfigData</tt> instance prepared with * this example: * <p> * <center> * <table border=1 cellspacing=1 cellpadding=5> * <tr><th>Method call</th><th>Result</th></tr> * <tr><td>get("title")</td><td>example</td></tr> * <tr><td>getNode("symbolAttributes").get("fillColor") * </td><td>0xcaffee</td></tr> * </table> * </center> * <p> * In addition <tt>FlatConfigData</tt> implements <b>inheritance</b> * of key-value pairs. * Basically a node in the tree of key-value pairs * may extend another node in the tree. * The extended node inherit all key-value pairs from the extending * one including the key-value pairs of all descendants. * The value of a inherited key-value pair may be overridden. * Also new key-value pairs may be placed in the inherited node or * anywhere in the subtree. * Note, that the extending node has to be a node which is not a * descendant of the extended node (otherwise a circulary chain * of references occurs). As a consequence not more than 20 inheritance * levels are allowed. * <p> * The implementation of this kind of inheritance in a flat hashtable * is done by an additional key-value pair of the form * <pre> * <i>extending-node</i><b>/</b> = <i>extended-node</i><b>/</b> * </pre> * Example: * <pre> * A/a/priority = high * A/a/alpha/hello = universe * A/a/alpha/answer = 42 * <b>A/b/1/ = A/a/</b> * A/b/1/alpha/hello = world * A/b/1/alpha/question = 6 * 7 * </pre> * The following table shows the result of various method calls * applied at the node <tt>A/b/1/</tt> of a <tt>FlatConfigData</tt> * instance prepared with this example: * <p> * <center> * <table border=1 cellspacing=1 cellpadding=5> * <tr><th>Method call</th><th>Result</th><th>Comment</th></tr> * <tr><td>get("priority")</td><td>high</td><td>inherited</td></tr> * <tr><td>getNode("alpha").get("hello") * </td><td>world</td><td>overridden</td></tr> * <tr><td>getNode("alpha").get("question") * </td><td>6 * 7</td><td>added</td></tr> * <tr><td>getNode("alpha").get("answer") * </td><td>42</td><td>inherited</td></tr> * </table> * </center> * * @author Franz-Josef Elmer */public abstract class FlatConfigData implements ConfigData { private final String _path; /** Creates a new instance for the specified path. */ public FlatConfigData(String path) { _path = path; } /** * Returns the full key. * @param key A (relative) key. <tt>null</tt> is not allowed. * @return the path concatenated with <tt>key</tt> or <tt>key</tt> * if the path is undefined. */ public String getFullKey(String key) { return _path == null ? key : _path + key; } /** * Returns the value associated with this key. * @param key The relative key. <tt>null</tt> is not allowed. * @return the associated value. Will be <tt>null</tt> if no value exists * for <tt>key</tt>. */ public String get(String key) { return get(_path, key, 0); } /** * Obtains a value in accordance with hierarchy (<tt>path</tt>) and * inheritance (recursive calls of this routine). */ private String get(String path, String key, int numberOfLevels) { String result = null; if (numberOfLevels < 20) { String fullKey = path == null ? key : path + key; result = getValue(fullKey); if (result == null) { // posAfterDelim is the index in path just after '/' int posAfterDelim = path == null ? -1 : path.length(); String replacement; while (posAfterDelim > 0) { // look for a sub-tree replacement = getValue(path.substring(0, posAfterDelim)); if (replacement != null) { // sub-tree found, add last part of the original path result = get(replacement + path.substring(posAfterDelim), key, numberOfLevels + 1); // break whether result is null or not. break; } // remove last element from the path posAfterDelim = path.lastIndexOf('/', posAfterDelim - 2) + 1; } } } return result; } /** * Returns the <tt>ConfigData</tt> object associated with this key. * @param key The relative key. * @return the associated value. Will never return <tt>null</tt>. * Instead an empty <tt>ConfigData</tt> is returned. */ public ConfigData getNode(String key) { String path = (_path == null ? key : _path + key) + '/'; return createConfigData(path); } /** * Returns the value for the specified full key from the flat * representation of the hierarchically organized key-value pairs. * @param fullKey The full key including path. <tt>null</tt> is not allowed. * @return the value or <tt>null</tt> if not found. */ protected abstract String getValue(String fullKey); /** * Returns the <tt>FlatConfigData</tt> object for the specified full path. * In general <tt>path</tt> will be used in the constructor with * path argument. * @param path The full path. * @return a new instance in any case. */ protected abstract ConfigData createConfigData(String path);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -