313b434b753111d01b00ac24becaaede6b57cbd9
[debian/jabref.git] / src / java / net / sf / jabref / export / ExportFormat.java
1 package net.sf.jabref.export;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.Reader;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Set;
9
10 import javax.swing.filechooser.FileFilter;
11
12 import net.sf.jabref.BibtexDatabase;
13 import net.sf.jabref.BibtexEntry;
14 import net.sf.jabref.MetaData;
15 import net.sf.jabref.Globals;
16 import net.sf.jabref.export.layout.Layout;
17 import net.sf.jabref.export.layout.LayoutHelper;
18
19 /**
20  * Base class for export formats based on templates.
21  * 
22  */
23 public class ExportFormat implements IExportFormat {
24
25         String displayName;
26         String consoleName;
27         String lfFileName;
28         String directory;
29         String extension;
30         FileFilter fileFilter;
31         boolean customExport = false;
32
33         /**
34          * Initialize another export format based on templates stored in dir with
35          * layoutFile lfFilename.
36          * 
37          * @param displayName
38          *            Name to display to the user.
39          * @param consoleName
40          *            Name to call this format in the console.
41          * @param lfFileName
42          *            Name of the main layout file.
43          * @param directory
44          *            Directory in which to find the layout file.
45          * @param extension
46          *            Should contain the . (for instance .txt).
47          */
48         public ExportFormat(String displayName, String consoleName,
49                 String lfFileName, String directory, String extension) {
50                 this.displayName = displayName;
51                 this.consoleName = consoleName;
52                 this.lfFileName = lfFileName;
53                 this.directory = directory;
54                 this.extension = extension;
55         }
56
57         /** Empty default constructor for subclasses */
58         protected ExportFormat() {
59                 // intentionally empty
60         }
61
62         /**
63          * Indicate whether this is a custom export. A custom export looks for its
64          * layout files using a normal file path, while a built-in export looks in
65          * the classpath.
66          * 
67          * @param custom
68          *            true to indicate a custom export format.
69          */
70         public void setCustomExport(boolean custom) {
71                 this.customExport = custom;
72         }
73
74         /**
75          * @see IExportFormat#getConsoleName()
76          */
77         public String getConsoleName() {
78                 return consoleName;
79         }
80
81         /**
82          * @see IExportFormat#getDisplayName()
83          */
84         public String getDisplayName() {
85                 return displayName;
86         }
87
88         /**
89          * This method should return a reader from which the given layout file can
90          * be read.
91          * 
92          * This standard implementation of this method will use the
93          * {@link FileActions#getReader(String)} method.
94          * 
95          * Subclasses of ExportFormat are free to override and provide their own
96          * implementation.
97          * 
98          * @param filename
99          *            the file name
100          * @throws IOException
101          *             if the reader could not be created
102          * 
103          * @return a newly created reader
104          */
105         protected Reader getReader(String filename) throws IOException {
106                 // If this is a custom export, just use the given file name:
107                 String dir;
108                 if (customExport) {
109                         dir = "";
110                 } else {
111                         dir = Globals.LAYOUT_PREFIX
112                                 + (directory == null ? "" : directory + "/");
113                 }
114                 return FileActions.getReader(dir + filename);
115         }
116
117         /**
118          * Perform the export of {@code database}.
119          * 
120          * @param database
121          *            The database to export from.
122      * @param metaData
123      *            The database's meta data.
124          * @param file
125          *            the file to write the resulting export to
126          * @param encoding
127          *            The encoding of the database
128          * @param entryIds
129          *            Contains the IDs of all entries that should be exported. If
130          *            <code>null</code>, all entries will be exported.
131          * 
132          * @throws IOException
133          *             if a problem occurred while trying to write to {@code writer}
134          *             or read from required resources.
135          * @throws Exception
136          *             if any other error occurred during export.
137          * 
138          * @see net.sf.jabref.export.IExportFormat#performExport(net.sf.jabref.BibtexDatabase,
139          *      net.sf.jabref.MetaData, java.lang.String, java.lang.String, java.util.Set)
140          */
141         public void performExport(final BibtexDatabase database,
142             final MetaData metaData, final String file,
143                 final String encoding, Set<String> entryIds) throws Exception {
144
145                 File outFile = new File(file);
146                 SaveSession ss = getSaveSession(encoding, outFile);
147                 VerifyingWriter ps = ss.getWriter();
148
149                 // Print header
150                 Layout beginLayout = null;
151                 Reader reader;
152                 try {
153                         reader = getReader(lfFileName + ".begin.layout");
154                         LayoutHelper layoutHelper = new LayoutHelper(reader);
155                         beginLayout = layoutHelper
156                                 .getLayoutFromText(Globals.FORMATTER_PACKAGE);
157                         reader.close();
158                 } catch (IOException ex) {
159                         // If an exception was cast, export filter doesn't have a begin
160                         // file.
161                 }
162                 // Write the header
163                 if (beginLayout != null) {
164                         ps.write(beginLayout.doLayout(database, encoding));
165                 }
166
167                 /*
168                  * Write database entries; entries will be sorted as they appear on the
169                  * screen, or sorted by author, depending on Preferences. We also supply
170                  * the Set entries - if we are to export only certain entries, it will
171                  * be non-null, and be used to choose entries. Otherwise, it will be
172                  * null, and be ignored.
173                  */
174                 List<BibtexEntry> sorted = FileActions.getSortedEntries(database,
175                         entryIds, false);
176
177                 // Load default layout
178                 reader = getReader(lfFileName + ".layout");
179
180                 LayoutHelper layoutHelper = new LayoutHelper(reader);
181                 Layout defLayout = layoutHelper
182                         .getLayoutFromText(Globals.FORMATTER_PACKAGE);
183                 reader.close();
184                 HashMap<String, Layout> layouts = new HashMap<String, Layout>();
185                 Layout layout;
186                 for (BibtexEntry entry : sorted) {
187                         // Get the layout
188                         String type = entry.getType().getName().toLowerCase();
189                         if (layouts.containsKey(type))
190                                 layout = layouts.get(type);
191                         else {
192                                 try {
193                                         // We try to get a type-specific layout for this entry.
194                                         reader = getReader(lfFileName + "." + type + ".layout");
195                                         layoutHelper = new LayoutHelper(reader);
196                                         layout = layoutHelper
197                                                 .getLayoutFromText(Globals.FORMATTER_PACKAGE);
198                                         layouts.put(type, layout);
199                                         reader.close();
200                                 } catch (IOException ex) {
201                                         // The exception indicates that no type-specific layout
202                                         // exists, so we
203                                         // go with the default one.
204                                         layout = defLayout;
205                                 }
206                         }
207
208                         // Write the entry
209                         ps.write(layout.doLayout(entry, database));
210                 }
211
212                 // Print footer
213
214                 // changed section - begin (arudert)
215                 Layout endLayout = null;
216                 try {
217                         reader = getReader(lfFileName + ".end.layout");
218                         layoutHelper = new LayoutHelper(reader);
219                         endLayout = layoutHelper
220                                 .getLayoutFromText(Globals.FORMATTER_PACKAGE);
221                         reader.close();
222                 } catch (IOException ex) {
223                         // If an exception was thrown, export filter doesn't have an end
224                         // file.
225                 }
226
227                 // Write footer
228                 if (endLayout != null) {
229                         ps.write(endLayout.doLayout(database, encoding));
230                 }
231
232                 finalizeSaveSession(ss);
233         }
234
235         protected SaveSession getSaveSession(final String encoding,
236                 final File outFile) throws IOException {
237                 return new SaveSession(outFile, encoding, false);
238         }
239
240         /**
241          * @see net.sf.jabref.export.IExportFormat#getFileFilter()
242          */
243         public FileFilter getFileFilter() {
244                 if (fileFilter == null)
245                         fileFilter = new ExportFileFilter(this, extension);
246                 return fileFilter;
247         }
248
249         public void finalizeSaveSession(final SaveSession ss) throws Exception {
250                 ss.getWriter().flush();
251                 ss.getWriter().close();
252
253                 if (!ss.getWriter().couldEncodeAll()) {
254                         System.err.println("Could not encode...");
255                 }
256                 ss.commit();
257         }
258 }