b31b2213aca6a308d6dcc460c4e06f00662f5901
[debian/jabref.git] / src / java / net / sf / jabref / external / AccessLinksForEntries.java
1 package net.sf.jabref.external;
2
3 import java.awt.BorderLayout;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
6 import java.io.File;
7 import java.io.IOException;
8 import java.util.ArrayList;
9 import java.util.HashSet;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.Set;
13
14 import javax.swing.JDialog;
15 import javax.swing.JProgressBar;
16 import javax.swing.SwingUtilities;
17
18 import net.sf.jabref.BaseAction;
19 import net.sf.jabref.BasePanel;
20 import net.sf.jabref.BibtexEntry;
21 import net.sf.jabref.GUIGlobals;
22 import net.sf.jabref.MetaData;
23 import net.sf.jabref.Util;
24 import net.sf.jabref.gui.FileListEntry;
25 import net.sf.jabref.gui.FileListTableModel;
26
27
28 /**
29  * This class handles the task of looking up all external files linked for a set
30  * of entries. This is useful for tasks where the user wants e.g. to send a database
31  * with external files included.
32  */
33 public class AccessLinksForEntries {
34
35     /**
36      * Look up all external files linked from (at least) one of the entries in a set.
37      * This method does not verify the links.
38      *
39      * @param entries The set of entries.
40      * @return A list of FileListEntry objects pointing to the external files.
41      */
42     public static List<FileListEntry> getExternalLinksForEntries(List<BibtexEntry> entries) {
43         List<FileListEntry> files = new ArrayList<FileListEntry>();
44         FileListTableModel model = new FileListTableModel();
45         for (Iterator<BibtexEntry> iterator = entries.iterator(); iterator.hasNext();) {
46             BibtexEntry entry = iterator.next();
47             String links = entry.getField(GUIGlobals.FILE_FIELD);
48             if (links == null)
49                 continue;
50             model.setContent(links);
51             for (int i=0; i<model.getRowCount(); i++)
52                 files.add(model.getEntry(i));
53         }
54         return files;
55     }
56
57     /**
58      * Take a list of external links and copy the referred files to a given directory.
59      * This method should be run off the Event Dispatch Thread. A progress bar, if given,
60      * will be updated on the EDT.
61      *
62      * @param files The list of file links.
63      * @param toDir The directory to copy the files to.
64      * @param metaData The MetaData for the database containing the external links. This is needed
65      *  because the database might have its own file directory.
66      * @param prog A JProgressBar which will be updated to show the progress of the process.
67      *  This argument can be null if no progress bar is needed.
68      * @param deleteOriginalFiles if true, the files in their original locations will be deleted
69      *  after copying, for each file whose source directory is different from the destination
70      *  directory differs.
71      * @param callback An ActionListener which should be notified when the process is finished.
72      *  This parameter can be null if no callback is needed.
73      */
74     public static void copyExternalLinksToDirectory(final List<FileListEntry> files, File toDir,
75                                                     MetaData metaData, final JProgressBar prog,
76                                                     boolean deleteOriginalFiles,
77                                                     final ActionListener callback) {
78
79         if (prog != null) SwingUtilities.invokeLater(new Runnable() {
80             public void run() {
81                 prog.setMaximum(files.size());
82                 prog.setValue(0);
83                 prog.setIndeterminate(false);
84             }
85         });
86
87         Set<String> fileNames = new HashSet<String>();
88
89         int i=0;
90
91         for (Iterator<FileListEntry> iterator = files.iterator(); iterator.hasNext();) {
92             FileListEntry entry = iterator.next();
93             File file = new File(entry.getLink());
94
95             // We try to check the extension for the file:
96             String name = file.getName();
97             int pos = name.lastIndexOf('.');
98             String extension = ((pos >= 0) && (pos < name.length() - 1)) ? name.substring(pos + 1)
99                 .trim().toLowerCase() : null;
100
101             // Find the default directory for this field type, if any:
102             String dir = metaData.getFileDirectory(extension);
103             // Include the standard "file" directory:
104             String fileDir = metaData.getFileDirectory(GUIGlobals.FILE_FIELD);
105
106             // Include the directory of the bib file:
107             String databaseDir = metaData.getFile().getParent();
108             File tmp = Util.expandFilename(entry.getLink(),
109                     new String[] { dir, fileDir, databaseDir });
110             if (tmp != null)
111                 file = tmp;
112
113             // Check if we have arrived at an existing file:
114             if (file.exists()) {
115                 if (fileNames.contains(name)) {
116                     // Oops, a file of that name already exists....
117                 }
118                 else {
119                     fileNames.add(name);
120                     File destination = new File(toDir, name);
121
122                     // Check if the source and destination locations differ:
123                     if (!destination.equals(file)) {
124                         try {
125                             // Copy the file:
126                             Util.copyFile(file, destination, false);
127                             // Delete the original file if requested:
128                             if (deleteOriginalFiles)
129                                 file.delete();
130                             
131                         } catch (IOException ex) {
132                             ex.printStackTrace();
133                         }
134                     }
135                     else {
136                         // Destination and source is the same. Do nothing.
137                     }
138                     // Update progress bar:
139                     i++;
140                     final int j = i;
141
142                     if (prog != null) SwingUtilities.invokeLater(new Runnable() {
143                         public void run() {
144                             prog.setValue(j);
145                         }
146                     });
147                 }
148             }
149             else {
150                 // The link could not be resolved to an existing file.
151                 
152             }
153         }
154
155         if (callback != null) {
156             callback.actionPerformed(null);
157         }
158     }
159
160
161     public static class CopyLinkedFiles extends BaseAction {
162         private BasePanel panel;
163
164         public CopyLinkedFiles(BasePanel panel) {
165
166             this.panel = panel;
167         }
168
169         @Override
170         public void action() throws Throwable {
171
172             ArrayList<BibtexEntry> entries = new ArrayList<BibtexEntry>();
173             BibtexEntry[] sel = panel.getSelectedEntries();
174             for (int i = 0; i < sel.length; i++) {
175                 BibtexEntry bibtexEntry = sel[i];
176                 entries.add(bibtexEntry);
177             }
178             final List<FileListEntry> links =
179                     AccessLinksForEntries.getExternalLinksForEntries(entries);
180             for (Iterator<FileListEntry> iterator = links.iterator(); iterator.hasNext();) {
181                 FileListEntry entry = iterator.next();
182                 System.out.println("Link: " + entry.getLink());
183             }
184
185             final JProgressBar prog = new JProgressBar();
186             prog.setIndeterminate(true);
187             final JDialog diag = new JDialog(panel.frame(), false);
188             diag.getContentPane().add(prog, BorderLayout.CENTER);
189             diag.pack();
190             diag.setLocationRelativeTo(panel.frame());
191             diag.setVisible(true);
192             Thread t = new Thread(new Runnable() {
193                 public void run() {
194                     AccessLinksForEntries.copyExternalLinksToDirectory(links,
195                             new File("/home/alver/tmp"), panel.metaData(), prog, false,
196                             new ActionListener() {
197                                 public void actionPerformed(ActionEvent actionEvent) {
198                                     diag.dispose();
199                                 }
200                             });
201                 }
202             });
203             t.start();
204
205         }
206     }
207
208
209 }