package org.docear.plugin.pdfutilities.features; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Stack; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.docear.addons.highlights.IHighlightsImporter; import org.docear.plugin.core.DocearController; import org.docear.plugin.core.event.DocearEvent; import org.docear.plugin.core.event.DocearEventType; import org.docear.plugin.core.features.DocearMapModelController; import org.docear.plugin.core.logger.DocearLogEvent; import org.docear.plugin.core.ui.SwingWorkerDialog; import org.docear.plugin.core.util.DirectoryFileFilter; import org.docear.plugin.core.util.HtmlUtils; import org.docear.plugin.core.util.MapUtils; import org.docear.plugin.core.util.NodeUtilities; import org.docear.plugin.core.workspace.AVirtualDirectory; import org.docear.plugin.core.workspace.model.DocearWorkspaceProject; import org.docear.plugin.pdfutilities.actions.AbstractMonitoringAction; import org.docear.plugin.pdfutilities.addons.DocearAddonController; import org.docear.plugin.pdfutilities.features.DocearNodeMonitoringExtension.DocearExtensionKey; import org.docear.plugin.pdfutilities.features.IAnnotation.AnnotationType; import org.docear.plugin.pdfutilities.map.AnnotationController; import org.docear.plugin.pdfutilities.map.MapConverter; import org.docear.plugin.pdfutilities.pdf.DocumentReadOnlyException; import org.docear.plugin.pdfutilities.pdf.PdfAnnotationImporter; import org.docear.plugin.pdfutilities.pdf.PdfFileFilter; import org.docear.plugin.pdfutilities.pdf.ReadOnlyExceptionWarningHandler; import org.docear.plugin.pdfutilities.util.CustomFileFilter; import org.docear.plugin.pdfutilities.util.CustomFileListFilter; import org.docear.plugin.pdfutilities.util.MonitoringUtils; import org.freeplane.core.resources.ResourceController; import org.freeplane.core.ui.components.UITools; import org.freeplane.core.util.LogUtils; import org.freeplane.core.util.TextUtils; import org.freeplane.features.link.LinkController; import org.freeplane.features.map.INodeView; import org.freeplane.features.map.MapModel; import org.freeplane.features.map.NodeModel; import org.freeplane.features.map.mindmapmode.MMapController; import org.freeplane.features.mode.Controller; import org.freeplane.plugin.workspace.URIUtils; import org.freeplane.plugin.workspace.WorkspaceController; import org.freeplane.plugin.workspace.features.WorkspaceMapModelExtension; import org.freeplane.plugin.workspace.model.project.AWorkspaceProject; import org.freeplane.view.swing.map.MapView; import org.freeplane.view.swing.map.NodeView; import org.jdesktop.swingworker.SwingWorker; import de.intarsys.pdf.cos.COSRuntimeException; public class MonitoringWorker extends SwingWorker<Map<AnnotationID, Collection<IAnnotation>>, AnnotationModel[]> { private final List<NodeModel> targets; List<URI> monitorFiles = new ArrayList<URI>(); List<URI> otherFilesLinkedInMindMap = new ArrayList<URI>(); List<MapModel> monitoredMindmaps = new ArrayList<MapModel>(); Map<AnnotationID, List<NodeModel>> nodeIndex = new HashMap<AnnotationID, List<NodeModel>>(); Map<AnnotationID, AnnotationModel> importedFiles = new HashMap<AnnotationID, AnnotationModel>(); Map<AnnotationID, AnnotationModel> importedOtherFiles = new HashMap<AnnotationID, AnnotationModel>(); List<NodeModel> orphanedNodes = new ArrayList<NodeModel>(); List<AnnotationModel> newAnnotations = new ArrayList<AnnotationModel>(); Map<String, List<NodeModel>> equalChildIndex = new HashMap<String, List<NodeModel>>(); Map<AnnotationID, Collection<IAnnotation>> conflicts = new HashMap<AnnotationID, Collection<IAnnotation>>(); private boolean isfolded; private boolean canceledDuringPasting; private NodeModel currentTarget; private long time; boolean highlightAddon; public MonitoringWorker(List<NodeModel> targets) { this.targets = targets; highlightAddon = DocearAddonController.getController().hasPlugin(IHighlightsImporter.class); time = System.currentTimeMillis(); } protected Map<AnnotationID, Collection<IAnnotation>> doInBackground() throws Exception { DocearController.getController().getSemaphoreController().lock("MindmapUpdate"); NodeView.setModifyModelWithoutRepaint(true); MapView.setNoRepaint(true); IConversionProcessHandler oldHandler = AnnotationConverter.getConversionProcessHandler(); BatchMapConversionHandler batchHandler = new BatchMapConversionHandler(new ChangeListener() { public void stateChanged(ChangeEvent e) { try { fireStatusUpdate(SwingWorkerDialog.DETAILS_LOG_TEXT, null, String.valueOf(e.getSource())); } catch (Exception e1) { } } }); AnnotationConverter.SetConversionProcessHandler(batchHandler); try { // Controller.getCurrentController().getViewController().getMapView().setVisible(false); for (final NodeModel target : targets) { currentTarget = target; WorkspaceMapModelExtension ext = WorkspaceController.getMapModelExtension(target.getMap()); if(ext == null || ext.getProject() == null || !ext.getProject().isLoaded()) { fireStatusUpdate(SwingWorkerDialog.DETAILS_LOG_TEXT, null, TextUtils.getText("docear.map.projectnotloaded")); continue; } File file = MonitoringUtils.getPdfDirFromMonitoringNode(target); if(file == null) { continue; } URI uri = file.toURI(); if (uri != null) { DocearController.getController().getDocearEventLogger() .appendToLog(this, DocearLogEvent.MONITORING_FOLDER_READ, URIUtils.getAbsoluteURI(uri)); } if (canceled()) return conflicts; String textWithoutHTML = HtmlUtils.extractText(target.getText()); if(highlightAddon){ fireStatusUpdate(SwingWorkerDialog.SET_SUB_HEADLINE, null, TextUtils.getText("AbstractMonitoringAction.6") + textWithoutHTML + TextUtils.getText("AbstractMonitoringAction.7")); //$NON-NLS-1$ //$NON-NLS-2$ } else{ fireStatusUpdate(SwingWorkerDialog.SET_SUB_HEADLINE, null, TextUtils.getText("AbstractMonitoringAction.6.noAddon") + textWithoutHTML + TextUtils.getText("AbstractMonitoringAction.7.noAddon")); //$NON-NLS-1$ //$NON-NLS-2$ } fireStatusUpdate(SwingWorkerDialog.SET_PROGRESS_BAR_INDETERMINATE, null, null); if (!cleanUpCollections()) continue; if (!setupPreconditions(target)) continue; if (!buildNodeIndex(target)) continue; if (!loadMonitoredFiles(target)) continue; if (!searchNewAndConflictedNodes()) continue; if (!searchingOrphanedNodes(target)) continue; isfolded = target.isFolded(); if (newAnnotations.size() > 100) { fireStatusUpdate(SwingWorkerDialog.SET_PROGRESS_BAR_INDETERMINATE, null, null); fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.8")); //$NON-NLS-1$ SwingUtilities.invokeAndWait(new Runnable() { public void run() { target.setFolded(true); } }); } canceledDuringPasting = true; if (!pasteNewNodesAndRemoveOrphanedNodes(target)) { canceledDuringPasting = false; if (newAnnotations.size() > 100) { fireStatusUpdate(SwingWorkerDialog.SET_PROGRESS_BAR_INDETERMINATE, null, null); fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.9")); //$NON-NLS-1$ SwingUtilities.invokeAndWait(new Runnable() { public void run() { target.setFolded(isfolded); } }); } continue; } DocearEvent event = new DocearEvent(this, (DocearWorkspaceProject) WorkspaceController.getMapProject(target.getMap()), DocearEventType.MINDMAP_ADD_PDF_TO_NODE, true); DocearController.getController().getEventQueue().dispatchEvent(event); if (newAnnotations.size() > 100) { fireStatusUpdate(SwingWorkerDialog.SET_PROGRESS_BAR_INDETERMINATE, null, null); fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.9")); //$NON-NLS-1$ SwingUtilities.invokeAndWait(new Runnable() { public void run() { target.setFolded(isfolded); } }); } } return conflicts; } finally { closeAll(); AnnotationConverter.SetConversionProcessHandler(oldHandler); batchHandler.close(); } } private boolean closeAll() { Map<String, MapModel> maps = Controller.getCurrentController().getMapViewManager().getMaps(); try { for (Entry<String, MapModel> entry : maps.entrySet()) { monitoredMindmaps.remove(entry.getValue()); } for (MapModel map : monitoredMindmaps) { map.destroy(); } new Thread( new Runnable() { public void run() { System.gc(); } }).start(); return true; } catch (Exception e) { e.printStackTrace(); } // monitoredMindmaps.clear(); // nodeIndex.clear(); // importedFiles.clear(); // newAnnotations.clear(); // equalChildIndex.clear(); // orphanedNodes.clear(); // importedOtherFiles.clear(); // otherFilesLinkedInMindMap.clear(); return false; } private boolean searchingOrphanedNodes(NodeModel target) throws InterruptedException, InvocationTargetException { fireStatusUpdate(SwingWorkerDialog.SET_PROGRESS_BAR_DETERMINATE, null, null); fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.11")); //$NON-NLS-1$ int count = 0; for (AnnotationID id : nodeIndex.keySet()) { if (canceled()) return false; count++; fireProgressUpdate(100 * count / nodeIndex.keySet().size()); if (importedFiles.containsKey(id)) continue; for (NodeModel node : nodeIndex.get(id)) { if (!isMonitoringNodeChild(target, node)) continue; AnnotationNodeModel annotation = AnnotationController.getAnnotationNodeModel(node); if (annotation == null) continue; if (annotation.getAnnotationType() == null) continue; if (annotation.getAnnotationType().equals(AnnotationType.FILE)) continue; if (orphanedNodes.contains(node)) continue; try { File file = URIUtils.getAbsoluteFile(URIUtils.getAbsoluteURI(node)); if (file != null && !file.exists()) { orphanedNodes.add(node); continue; } else if (file != null) { File monitoringDirectory = MonitoringUtils.getPdfDirFromMonitoringNode(target); boolean ok = false; if(monitoringDirectory instanceof AVirtualDirectory) { for(File repo : monitoringDirectory.listFiles()) { if (file.getPath().startsWith(repo.getPath())) { ok = true; } } } else if (file.getPath().startsWith(monitoringDirectory.getPath())) { ok = true; } if(ok) { AnnotationModel annoation = new PdfAnnotationImporter().searchAnnotation(URIUtils.getAbsoluteURI(node), node); if (annoation == null) { orphanedNodes.add(node); } } } } catch (Exception e) { LogUtils.info("Exception during import file: " + URIUtils.getAbsoluteURI(node)); //$NON-NLS-1$ } } } return true; } private boolean isMonitoringNodeChild(NodeModel monitoringNode, NodeModel node) { List<NodeModel> pathToRoot = Arrays.asList(node.getPathToRoot()); return pathToRoot.contains(monitoringNode); } private boolean cleanUpCollections() { monitorFiles.clear(); monitoredMindmaps.clear(); nodeIndex.clear(); importedFiles.clear(); newAnnotations.clear(); equalChildIndex.clear(); orphanedNodes.clear(); importedOtherFiles.clear(); otherFilesLinkedInMindMap.clear(); return true; } @Override protected void done() { DocearController.getController().getSemaphoreController().unlock("MindmapUpdate"); try { if (this.isCancelled() || Thread.currentThread().isInterrupted()) { if (newAnnotations.size() > 100 && canceledDuringPasting) { if (currentTarget != null) { currentTarget.setFolded(isfolded); } } this.firePropertyChange(SwingWorkerDialog.IS_DONE, null, TextUtils.getText("AbstractMonitoringAction.15")); //$NON-NLS-1$ } else { if (currentTarget != null) { DocearController.getController().getEventQueue().dispatchEvent(new DocearEvent(this, (DocearWorkspaceProject) WorkspaceController.getMapProject(currentTarget.getMap()), DocearEventType.UPDATE_MAP, currentTarget.getMap())); } this.firePropertyChange(SwingWorkerDialog.IS_DONE, null, TextUtils.getText("AbstractMonitoringAction.16")); //$NON-NLS-1$ } } finally { NodeView.setModifyModelWithoutRepaint(false); MapView.setNoRepaint(false); } if (currentTarget!= null) { MapModel map = currentTarget.getMap(); LogUtils.info("updating view for map: " + map.getTitle()); for(INodeView nodeView : map.getRootNode().getViewers()) { if(nodeView instanceof NodeView) { ((NodeView) nodeView).updateAll(); } } } time = System.currentTimeMillis() - time; LogUtils.info("monitoring execution time: " + (time / 1000)); System.out.println("monitoring execution time: " + (time / 1000)); } private boolean canceled() throws InterruptedException { // Thread.sleep(1L); return (this.isCancelled() || Thread.currentThread().isInterrupted()); } private boolean pasteNewNodesAndRemoveOrphanedNodes(NodeModel target) throws InterruptedException, InvocationTargetException { fireStatusUpdate(SwingWorkerDialog.SET_PROGRESS_BAR_DETERMINATE, null, null); fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.17")); //$NON-NLS-1$ NodeModel monitoringNode = target; if (MonitoringUtils.isMonitoringNode(target) || !MonitoringUtils.isIncomingNode(target)) { target = MonitoringUtils.getIncomingNode(target); } if(target == null) { fireStatusUpdate(SwingWorkerDialog.DETAILS_LOG_TEXT, null, TextUtils.getText("docear.monitoring.incoming.error")); return false; } for (AnnotationModel annotation : newAnnotations) { if (canceled()) return false; try { fireProgressUpdate(100 * newAnnotations.indexOf(annotation) / newAnnotations.size()); if (annotation.isInserted()) continue; // PDF's with no new annotations should not be imported, // see Ticket #283 if (annotation.getAnnotationType().equals(AnnotationType.PDF_FILE) && annotation.getChildren().size() > 0 && !annotation.hasNewChildren()) continue; Stack<NodeModel> treePathStack = getTreePathStack(annotation , monitoringNode.getMap() , MonitoringUtils.getPdfDirFromMonitoringNode(monitoringNode) , MonitoringUtils.isFlattenSubfolders(monitoringNode)); if (canceled()) return false; NodeModel tempTarget = target; while (!treePathStack.isEmpty()) { NodeModel insertNode = treePathStack.pop(); NodeModel equalChild = getEqualChild(insertNode); if (equalChild == null) { final NodeModel finalTarget = tempTarget; final NodeModel finalInsertNode = insertNode; if (canceled()) return false; SwingUtilities.invokeAndWait(new Runnable() { public void run() { int newNodePostion = AnnotationController.getAnnotationPosition(finalInsertNode); boolean pasted = false; for (NodeModel child : finalTarget.getChildren()) { int childPosition = AnnotationController.getAnnotationPosition(child); if (childPosition > newNodePostion) { // finalTarget.insert(finalInsertNode, // finalTarget.getChildPosition(child)); ((MMapController) Controller.getCurrentModeController().getMapController()).addNewNode(finalInsertNode, finalTarget, finalTarget.getChildPosition(child), finalTarget.isNewChildLeft()); pasted = true; break; } } if (!pasted) { ((MMapController) Controller.getCurrentModeController().getMapController()).addNewNode(finalInsertNode, finalTarget, finalTarget.getChildCount(), finalTarget.isNewChildLeft()); } } }); tempTarget = insertNode; String key = normalizeWhitespaces(insertNode.getText()); if (!equalChildIndex.containsKey(key)) { equalChildIndex.put(key, new ArrayList<NodeModel>()); } equalChildIndex.get(key).add(insertNode); } else { tempTarget = equalChild; } } } catch (InterruptedException e) { } catch (Exception e) { LogUtils.warn(e); } } Boolean alwaysKeepOrphanedNodes = ResourceController.getResourceController().getBooleanProperty("docear.reference.keep_orphaned_nodes"); if (!alwaysKeepOrphanedNodes && orphanedNodes.size() > 0) { if (canceled()) return false; try { int result = UITools.showConfirmDialog(target, TextUtils.getText("AbstractMonitoringAction.18"), TextUtils.getText("AbstractMonitoringAction.18"), JOptionPane.YES_NO_OPTION); //$NON-NLS-1$ //$NON-NLS-2$ fireStatusUpdate(SwingWorkerDialog.SET_ON_TOP, null, null); if (result == JOptionPane.OK_OPTION) { fireStatusUpdate(SwingWorkerDialog.SET_PROGRESS_BAR_DETERMINATE, null, null); fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.20")); //$NON-NLS-1$ for (final NodeModel node : orphanedNodes) { SwingUtilities.invokeAndWait(new Runnable() { public void run() { try { if (node.getParentNode() != null) { node.removeFromParent(); } } catch (Exception e) { LogUtils.warn(e); } } }); } } } catch (Exception e) { LogUtils.warn(e); } } return true; } private NodeModel getEqualChild(NodeModel insertNode) { List<NodeModel> nodes = equalChildIndex.get(normalizeWhitespaces(insertNode.getText())); if (nodes != null) { for (NodeModel equalChild : nodes) { if (isEqualNode(equalChild, insertNode)) { return equalChild; } } } return null; } private URI getAbsoluteURIFromNode(NodeModel node, MapModel map) { try { return URIUtils.resolveURI(map.getURL().toURI(), NodeUtilities.getLink(node)); } catch (Exception e) { LogUtils.info("Exception in "+AbstractMonitoringAction.class +".getAbsoluteURIFromNode(NodeModel,MapModel): "+e.getMessage()); } return null; } private boolean isEqualNode(NodeModel node1, NodeModel node2) { if (!normalizeWhitespaces(node1.getText()).equals(normalizeWhitespaces(node2.getText()))) { return false; } URI uri1 = getAbsoluteURIFromNode(node1, node1.getMap()); URI uri2 = getAbsoluteURIFromNode(node2, node2.getMap()); if (uri1 != null && uri2 != null) { if (!uri1.equals(uri2)) { return false; } } if (uri1 != null && uri2 == null) { return false; } if (uri1 == null && uri2 != null) { return false; } if (node1.containsExtension(DocearNodeMonitoringExtension.class) && !node2.containsExtension(DocearNodeMonitoringExtension.class)) { return false; } if (node2.containsExtension(DocearNodeMonitoringExtension.class) && !node1.containsExtension(DocearNodeMonitoringExtension.class)) { return false; } if (node1.containsExtension(IAnnotation.class) && !node2.containsExtension(IAnnotation.class)) { return false; } if (node2.containsExtension(IAnnotation.class) && !node1.containsExtension(IAnnotation.class)) { return false; } if (node1.containsExtension(DocearNodeMonitoringExtension.class) && !node2.containsExtension(DocearNodeMonitoringExtension.class)) { return false; } if (node1.containsExtension(AnnotationModel.class) && !node2.containsExtension(AnnotationModel.class)) { return false; } if (node2.containsExtension(AnnotationModel.class) && !node1.containsExtension(AnnotationModel.class)) { return false; } if (node1.containsExtension(AnnotationModel.class) && node2.containsExtension(AnnotationModel.class)) { IAnnotation anno1 = AnnotationController.getAnnotationNodeModel(node1); IAnnotation anno2 = AnnotationController.getAnnotationNodeModel(node2); if (anno1.getAnnotationType() != anno2.getAnnotationType()) { return false; } if (!anno1.getAnnotationID().equals(anno2.getAnnotationID())) { return false; } } if (node1.containsExtension(IAnnotation.class) && node2.containsExtension(IAnnotation.class)) { IAnnotation anno1 = AnnotationController.getAnnotationNodeModel(node1); IAnnotation anno2 = AnnotationController.getAnnotationNodeModel(node2); if (anno1.getAnnotationType() != anno2.getAnnotationType()) { return false; } if (!anno1.getAnnotationID().equals(anno2.getAnnotationID())) { return false; } } return true; } private Stack<NodeModel> getTreePathStack(AnnotationModel annotation, MapModel map, File pdfRepository, boolean flattenSubFolders) throws InterruptedException { Stack<NodeModel> result = new Stack<NodeModel>(); AnnotationModel tempAnnotation = annotation; do { if (canceled()) return result; // Scripting Error Bugfix if (tempAnnotation.getTitle() != null && tempAnnotation.getTitle().length() > 1 && tempAnnotation.getTitle().charAt(0) == '=') { tempAnnotation.setTitle(" " + tempAnnotation.getTitle()); //$NON-NLS-1$ } NodeModel node = ((MMapController) Controller.getCurrentModeController().getMapController()).newNode(tempAnnotation.getTitle(), map); AnnotationController.setModel(node, tempAnnotation); NodeUtilities.setLinkFrom(tempAnnotation.getSource(), node); tempAnnotation.setIsNewID(false); result.push(node); tempAnnotation.setInserted(true); tempAnnotation = tempAnnotation.getParent(); } while (tempAnnotation != null); if (!flattenSubFolders) { File annoFile = URIUtils.getAbsoluteFile(annotation.getSource()); if (annoFile != null) { File parent = annoFile.getParentFile(); while (parent != null && !MonitoringUtils.isParent(pdfRepository, parent)) { if (canceled()) return result; NodeModel node = ((MMapController) Controller.getCurrentModeController().getMapController()).newNode(parent.getName(), map); DocearNodeMonitoringExtensionController.setEntry(node, DocearExtensionKey.MONITOR_PATH, null); NodeUtilities.setLinkFrom(LinkController.normalizeURI(parent.toURI()), node); result.push(node); parent = parent.getParentFile(); } } } return result; } private boolean searchNewAndConflictedNodes() throws InterruptedException, InvocationTargetException { fireStatusUpdate(SwingWorkerDialog.SET_PROGRESS_BAR_DETERMINATE, null, null); fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.22")); //$NON-NLS-1$ int count = 0; for (AnnotationID id : importedFiles.keySet()) { if (canceled()) return false; fireProgressUpdate(100 * count / importedFiles.keySet().size()); System.out.println(""); if (!nodeIndex.containsKey(id)) { importedFiles.get(id).setNew(true); newAnnotations.add(importedFiles.get(id)); } else { AnnotationModel importedAnnotation = importedFiles.get(id); if (importedAnnotation.getAnnotationType().equals(AnnotationType.TRUE_HIGHLIGHTED_TEXT)) continue; for (NodeModel node : nodeIndex.get(id)) { AnnotationNodeModel oldAnnotation = AnnotationController.getAnnotationNodeModel(node); if (oldAnnotation != null) { if (oldAnnotation.getAnnotationType() == null) continue; if (oldAnnotation.getAnnotationType().equals(AnnotationType.PDF_FILE)) continue; if (oldAnnotation.getAnnotationType().equals(AnnotationType.FILE)) continue; String oldAnnotationWithoutHTML = HtmlUtils.extractText(oldAnnotation.getTitle()); String oldAnnotationTitle = oldAnnotation.getTitle().replace("\r", "").replace("\n", "").replace("\t", "")/*.replace(" ", "")*/; String importedAnnotationWithoutHTML = HtmlUtils.extractText(importedAnnotation.getTitle()); String importedAnnotationTitle = importedAnnotation.getTitle().replace("\r", "").replace("\n", "").replace("\t", "") /*.replace(" ", "")*/; importedAnnotationWithoutHTML = importedAnnotationWithoutHTML.replace("\r", "").replace("\n", "").replace("\t", "")/*.replace(" ", "")*/; oldAnnotationWithoutHTML = oldAnnotationWithoutHTML.replace("\r", "").replace("\n", "").replace("\t", "")/*.replace(" ", "")*/; if (!importedAnnotationTitle.trim().equals(oldAnnotationTitle.trim()) && !importedAnnotationTitle.trim().equals(oldAnnotationWithoutHTML.trim()) && !importedAnnotationWithoutHTML.trim().equals(oldAnnotationWithoutHTML.trim())) { importedAnnotation.setConflicted(true); AnnotationController.addConflictedAnnotation(importedAnnotation, conflicts); for (NodeModel conflictedNode : nodeIndex.get(id)) { AnnotationNodeModel conflictedAnnotation = AnnotationController.getAnnotationNodeModel(conflictedNode); if (conflictedAnnotation != null) { AnnotationController.addConflictedAnnotation(conflictedAnnotation, conflicts); } } break; } } } } count++; } return true; } private boolean loadMonitoredFiles(NodeModel target) throws InterruptedException, InvocationTargetException { fireStatusUpdate(SwingWorkerDialog.SET_PROGRESS_BAR_DETERMINATE, null, null); fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.23")); //$NON-NLS-1$ ReadOnlyExceptionWarningHandler warningHandler = new ReadOnlyExceptionWarningHandler(); for (URI uri : monitorFiles) { warningHandler.prepare(); if (canceled()) return false; try { fireProgressUpdate(100 * monitorFiles.indexOf(uri) / monitorFiles.size()); File file = URIUtils.getAbsoluteFile(uri); fireStatusUpdate(SwingWorkerDialog.NEW_FILE, null, file.getName()); if (PdfFileFilter.accept(uri)) { AnnotationModel pdf; while(warningHandler.retry()) { try { pdf = new PdfAnnotationImporter().importPdf(uri); addAnnotationsToImportedFiles(pdf, target); warningHandler.consume(); } catch (DocumentReadOnlyException e) { if(warningHandler.skip()) { break; } warningHandler.showDialog(file); } } } else { AnnotationModel annotation = new AnnotationModel(0, AnnotationType.FILE); annotation.setSource(uri); annotation.setTitle(file.getName()); AnnotationID id = annotation.getAnnotationID(); if (!importedFiles.containsKey(id)) { importedFiles.put(id, annotation); } } } catch (IOException e) { LogUtils.info("IOexception during update file: " + uri); //$NON-NLS-1$ } catch (COSRuntimeException e) { LogUtils.info("COSRuntimeException during update file: " + uri); //$NON-NLS-1$ } } return true; } private void addAnnotationsToImportedFiles(AnnotationModel annotation, NodeModel target) throws InterruptedException { if (canceled()) return; AnnotationID id = annotation.getAnnotationID(); if (!importedFiles.containsKey(id)) { importedFiles.put(id, annotation); } for (AnnotationModel child : annotation.getChildren()) { child.setParent(annotation); addAnnotationsToImportedFiles(child, target); } } private boolean buildNodeIndex(NodeModel target) throws InterruptedException, InvocationTargetException { fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.27")); //$NON-NLS-1$ AWorkspaceProject workingProject = WorkspaceController.getMapProject(); for (MapModel map : monitoredMindmaps) { AWorkspaceProject project = WorkspaceController.getMapProject(map); if(project == null) { fireStatusUpdate(SwingWorkerDialog.DETAILS_LOG_TEXT, null, TextUtils.format("docear.map.ignore.noproject", map.getTitle(), map.getFile())); continue; } if(!workingProject.equals(project)) { fireStatusUpdate(SwingWorkerDialog.DETAILS_LOG_TEXT, null, TextUtils.format("docear.map.ignore.otherproject", map.getTitle(), map.getFile())); continue; } if(!project.isLoaded()) { fireStatusUpdate(SwingWorkerDialog.DETAILS_LOG_TEXT, null, TextUtils.format("docear.map.ignore.projectnotloaded", map.getTitle(), map.getFile())); continue; } if(!DocearWorkspaceProject.isCompatible(project)) { fireStatusUpdate(SwingWorkerDialog.DETAILS_LOG_TEXT, null, TextUtils.format("docear.map.ignore.wrongversion", map.getTitle(), map.getFile())); continue; } if (canceled()) return false; buildAnnotationNodeIndex(map.getRootNode()); } buildEqualChildIndex(target.getChildren()); if (canceled()) return false; return true; } private void buildAnnotationNodeIndex(NodeModel node) throws InterruptedException { if (canceled()) return; AnnotationNodeModel annotation = AnnotationController.getAnnotationNodeModel(node); if (annotation != null && annotation.getAnnotationID() != null) { AnnotationID id = annotation.getAnnotationID(); List<NodeModel> nodeList = nodeIndex.get(id); if (nodeList == null) { nodeList = new ArrayList<NodeModel>(); nodeIndex.put(id, nodeList); } nodeList.add(node); } for (NodeModel child : node.getChildren()) { buildAnnotationNodeIndex(child); } } private void buildEqualChildIndex(List<NodeModel> children) throws InterruptedException { if (canceled()) return; for (NodeModel child : children) { String key = normalizeWhitespaces(child.getText()); if (!equalChildIndex.containsKey(key)) { equalChildIndex.put(key, new ArrayList<NodeModel>()); } equalChildIndex.get(key).add(child); buildEqualChildIndex(child.getChildren()); } } private String normalizeWhitespaces(String text) { String temp = text.replaceAll("[\\s]+", " "); return temp; } private boolean setupPreconditions(NodeModel target) throws InterruptedException, InvocationTargetException { fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.28")); //$NON-NLS-1$ if (canceled()) return false; File monitoringDirectory = MonitoringUtils.getPdfDirFromMonitoringNode(target); if (monitoringDirectory == null) { UITools.informationMessage(TextUtils.getText("AbstractMonitoringAction.29")); //$NON-NLS-1$ return false; } CustomFileListFilter monitorFileFilter = new CustomFileListFilter(DocearController.getPropertiesController().getProperty( TextUtils.getText("AbstractMonitoringAction.30"))); //$NON-NLS-1$ monitorFiles = getFilteredFileList(monitoringDirectory, monitorFileFilter, MonitoringUtils.isMonitorSubDirectories(target)); fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.31")); //$NON-NLS-1$ if (canceled()) return false; Collection<URI> mindmapDirectories = MonitoringUtils.getMindmapDirFromMonitoringNode(target); Collection<URI> mindmapFiles = new ArrayList<URI>(); for (URI uri : mindmapDirectories) { uri = URIUtils.resolveURI(URIUtils.getAbsoluteURI(target.getMap()), uri); File dirFile = URIUtils.getFile(uri); if (dirFile == null || !dirFile.exists()) continue; if (dirFile.isDirectory()) { mindmapFiles.addAll(getFilteredFileList(dirFile, new CustomFileFilter(".*[.][mM][mM]"), MonitoringUtils.isMonitorSubDirectories(target))); //$NON-NLS-1$ } else { mindmapFiles.add(uri); } } if (target.getMap().getFile() != null && !mindmapFiles.contains(target.getMap().getFile().toURI())) { mindmapFiles.add(target.getMap().getFile().toURI()); } fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.33")); //$NON-NLS-1$ if (canceled()) return false; monitoredMindmaps = MapUtils.getMapsFromUris(mindmapFiles); if (updateMindmaps(monitoredMindmaps)) { monitoredMindmaps = MapUtils.getMapsFromUris(mindmapFiles); } return true; } private boolean updateMindmaps(Collection<MapModel> maps) throws InterruptedException, InvocationTargetException { List<MapModel> mapsToUpdate = new ArrayList<MapModel>(); for (MapModel map : maps) { if (DocearMapModelController.getModel(map) == null) { mapsToUpdate.add(map); } } if (mapsToUpdate.size() > 0) { int result = UITools.showConfirmDialog(null, getMessage(mapsToUpdate), getTitle(mapsToUpdate), JOptionPane.OK_CANCEL_OPTION); if (result == JOptionPane.OK_OPTION) { fireStatusUpdate(SwingWorkerDialog.PROGRESS_BAR_TEXT, null, TextUtils.getText("AbstractMonitoringAction.34") + mapsToUpdate.size() + TextUtils.getText("AbstractMonitoringAction.35")); //$NON-NLS-1$ //$NON-NLS-2$ if (!MapConverter.convert(mapsToUpdate)) { fireStatusUpdate(SwingWorkerDialog.IS_CANCELED, null, TextUtils.getText("AbstractMonitoringAction.36")); //$NON-NLS-1$ } } else { fireStatusUpdate(SwingWorkerDialog.IS_CANCELED, null, TextUtils.getText("AbstractMonitoringAction.36")); //$NON-NLS-1$ } return true; } else { return false; } } private String getMessage(List<MapModel> mapsToConvert) { if (mapsToConvert.size() > 1) { return mapsToConvert.size() + TextUtils.getText("AbstractMonitoringAction.39") + TextUtils.getText("update_splmm_to_docear_explanation"); //$NON-NLS-1$ //$NON-NLS-2$ } else if (mapsToConvert.size() == 1) { return mapsToConvert.get(0).getTitle() + TextUtils.getText("AbstractMonitoringAction.41") + TextUtils.getText("update_splmm_to_docear_explanation"); //$NON-NLS-1$ //$NON-NLS-2$ } return ""; //$NON-NLS-1$ } private String getTitle(List<MapModel> mapsToConvert) { if (mapsToConvert.size() > 1) { return mapsToConvert.size() + TextUtils.getText("AbstractMonitoringAction.44"); //$NON-NLS-1$ } else if (mapsToConvert.size() == 1) { return mapsToConvert.get(0).getTitle() + TextUtils.getText("AbstractMonitoringAction.45"); //$NON-NLS-1$ } return ""; //$NON-NLS-1$ } private void fireStatusUpdate(final String propertyName, final Object oldValue, final Object newValue) throws InterruptedException, InvocationTargetException { SwingUtilities.invokeAndWait(new Runnable() { public void run() { firePropertyChange(propertyName, oldValue, newValue); } }); } private void fireProgressUpdate(final int progress) throws InterruptedException, InvocationTargetException { SwingUtilities.invokeAndWait(new Runnable() { public void run() { if (progress < 0) { setProgress(0); return; } if (progress > 100) { setProgress(100); return; } setProgress(progress); } }); } private List<URI> getFilteredFileList(File monitoringDir, FileFilter fileFilter, boolean readSubDirectories) { List<URI> result = new ArrayList<URI>(); Collection<File> tempResult = new ArrayList<File>(); if(monitoringDir == null || !monitoringDir.isDirectory()) return result; File[] monitorFiles = monitoringDir.listFiles(fileFilter); if(monitorFiles != null && monitorFiles.length > 0){ tempResult.addAll(Arrays.asList(monitorFiles)); } for(File file : tempResult){ result.add(file.toURI()); } if(readSubDirectories){ File[] subDirs = monitoringDir.listFiles(new DirectoryFileFilter()); if(subDirs != null && subDirs.length > 0){ for(File subDir : subDirs){ result.addAll(getFilteredFileList(subDir, fileFilter, readSubDirectories)); } } } return result; } }