52f09b047602e40598a16b6f6c6fab17a2b15e36
[debian/jabref.git] / src / java / net / sf / jabref / export / ExportFormats.java
1 package net.sf.jabref.export;
2
3 import java.awt.event.ActionEvent;
4 import java.io.File;
5 import java.util.*;
6
7 import javax.swing.AbstractAction;
8 import javax.swing.JFileChooser;
9 import javax.swing.JOptionPane;
10 import javax.swing.filechooser.FileFilter;
11
12 import net.sf.jabref.*;
13 import net.sf.jabref.plugin.PluginCore;
14 import net.sf.jabref.plugin.core.JabRefPlugin;
15 import net.sf.jabref.plugin.core.generated._JabRefPlugin.ExportFormatExtension;
16 import net.sf.jabref.plugin.core.generated._JabRefPlugin.ExportFormatProviderExtension;
17 import net.sf.jabref.plugin.core.generated._JabRefPlugin.ExportFormatTemplateExtension;
18
19 /**
20  * User: alver
21  * 
22  * Date: Oct 18, 2006 
23  * 
24  * Time: 9:35:08 PM 
25  */
26 public class ExportFormats {
27
28         private static Map<String,IExportFormat> exportFormats = new TreeMap<String,IExportFormat>();
29
30     public static void initAllExports() {
31         exportFormats.clear();
32
33         // Initialize Build-In Export Formats
34         putFormat(new ExportFormat(
35                 Globals.lang("HTML"), "html", "html", null, ".html"));
36         putFormat(new ExportFormat(
37                 Globals.lang("Simple HTML"), "simplehtml", "simplehtml", null, ".html"));
38         putFormat(new ExportFormat(Globals.lang("Docbook"), "docbook", "docbook", null, ".xml"));
39         putFormat(new ExportFormat(Globals.lang("BibTeXML"), "bibtexml", "bibtexml", null, ".xml"));
40         putFormat(new ModsExportFormat());
41         putFormat(new ExportFormat(Globals.lang("HTML table"),
42                 "tablerefs", "tablerefs", "tablerefs", ".html"));
43         putFormat(new ExportFormat(Globals.lang("HTML table (with Abstract & BibTeX)"),
44                 "tablerefsabsbib", "tablerefsabsbib", "tablerefsabsbib", ".html"));
45         putFormat(new ExportFormat(Globals.lang("Harvard RTF"), "harvard", "harvard",
46                 "harvard", ".rtf"));
47         putFormat(new ExportFormat(Globals.lang("Endnote"), "endnote", "EndNote",
48                 "endnote", ".txt"));
49         putFormat(new ExportFormat(Globals.lang("OpenOffice CSV"), "oocsv", "openoffice-csv",
50             "openoffice", ".csv"));
51         putFormat(new OpenOfficeDocumentCreator());
52         putFormat(new OpenDocumentSpreadsheetCreator());
53         putFormat(new MSBibExportFormat());
54         putFormat(new MySQLExport());
55     
56         // Add Export Formats contributed by Plugins
57         JabRefPlugin plugin = JabRefPlugin.getInstance(PluginCore.getManager());
58                 if (plugin != null){
59                         
60                         // 1. ExportFormats based on Templates
61                         for (ExportFormatTemplateExtension e : plugin.getExportFormatTemplateExtensions()){
62                                 ExportFormat format = PluginBasedExportFormat.getFormat(e);
63                                 if (format != null){
64                                         putFormat(format);
65                                 }
66                         }
67
68                         // 2. ExportFormat classed 
69                         for (final ExportFormatExtension e : plugin.getExportFormatExtensions()) {
70                                 putFormat(new IExportFormat(){
71
72                                         public String getConsoleName() {
73                                                 return e.getConsoleName();
74                                         }
75
76                                         public String getDisplayName() {
77                                                 return e.getDisplayName();
78                                         }
79
80                                         public FileFilter getFileFilter() {
81                                                 return new ExportFileFilter(this, e.getExtension());
82                                         }
83
84                                         IExportFormat wrapped;
85                                         public void performExport(BibtexDatabase database, MetaData metaData,
86                                                 String file, String encoding, Set<String> entryIds)
87                                                 throws Exception {
88
89                                                 if (wrapped == null)
90                                                         wrapped = e.getExportFormat();
91                                                 wrapped.performExport(database, metaData, file, encoding, entryIds);
92                                         }
93                                 });
94                         }
95                 
96                         // 3. Formatters provided by Export Format Providers
97                         for (ExportFormatProviderExtension e : plugin.getExportFormatProviderExtensions()) {
98                                 IExportFormatProvider formatProvider = e.getFormatProvider();
99                                 for (IExportFormat exportFormat : formatProvider.getExportFormats()) {
100                                         putFormat(exportFormat);
101                                 }
102                         }
103                 }
104                 
105         // Now add custom export formats
106         for (IExportFormat format : Globals.prefs.customExports.getCustomExportFormats().values()){
107             putFormat(format);
108         }
109     }
110
111         /**
112          * Build a string listing of all available export formats.
113          * 
114          * @param maxLineLength
115          *            The max line length before a line break must be added.
116          * @param linePrefix
117          *            If a line break is added, this prefix will be inserted at the
118          *            beginning of the next line.
119          * @return The string describing available formats.
120          */
121         public static String getConsoleExportList(int maxLineLength, int firstLineSubtr,
122                 String linePrefix) {
123                 StringBuffer sb = new StringBuffer();
124                 int lastBreak = -firstLineSubtr;
125
126                 for (Iterator<String> i = exportFormats.keySet().iterator(); i.hasNext();) {
127                         String name = i.next();
128                         if (sb.length() + 2 + name.length() - lastBreak > maxLineLength) {
129                                 sb.append(",\n");
130                                 lastBreak = sb.length();
131                                 sb.append(linePrefix);
132                         } else if (sb.length() > 0)
133                                 sb.append(", ");
134                         sb.append(name);
135                 }
136
137                 return sb.toString();
138         }
139
140     /**
141      * Get a Map of all export formats.
142      * @return A Map containing all export formats, mapped to their console names.
143      */
144     public static Map<String, IExportFormat> getExportFormats() {
145         // It is perhaps overly paranoid to make a defensive copy in this case:
146         return Collections.unmodifiableMap(exportFormats);
147     } 
148
149     /**
150          * Look up the named export format.
151          * 
152          * @param consoleName
153          *            The export name given in the JabRef console help information.
154          * @return The ExportFormat, or null if no exportformat with that name is
155          *         registered.
156          */
157         public static IExportFormat getExportFormat(String consoleName) {
158                 return exportFormats.get(consoleName);
159         }
160
161         /**
162          * Create an AbstractAction for performing an export operation.
163          * 
164          * @param frame
165          *            The JabRefFrame of this JabRef instance.
166          * @param selectedOnly
167          *            true indicates that only selected entries should be exported,
168          *            false indicates that all entries should be exported.
169          * @return The action.
170          */
171         public static AbstractAction getExportAction(JabRefFrame frame, boolean selectedOnly) {
172
173                 class ExportAction extends MnemonicAwareAction {
174
175                         private static final long serialVersionUID = 639463604530580554L;
176
177                         private JabRefFrame frame;
178
179                         private boolean selectedOnly;
180
181                         public ExportAction(JabRefFrame frame, boolean selectedOnly) {
182                                 this.frame = frame;
183                                 this.selectedOnly = selectedOnly;
184                                 putValue(NAME, selectedOnly ? "Export selected entries" : "Export");
185                         }
186
187                         public void actionPerformed(ActionEvent e) {
188                                 ExportFormats.initAllExports();
189                                 JFileChooser fc = ExportFormats.createExportFileChooser(
190                     Globals.prefs.get("exportWorkingDirectory"));
191                                 fc.showSaveDialog(frame);
192                                 File file = fc.getSelectedFile();
193                                 if (file == null)
194                                         return;
195                                 FileFilter ff = fc.getFileFilter();
196                                 if (ff instanceof ExportFileFilter) {
197
198
199                     ExportFileFilter eff = (ExportFileFilter) ff;
200                     String path = file.getPath();
201                     if (!path.endsWith(eff.getExtension()))
202                         path = path + eff.getExtension();
203                     file = new File(path);
204                     if (file.exists()) {
205                         // Warn that the file exists:
206                         if (JOptionPane.showConfirmDialog(frame, "'" + file.getName() + "' "
207                             + Globals.lang("exists. Overwrite file?"), Globals.lang("Export"),
208                             JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION)
209                             return;
210                     }
211                     final IExportFormat format = eff.getExportFormat();
212                     Set<String> entryIds = null;
213                     if (selectedOnly) {
214                         BibtexEntry[] selected = frame.basePanel().getSelectedEntries();
215                         entryIds = new HashSet<String>();
216                         for (int i = 0; i < selected.length; i++) {
217                             BibtexEntry bibtexEntry = selected[i];
218                             entryIds.add(bibtexEntry.getId());
219                         }
220                     }
221
222                     // Set the global variable for this database's file directory before exporting,
223                     // so formatters can resolve linked files correctly.
224                     // (This is an ugly hack!)
225                     Globals.prefs.fileDirForDatabase = frame.basePanel().metaData()
226                             .getFileDirectory(GUIGlobals.FILE_FIELD);                    
227
228                     // Make sure we remember which filter was used, to set
229                     // the default for next time:
230                     Globals.prefs.put("lastUsedExport", format.getConsoleName());
231                     Globals.prefs.put("exportWorkingDirectory", file.getParent());
232                     
233                     final File finFile = file;
234                     final Set<String> finEntryIDs = entryIds;
235                     AbstractWorker exportWorker = new AbstractWorker() {
236                         String errorMessage = null;
237                         public void run() {
238                             try {
239                                 format.performExport(frame.basePanel().database(),
240                                         frame.basePanel().metaData(),
241                                         finFile.getPath(), frame
242                                     .basePanel().getEncoding(), finEntryIDs);
243                             } catch (Exception ex) {
244                                 if (ex.getMessage()==null ) {
245                                     errorMessage = ex.toString();
246                                 } else {
247                                     errorMessage = ex.getMessage();
248                                 }
249                             }
250                         }
251
252                         public void update() {
253                             // No error message. Report success:
254                             if (errorMessage == null) {
255                                 frame.output(Globals.lang("%0 export successful", format.getDisplayName()));
256                             }
257                             // ... or show an error dialog:
258                             else {
259                                 frame.output(Globals.lang("Could not save file")
260                                         + " - " + errorMessage);
261                                 // Need to warn the user that saving failed!
262                                 JOptionPane.showMessageDialog(frame, Globals.lang("Could not save file")
263                                     + ".\n" + errorMessage, Globals.lang("Save database"),
264                                     JOptionPane.ERROR_MESSAGE);
265                             }
266                         }
267                     };
268
269                     // Run the export action in a background thread:
270                     (exportWorker.getWorker()).run();
271                     // Run the update method:
272                     exportWorker.update();
273                 }
274                         }
275                 }
276
277                 return new ExportAction(frame, selectedOnly);
278         }
279
280     
281     public static JFileChooser createExportFileChooser(String currentDir) {
282                 String lastUsedFormat = Globals.prefs.get("lastUsedExport");
283                 FileFilter defaultFilter = null;
284                 JFileChooser fc = new JFileChooser(currentDir);
285                 TreeSet<FileFilter> filters = new TreeSet<FileFilter>();
286                 for (Map.Entry<String, IExportFormat> e : exportFormats.entrySet()) {
287                         String formatName = e.getKey() ;
288                         IExportFormat format = e.getValue();
289                         filters.add(format.getFileFilter());
290                         if (formatName.equals(lastUsedFormat))
291                                 defaultFilter = format.getFileFilter();
292                 }
293                 for (FileFilter ff : filters) {
294                         fc.addChoosableFileFilter(ff);
295                 }
296                 fc.setAcceptAllFileFilterUsed(false);
297                 if (defaultFilter != null)
298                         fc.setFileFilter(defaultFilter);
299                 return fc;
300         }
301
302         private static void putFormat(IExportFormat format) {
303                 exportFormats.put(format.getConsoleName(), format);
304         }
305
306 }