package org.docear.plugin.pdfutilities.util; import java.awt.Color; import java.io.File; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; import javax.swing.Icon; import javax.swing.ImageIcon; import org.docear.plugin.core.CoreConfiguration; import org.docear.plugin.core.DocearController; import org.docear.plugin.core.logging.DocearLogger; 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.PdfUtilitiesController; import org.docear.plugin.pdfutilities.features.AnnotationID; import org.docear.plugin.pdfutilities.features.AnnotationModel; import org.docear.plugin.pdfutilities.features.AnnotationNodeModel; import org.docear.plugin.pdfutilities.features.DocearNodeMonitoringExtension.DocearExtensionKey; import org.docear.plugin.pdfutilities.features.DocearNodeMonitoringExtensionController; import org.docear.plugin.pdfutilities.features.IAnnotation; import org.docear.plugin.pdfutilities.features.IAnnotation.AnnotationType; import org.docear.plugin.pdfutilities.features.IcomingNodeExtension; import org.docear.plugin.pdfutilities.map.AnnotationController; import org.docear.plugin.pdfutilities.pdf.PdfFileFilter; import org.freeplane.core.util.TextUtils; import org.freeplane.features.attribute.AttributeController; import org.freeplane.features.attribute.NodeAttributeTableModel; import org.freeplane.features.edge.EdgeController; import org.freeplane.features.edge.mindmapmode.MEdgeController; import org.freeplane.features.link.LinkController; 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.features.mode.mindmapmode.MModeController; import org.freeplane.features.nodestyle.NodeStyleController; import org.freeplane.features.nodestyle.mindmapmode.MNodeStyleController; import org.freeplane.features.url.UrlManager; 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; public abstract class MonitoringUtils { private static final Icon defaultAnnotationIcon = new ImageIcon(WorkspaceController.class.getResource("/images/16x16/annotation_link.png")); private static final Icon defaultPdfIcon = new ImageIcon(WorkspaceController.class.getResource("/images/16x16/acrobat.png")); public static boolean isMonitoringNode(NodeModel node) { NodeAttributeTableModel attributeModel = (NodeAttributeTableModel) node.getExtension(NodeAttributeTableModel.class); return (attributeModel != null && attributeModel.getAttributeKeyList().contains(PdfUtilitiesController.MON_INCOMING_FOLDER)); } public static File getPdfDirFromMonitoringNode(NodeModel node) { if(!isMonitoringNode(node)) return null; NodeAttributeTableModel attributeModel = (NodeAttributeTableModel) node.getExtension(NodeAttributeTableModel.class); if(attributeModel == null || !attributeModel.getAttributeKeyList().contains(PdfUtilitiesController.MON_INCOMING_FOLDER)){ return null; } Object value = attributeModel.getValue(attributeModel.getAttributePosition(PdfUtilitiesController.MON_INCOMING_FOLDER)); if (value instanceof String) { try { value = new URI((String) value); } catch (URISyntaxException e) { e.printStackTrace(); } } WorkspaceMapModelExtension ext = WorkspaceController.getMapModelExtension(node.getMap()); if(ext == null || ext.getProject() == null || !ext.getProject().isLoaded()) { return null; } if(value.toString().equals(CoreConfiguration.DOCUMENT_REPOSITORY_PATH)){ return ((DocearWorkspaceProject)ext.getProject()).getProjectLiteratureRepository(); } else{ try { return URIUtils.getAbsoluteFile(UrlManager.getController().getAbsoluteUri(node.getMap(), (URI)value)); } catch (MalformedURLException e) { return null; } } } public static Collection<URI> getMindmapDirFromMonitoringNode(NodeModel node) { List<URI> result = new ArrayList<URI>(); if(!isMonitoringNode(node)) return result; NodeAttributeTableModel attributeModel = (NodeAttributeTableModel) node.getExtension(NodeAttributeTableModel.class); if(attributeModel == null || !attributeModel.getAttributeKeyList().contains(PdfUtilitiesController.MON_MINDMAP_FOLDER)){ return result; } Object value = attributeModel.getValue(attributeModel.getAttributePosition(PdfUtilitiesController.MON_MINDMAP_FOLDER)); if(value.toString().equals(CoreConfiguration.LIBRARY_PATH)){ AWorkspaceProject project = WorkspaceController.getMapProject(node.getMap()); if(project == null || !(project instanceof DocearWorkspaceProject)) { //WORKSPACE - DOCEAR info: better with an exception? return result; } return ((DocearWorkspaceProject) project).getLibraryMaps(); } else{ result.add(URIUtils.getAbsoluteURI((URI)value)); return result; } } public static void removeMonitoringEntries(NodeModel selected) { NodeAttributeTableModel attributeModel = (NodeAttributeTableModel) selected.getExtension(NodeAttributeTableModel.class); if(attributeModel == null) return; if(attributeModel.getAttributeKeyList().contains(PdfUtilitiesController.MON_INCOMING_FOLDER)){ AttributeController.getController(MModeController.getMModeController()).performRemoveRow(attributeModel, attributeModel.getAttributePosition(PdfUtilitiesController.MON_INCOMING_FOLDER)); } if(attributeModel.getAttributeKeyList().contains(PdfUtilitiesController.MON_MINDMAP_FOLDER)){ AttributeController.getController(MModeController.getMModeController()).performRemoveRow(attributeModel, attributeModel.getAttributePosition(PdfUtilitiesController.MON_MINDMAP_FOLDER)); } if(attributeModel.getAttributeKeyList().contains(PdfUtilitiesController.MON_AUTO)){ AttributeController.getController(MModeController.getMModeController()).performRemoveRow(attributeModel, attributeModel.getAttributePosition(PdfUtilitiesController.MON_AUTO)); } if(attributeModel.getAttributeKeyList().contains(PdfUtilitiesController.MON_SUBDIRS)){ AttributeController.getController(MModeController.getMModeController()).performRemoveRow(attributeModel, attributeModel.getAttributePosition(PdfUtilitiesController.MON_SUBDIRS)); } if(attributeModel.getAttributeKeyList().contains(PdfUtilitiesController.MON_FLATTEN_DIRS)){ AttributeController.getController(MModeController.getMModeController()).performRemoveRow(attributeModel, attributeModel.getAttributePosition(PdfUtilitiesController.MON_FLATTEN_DIRS)); } if(attributeModel.getAttributeKeyList().contains(PdfUtilitiesController.MON_EXTRA_INCOMING)){ AttributeController.getController(MModeController.getMModeController()).performRemoveRow(attributeModel, attributeModel.getAttributePosition(PdfUtilitiesController.MON_EXTRA_INCOMING)); } } public static boolean isAutoMonitorNode(NodeModel node) { if(NodeUtilities.getAttributeValue(node, PdfUtilitiesController.MON_AUTO) == null) return false; Integer value = NodeUtilities.getAttributeIntValue(node, PdfUtilitiesController.MON_AUTO); switch(value){ case 0: return false; case 1: return true; case 2: return DocearController.getPropertiesController().getBooleanProperty("docear_auto_monitoring"); //$NON-NLS-1$ default: return false; } } public static Stack<File> getFolderStructureStack(NodeModel monitoringNode, URI pdfFile){ Stack<File> folderStack = new Stack<File>(); File pdfDirFile = getPdfDirFromMonitoringNode(monitoringNode); if(pdfDirFile == null || !pdfDirFile.exists() || !pdfDirFile.isDirectory()){ return folderStack; } File parent = URIUtils.getAbsoluteFile(pdfFile).getParentFile(); while(parent != null && !isParent(pdfDirFile, parent)){ folderStack.push(parent); parent = parent.getParentFile(); if(parent == null){ folderStack.clear(); } } return folderStack; } public static boolean isParent(File parent, File f) { File file = new File(f.toURI().normalize()); if(parent instanceof AVirtualDirectory) { for(File fi : parent.listFiles()) { File parentFile = new File(fi.toURI().normalize()); if(file.equals(parentFile)) { return true; } } } else { return file.equals(parent); } return false; } public static boolean isPdfLinkedNode(NodeModel node){ URI link = NodeUtilities.getURI(node); return PdfFileFilter.accept(link); } public static List<NodeModel> insertNewChildNodesFrom(URI pdfUri, Collection<AnnotationModel> annotations, boolean isLeft, boolean flattenSubfolder, NodeModel target){ File pdfFile = URIUtils.getAbsoluteFile(pdfUri); AnnotationModel root = new AnnotationModel(0, AnnotationType.PDF_FILE); root.setSource(pdfFile.toURI()); root.setTitle(pdfFile.getName()); root.getChildren().addAll(annotations); Collection<AnnotationModel> newList = new ArrayList<AnnotationModel>(); newList.add(root); if(!flattenSubfolder){ Stack<File> folderStack = getFolderStructureStack(target, pdfUri); target = createFolderStructurePath(target, folderStack); } return insertNewChildNodesFrom(newList, isLeft, target, target); } public static NodeModel createFolderStructurePath(NodeModel target, Stack<File> pathStack) { if (pathStack.isEmpty()) { return target; } File parent = pathStack.pop(); NodeModel pathNode = null; for (NodeModel child : target.getChildren()) { if (child.getText().equals(parent.getName()) && DocearNodeMonitoringExtensionController.containsKey(child, DocearExtensionKey.MONITOR_PATH)) { pathNode = child; break; } } if (pathNode != null) { return createFolderStructurePath(pathNode, pathStack); } else { pathNode = ((MMapController) Controller.getCurrentModeController().getMapController()).newNode(parent.getName(), target.getMap()); DocearNodeMonitoringExtensionController.setEntry(pathNode, DocearExtensionKey.MONITOR_PATH, null); NodeUtilities.setLinkFrom(LinkController.normalizeURI(parent.toURI()), pathNode); NodeUtilities.insertChildNodeFrom(pathNode, target.isLeft(), target); return createFolderStructurePath(pathNode, pathStack); } } public static Map<AnnotationID, Collection<AnnotationNodeModel>> getOldAnnotationsFromMaps(Collection<URI> mindmaps){ Map<AnnotationID, Collection<AnnotationNodeModel>> result = new HashMap<AnnotationID, Collection<AnnotationNodeModel>>(); for(MapModel map : MapUtils.getMapsFromUris(mindmaps)){ Map<AnnotationID, Collection<AnnotationNodeModel>> temp = getOldAnnotationsFrom(map.getRootNode()); for(AnnotationID id : temp.keySet()){ if(!result.containsKey(id)){ result.put(id, new ArrayList<AnnotationNodeModel>()); } result.get(id).addAll(temp.get(id)); } } return result; } public static Map<AnnotationID, Collection<AnnotationNodeModel>> getOldAnnotationsFromCurrentMap(){ return getOldAnnotationsFrom(((MMapController) Controller.getCurrentModeController().getMapController()).getRootNode()); } private static Map<AnnotationID, Collection<AnnotationNodeModel>> getOldAnnotationsFrom(NodeModel parent){ Map<AnnotationID, Collection<AnnotationNodeModel>> result = new HashMap<AnnotationID, Collection<AnnotationNodeModel>>(); try { Thread.sleep(1L); if(Thread.currentThread().isInterrupted()) return result; } catch (InterruptedException e) { } if(isPdfLinkedNode(parent)){ URI uri = URIUtils.getAbsoluteURI(NodeUtilities.getURI(parent)); AnnotationNodeModel oldAnnotation = AnnotationController.getAnnotationNodeModel(parent); if(uri != null && oldAnnotation != null){ result.put(oldAnnotation.getAnnotationID(), new ArrayList<AnnotationNodeModel>()); result.get(oldAnnotation.getAnnotationID()).add(oldAnnotation); } } for(NodeModel child : parent.getChildren()){ Map<AnnotationID, Collection<AnnotationNodeModel>> children = getOldAnnotationsFrom(child); for(AnnotationID id : children.keySet()){ if(!result.containsKey(id)){ result.put(id, new ArrayList<AnnotationNodeModel>()); } result.get(id).addAll(children.get(id)); } } return result; } public static NodeModel insertChildNodesFromPdf(URI pdfFile, List<AnnotationModel> annotations, boolean isLeft, NodeModel target){ NodeModel node = insertChildNodeFrom(pdfFile, isLeft, target, AnnotationType.PDF_FILE); insertChildNodesFrom(annotations, isLeft, node); return node; } public static List<NodeModel> insertChildNodesFrom(List<AnnotationModel> annotations, boolean isLeft, NodeModel target){ List<NodeModel> nodes = new ArrayList<NodeModel>(); for(AnnotationModel annotation : annotations){ NodeModel node = insertChildNodeFrom(annotation.getSource(), annotation, isLeft, target); insertChildNodesFrom(annotation.getChildren(), isLeft, node); nodes.add(node); } return nodes; } public static NodeModel insertChildNodeFrom(URI uri, boolean isLeft, NodeModel target, AnnotationType type){ if(uri == null) { return null; } File file = URIUtils.getAbsoluteFile(uri); final NodeModel node = ((MMapController) Controller.getCurrentModeController().getMapController()).newNode(file.getName(), target.getMap()); if(type != null){ AnnotationModel model;//new AnnotationID(file, -1), type); if(type == AnnotationType.PDF_FILE){ model = new AnnotationModel(0); model.setSource(file.toURI()); } else { model = new AnnotationModel(-1); model.setSource(uri); } model.setAnnotationType(type); AnnotationController.setModel(node, model); } NodeUtilities.setLinkFrom(uri, node); return NodeUtilities.insertChildNodeFrom(node, isLeft, target); } public static NodeModel insertChildNodeFrom(URI file, IAnnotation annotation, boolean isLeft, NodeModel target){ if(annotation.getTitle() != null && annotation.getTitle().length() > 1 && annotation.getTitle().charAt(0) == '='){ annotation.setTitle(" " + annotation.getTitle()); //$NON-NLS-1$ } final NodeModel node = ((MMapController) Controller.getCurrentModeController().getMapController()).newNode(annotation.getTitle(), target.getMap()); AnnotationController.setModel(node, annotation); NodeUtilities.setLinkFrom(file, node); return NodeUtilities.insertChildNodeFrom(node, isLeft, target); } public static List<NodeModel> insertNewChildNodesFrom(Collection<AnnotationModel> annotations, boolean isLeft, NodeModel target, NodeModel rootTarget) { List<NodeModel> nodes = new ArrayList<NodeModel>(); for(AnnotationModel annotation : annotations){ if(annotation.isNew() || annotation.hasNewChildren()){ NodeModel equalChild = targetHasEqualChild(rootTarget, annotation); if(equalChild == null){ NodeModel node = insertChildNodeFrom(annotation.getSource(), annotation, isLeft, target); insertNewChildNodesFrom(annotation.getChildren(), isLeft, node, rootTarget); nodes.add(node); } else{ insertNewChildNodesFrom(annotation.getChildren(), isLeft, equalChild, rootTarget); nodes.add(equalChild); } } } return nodes; } public static NodeModel targetHasEqualChild(NodeModel target, IAnnotation annotation){ if(annotation == null) return null; for(NodeModel child : target.getChildren()){ IAnnotation oldAnnotation = AnnotationController.getAnnotationNodeModel(child); NodeModel equalChild = targetHasEqualChild(child, annotation); if(equalChild != null) { return equalChild; } if(oldAnnotation == null || oldAnnotation.getAnnotationType() != annotation.getAnnotationType()){ continue; } if(annotation.getAnnotationType().equals(AnnotationType.PDF_FILE)){ if(annotation.getSource().equals(URIUtils.getAbsoluteURI(child))){ return child; } } if(oldAnnotation != null && oldAnnotation.getAnnotationID().equals(annotation.getAnnotationID())){ return child; } } return null; } public static void markAsIncomingNode(NodeModel node, boolean addStyle) { IcomingNodeExtension ext = node.getExtension(IcomingNodeExtension.class); NodeModel parent = node.getParentNode(); if(ext == null) { if(parent == null || isMonitoringNode(parent)) { node.addExtension(new IcomingNodeExtension()); } } else { if(parent != null && !isMonitoringNode(parent)) { node.removeExtension(new IcomingNodeExtension()); } } if(addStyle) { try { MNodeStyleController mNodeStyleController = ((MNodeStyleController) NodeStyleController.getController()); mNodeStyleController.setBold(node, true); mNodeStyleController.setBackgroundColor(node, new Color(0, 0x66, 0x99)); mNodeStyleController.setColor(node, Color.white); mNodeStyleController.setFontFamily(node, "Courier New"); final MEdgeController edgeController = (MEdgeController) EdgeController.getController(); edgeController.setColor(node, new Color(0, 0x66, 0x99)); } catch(Exception e) { DocearLogger.warn(e); } } } public static boolean isIncomingNode(NodeModel node) { return node.getExtension(IcomingNodeExtension.class) != null; } public static NodeModel getIncomingNode(NodeModel monitoringNode) { if(monitoringNode == null || (!isExtraIncomingNodeEnabled(monitoringNode) && isIncomingNode(monitoringNode))) { return monitoringNode; } if(isMonitoringNode(monitoringNode)) { if(!isExtraIncomingNodeEnabled(monitoringNode)) { markAsIncomingNode(monitoringNode, false); return monitoringNode; } else { for (NodeModel node : monitoringNode.getChildren()) { if(isIncomingNode(node)) { return node; } } MMapController mapCtrl = (MMapController) Controller.getCurrentModeController().getMapController(); NodeModel nuIncoming = mapCtrl.newNode(TextUtils.getRawText("docear.monitoring.incoming.text"), monitoringNode.getMap()); markAsIncomingNode(nuIncoming, true); mapCtrl.addNewNode(nuIncoming, monitoringNode, 0, false); return nuIncoming; } } else { return getIncomingNode(monitoringNode.getParentNode()); } } public static void setExtraIncomingNodeEnable(NodeModel monitoringNode, boolean enabled) { NodeUtilities.setAttribute(monitoringNode, PdfUtilitiesController.MON_EXTRA_INCOMING , enabled ? "1" : "0"); } public static boolean setupMonitoringNode(NodeModel node, Object incomingFolderValue) { boolean dirtyMap = false; dirtyMap |= NodeUtilities.setAttributeIfNotExists(node, PdfUtilitiesController.MON_INCOMING_FOLDER, incomingFolderValue); dirtyMap |= NodeUtilities.setAttributeIfNotExists(node, PdfUtilitiesController.MON_MINDMAP_FOLDER, CoreConfiguration.LIBRARY_PATH); dirtyMap |= NodeUtilities.setAttributeIfNotExists(node, PdfUtilitiesController.MON_AUTO, 2); dirtyMap |= NodeUtilities.setAttributeIfNotExists(node, PdfUtilitiesController.MON_SUBDIRS, 2); dirtyMap |= NodeUtilities.setAttributeIfNotExists(node, PdfUtilitiesController.MON_EXTRA_INCOMING, 2); dirtyMap |= NodeUtilities.setAttributeIfNotExists(node, PdfUtilitiesController.MON_FLATTEN_DIRS, 2); return dirtyMap; } public static boolean isExtraIncomingNodeEnabled(NodeModel monitoringNode) { int value = NodeUtilities.getAttributeIntValue(monitoringNode, PdfUtilitiesController.MON_EXTRA_INCOMING); switch (value) { case 1: return true; case 2: return DocearController.getPropertiesController().getBooleanProperty("docear_extra_incoming_node"); //$NON-NLS-1$ default: return false; } } public static boolean isFlattenSubfolders(NodeModel monitoringNode) { int value = NodeUtilities.getAttributeIntValue(monitoringNode, PdfUtilitiesController.MON_FLATTEN_DIRS); switch (value) { case 1: return true; case 2: return DocearController.getPropertiesController().getBooleanProperty("docear_flatten_subdir"); //$NON-NLS-1$ default: return false; } } public static boolean isMonitorSubDirectories(NodeModel target) { int value = NodeUtilities.getAttributeIntValue(target, PdfUtilitiesController.MON_SUBDIRS); switch (value) { case 1: return true; case 2: return DocearController.getPropertiesController().getBooleanProperty("docear_subdir_monitoring"); //$NON-NLS-1$ default: return false; } } public static Icon getAnnotationModelIcon(NodeModel node) { Icon icon = null; IAnnotation model = AnnotationController.getAnnotationNodeModel(node); if(model != null) { if(model.getAnnotationType().equals(AnnotationType.PDF_FILE)){ icon = defaultPdfIcon; } else if(!model.getAnnotationType().equals(AnnotationType.FILE)){ icon = defaultAnnotationIcon; } } return icon; } }