1 | public void actionPerformed(ActionEvent e) { | | 1 | /** |
2 | BasePanel bp = frame.basePanel(); | | 2 | * Take a list of external links and copy the referred files to a given directory. |
3 | if (bp == null) | | 3 | * This method should be run off the Event Dispatch Thread. A progress bar, if given, |
4 | return; | | 4 | * will be updated on the EDT. |
5 | if (bp.getSelectedEntries().length == 0) { | | 5 | * |
6 | // no entries selected, silently ignore action | | 6 | * @param files The list of file links. |
7 | return; | | 7 | * @param toDir The directory to copy the files to. |
8 | } | | 8 | * @param metaData The MetaData for the database containing the external links. This is needed |
9 | | | 9 | * because the database might have its own file directory. |
10 | // Lazy creation of the dialog: | | 10 | * @param prog A JProgressBar which will be updated to show the progress of the process. |
11 | if (diag == null) { | | 11 | * This argument can be null if no progress bar is needed. |
12 | createDialog(); | | 12 | * @param deleteOriginalFiles if true, the files in their original locations will be deleted |
13 | } | | 13 | * after copying, for each file whose source directory is different from the destination |
14 | | | 14 | * directory differs. |
15 | cancelled = true; | | 15 | * @param callback An ActionListener which should be notified when the process is finished. |
16 | | | 16 | * This parameter can be null if no callback is needed. |
17 | fillKeyWordList(); | | 17 | */ |
18 | | | 18 | public static void copyExternalLinksToDirectory(final List<FileListEntry> files, File toDir, |
19 | diag.pack(); | | 19 | MetaData metaData, final JProgressBar prog, |
20 | Util.placeDialog(diag, frame); | | 20 | boolean deleteOriginalFiles, |
21 | diag.setVisible(true); | | 21 | final ActionListener callback) { |
22 | if (cancelled) | | 22 | |
23 | return; | | 23 | if (prog != null) SwingUtilities.invokeLater(new Runnable() { |
24 | | | 24 | public void run() { |
25 | HashSet<String> keywordsToAdd = new HashSet<String>(); | | 25 | prog.setMaximum(files.size()); |
26 | HashSet<String> userSelectedKeywords = new HashSet<String>(); | | 26 | prog.setValue(0); |
27 | // build keywordsToAdd and userSelectedKeywords in parallel | | 27 | prog.setIndeterminate(false); |
28 | for (Enumeration keywords = keywordListModel.elements(); keywords.hasMoreElements(); ) { | | 28 | } |
29 | String keyword = (String)keywords.nextElement(); | | 29 | }); |
30 | userSelectedKeywords.add(keyword); | | 30 | |
31 | if (!sortedKeywordsOfAllEntriesBeforeUpdateByUser.contains(keyword)) { | | 31 | Set<String> fileNames = new HashSet<String>(); |
32 | keywordsToAdd.add(keyword); | | 32 | |
33 | } | | 33 | int i=0; |
34 | } | | 34 | |
35 | | | 35 | for (Iterator<FileListEntry> iterator = files.iterator(); iterator.hasNext();) { |
36 | HashSet<String> keywordsToRemove = new HashSet<String>(); | | 36 | FileListEntry entry = iterator.next(); |
37 | for (String keyword: sortedKeywordsOfAllEntriesBeforeUpdateByUser) { | | 37 | File file = new File(entry.getLink()); |
38 | if (!userSelectedKeywords.contains(keyword)) { | | 38 | |
39 | keywordsToRemove.add(keyword); | | 39 | // We try to check the extension for the file: |
40 | } | | 40 | String name = file.getName(); |
41 | } | | 41 | int pos = name.lastIndexOf('.'); |
42 | | | 42 | String extension = ((pos >= 0) && (pos < name.length() - 1)) ? name.substring(pos + 1) |
43 | if (keywordsToAdd.isEmpty() && keywordsToRemove.isEmpty()) { | | 43 | .trim().toLowerCase() : null; |
44 | // nothing to be done if nothing is new and nothing is obsolete | | 44 | |
45 | return; | | 45 | // Find the default directory for this field type, if any: |
46 | } | | 46 | String[] dir = metaData.getFileDirectory(extension); |
47 | | | 47 | // Include the standard "file" directory: |
48 | if (SpecialFieldsUtils.keywordSyncEnabled()) { | | 48 | String[] fileDir = metaData.getFileDirectory(GUIGlobals.FILE_FIELD); |
49 | if (!keywordsToAdd.isEmpty()) { | | 49 | // Include the directory of the bib file: |
50 | // we need to check whether a special field is added | | 50 | ArrayList<String> al = new ArrayList<String>(); |
51 | // for each field: | | 51 | for (int i2 = 0; i2 < dir.length; i2++) |
52 | // check if something is added | | 52 | if (!al.contains(dir[i2])) al.add(dir[i2]); |
53 | // if yes, add all keywords of that special fields to the keywords to be removed | | 53 | for (int i2 = 0; i2 < fileDir.length; i2++) |
54 | | | 54 | if (!al.contains(fileDir[i2])) al.add(fileDir[i2]); |
55 | HashSet<String> clone; | | 55 | |
56 | | | 56 | String[] dirs = al.toArray(new String[al.size()]); |
57 | // Priority | | 57 | File tmp = Util.expandFilename(entry.getLink(), dirs); |
58 | clone = (HashSet<String>) keywordsToAdd.clone(); | | 58 | if (tmp != null) |
59 | clone.retainAll(Priority.getInstance().getKeyWords()); | | 59 | file = tmp; |
60 | if (!clone.isEmpty()) { | | 60 | |
61 | keywordsToRemove.addAll(Priority.getInstance().getKeyWords()); | | 61 | // Check if we have arrived at an existing file: |
62 | } | | 62 | if (file.exists()) { |
63 | | | 63 | if (fileNames.contains(name)) { |
64 | // Quality | | 64 | // Oops, a file of that name already exists.... |
65 | clone = (HashSet<String>) keywordsToAdd.clone(); | | 65 | } |
66 | clone.retainAll(Quality.getInstance().getKeyWords()); | | 66 | else { |
67 | if (!clone.isEmpty()) { | | 67 | fileNames.add(name); |
68 | keywordsToRemove.addAll(Quality.getInstance().getKeyWords()); | | 68 | File destination = new File(toDir, name); |
69 | } | | 69 | |
70 | | | 70 | // Check if the source and destination locations differ: |
71 | // Rank | | 71 | if (!destination.equals(file)) { |
72 | clone = (HashSet<String>) keywordsToAdd.clone(); | | 72 | try { |
73 | clone.retainAll(Rank.getInstance().getKeyWords()); | | 73 | // Copy the file: |
74 | if (!clone.isEmpty()) { | | 74 | Util.copyFile(file, destination, false); |
75 | keywordsToRemove.addAll(Rank.getInstance().getKeyWords()); | | 75 | // Delete the original file if requested: |
76 | } | | 76 | if (deleteOriginalFiles) |
77 | | | 77 | file.delete(); |
78 | // Relevance | | 78 | |
79 | clone = (HashSet<String>) keywordsToAdd.clone(); | | 79 | } catch (IOException ex) { |
80 | clone.retainAll(Relevance.getInstance().getKeyWords()); | | 80 | ex.printStackTrace(); |
81 | if (!clone.isEmpty()) { | | 81 | } |
82 | keywordsToRemove.addAll(Relevance.getInstance().getKeyWords()); | | 82 | } |
83 | } | | 83 | else { |
84 | } | | 84 | // Destination and source is the same. Do nothing. |
85 | } | | 85 | } |
86 | | | 86 | // Update progress bar: |
87 | BibtexEntry[] entries = bp.getSelectedEntries(); | | 87 | i++; |
88 | NamedCompound ce = new NamedCompound(Globals.lang("Update keywords")); | | 88 | final int j = i; |
89 | for (BibtexEntry entry: entries) { | | 89 | |
90 | ArrayList<String> separatedKeywords = Util.getSeparatedKeywords(entry); | | 90 | if (prog != null) SwingUtilities.invokeLater(new Runnable() { |
91 | | | 91 | public void run() { |
92 | // we "intercept" with a treeset | | 92 | prog.setValue(j); |
93 | // pro: no duplicates | | 93 | } |
94 | // possible con: alphabetical sorting of the keywords | | 94 | }); |
95 | TreeSet<String> keywords = new TreeSet<String>(); | | 95 | } |
96 | keywords.addAll(separatedKeywords); | | 96 | } |
97 | | | 97 | else { |
98 | // update keywords | | 98 | // The link could not be resolved to an existing file. |
99 | keywords.removeAll(keywordsToRemove); | | 99 | |
100 | keywords.addAll(keywordsToAdd); | | 100 | } |
101 | | | 101 | } |
102 | // put keywords back | | 102 | |
103 | separatedKeywords.clear(); | | 103 | if (callback != null) { |
104 | separatedKeywords.addAll(keywords); | | 104 | callback.actionPerformed(null); |
105 | Util.putKeywords(entry, separatedKeywords, ce); | | 105 | } |
106 | | | 106 | } |
107 | if (SpecialFieldsUtils.keywordSyncEnabled()) { | | | |
108 | SpecialFieldsUtils.syncSpecialFieldsFromKeywords(entry, ce); | | | |
109 | } | | | |
110 | } | | | |
111 | ce.end(); | | | |
112 | bp.undoManager.addEdit(ce); | | | |
113 | bp.markBaseChanged(); | | | |
114 | } | | | |