/** * Copyright 2006 by Know-Center, Graz, Austria * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a * joint initiative of the Federal Chancellery Austria and Graz University of * Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. * * $Id: PropertyTree.java,v 1.4 2006/10/31 08:06:28 wprinz Exp $ */ package at.knowcenter.wag.egov.egiz.cfg; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Vector; /** * This class can be used to store a property config tree. The property key are separated by the * {@link at.knowcenter.wag.egov.egiz.cfg.PropertyTree#SPLIT_STRING}. Therefore the keys an also * the values of a configuration is stored in nested hashes. The keys in an area are stored in a * HashMap. The values of a key are stored in a Vector to overload some keys. The property tree can * be used to extract sub nodes and sub keys of different tree levels. * * @author wlackner * @see java.util.HashMap * @see java.util.Vector */ public class PropertyTree implements Serializable { /** * SVUID. */ private static final long serialVersionUID = -1686170519955886222L; /** * The key split string. A key can be a complex key. Sub keys are separated from each other with * the split string. This string is used to devide the complex key. */ public static final String SPLIT_STRING = "\\."; /** * Stores the key references to the sub nodes */ private Map keys_ = new HashMap(3); /** * Stores all values of a node */ private Vector values_ = new Vector(3); /** * The default constructor od the class. */ public PropertyTree() { } /** * This method takes a key value tupel and store them in the property tree. The key splitted into * different levels (splitted by the string * {@link at.knowcenter.wag.egov.egiz.cfg.PropertyTree#SPLIT_STRING}). All subnodes not stored in * the tree will be created. The last part of the key (last splitted element) adds the value to * there own value data structure (Vector).
* Example: setKeyValue("key.1_level.2_level","the value for k_1_2")null if the key is not a subtree referece */ private PropertyTree getLastSubTree(String splitKey) { String[] keys = splitKey.split(SPLIT_STRING); PropertyTree curr_tree = this; for (int key_idx = 0; key_idx < keys.length; key_idx++) { String key = keys[key_idx]; if (!curr_tree.containsNode(key)) { return null; } curr_tree = (PropertyTree) curr_tree.getSubNode(key); } return curr_tree; } /** * This method return the subtree that corresponds to a particular key. The key does not split. * Therefore the key must be a children of the current node. Search only in the key map of the * current node. * * @param key the key that has to be a sub node * @return a sub tree (PropertyTree) or null if the key is not a children of the * current node */ private PropertyTree getSubNode(String key) { return (PropertyTree) keys_.get(key); } /** * Returns the last value (keys can be overloaded) of a key. The key are splitted into subnodes * and the last node of the key is the current value holder. If a key or subnode is not in the sub * tree the return value is null. * * @param key the key that holds the value (can be a nested key like "key.1.2.3") * @return the value of the key (last node of the key) or null otherwise */ public String getLastValue(String key) { PropertyTree curr_tree = getLastSubTree(key); String result = null; if (curr_tree != null && !curr_tree.values_.isEmpty()) { result = (String) curr_tree.values_.lastElement(); } // if (logger_.isDebugEnabled()) { // logger_.debug("getLastValue:" + key + "=" + result); // } return result; } /** * Returns the first value (keys can be overloaded) of a key. The key are splitted into subnodes * and the last node of the key is the current value holder. If a key or subnode is not in the sub * tree the return value is null. * * @param key the key that holds the value (can be a nested key like "key.1.2.3") * @return the value of the key (last node of the key) or null otherwise */ public String getFirstValue(String key) { PropertyTree curr_tree = getLastSubTree(key); String result = null; if (curr_tree != null && !curr_tree.values_.isEmpty()) { result = (String) curr_tree.values_.firstElement(); } // if (logger_.isDebugEnabled()) { // logger_.debug("getFirstValue:" + key + "=" + result); // } return result; } /** * This method return all values of the current node. The values are stored as String values. * * @return the values (type String) of the current node * @see Vector */ public Vector getValues() { return values_; } /** * This method return all keys (sub tree references) of the current node as a Map. The keys are * stored as String values. * * @return the keys (type String) of the current node * @see Map */ public Map getKeyEntries() { return keys_; } /** * This method return all keys (sub tree references) of the current node as an ArrayList. The keys * are stored as String values. * * @return the keys (type String) of the current node * @see ArrayList */ public ArrayList getKeys() { if (!keys_.isEmpty()) { Object[] objs = keys_.keySet().toArray(); ArrayList keys = new ArrayList(objs.length); for (int idx = 0; idx < objs.length; idx++) { keys.add((String) objs[idx]); } return keys; } return null; } /** * * This method return all sub tree references of a key as an ArrayList. The keys are stored as * String values. * * @param key (can be a nested key like "key.1.2.3") * @return the keys (type String) of the current node * @see ArrayList */ public ArrayList getKeys(String key) { PropertyTree curr_tree = getLastSubTree(key); if (curr_tree != null) { return curr_tree.getKeys(); } return null; } /** * This method return all values of a key. The values are stored as String values. * * @param key (can be a nested key like "key.1.2.3") * @return the values (type Vector) of the key or null if the key is not in the sub * tree of the current node * @see Vector */ public Vector getValues(String key) { PropertyTree curr_tree = getLastSubTree(key); if (curr_tree != null) { return curr_tree.values_; } return null; } /** * Store a sub tree (type PropertyTree) in the current node. The key and it's sub tree are stored * in a HashMap. * * @param key the reference of the sub tree * @param tree the sub tree of the key * @see HashMap */ private void setSubTree(String key, PropertyTree tree) { if (tree == null) { tree = new PropertyTree(); } keys_.put(key, tree); } /** * Extracts a sub tree of a nested key. The Method returns the last sub tree of the nested key. * Example: if the key is like: key.1.2.3 the sub tree of the last * node 3 is returned. * * @param key the reference of the sub tree * @return a sub tree of the key or null if the key can not be found */ public PropertyTree getSubTree(String key) { return getLastSubTree(key); } /** * This method checks if a key is a reference to a sub tree in the current node. * * @param key a simple key that is a parent reference of a sub tree * @return true if the key is found, false otherwise */ public boolean containsNode(String key) { return keys_.containsKey(key); } /** * The default toString method. It starts with the current node recursively downwards and return * the String representation of the node. * * @return the string representation of the node */ public String toString() { return toString("", this); } /** * This is a helper function to define the prefix for different levels in the toString method, not * realy nice ;-). * It replaces all "." chars with " ". * * @param key * @return a replaces prefix string */ private static String getEmptyString(String key) { return key.replaceAll(".", " "); } /** * This method concatenates all values of the current node and return them as a combinded string. * * @param prefix * @param tree * @return the string representation of the node values */ private static String printValues(String prefix, PropertyTree tree) { String os = ""; Iterator values = tree.getValues().iterator(); while (values.hasNext()) { String value = (String) values.next(); os += prefix + "=" + value; } return os; } /** * The toString method. It starts with a special level prefix, sub tree and recursively adds all * sub trees. * * @param prefix the prefix for this node * @param tree the current node * @return the string representation of the node */ public static String toString(String prefix, PropertyTree tree) { String os = ""; Iterator entries = tree.getKeyEntries().entrySet().iterator(); while (entries.hasNext()) { Map.Entry entry = (Map.Entry) entries.next(); String key = (String) entry.getKey(); PropertyTree sub = (PropertyTree) entry.getValue(); String os_key = "\n" + prefix + "." + key; os += printValues(os_key, sub); String subs = toString(prefix + getEmptyString(key) + " |", sub); if (subs.length() > 0) { os += os_key + "|" + subs; } } return os; } public void removeEntry(String key) { this.keys_.remove(key); } }