package edu.uw.zookeeper.data; import java.util.Map; import javax.annotation.Nonnull; /** * NameTrie in which every edge is a ZNodeLabel or RelativeZNodePath. * * Not threadsafe. */ public class SimpleNameTrie<E extends AbstractNameTrie.SimpleNode<E>> extends AbstractNameTrie<E> { public static <E extends AbstractNameTrie.SimpleNode<E>> SimpleNameTrie<E> forRoot(E root) { return new SimpleNameTrie<E>(root); } protected SimpleNameTrie(E root) { super(root); } @Override public @Nonnull E longestPrefix(ZNodePath path) { E node = root(); ZNodeName remaining = path.suffix(node.path()); while (!(remaining instanceof EmptyZNodeLabel)) { E next = node.get(remaining); if (next != null) { remaining = EmptyZNodeLabel.getInstance(); } else if (remaining instanceof RelativeZNodePath) { RelativeZNodePath relative = (RelativeZNodePath) remaining; for (Map.Entry<ZNodeName, E> child: node.entrySet()) { if (relative.startsWith(child.getKey())) { next = child.getValue(); remaining = relative.suffix(child.getKey().length()); break; } } } if (next != null) { node = next; } else { break; } } return node; } @Override public E get(Object k) { ZNodePath path = toPath(k); E node = longestPrefix(path); if (node.path().length() == path.length()) { return node; } else { return null; } } @Override public E put(ZNodePath k, E v) { if (k.isRoot()) { throw new IllegalArgumentException(String.valueOf(k)); } E parent = longestPrefix(k); if (parent.path().length() == k.length()) { parent = parent.parent().get(); } return parent.put(k.suffix(parent.path()), v); } @Override public E remove(Object k) { ZNodePath path = toPath(k); if (path.isRoot()) { throw new IllegalArgumentException(String.valueOf(k)); } E node = get(path); if ((node != null) && node.remove()) { return node; } return null; } }