package org.myrobotlab.framework; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Vector; import org.myrobotlab.logging.LoggerFactory; import org.slf4j.Logger; public class IndexNode<T> { public final static Logger log = LoggerFactory.getLogger(IndexNode.class); private HashMap<String, IndexNode<T>> branches = new HashMap<String, IndexNode<T>>(); private T value; public IndexNode() { } public IndexNode(T value) { // leaf value this.value = value; } public void buildTree(IndexNode<T> node, String key, T value) { // if there is a "." - then we are a branch - not a leaf if (key.indexOf(".") > 0) { // if (key.length() > 0) { // build branches of tree String branch = key.substring(0, key.indexOf(".")); String theRest = key.substring(key.indexOf(".") + 1); log.info(String.format("adding branch %s", branch)); if (!node.branches.containsKey(branch)) { // log.debug(String.format("adding branch %s", branch)); IndexNode<T> twig = new IndexNode<T>(); node.branches.put(branch, twig); } buildTree(node.getNode(branch), theRest, value); } else { // add a leaf log.debug(String.format("adding leaf %s=%s", key, value)); node.branches.put(key, new IndexNode<T>(value)); } } public void clear() { branches.clear(); } public boolean containsKey(String key) { IndexNode<T> node = getNode(key); return node != null; } // http://stackoverflow.com/questions/2319538/most-concise-way-to-convert-a-setstring-to-a-liststring // FIXME not the most effecient - should simply return the Set<Entry<String, // IndexNode<ServiceReservation>>> from each branches !!! // good thing you put the key in the data node :P (lame) // limitCount = 0 means no limit public ArrayList<T> crawlForData(ArrayList<T> data, int limitCount, String key) { if (value != null) { // found some data add it data.add(value); } if (key != null && key.contains(".")) { String subkey = key.substring(0, 1); String climb = key.substring(1); IndexNode<T> t = branches.get(subkey); if (t == null) { return data; // nothing here - return what was passed in } else { t.crawlForData(data, limitCount, climb); // climb some more } } else { // no key at this point - just get data if (limitCount < 1 || data.size() < limitCount) { // still under our data limit // look for more data - by crawling up children for (String k : branches.keySet()) { // return crawlForData(data, limitCount, // String.format("%s%s",key,k)); // FIXME - data structure change will do concurrent mod erro IndexNode<T> n = branches.get(k); n.crawlForData(data, limitCount, ""); } } } return data; } public HashMap<String, IndexNode<T>> getBranches() { return branches; } public IndexNode<T> getNode(String key) { if (key == null) { return this; } IndexNode<T> target = null; if (key.contains(".")) { String subkey = key.substring(0, key.indexOf(".")); String climb = key.substring(key.indexOf(".") + 1); IndexNode<T> t = branches.get(subkey); if (t == null) { return null; } else { return t.getNode(climb); } } else { target = branches.get(key); } return target; } public T getValue() { return value; } public T getValue(T defaultValue) { return (value == null) ? defaultValue : value; } public Enumeration<String> propertyNames() { Vector<String> n = new Vector<String>(branches.keySet()); return n.elements(); } public Enumeration<String> propertySortedNames() { List<String> n = new Vector<String>(branches.keySet()); Collections.sort(n); return ((Vector<String>) n).elements(); } public IndexNode<T> putNode(String key, T value) { if (key == null) { setValue(value); return this; } if (key.contains(".")) { // if (key.length() > 1) { // find the last node we from which // we need to start building branches // String subkey = key.substring(0, 1); // String climb = key.substring(1); String subkey = key.substring(0, key.indexOf(".")); String climb = key.substring(key.indexOf(".") + 1); IndexNode<T> t = branches.get(subkey); if (t == null) { // no branch - we need to build it IndexNode<T> twig = new IndexNode<T>(); branches.put(subkey, twig); return twig.putNode(climb, value); } else { return t.putNode(climb, value); } } else { IndexNode<T> targetNode = branches.get(key); if (targetNode == null) { return branches.put(key, new IndexNode<T>(value)); } else { targetNode.setValue(value); return targetNode; } } // return destination; } public void setValue(T value) { this.value = value; } public int size() { return branches.size(); } @Override public String toString() { return toString(null); } public String toString(String contextPath) { StringBuffer sb = new StringBuffer(); if (contextPath != null && getValue() != null) { sb.append(contextPath); sb.append("="); sb.append(getValue()); sb.append("\n"); } for (String key : branches.keySet()) { if (contextPath != null) { sb.append(branches.get(key).toString(contextPath + "." + key)); } else { sb.append(branches.get(key).toString(key)); } } return sb.toString(); } }