package com.neverwinterdp.registry.event;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.neverwinterdp.registry.ErrorCode;
import com.neverwinterdp.registry.Registry;
import com.neverwinterdp.registry.RegistryException;
@Singleton
public class RegistryListener {
@Inject
private Registry registry;
private TreeMap<String, NodeWatcherWrapper> watchers = new TreeMap<String, NodeWatcherWrapper>() ;
private boolean closed = false;
public RegistryListener() { }
public RegistryListener(Registry registry) {
this.registry = registry;
}
public TreeMap<String, NodeWatcherWrapper> getWatchers() { return this.watchers; }
public void watch(String path, NodeWatcher nodeWatcher, boolean persistent) throws RegistryException {
if(registry.exists(path)) {
watchModify(path, nodeWatcher, persistent);
return;
}
String key = createKey(path, nodeWatcher);
NodeWatcherWrapper wrapper = null ;
if(!persistent) {
wrapper = new OneTimeNodeWatcher(key, nodeWatcher);
} else {
wrapper = new PersistentNodeWatcher(key, nodeWatcher);
}
registry.watchExists(path, wrapper);
watchers.put(key, wrapper) ;
}
public void watch(String path, NodeWatcher nodeWatcher) throws RegistryException {
watch(path, nodeWatcher, true) ;
}
public void watchModify(String path, NodeWatcher nodeWatcher, boolean persistent) throws RegistryException {
String key = createKey(path, nodeWatcher);
NodeWatcherWrapper wrapper = null ;
if(!persistent) {
wrapper = new OneTimeNodeWatcher(key, nodeWatcher);
} else {
wrapper = new PersistentNodeWatcher(key, nodeWatcher);
}
registry.watchModify(path, wrapper);
watchers.put(key, wrapper) ;
}
public void close() { closed = true; }
public void dump(Appendable out) throws IOException {
for(Map.Entry<String, NodeWatcherWrapper> entry : watchers.entrySet()) {
out.append(entry.getKey()).append("\n");
}
}
private String createKey(String path, NodeWatcher watcher) throws RegistryException {
String key = path + "[" + watcher.getClass().getName() + "#" + watcher.hashCode() + "]";
if(watchers.containsKey(key)) {
throw new RegistryException(ErrorCode.Unknown, "Already watch " + path + " with the watcher " + watcher.getClass()) ;
}
return key;
}
class PersistentNodeWatcher extends NodeWatcherWrapper {
String key ;
PersistentNodeWatcher(String key, NodeWatcher nodeWatcher) {
super(nodeWatcher);
this.key = key;
}
@Override
public void onEvent(NodeEvent event) {
if(closed) return;
try {
if(isComplete()) {
watchers.remove(key);
return;
}
registry.watchModify(event.getPath(), this);
} catch(RegistryException ex) {
if(ex.getErrorCode() != ErrorCode.NoNode) {
System.err.println("watch " + event.getPath() + ": " + ex.getMessage());
} else {
watchers.remove(key);
}
}
nodeWatcher.onEvent(event);
}
}
class OneTimeNodeWatcher extends NodeWatcherWrapper {
private String key;
OneTimeNodeWatcher(String key, NodeWatcher nodeWatcher) {
super(nodeWatcher);
this.key = key;
}
@Override
public void onEvent(NodeEvent event) {
if(closed) return;
nodeWatcher.onEvent(event);
watchers.remove(key);
}
}
}