package org.myrobotlab.memory; import java.util.HashMap; import java.util.Map; import org.myrobotlab.codec.CodecUtils; import org.myrobotlab.logging.LoggerFactory; import org.myrobotlab.logging.Logging; import org.slf4j.Logger; public class Memory { public final static Logger log = LoggerFactory.getLogger(Memory.class.getCanonicalName()); Node root = new Node("/"); // test for new Node("") & new Node(".") boolean autoBuildPaths = true; // private ArrayList<MemoryChangeListener> listeners = new // ArrayList<MemoryChangeListener>(); MemoryChangeListener listener = null; public void addMemoryChangeListener(MemoryChangeListener listener) { if (this.listener == null) { this.listener = listener; } else { log.error("too many listeners"); // bad form - shouldn't follow rxtx ;p } } // TODO - move these into Memory ??? public void crawlAndPublish() { crawlAndPublish("", root); } // TODO - move these into Memory ??? public void crawlAndPublish(String parentPath, Node currentNode) { log.info("{}.{}", parentPath, currentNode.getName()); // publish recursively HashMap<String, Object> objects = currentNode.getNodes(); for (Map.Entry<String, Object> o : objects.entrySet()) { Object value = o.getValue(); if (value.getClass() == Node.class) { Node node = (Node) value; String newPath = String.format("%s/%s", parentPath, node.getName()); if (listener != null) { // FIXME - don't publish root - design // problem ! listener.publish(parentPath, node); } crawlAndPublish(newPath, node); } } } public Object get(String path) { if (path == null || path == "") // TODO - test for .getNode(null) !!! { return root; } else { // return root.getNode(path); return root.get(path); } } public Node getNode(String path) { return (Node) get(path); } public Node getRoot() { return root; } // TODO - optimization put reference in of parents ??? public Object put(String parentPath, Node node) { // FIXME - A CLUE the root node name is null ! Object object = root.get(parentPath); /* * AUTOBUILD - WOULD BE NICE if (object == null && autoBuildPaths) { int * pos0 = 0; int pos1 = parentPath.indexOf("/"); while (pos1 != -1) { String * parentKey = parentPath.substring(pos0, pos1); pos0 = pos1; pos1 = * parentPath.indexOf("/", pos0 + 1); String childKey = * parentPath.substring(pos0 + 1, pos1); log.info("adding {} -> new node {}" * , parentKey, childKey); put(parentKey, new Node(childKey)); if (listener * != null) { listener.onPut(null, node); // <-- ? needs full path? } * * } * * } */ if (object == null) { log.error("could not add node {} to path {}", node.getName(), parentPath); return null; } Class<?> c = object.getClass(); Object ret = null; if (c == Node.class) { Node parent = (Node) object; ret = parent.getNodes().put(node.getName(), node); } else if (c == HashMap.class) { // it must be data right ? HashMap<String, Object> data = (HashMap<String, Object>) object; ret = data.put(node.getName(), node); } else { log.error("wtf ??? - something besides node or hashmap !!!"); } if (listener != null) { listener.onPut(parentPath, node); } return ret; } /* * public static void main(String[] args) { * LoggingFactory.getInstance().configure(); * LoggingFactory.getInstance().setLevel(Level.INFO); * * Memory memory = new Memory(); // name root ? // memory.put(null, new * Node("k1")); test case - delemiter in name // memory.put(new Node("k1")) * simplified root case memory.put("", new Node("k1")); memory.put("/k1", new * Node("k2")); memory.put("/k1/k2", new Node("k3")); Node node = * memory.getNode("/k1/k2/k3"); log.info("{}", node.getName()); * * memory.putNode("/k1/k2/k3", "k4"); log.info("{}", * memory.getNode("/k1/k2/k3/k4").getName()); // is this // object of // node? * // memory.get log.info("{}", node.getName()); * * memory.put("/k1/k2/k3", "k5", new Integer(5)); log.info("{}", * memory.get("/k1/k2/k3/k5")); * * memory.toXMLFile("m1.xml"); * * memory.putNode("/k1/k2/k3/k4", "v4"); // bad test cases * * memory.put(null, new Node(null)); memory.put(null, new Node("/")); * memory.put(null, new Node("/k1/k2")); memory.put("/k1/k2/", new * Node("k4")); memory.toXMLFile("m1.xml"); * * // memory.put("k1.k2.k3.k4", new Node("k5")); * * } */ public Object put(String path, String key, Object value) { Object o = root.get(path); Class<?> c = o.getClass(); if (c == Node.class) { Node node = (Node) o; return node.put(key, value); } else { log.error("path {} is not to a Node", path); return null; } } /** * put gets the last node in path - and adds a key to the node's data with a * node with Node named with the second parameter * * @param path * @param nodeName * @return */ public Object putNode(String path, String nodeName) { Object o = root.get(path); Class<?> c = o.getClass(); if (c == Node.class) { Node newNode = new Node(nodeName); Node node = (Node) o; return node.put(newNode); } else { log.error("path {} is not to a Node", path); return null; } } public String toJSON() { return CodecUtils.toJson(this); } public void toJSONFile(String string) { try { CodecUtils.toJsonFile(this, string); } catch (Exception e) { Logging.logError(e); } } }