package com.neverwinterdp.registry; import java.io.IOException; import java.util.Collections; import java.util.List; import com.neverwinterdp.registry.election.LeaderElection; import com.neverwinterdp.registry.event.NodeWatcher; import com.neverwinterdp.registry.lock.Lock; import com.neverwinterdp.util.JSONSerializer; public class Node { private Registry registry ; private String path ; public Node(Registry registry, String path) { this.registry = registry ; this.path = path ; } public Registry getRegistry() { return this.registry ; } public String getPath() { return path; } public String getName() { int idx = path.lastIndexOf('/') ; return path.substring(idx + 1) ; } public String getParentPath() { if(path.length() == 1 && path.equals("/")) return null ; int idx = path.lastIndexOf('/') ; return path.substring(0, idx) ; } public Node getParentNode() { return new Node(registry, getParentPath()); } public boolean exists() throws RegistryException { return registry.exists(path) ; } public void create(NodeCreateMode mode) throws RegistryException { registry.create(path, mode); } public void create(byte[] data, NodeCreateMode mode) throws RegistryException { registry.create(path, data, mode); } public <T> void create(T data, NodeCreateMode mode) throws RegistryException { registry.create(path, data, mode); } public byte[] getData() throws RegistryException { return registry.getData(path); } public <T> T getDataAs(Class<T> type) throws RegistryException { return registry.getDataAs(path, type); } public <T> T getDataAs(Class<T> type, DataMapperCallback<T> callback) throws RegistryException { return registry.getDataAs(path, type, callback); } public void setData(byte[] data) throws RegistryException { registry.setData(path, data); } public <T> void setData(T data) throws RegistryException { registry.setData(path, data); } public void delete() throws RegistryException { registry.delete(path); } public void rdelete() throws RegistryException { registry.rdelete(path); } public void rdelete(Transaction transaction) throws RegistryException { transaction.rdelete(path); } public Lock getLock(String name) { return new Lock(registry, path, name) ; } public LeaderElection getLeaderElection() { return new LeaderElection(registry, path) ; } public void watch(NodeWatcher watcher) throws RegistryException { registry.watchExists(path, watcher); } public void watchChildren(NodeWatcher watcher) throws RegistryException { registry.watchChildren(path, watcher); } public void unwatch() throws RegistryException { throw new RegistryException(ErrorCode.Unknown, "Zookeeper does not support this method"); } public boolean hasChild(String name) throws RegistryException { return registry.exists(path + "/" + name) ; } public Node getChild(String name) throws RegistryException { return new Node(registry, path + "/" + name) ; } public Node getDescendant(String descendant) throws RegistryException { return new Node(registry, path + "/" + descendant) ; } public List<String> getChildren() throws RegistryException { return registry.getChildren(path) ; } public List<String> getChildrenPath() throws RegistryException { return registry.getChildrenPath(path); } public <T> List<T> getChildrenAs(Class<T> type) throws RegistryException { return registry.getChildrenAs(path, type) ; } public <T> List<T> getChildrenAs(Class<T> type, DataMapperCallback<T> callback) throws RegistryException { return registry.getChildrenAs(path, type, callback) ; } public Node createChild(String name, NodeCreateMode mode) throws RegistryException { return registry.create(path + "/" + name, mode); } @Deprecated public Node createChild(Transaction transaction, String name, NodeCreateMode mode) { return createChild(transaction, name, new byte[0], mode); } public <T> Node createChild(Transaction transaction, String name, T data, NodeCreateMode mode) { return createChild(transaction, name, JSONSerializer.INSTANCE.toBytes(data), mode); } public Node createChild(Transaction transaction, String name, byte[] data, NodeCreateMode mode) { String childPath = path + "/" + name; transaction.create(childPath, data, mode); return new Node(registry, childPath); } public Node createChild(String name, byte[] data, NodeCreateMode mode) throws RegistryException { return registry.create(path + "/" + name, data, mode); } public <T> Node createChild(String name, T data, NodeCreateMode mode) throws RegistryException { return registry.create(path + "/" + name, data, mode); } public void createChildRef(String name, String toPath, NodeCreateMode mode) throws RegistryException { registry.createRef(path + "/" + name, toPath, mode); } public Node createDescendantIfNotExists(String descendant) throws RegistryException { registry.createIfNotExist(path + "/" + descendant) ; return new Node(registry, path + "/" + descendant); } public void dump(Appendable out) throws RegistryException, IOException { List<String> childNodes = registry.getChildren(path); Collections.sort(childNodes); for(String node : childNodes) { dump(out, path, node, registry, ""); } } private void dump(Appendable out, String parent, String node, Registry registry, String indentation) throws IOException, RegistryException { //During the recursive traverse, a node can be added or removed by the other process //So we can ignore all the No node exists exception String path = parent + "/" + node; if("/".equals(parent)) path = "/" + node; byte[] data = {}; try { data = registry.getData(path); } catch(RegistryException ex) { } String stringData = ""; if(data != null && data.length > 0) { stringData = " - " + new String(data); stringData = stringData.replace("\r\n", " "); stringData = stringData.replace("\n", " "); if(stringData.length() > 80) { stringData = stringData.substring(0, 80); } } out.append(indentation + node + stringData).append('\n'); List<String > children = null ; try { children = registry.getChildren(path); } catch(RegistryException ex) { } if(children != null) { Collections.sort(children); for(String child : children) { dump(out, path, child, registry, indentation + " "); } } } }