6e2ed7f2eec59dd9b9f1069db280575660485e4d
[debian/jabref.git] / src / java / spl / PdfImporter.java
1 package spl;\r
2 \r
3 import java.io.*;\r
4 import java.util.ArrayList;\r
5 import java.util.Arrays;\r
6 import java.util.List;\r
7 \r
8 import javax.swing.*;\r
9 \r
10 import net.sf.jabref.*;\r
11 import net.sf.jabref.external.DroppedFileHandler;\r
12 import net.sf.jabref.gui.FileListEntry;\r
13 import net.sf.jabref.gui.FileListTableModel;\r
14 import net.sf.jabref.gui.MainTable;\r
15 import net.sf.jabref.imports.PdfContentImporter;\r
16 import net.sf.jabref.imports.PdfXmpImporter;\r
17 import net.sf.jabref.labelPattern.LabelPatternUtil;\r
18 import net.sf.jabref.undo.UndoableInsertEntry;\r
19 import net.sf.jabref.util.XMPUtil;\r
20 \r
21 import org.sciplore.beans.Document;\r
22 \r
23 import spl.filter.PdfFileFilter;\r
24 import spl.gui.ImportDialog;\r
25 import spl.gui.MetaDataListDialog;\r
26 \r
27 \r
28 /**\r
29  * Created by IntelliJ IDEA.\r
30  * User: Christoph Arbeit\r
31  * Date: 08.09.2010\r
32  * Time: 14:49:08\r
33  * To change this template use File | Settings | File Templates.\r
34  */\r
35 public class PdfImporter {\r
36 \r
37     private JabRefFrame frame;\r
38     private BasePanel panel;\r
39     private MainTable entryTable;\r
40     private int dropRow;\r
41 \r
42     public PdfImporter(JabRefFrame frame, BasePanel panel, MainTable entryTable, int dropRow) {\r
43         this.frame = frame;\r
44         this.panel = panel;\r
45         this.entryTable = entryTable;\r
46         this.dropRow = dropRow;\r
47     }\r
48 \r
49     /**\r
50      * \r
51      * Imports the PDF files given by fileNames\r
52      * \r
53      * @param fileNames states the names of the files to import\r
54      * @return list of non-PDF files\r
55      */\r
56     public String[] importPdfFiles(String[] fileNames, OutputPrinter status){\r
57         List<String> files = new ArrayList<String>(Arrays.asList(fileNames));\r
58         List<String> noPdfFiles = new ArrayList<String>();\r
59         PdfFileFilter pdfFilter = new PdfFileFilter();\r
60         for(String file : files){\r
61             if(!pdfFilter.accept(file)){\r
62                 noPdfFiles.add(file);\r
63             }\r
64         }\r
65         files.removeAll(noPdfFiles);\r
66         importPdfFiles(files, status);\r
67         String[] noPdfFilesArray = new String[noPdfFiles.size()];\r
68         noPdfFiles.toArray(noPdfFilesArray);\r
69         return noPdfFilesArray;\r
70     }\r
71 \r
72     /**\r
73      * @param fileNames - PDF files to import\r
74      * @return true if the import succeeded, false otherwise\r
75      */\r
76     private boolean importPdfFiles(List<String> fileNames, OutputPrinter status){\r
77         if(panel == null) return false;\r
78         ImportDialog importDialog = null;\r
79         boolean doNotShowAgain = false;\r
80         boolean neverShow = Globals.prefs.getBoolean(ImportSettingsTab.PREF_IMPORT_ALWAYSUSE);\r
81         int globalChoice = Globals.prefs.getInt(ImportSettingsTab.PREF_IMPORT_DEFAULT_PDF_IMPORT_STYLE);\r
82 \r
83         // Get a list of file directories:\r
84         String[] dirsS = panel.metaData().getFileDirectory(GUIGlobals.FILE_FIELD);\r
85 \r
86         for(String fileName : fileNames){\r
87             List<BibtexEntry> xmpEntriesInFile = readXmpEntries(fileName);\r
88             if (!neverShow && !doNotShowAgain) {\r
89                 importDialog = new ImportDialog(dropRow, fileName);\r
90                 if(!hasXmpEntries(xmpEntriesInFile)){\r
91                         importDialog.disableXMPChoice();\r
92                 }\r
93                 Tools.centerRelativeToWindow(importDialog, frame);\r
94                 importDialog.showDialog();\r
95                 doNotShowAgain = importDialog.getDoNotShowAgain();\r
96             }\r
97             if (neverShow || (importDialog.getResult() == JOptionPane.OK_OPTION)) {\r
98                 int choice = (neverShow?globalChoice:importDialog.getChoice());\r
99                 DroppedFileHandler dfh;\r
100                 BibtexEntry entry;\r
101                 BibtexEntryType type;\r
102                 InputStream in = null;\r
103                 List<BibtexEntry> res = null;\r
104                 MetaDataListDialog metaDataListDialog;\r
105                 switch (choice) {\r
106                         case ImportDialog.XMP:\r
107                     //SplDatabaseChangeListener dataListener = new SplDatabaseChangeListener(frame, panel, entryTable, fileName);\r
108                     //panel.database().addDatabaseChangeListener(dataListener);\r
109                     //ImportMenuItem importer = new ImportMenuItem(frame, (entryTable == null));\r
110                     PdfXmpImporter importer = new PdfXmpImporter();\r
111                     try {\r
112                         in = new FileInputStream(fileName);\r
113                         res = importer.importEntries(in, frame);\r
114                         //importer.automatedImport(new String[]{ fileName });\r
115                     } catch (IOException ex) {\r
116                         ex.printStackTrace();\r
117                     } finally {\r
118                         try { in.close(); } catch (Exception f) {}\r
119                     }\r
120 \r
121                     // import failed -> generate default entry\r
122                     if ((res == null) || (res.size() == 0)) {\r
123                         createNewBlankEntry(fileName);\r
124                         return true;\r
125                     }\r
126 \r
127                     // only one entry is imported\r
128                     entry = res.get(0);\r
129 \r
130                     // insert entry to database and link file\r
131                     panel.database().insertEntry(entry);\r
132                     panel.markBaseChanged();\r
133                     FileListTableModel tm = new FileListTableModel();\r
134                     File toLink = new File(fileName);\r
135                     tm.addEntry(0, new FileListEntry(toLink.getName(),\r
136                             Util.shortenFileName(toLink, dirsS).getPath(),\r
137                             Globals.prefs.getExternalFileTypeByName("pdf")));\r
138                     entry.setField(GUIGlobals.FILE_FIELD, tm.getStringRepresentation());\r
139 \r
140                                 break;\r
141 \r
142                         case ImportDialog.CONTENT:\r
143                         PdfContentImporter contentImporter = new PdfContentImporter();\r
144                         \r
145                         File file = new File (fileName);\r
146 \r
147                         try {\r
148                                                 in = new FileInputStream(file);\r
149                                         } catch (Exception e) {\r
150                                                 // import failed -> generate default entry\r
151                                                 Globals.logger(Globals.lang("Import failed"));\r
152                                                 e.printStackTrace();\r
153                                                 createNewBlankEntry(fileName);\r
154                                                 return true;\r
155                                         }\r
156                                         try {\r
157                                                 res = contentImporter.importEntries(in, status);\r
158                                         } catch (Exception e) {\r
159                                                 // import failed -> generate default entry\r
160                                                 Globals.logger(Globals.lang("Import failed"));\r
161                                                 e.printStackTrace();\r
162                                                 createNewBlankEntry(fileName);\r
163                                                 return true;\r
164                                         } finally {\r
165                                                 try { in.close(); } catch (Exception f) {}\r
166                                         }\r
167                                         \r
168                                         // import failed -> generate default entry\r
169                                         if ((res == null) || (res.size() == 0)) {\r
170                                                 createNewBlankEntry(fileName);\r
171                                                 return true;\r
172                                         }\r
173                                         \r
174                                         // only one entry is imported\r
175                                         entry = res.get(0);\r
176                                         \r
177                                         // insert entry to database and link file\r
178                                         \r
179                     panel.database().insertEntry(entry);\r
180                     panel.markBaseChanged();\r
181                     LabelPatternUtil.makeLabel(panel.metaData(), panel.database(), entry);\r
182                                         dfh = new DroppedFileHandler(frame, panel);\r
183                                         dfh.linkPdfToEntry(fileName, entryTable, entry);\r
184                     panel.highlightEntry(entry);\r
185                     if (Globals.prefs.getBoolean("autoOpenForm")) {\r
186                         EntryEditor editor = panel.getEntryEditor(entry);\r
187                         panel.showEntryEditor(editor);\r
188                         panel.adjustSplitter();\r
189                     }\r
190                     break;\r
191                         case ImportDialog.MRDLIB:\r
192                     metaDataListDialog = new MetaDataListDialog(fileName, true);\r
193                     Tools.centerRelativeToWindow(metaDataListDialog, frame);\r
194                     metaDataListDialog.showDialog();\r
195                     Document document = metaDataListDialog.getXmlDocuments();\r
196                     if(document != null /*&& documents.getDocuments() != null && documents.getDocuments().size() > 0*/ && metaDataListDialog.getResult() == JOptionPane.OK_OPTION){\r
197                         int selected = metaDataListDialog.getTableMetadata().getSelectedRow();\r
198                         if(selected > -1 /*&& selected < documents.getDocuments().size()*/){\r
199                             //Document document = documents/*.getDocuments().get(selected)*/;\r
200                             String id = Util.createNeutralId();\r
201                             entry = new BibtexEntry(id);\r
202                             if(fieldExists(document.getType())){\r
203                                 type = BibtexEntryType.getStandardType(document.getType());\r
204                                 if(type == null){\r
205                                     type = BibtexEntryType.ARTICLE;\r
206                                 }\r
207                                 entry.setType(type);\r
208                             }\r
209                             else{\r
210                                 entry.setType(BibtexEntryType.ARTICLE);\r
211                             }\r
212                             ArrayList<BibtexEntry> list = new ArrayList<BibtexEntry>();\r
213                             list.add(entry);\r
214                             Util.setAutomaticFields(list, true, true, false);\r
215                             //insertFields(entry.getRequiredFields(), entry, document);\r
216                             insertFields(BibtexFields.getAllFieldNames(), entry, document);\r
217                             //insertFields(entry.getOptionalFields(), entry, document);\r
218                             panel.database().insertEntry(entry);\r
219                             dfh = new DroppedFileHandler(frame, panel);\r
220                             dfh.linkPdfToEntry(fileName, entryTable, entry);\r
221                             LabelPatternUtil.makeLabel(panel.metaData(), panel.database(), entry);\r
222                         }\r
223                         else{\r
224                             createNewBlankEntry(fileName);\r
225                         }\r
226                     }\r
227                     else if(metaDataListDialog.getResult() == JOptionPane.CANCEL_OPTION ){\r
228                         continue;\r
229                     }\r
230                     else if(metaDataListDialog.getResult() == JOptionPane.NO_OPTION ){\r
231                         createNewBlankEntry(fileName);\r
232                     }\r
233                     else if(document == null /*|| document.getDocuments() == null || document.getDocuments().size() <= 0*/ && metaDataListDialog.getResult() == JOptionPane.OK_OPTION){\r
234                         createNewBlankEntry(fileName);\r
235                     }\r
236                     break;\r
237                         case ImportDialog.NOMETA:\r
238                     createNewBlankEntry(fileName);\r
239                     break;\r
240                         case ImportDialog.UPDATEEMPTYFIELDS:\r
241                     metaDataListDialog = new MetaDataListDialog(fileName, false);                   \r
242                     Tools.centerRelativeToWindow(metaDataListDialog, frame);\r
243                     metaDataListDialog.showDialog();\r
244                     document = metaDataListDialog.getXmlDocuments();\r
245                     if(document != null /*&& document.getDocuments() != null && document.getDocuments().size() > 0*/ && metaDataListDialog.getResult() == JOptionPane.OK_OPTION){\r
246                         int selected = metaDataListDialog.getTableMetadata().getSelectedRow();\r
247                         if(selected > -1 /*&& selected < document.getDocuments().size()*/){\r
248                             //XmlDocument document = documents.getDocuments().get(selected);\r
249                             entry = entryTable.getEntryAt(dropRow);\r
250                             if(fieldExists(document.getType())){\r
251                                 type = BibtexEntryType.getStandardType(document.getType());\r
252                                 if(type != null){\r
253                                     entry.setType(type);\r
254                                 }\r
255                             }\r
256                             //insertFields(entry.getRequiredFields(), entry, document);\r
257                             insertFields(BibtexFields.getAllFieldNames(), entry, document);\r
258                             //insertFields(entry.getOptionalFields(), entry, document);\r
259 \r
260                             dfh = new DroppedFileHandler(frame, panel);\r
261                             dfh.linkPdfToEntry(fileName, entryTable, dropRow);\r
262                         }\r
263                     }\r
264                     break;\r
265                         case ImportDialog.ONLYATTACH:\r
266                     dfh = new DroppedFileHandler(frame, panel);\r
267                     dfh.linkPdfToEntry(fileName, entryTable, dropRow);\r
268                     break;\r
269                 }\r
270             }\r
271 \r
272 \r
273 \r
274         }\r
275         return true;\r
276     }\r
277 \r
278     private void createNewBlankEntry(String fileName) {\r
279         BibtexEntry newEntry = createNewEntry();\r
280         if(newEntry != null){\r
281             DroppedFileHandler dfh = new DroppedFileHandler(frame, panel);\r
282             dfh.linkPdfToEntry(fileName, entryTable, newEntry);\r
283         }\r
284     }\r
285 \r
286     private void insertFields(String[] fields, BibtexEntry entry, Document xmlDocument) {\r
287         DocumentWrapper document = new DocumentWrapper(xmlDocument);\r
288         for(String field : fields){\r
289             if(entry.getField(field) != null){\r
290                 continue;\r
291             }\r
292             if(field.equalsIgnoreCase("author")){\r
293                 entry.setField(field, document.getAuthors("and"));\r
294             }\r
295             if(field.equalsIgnoreCase("title")){\r
296                 entry.setField(field, document.getTitle());\r
297             }\r
298             if(field.equalsIgnoreCase("abstract")){\r
299                 entry.setField(field, document.getAbstract());\r
300             }\r
301             /*if(field.equalsIgnoreCase("keywords")){\r
302                 entry.setField(field, document.getKeyWords());\r
303             }*/\r
304             if(field.equalsIgnoreCase("doi")){\r
305                 entry.setField(field, document.getDoi());\r
306             }\r
307             /*if(field.equalsIgnoreCase("pages")){\r
308                 entry.setField(field, document.getPages());\r
309             }\r
310             if(field.equalsIgnoreCase("volume")){\r
311                 entry.setField(field, document.getVolume());\r
312             }\r
313             if(field.equalsIgnoreCase("number")){\r
314                 entry.setField(field, document.getNumber());\r
315             }*/\r
316             if(field.equalsIgnoreCase("year")){\r
317                 entry.setField(field, document.getYear());\r
318             }\r
319             /*if(field.equalsIgnoreCase("month")){\r
320                 entry.setField(field, document.getMonth());\r
321             }\r
322             if(field.equalsIgnoreCase("day")){\r
323                 entry.setField(field, document.getDay());\r
324             }\r
325             if(field.equalsIgnoreCase("booktitle")){\r
326                 entry.setField(field, document.getVenue());\r
327             }\r
328             if(field.equalsIgnoreCase("journal")){\r
329                 entry.setField(field, document.getVenue());\r
330             }*/\r
331         }\r
332     }\r
333 \r
334     private boolean fieldExists(String string) {\r
335         return string != null && !string.isEmpty();\r
336     }\r
337 \r
338     private BibtexEntry createNewEntry() {\r
339 \r
340         // Find out what type is wanted.\r
341         EntryTypeDialog etd = new EntryTypeDialog(frame);\r
342         // We want to center the dialog, to make it look nicer.\r
343         Util.placeDialog(etd, frame);\r
344         etd.setVisible(true);\r
345         BibtexEntryType type = etd.getChoice();\r
346 \r
347         if (type != null) { // Only if the dialog was not cancelled.\r
348             String id = Util.createNeutralId();\r
349             final BibtexEntry be = new BibtexEntry(id, type);\r
350             try {\r
351                 panel.database().insertEntry(be);\r
352 \r
353                 // Set owner/timestamp if options are enabled:\r
354                 ArrayList<BibtexEntry> list = new ArrayList<BibtexEntry>();\r
355                 list.add(be);\r
356                 Util.setAutomaticFields(list, true, true, false);\r
357 \r
358                 // Create an UndoableInsertEntry object.\r
359                 panel.undoManager.addEdit(new UndoableInsertEntry(panel.database(), be, panel));\r
360                 panel.output(Globals.lang("Added new")+" '"+type.getName().toLowerCase()+"' "\r
361                        +Globals.lang("entry")+".");\r
362 \r
363                 // We are going to select the new entry. Before that, make sure that we are in\r
364                 // show-entry mode. If we aren't already in that mode, enter the WILL_SHOW_EDITOR\r
365                 // mode which makes sure the selection will trigger display of the entry editor\r
366                 // and adjustment of the splitter.\r
367                 if (panel.getMode() != panel.SHOWING_EDITOR) {\r
368                     panel.setMode(panel.WILL_SHOW_EDITOR);\r
369                 }\r
370 \r
371                 /*int row = entryTable.findEntry(be);\r
372                 if (row >= 0)\r
373                     // Selects the entry. The selection listener will open the editor.                      \r
374                      if (row >= 0) {\r
375                         try{\r
376                             entryTable.setRowSelectionInterval(row, row);\r
377                         }catch(IllegalArgumentException e){\r
378                             System.out.println("RowCount: " + entryTable.getRowCount());\r
379                         }\r
380 \r
381                         //entryTable.setActiveRow(row);\r
382                         entryTable.ensureVisible(row);\r
383                      }\r
384                 else {\r
385                     // The entry is not visible in the table, perhaps due to a filtering search\r
386                     // or group selection. Show the entry editor anyway:\r
387                     panel.showEntry(be);\r
388                 }   */\r
389                 panel.showEntry(be);\r
390                 panel.markBaseChanged(); // The database just changed.\r
391                 new FocusRequester(panel.getEntryEditor(be));\r
392                 return be;\r
393             } catch (KeyCollisionException ex) {\r
394                 Util.pr(ex.getMessage());\r
395             }\r
396         }\r
397         return null;\r
398     }\r
399 \r
400     private List<BibtexEntry> readXmpEntries(String fileName){\r
401         List<BibtexEntry> xmpEntriesInFile = null;\r
402         try {\r
403             xmpEntriesInFile = XMPUtil.readXMP(fileName);\r
404         } catch (Exception e) {\r
405            // Todo Logging\r
406         }\r
407         return xmpEntriesInFile;\r
408     }\r
409 \r
410     private boolean hasXmpEntries(List<BibtexEntry> xmpEntriesInFile){\r
411         if ((xmpEntriesInFile == null) || (xmpEntriesInFile.size() == 0)) {\r
412             return false;\r
413         }\r
414         else{\r
415             return true;\r
416         }\r
417     }\r
418 \r
419     public MainTable getEntryTable() {\r
420         return entryTable;\r
421     }\r
422 \r
423     public void setEntryTable(MainTable entryTable) {\r
424         this.entryTable = entryTable;\r
425     }\r
426 \r
427     public int getDropRow() {\r
428         return dropRow;\r
429     }\r
430 \r
431     public void setDropRow(int dropRow) {\r
432         this.dropRow = dropRow;\r
433     }\r
434 }\r