package org.docear.plugin.pdfutilities.listener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import javax.swing.SwingUtilities;
import name.pachler.nio.file.WatchKey;
import org.docear.plugin.pdfutilities.actions.UpdateMonitoringFolderAction;
import org.docear.plugin.pdfutilities.map.MapConverter;
import org.docear.plugin.pdfutilities.util.MonitoringUtils;
import org.freeplane.core.util.LogUtils;
import org.freeplane.features.icon.IconController;
import org.freeplane.features.map.IMapLifeCycleListener;
import org.freeplane.features.map.MapModel;
import org.freeplane.features.map.NodeModel;
import org.freeplane.plugin.workspace.WorkspaceUtils;
public class DocearAutoMonitoringListener implements IMapLifeCycleListener, WindowFocusListener{
private List<NodeModel> autoMonitorNodes = new ArrayList<NodeModel>();
private boolean startup = true;
private FileFilter directoryFilter = new FileFilter() {
public boolean accept(File file) {
if(file.isDirectory()) {
return true;
}
return false;
}
};
Comparator<WatchKey> watchKeyComparator = new Comparator<WatchKey>() {
public int compare(WatchKey key1, WatchKey key2) {
int hash1 = key1.hashCode();
int hash2 = key2.hashCode();
if(hash1 > hash2) {
return 1;
}
else if(hash1 < hash2) {
return -1;
}
return 0;
}
};
//TODO: enable automatic file monitoring
//private WatchService watcher = FileSystems.getDefault().newWatchService();
private Map<MapModel, List<WatchKey>> mapKeysMap = new HashMap<MapModel, List<WatchKey>>();
private Map<WatchKey, MapModel> keyMapMap = new TreeMap<WatchKey, MapModel>(watchKeyComparator);
private Map<WatchKey, String> watchables = new TreeMap<WatchKey, String>(watchKeyComparator);
public DocearAutoMonitoringListener() {
//TODO: enable automatic file monitoring
// new Thread() {
// public void run() {
// try {
// WatchKey key = null;
// while((key = watcher.take()) != null) {
// Path watchPath = null;
// if(key instanceof PathWatchKey) {
// watchPath = (Path) ((PathWatchKey) key).watchable();
// }
// for(WatchEvent<?> event : key.pollEvents()) {
// Object obj = event.context();
// File file = new File(watchPath.toString(), obj.toString());
// if(StandardWatchEventKind.ENTRY_CREATE.equals(event.kind())) {
// onCreateFile(file, key);
// }
// else if(StandardWatchEventKind.ENTRY_DELETE.equals(event.kind())) {
// onDeleteFile(file, key);
// }
// else if(StandardWatchEventKind.ENTRY_MODIFY.equals(event.kind())) {
// onModifyFile(file, key);
// }
// else {
// LogUtils.info("DirectoryWatcher: unknown event kind"+ event.kind());
// }
// }
// key.reset();
// }
// } catch (InterruptedException e) {
// }
// finally {
// LogUtils.info("closing directory watcher...");
// try {
// watcher.close();
// } catch (IOException e) {
// }
// }
// }
// }.start();
}
public void onCreate(final MapModel map) {
if(map == null || map.getFile() == null) return;
List<? extends NodeModel> monitoringNodes = (List<? extends NodeModel>) getAutoMonitorNodes(map.getRootNode());
autoMonitorNodes.addAll(monitoringNodes);
//TODO: enable automatic file monitoring
// registerMonitoredDirectories(map, monitoringNodes);
if(!startup){
SwingUtilities.invokeLater(new Thread() {
public void run() {
LogUtils.info("Monitoring started"); //$NON-NLS-1$
//startMonitoring();
} //run()
}); // Thread
}
}
public void onRemove(MapModel map) {
List<WatchKey> keys = mapKeysMap.get(map);
if(keys != null) {
for (WatchKey watchKey : keys) {
cleanUpWatchKey(watchKey);
}
}
}
public void windowGainedFocus(WindowEvent e) {
if(startup && !MapConverter.currentlyConverting){
startup = false;
//startMonitoring();
}
}
public void windowLostFocus(WindowEvent e) {
}
private List<? extends NodeModel> getAutoMonitorNodes(NodeModel node) {
List<NodeModel> result = new ArrayList<NodeModel>();
if(MonitoringUtils.isAutoMonitorNode(node)){
result.add(node);
}
for(NodeModel child : node.getChildren()){
result.addAll(getAutoMonitorNodes(child));
}
return result;
}
public void onSavedAs(MapModel map) {
}
public void onSaved(MapModel map) {
}
private synchronized void startMonitoring() {
if(autoMonitorNodes.size() > 0){
UpdateMonitoringFolderAction.updateNodesAgainstMonitoringDir(autoMonitorNodes, !startup);
autoMonitorNodes.clear();
}
}
private void registerMonitoredDirectories(MapModel map, List<? extends NodeModel> monitoringNodes) {
List<WatchKey> keys = mapKeysMap.get(map);
if(keys == null) {
keys = new ArrayList<WatchKey>();
mapKeysMap.put(map, keys);
}
for(NodeModel model : monitoringNodes) {
File dir = WorkspaceUtils.resolveURI(MonitoringUtils.getPdfDirFromMonitoringNode(model), map);
addMonitoringDirectory(map, dir);
}
}
private void addMonitoringDirectory(MapModel map, File dir) {
//TODO: enable automatic file monitoring
// if(dir != null && dir.exists() && dir.isDirectory()) {
// try {
// WatchKey key = Paths.get(dir.getPath()).register(watcher, StandardWatchEventKind.ENTRY_CREATE, StandardWatchEventKind.ENTRY_DELETE, StandardWatchEventKind.ENTRY_MODIFY);
// mapKeysMap.get(map).add(key);
// watchables.put(key, dir.getPath());
// keyMapMap.put(key, map);
// } catch (IOException e) {
// LogUtils.warn(e);
// return;
// }
// File[] subDirs = dir.listFiles(directoryFilter );
// for (File file : subDirs) {
// addMonitoringDirectory(map, file);
// }
// }
}
private void cleanUpWatchKey(WatchKey watchKey) {
watchKey.cancel();
watchables.remove(watchKey);
keyMapMap.remove(watchKey);
}
private void onModifyFile(File file, WatchKey key) {
synchronized (watchables) {
System.out.println("modified "+ file);
}
}
private void onDeleteFile(File file, WatchKey key) {
synchronized (watchables) {
System.out.println("deleted "+ file);
Set<Entry<WatchKey, String>> entries= watchables.entrySet();
for (Entry<WatchKey, String> entry : entries) {
if(entry.getValue().equals(file.getPath())) {
//what to do
}
}
}
}
private void onCreateFile(File file, WatchKey key) {
synchronized (watchables) {
System.out.println("created "+ file);
if(file.exists()) {
if(file.isDirectory()) {
addMonitoringDirectory(keyMapMap.get(key), file);
}
}
}
}
}