d1ab52ef0b79370aaa591ba6cdf9fc2668843ec9
[debian/jabref.git] / src / java / net / sf / jabref / imports / EndnoteImporter.java
1 package net.sf.jabref.imports;
2
3 import java.util.regex.Pattern;
4 import java.io.InputStream;
5 import java.io.BufferedReader;
6 import java.io.IOException;
7 import java.util.List;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import net.sf.jabref.BibtexEntry;
11 import net.sf.jabref.Globals;
12 import net.sf.jabref.Util;
13 import net.sf.jabref.AuthorList;
14 import net.sf.jabref.BibtexFields;
15
16 /**
17  * Importer for the Refer/Endnote format.
18  *
19  * check here for details on the format
20  * http://www.ecst.csuchico.edu/~jacobsd/bib/formats/endnote.html
21  */
22 public class EndnoteImporter extends ImportFormat {
23
24     /**
25      * Return the name of this import format.
26      */
27     public String getFormatName() {
28     return "Refer/Endnote";
29     }
30
31     /*
32      *  (non-Javadoc)
33      * @see net.sf.jabref.imports.ImportFormat#getCLIId()
34      */
35     public String getCLIId() {
36       return "refer";
37     }
38
39     /**
40      * Check whether the source is in the correct format for this importer.
41      */
42     public boolean isRecognizedFormat(InputStream stream) throws IOException {
43
44     // Our strategy is to look for the "%A *" line.
45     BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
46     Pattern pat1 = Pattern.compile("%A .*"),
47             pat2 = Pattern.compile("%E .*");
48     String str;
49     while ((str = in.readLine()) != null){
50         if (pat1.matcher(str).matches() || pat2.matcher(str).matches())
51             return true;
52     }
53     return false;
54     }
55
56     /**
57      * Parse the entries in the source, and return a List of BibtexEntry
58      * objects.
59      */
60     public List importEntries(InputStream stream) throws IOException {
61     ArrayList bibitems = new ArrayList();
62     StringBuffer sb = new StringBuffer();
63     BufferedReader in = new BufferedReader(ImportFormatReader.getReaderDefaultEncoding(stream));
64     String ENDOFRECORD = "__EOREOR__";
65
66     String str;
67     boolean first = true;
68     while ((str = in.readLine()) != null){
69         str = str.trim();
70         // if(str.equals("")) continue;
71         if (str.indexOf("%0") == 0){
72         if (first){
73             first = false;
74         }else{
75             sb.append(ENDOFRECORD);
76         }
77         sb.append(str);
78         }else sb.append(str);
79         sb.append("\n");
80     }
81
82     String[] entries = sb.toString().split(ENDOFRECORD);
83     HashMap hm = new HashMap();
84     String author = "", Type = "", editor = "";
85     for (int i = 0; i < entries.length; i++){
86         hm.clear();
87         author = "";
88         Type = "";
89         editor = "";
90         boolean IsEditedBook = false;
91         String[] fields = entries[i].trim().substring(1).split("\n%");
92         //String lastPrefix = "";
93         for (int j = 0; j < fields.length; j++){
94
95         if (fields[j].length() < 3) continue;
96
97         /*
98            * Details of Refer format for Journal Article and Book:
99            *
100            * Generic Ref Journal Article Book Code Author %A Author Author Year %D
101            * Year Year Title %T Title Title Secondary Author %E Series Editor
102            * Secondary Title %B Journal Series Title Place Published %C City
103            * Publisher %I Publisher Volume %V Volume Volume Number of Volumes %6
104            * Number of Volumes Number %N Issue Pages %P Pages Number of Pages
105            * Edition %7 Edition Subsidiary Author %? Translator Alternate Title %J
106            * Alternate Journal Label %F Label Label Keywords %K Keywords Keywords
107            * Abstract %X Abstract Abstract Notes %O Notes Notes
108            */
109
110         String prefix = fields[j].substring(0, 1);
111
112         String val = fields[j].substring(2);
113
114         if (prefix.equals("A")){
115             if (author.equals("")) author = val;
116             else author += " and " + val;
117         }else if (prefix.equals("E")){
118             if (editor.equals("")) editor = val;
119             else editor += " and " + val;
120         }else if (prefix.equals("T")) hm.put("title", val);
121         else if (prefix.equals("0")){
122             if (val.indexOf("Journal") == 0) Type = "article";
123             else if ((val.indexOf("Book Section") == 0)) Type = "incollection";
124             else if ((val.indexOf("Book") == 0)) Type = "book";
125             else if (val.indexOf("Edited Book") == 0) {
126                 Type = "book";
127                 IsEditedBook = true;
128             }else if (val.indexOf("Conference") == 0) // Proceedings
129             Type = "inproceedings";
130             else if (val.indexOf("Report") == 0) // Techreport
131             Type = "techreport";
132             else if (val.indexOf("Review") == 0)
133                 Type = "article";
134             else if (val.indexOf("Thesis") == 0)
135                 Type = "phdthesis";
136             else Type = "misc"; //
137         }else if (prefix.equals("7")) hm.put("edition", val);
138         else if (prefix.equals("C")) hm.put("address", val);
139         else if (prefix.equals("D")) hm.put("year", val);
140         else if (prefix.equals("8")) hm.put("date", val);
141         else if (prefix.equals("J")){
142             // "Alternate journal. Let's set it only if no journal
143             // has been set with %B.
144             if (hm.get("journal") == null) hm.put("journal", val);
145         }else if (prefix.equals("B")){
146             // This prefix stands for "journal" in a journal entry, and
147             // "series" in a book entry.
148             if (Type.equals("article")) hm.put("journal", val);
149             else if (Type.equals("book") || Type.equals("inbook")) hm.put(
150                                           "series", val);
151             else /* if (Type.equals("inproceedings")) */
152             hm.put("booktitle", val);
153         }else if (prefix.equals("I")) {
154             if (Type.equals("phdthesis"))
155                 hm.put("school", val);
156             else
157                  hm.put("publisher", val);
158         }
159             // replace single dash page ranges (23-45) with double dashes (23--45):
160         else if (prefix.equals("P")) hm.put("pages", val.replaceAll("([0-9]) *- *([0-9])","$1--$2"));
161         else if (prefix.equals("V")) hm.put("volume", val);
162         else if (prefix.equals("N")) hm.put("number", val);
163         else if (prefix.equals("U")) hm.put("url", val);
164         else if (prefix.equals("O")) hm.put("note", val);
165         else if (prefix.equals("K")) hm.put("keywords", val);
166         else if (prefix.equals("X")) hm.put("abstract", val);
167         else if (prefix.equals("9")){
168             //Util.pr(val);
169             if (val.indexOf("Ph.D.") == 0) Type = "phdthesis";
170             if (val.indexOf("Masters") == 0) Type = "mastersthesis";
171         }else if (prefix.equals("F")) hm.put(BibtexFields.KEY_FIELD, Util
172                              .checkLegalKey(val));
173         }
174
175         // For Edited Book, EndNote puts the editors in the author field.
176         // We want them in the editor field so that bibtex knows it's an edited book
177         if (IsEditedBook && editor.equals("")) {
178            editor = author;
179            author = "";
180         }
181
182         //fixauthorscomma
183         if (!author.equals("")) hm.put("author", fixAuthor(author));
184         if (!editor.equals("")) hm.put("editor", fixAuthor(editor));
185         BibtexEntry b = new BibtexEntry(BibtexFields.DEFAULT_BIBTEXENTRY_ID, Globals
186                         .getEntryType(Type)); // id assumes an existing database so don't
187         // create one here
188         b.setField(hm);
189         //if (hm.isEmpty())
190         if (b.getAllFields().length > 0) bibitems.add(b);
191
192     }
193     return bibitems;
194
195     }
196
197     /**
198      * We must be careful about the author names, since they can be presented differently
199      * by different sources. Normally each %A tag brings one name, and we get the authors
200      * separated by " and ". This is the correct behaviour.
201      * One source lists the names separated by comma, with a comma at the end. We can detect
202      * this format and fix it.
203      * @param s The author string
204      * @return The fixed author string
205      */
206     private String fixAuthor(String s) {
207         int index = s.indexOf(" and ");
208         if (index >= 0)
209             return AuthorList.fixAuthor_lastNameFirst(s);
210         // Look for the comma at the end:
211         index = s.lastIndexOf(",");
212         if (index == s.length()-1) {
213             String mod = s.substring(0, s.length()-1).replaceAll(", ", " and ");
214             return AuthorList.fixAuthor_lastNameFirst(mod);
215         } else
216             return AuthorList.fixAuthor_lastNameFirst(s);
217     }
218
219 }