package org.docear.plugin.bibtex.actions; import java.awt.event.ActionEvent; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.Enumeration; import javax.swing.JOptionPane; import javax.swing.tree.TreePath; import net.sf.jabref.BibtexDatabase; import net.sf.jabref.BibtexEntry; import org.docear.plugin.bibtex.ReferencesController; import org.docear.plugin.bibtex.jabref.DuplicateResolver; import org.docear.plugin.core.util.CoreUtils; import org.docear.plugin.core.util.NodeUtilities; import org.docear.plugin.pdfutilities.listener.DocearProjectModelListener; import org.docear.plugin.pdfutilities.map.AnnotationController; import org.docear.plugin.pdfutilities.util.MonitoringUtils; import org.freeplane.core.ui.EnabledAction; import org.freeplane.core.ui.components.UITools; import org.freeplane.core.util.LogUtils; import org.freeplane.core.util.TextUtils; import org.freeplane.features.map.NodeModel; import org.freeplane.features.mode.Controller; import org.freeplane.plugin.workspace.URIUtils; import org.freeplane.plugin.workspace.WorkspaceController; import org.freeplane.plugin.workspace.actions.AWorkspaceAction; import org.freeplane.plugin.workspace.components.menu.CheckEnableOnPopup; import org.freeplane.plugin.workspace.io.IFileSystemRepresentation; import org.freeplane.plugin.workspace.model.AWorkspaceTreeNode; import org.freeplane.plugin.workspace.model.IMutableLinkNode; import org.freeplane.plugin.workspace.model.project.AWorkspaceProject; import org.freeplane.plugin.workspace.nodes.LinkTypeFileNode; @CheckEnableOnPopup @EnabledAction(checkOnNodeChange=true) public class RenameByMetaData extends AWorkspaceAction { private static final long serialVersionUID = 1L; public static final String KEY = "workspace.action.renameByMetaData"; final static int[] illegalChars = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47}; static { Arrays.sort(illegalChars); } private BibtexEntry currentEntry = null; public RenameByMetaData(){ super(KEY); } @Override public void actionPerformed(ActionEvent e) { if(currentEntry == null) return; String newName = cleanFileName(currentEntry.getField("year") + "--" + currentEntry.getField("title") + ".pdf".replaceAll("[^\\x00-\\x7F]", "")); AWorkspaceTreeNode targetNode = this.getNodeFromActionEvent(e); if(targetNode != null){ String oldName = targetNode.getName(); if (targetNode instanceof IMutableLinkNode) { if (((IMutableLinkNode) targetNode).changeName(newName, true)) { targetNode.refresh(); } else { JOptionPane.showMessageDialog(UITools.getFrame(), TextUtils.getText("error_rename_file"), TextUtils.getText("error_rename_file_title"), JOptionPane.ERROR_MESSAGE); targetNode.setName(oldName); } } } else{ NodeModel node = Controller.getCurrentModeController().getMapController().getSelectedNode(); AWorkspaceProject project = WorkspaceController.getMapProject(node.getMap()); File oldFile = CoreUtils.resolveURI(NodeUtilities.getLink(node)).getAbsoluteFile(); File newFile = new File(oldFile.getParentFile(), newName); if(oldFile.renameTo(newFile)) { refreshWorkspaceNodes(project.getModel().getRoot(), oldFile, newFile); AnnotationController.getController().updateIndex(newFile, oldFile); DocearProjectModelListener.updateMaps(project, newFile, oldFile, true); } else { JOptionPane.showMessageDialog(UITools.getFrame(), TextUtils.getText("error_rename_file"), TextUtils.getText("error_rename_file_title"), JOptionPane.ERROR_MESSAGE); } } System.out.println(); } private void refreshWorkspaceNodes(AWorkspaceTreeNode root, File oldFile, File newFile) { Enumeration<AWorkspaceTreeNode> children = root.children(); while(children != null && children.hasMoreElements()){ AWorkspaceTreeNode child = children.nextElement(); File file = null; if(child instanceof IFileSystemRepresentation) { file = ((IFileSystemRepresentation) child).getFile(); } else if(child instanceof LinkTypeFileNode) { file = URIUtils.getAbsoluteFile(((LinkTypeFileNode) child).getLinkURI()); } try { if(file != null && file.getCanonicalPath().equals(oldFile.getCanonicalPath())){ ((IMutableLinkNode) child).changeName(newFile.getName(), false); child.refresh(); } } catch (IOException e) { LogUtils.warn(e.getMessage()); } refreshWorkspaceNodes(child, oldFile, newFile); } } public void setEnabledFor(AWorkspaceTreeNode node, TreePath[] selectedPaths) { File file = null; if(node instanceof IFileSystemRepresentation) { file = ((IFileSystemRepresentation) node).getFile(); } else { if(node instanceof LinkTypeFileNode) { file = URIUtils.getAbsoluteFile(((LinkTypeFileNode) node).getLinkURI()); } } if(file == null || !file.getName().toLowerCase().endsWith(".pdf") || !hasMetaData(file)) { setEnabled(false); return; } else{ setEnabled(true); return; } } public void setEnabled() { NodeModel node = Controller.getCurrentModeController().getMapController().getSelectedNode(); if (MonitoringUtils.isPdfLinkedNode(node)) { File file = CoreUtils.resolveURI(NodeUtilities.getLink(node)).getAbsoluteFile(); setEnabled(hasMetaData(file)); } else { setEnabled(false); } } private boolean hasMetaData(File file) { BibtexDatabase database = ReferencesController.getController().getJabrefWrapper().getDatabase(); if(database == null) return false; for(BibtexEntry entry : database.getEntries()){ URL entryUrl = null; String urlString = entry.getField("url"); try { if (urlString != null) { entryUrl = new URL(urlString); } if (file.toURI().toURL().equals(entryUrl)) { if(hasRequiredFields(entry)){ currentEntry = entry; return true; } return false; } } catch (MalformedURLException e) { LogUtils.info(urlString + ": " + e.getMessage()); } for (String jabrefPath : DuplicateResolver.getDuplicateResolver().retrieveFileLinksFromEntry(entry)) { File jabrefFile = new File(jabrefPath); if (jabrefFile != null && jabrefFile.getName().equals(file.getName())) { if(hasRequiredFields(entry)){ currentEntry = entry; return true; } return false; } } } return false; } private boolean hasRequiredFields(BibtexEntry entry) { //if(entry.getField("author") == null || entry.getField("author").isEmpty()) return false; if(entry.getField("title") == null || entry.getField("title").isEmpty()) return false; if(entry.getField("year") == null || entry.getField("year").isEmpty()) return false; return true; } private String cleanFileName(String badFileName) { StringBuilder cleanName = new StringBuilder(); for (int i = 0; i < badFileName.length(); i++) { int c = (int)badFileName.charAt(i); if (Arrays.binarySearch(illegalChars, c) < 0) { cleanName.append((char)c); } } return cleanName.toString(); } }