Coverage Report - net.sf.jabref.imports.ImportFormatReader
 
Classes in this File Line Coverage Branch Coverage Complexity
ImportFormatReader
20%
43/205
10%
11/110
4.8
 
 1  
 /*
 2  
  * Copyright (C) 2003 Morten O. Alver and Nizar N. Batada
 3  
  *
 4  
  * All programs in this directory and subdirectories are published under the GNU
 5  
  * General Public License as described below.
 6  
  *
 7  
  * This program is free software; you can redistribute it and/or modify it under
 8  
  * the terms of the GNU General Public License as published by the Free Software
 9  
  * Foundation; either version 2 of the License, or (at your option) any later
 10  
  * version.
 11  
  *
 12  
  * This program is distributed in the hope that it will be useful, but WITHOUT
 13  
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 14  
  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 15  
  * details.
 16  
  *
 17  
  * You should have received a copy of the GNU General Public License along with
 18  
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 19  
  * Place, Suite 330, Boston, MA 02111-1307 USA
 20  
  *
 21  
  * Further information about the GNU GPL is available at:
 22  
  * http://www.gnu.org/copyleft/gpl.ja.html
 23  
  *
 24  
  */
 25  
 package net.sf.jabref.imports;
 26  
 
 27  
 import java.io.*;
 28  
 import net.sf.jabref.util.Pair;
 29  
 import java.util.*;
 30  
 
 31  
 import net.sf.jabref.*;
 32  
 import net.sf.jabref.plugin.PluginCore;
 33  
 import net.sf.jabref.plugin.core.JabRefPlugin;
 34  
 import net.sf.jabref.plugin.core.generated._JabRefPlugin.ImportFormatExtension;
 35  
 
 36  
 
 37  
 public class ImportFormatReader {
 38  
 
 39  145548291
     public static String BIBTEX_FORMAT = "BibTeX";
 40  
 
 41  
   /** all import formats, in the default order of import formats */
 42  145548291
   private SortedSet<ImportFormat> formats = new TreeSet<ImportFormat>();
 43  
 
 44  
   public ImportFormatReader() {
 45  145548291
     super();
 46  145548291
   }
 47  
 
 48  
   public void resetImportFormats() {
 49  145548291
     formats.clear();
 50  
     
 51  
     // Add all our importers to the TreeMap. The map is used to build the import
 52  
     // menus, and .
 53  145548291
     formats.add(new CsaImporter());   
 54  145548291
     formats.add(new IsiImporter());
 55  145548291
     formats.add(new EndnoteImporter());
 56  145548291
     formats.add(new BibteXMLImporter());
 57  145548291
     formats.add(new BiblioscapeImporter());
 58  145548291
     formats.add(new SixpackImporter());
 59  145548291
     formats.add(new InspecImporter());
 60  145548291
     formats.add(new ScifinderImporter());
 61  145548291
     formats.add(new OvidImporter());
 62  145548291
     formats.add(new RisImporter());
 63  145548291
     formats.add(new JstorImporter());
 64  145548291
     formats.add(new SilverPlatterImporter());
 65  145548291
     formats.add(new BiomailImporter());
 66  145548291
     formats.add(new RepecNepImporter());  
 67  145548291
     formats.add(new PdfXmpImporter());
 68  145548291
     formats.add(new CopacImporter());
 69  145548291
     formats.add(new MsBibImporter());
 70  
 
 71  
     /**
 72  
      * Get import formats that are plug-ins
 73  
      */
 74  145548291
     JabRefPlugin jabrefPlugin = JabRefPlugin.getInstance(PluginCore.getManager());
 75  145548291
         if (jabrefPlugin != null){
 76  145548291
                 for (ImportFormatExtension ext : jabrefPlugin.getImportFormatExtensions()){
 77  145548291
                         ImportFormat importFormat = ext.getImportFormat();
 78  145548291
                         if (importFormat != null){
 79  145548291
                                 formats.add(importFormat);
 80  
                         }
 81  145548291
                 }
 82  
         }
 83  
         
 84  
         /**
 85  
          * Get custom import formats
 86  
          */
 87  145548291
     for (CustomImportList.Importer importer : Globals.prefs.customImports){
 88  
        try {
 89  0
         ImportFormat imFo = importer.getInstance();
 90  0
         formats.add(imFo);
 91  0
       } catch(Exception e) {
 92  0
         System.err.println("Could not instantiate " + importer.getName() + " importer, will ignore it. Please check if the class is still available.");
 93  0
         e.printStackTrace();
 94  0
       }      
 95  
     }
 96  145548291
   }
 97  
   
 98  
   /**
 99  
    * Format for a given CLI-ID.
 100  
    * 
 101  
    * <p>Will return the first format according to the default-order of
 102  
    * format that matches the given ID.</p>
 103  
    * 
 104  
    * @param cliId  CLI-Id
 105  
    * @return  Import Format or <code>null</code> if none matches
 106  
    */
 107  
   public ImportFormat getByCliId(String cliId) {
 108  0
     for (ImportFormat format : formats){
 109  0
       if (format.getCLIId().equals(cliId)) {
 110  0
         return format;
 111  
       }
 112  
     }
 113  0
     return null;
 114  
   }
 115  
   
 116  
   public List<BibtexEntry> importFromStream(String format, InputStream in)
 117  
     throws IOException {
 118  0
     ImportFormat importer = getByCliId(format);
 119  
 
 120  0
     if (importer == null)
 121  0
       throw new IllegalArgumentException("Unknown import format: " + format);
 122  
 
 123  0
     List<BibtexEntry> res = importer.importEntries(in);
 124  
 
 125  
     // Remove all empty entries
 126  0
     if (res != null)
 127  0
       purgeEmptyEntries(res);
 128  
 
 129  0
     return res;
 130  
   }
 131  
 
 132  
   public List<BibtexEntry> importFromFile(String format, String filename)
 133  
     throws IOException {
 134  0
     ImportFormat importer = getByCliId(format);
 135  
 
 136  0
     if (importer == null)
 137  0
       throw new IllegalArgumentException("Unknown import format: " + format);
 138  
 
 139  0
     return importFromFile(importer, filename);
 140  
   }
 141  
 
 142  
     public List<BibtexEntry> importFromFile(ImportFormat importer, String filename) throws IOException {
 143  0
         List<BibtexEntry> result = null;
 144  0
         InputStream stream = null;
 145  
         try {
 146  0
             File file = new File(filename);
 147  0
             stream = new FileInputStream(file);
 148  
 
 149  0
             if (!importer.isRecognizedFormat(stream))
 150  0
                 throw new IOException(Globals.lang("Wrong file format"));
 151  
 
 152  0
             stream = new FileInputStream(file);
 153  
 
 154  0
             result = importer.importEntries(stream);
 155  
         } finally {
 156  
 
 157  0
             try {
 158  0
                 if (stream != null)
 159  0
                     stream.close();
 160  0
             } catch (IOException ex) {
 161  0
                 throw ex;
 162  0
             }
 163  
         }
 164  
 
 165  0
         return result;
 166  
     }
 167  
 
 168  
   public static BibtexDatabase createDatabase(Collection<BibtexEntry> bibentries) {
 169  0
     purgeEmptyEntries(bibentries);
 170  
 
 171  0
     BibtexDatabase database = new BibtexDatabase();
 172  
 
 173  0
     for (Iterator<BibtexEntry> i = bibentries.iterator(); i.hasNext();) {
 174  0
       BibtexEntry entry = i.next();
 175  
 
 176  
       try {
 177  0
         entry.setId(Util.createNeutralId());
 178  0
         database.insertEntry(entry);
 179  0
       } catch (KeyCollisionException ex) {
 180  0
         System.err.println("KeyCollisionException [ addBibEntries(...) ]");
 181  0
       }
 182  0
     }
 183  
 
 184  0
     return database;
 185  
   }
 186  
 
 187  
   /**
 188  
    * All custom importers.
 189  
    * 
 190  
    * <p>Elements are in default order.</p>
 191  
    * 
 192  
    * @return all custom importers, elements are of type InputFormat
 193  
    */
 194  
   public SortedSet<ImportFormat> getCustomImportFormats() {
 195  281806960
     SortedSet<ImportFormat> result = new TreeSet<ImportFormat>();
 196  281806960
     for (ImportFormat format : formats){
 197  5072525280
       if (format.getIsCustomImporter()) {
 198  0
         result.add(format);  
 199  
       }
 200  
     }
 201  281806960
     return result;
 202  
   }
 203  
   
 204  
   /**
 205  
    * All built-in importers.
 206  
    * 
 207  
    * <p>Elements are in default order.</p>
 208  
    * 
 209  
    * @return all custom importers, elements are of type InputFormat
 210  
    */
 211  
   public SortedSet<ImportFormat> getBuiltInInputFormats() {
 212  281806960
                 SortedSet<ImportFormat> result = new TreeSet<ImportFormat>();
 213  281806960
                 for (ImportFormat format : formats) {
 214  5072525280
                         if (!format.getIsCustomImporter()) {
 215  5072525280
                                 result.add(format);
 216  
                         }
 217  
                 }
 218  281806960
                 return result;
 219  
         }
 220  
   
 221  
   /**
 222  
          * All importers.
 223  
          * 
 224  
          * <p>
 225  
          * Elements are in default order.
 226  
          * </p>
 227  
          * 
 228  
          * @return all custom importers, elements are of type InputFormat
 229  
          */
 230  
   public SortedSet<ImportFormat> getImportFormats() {
 231  113688
     return this.formats;
 232  
   }
 233  
 
 234  
   /**
 235  
    * Human readable list of all known import formats (name and CLI Id).
 236  
    * 
 237  
    * <p>List is in default-order.</p>
 238  
    * 
 239  
    * @return  human readable list of all known import formats
 240  
    */
 241  
   public String getImportFormatList() {
 242  0
     StringBuffer sb = new StringBuffer();
 243  
 
 244  0
     for (ImportFormat imFo : formats){
 245  0
       int pad = Math.max(0, 14 - imFo.getFormatName().length());
 246  0
       sb.append("  ");
 247  0
       sb.append(imFo.getFormatName());
 248  
 
 249  0
       for (int j = 0; j < pad; j++)
 250  0
         sb.append(" ");
 251  
 
 252  0
       sb.append(" : ");
 253  0
       sb.append(imFo.getCLIId());
 254  0
       sb.append("\n");
 255  0
     }
 256  
 
 257  0
     String res = sb.toString();
 258  
 
 259  0
     return res; //.substring(0, res.length()-1);
 260  
   }
 261  
 
 262  
 
 263  
     /**
 264  
      * Expand initials, e.g. EH Wissler -> E. H. Wissler or Wissler, EH -> Wissler, E. H.
 265  
      * @param name
 266  
      * @return The name after expanding initials.
 267  
      */
 268  
     public static String expandAuthorInitials(String name) {
 269  0
       String[] authors = name.split(" and ");
 270  0
       StringBuffer sb = new StringBuffer();
 271  0
       for (int i=0; i<authors.length; i++) {
 272  0
           if (authors[i].indexOf(", ") >= 0) {
 273  0
               String[] names = authors[i].split(", ");
 274  0
               if (names.length > 0) {
 275  0
                   sb.append(names[0]);
 276  0
                   if (names.length > 1)
 277  0
                     sb.append(", ");
 278  
               }
 279  0
               for (int j=1; j<names.length; j++) {
 280  0
                   sb.append(expandAll(names[j]));
 281  
               }
 282  
 
 283  0
           } else {
 284  0
               String[] names = authors[i].split(" ");
 285  0
               if (names.length > 0) {
 286  0
                   sb.append(expandAll(names[0]));
 287  
               }
 288  0
               for (int j=1; j<names.length; j++) {
 289  0
                   sb.append(" ");
 290  0
                   sb.append(names[j]);
 291  
               }
 292  
           }
 293  0
           if (i < authors.length-1)
 294  0
               sb.append(" and ");
 295  
       }
 296  
 
 297  0
       return sb.toString().trim();
 298  
   }
 299  
   
 300  
 //------------------------------------------------------------------------------
 301  
 
 302  
 
 303  
     public static String expandAll(String s) {
 304  
         //System.out.println("'"+s+"'");
 305  
         // Avoid arrayindexoutof.... :
 306  0
         if (s.length() == 0)
 307  0
           return s;
 308  
         // If only one character (uppercase letter), add a dot and return immediately:
 309  0
         if ((s.length() == 1) && (Character.isLetter(s.charAt(0)) &&
 310  
                 Character.isUpperCase(s.charAt(0))))
 311  0
           return s+".";
 312  0
         StringBuffer sb = new StringBuffer();
 313  0
         char c = s.charAt(0), d = 0;
 314  0
         for (int i=1; i<s.length(); i++) {
 315  0
             d = s.charAt(i);
 316  0
             if (Character.isLetter(c) && Character.isUpperCase(c) &&
 317  
                     Character.isLetter(d) && Character.isUpperCase(d)) {
 318  0
                 sb.append(c);
 319  0
                 sb.append(". ");
 320  
             }
 321  
             else {
 322  0
                 sb.append(c);
 323  
             }
 324  0
             c = d;
 325  
         }
 326  0
         if (Character.isLetter(c) && Character.isUpperCase(c) &&
 327  
               Character.isLetter(d) && Character.isUpperCase(d)) {
 328  0
             sb.append(c);
 329  0
             sb.append(". ");
 330  
         }
 331  
         else {
 332  0
             sb.append(c);
 333  
         }
 334  0
         return sb.toString().trim();
 335  
     }
 336  
 
 337  
 
 338  
   static File checkAndCreateFile(String filename) {
 339  0
     File f = new File(filename);
 340  
 
 341  0
     if (!f.exists() && !f.canRead() && !f.isFile()) {
 342  0
       System.err.println("Error " + filename
 343  
         + " is not a valid file and|or is not readable.");
 344  0
       Globals.logger("Error " + filename + " is not a valid file and|or is not readable.");
 345  
 
 346  0
       return null;
 347  
     } else
 348  
 
 349  0
       return f;
 350  
   }
 351  
 
 352  
   //==================================================
 353  
   // Set a field, unless the string to set is empty.
 354  
   //==================================================
 355  
   public static void setIfNecessary(BibtexEntry be, String field, String content) {
 356  0
     if (!content.equals(""))
 357  0
       be.setField(field, content);
 358  0
   }
 359  
 
 360  
 
 361  
 
 362  
     public static Reader getReader(File f, String encoding)
 363  
       throws IOException {
 364  
       InputStreamReader reader;
 365  19544830
       reader = new InputStreamReader(new FileInputStream(f), encoding);
 366  
 
 367  19544830
       return reader;
 368  
     }
 369  
 
 370  
   public static Reader getReaderDefaultEncoding(InputStream in)
 371  
     throws IOException {
 372  
     InputStreamReader reader;
 373  0
     reader = new InputStreamReader(in, Globals.prefs.get("defaultEncoding"));
 374  
 
 375  0
     return reader;
 376  
   }
 377  
 
 378  
   public static BibtexDatabase import_File(String format, String filename)
 379  
     throws IOException {
 380  0
     BibtexDatabase database = null;
 381  0
     List<BibtexEntry> bibentries = null;
 382  0
     File f = new File(filename);
 383  
 
 384  0
     if (!f.exists())
 385  0
       throw new IOException(Globals.lang("File not found") + ": " + filename);
 386  
 
 387  
     try {
 388  0
       bibentries = Globals.importFormatReader.importFromFile(format, filename);
 389  0
     } catch (IllegalArgumentException ex) {
 390  0
       throw new IOException(Globals.lang("Could not resolve import format") + " '"
 391  
         + format + "'");
 392  0
     }
 393  
 
 394  0
     if (bibentries == null)
 395  0
       throw new IOException(Globals.lang("Import failed"));
 396  
 
 397  
     // Remove all empty entries:
 398  0
     purgeEmptyEntries(bibentries);
 399  
 
 400  
     // Add entries to database.
 401  0
     database = new BibtexDatabase();
 402  
 
 403  0
     Iterator<BibtexEntry> it = bibentries.iterator();
 404  
 
 405  0
     while (it.hasNext()) {
 406  0
       BibtexEntry entry = it.next();
 407  
 
 408  
       try {
 409  0
         entry.setId(Util.createNeutralId());
 410  0
         database.insertEntry(entry);
 411  0
       } catch (KeyCollisionException ex) {
 412  
         //ignore
 413  0
         System.err.println("KeyCollisionException [ addBibEntries(...) ]");
 414  0
       }
 415  0
     }
 416  
 
 417  0
     return database;
 418  
   }
 419  
 
 420  
   /**
 421  
    * Receives an ArrayList of BibtexEntry instances, iterates through them, and
 422  
    * removes all entries that have no fields set. This is useful for rooting out
 423  
    * an unsucessful import (wrong format) that returns a number of empty entries.
 424  
    */
 425  
   public static void purgeEmptyEntries(Collection<BibtexEntry> entries) {
 426  0
     for (Iterator<BibtexEntry> i = entries.iterator(); i.hasNext();) {
 427  0
       BibtexEntry entry = i.next();
 428  
 
 429  
       // If there are no fields, remove the entry:
 430  0
       if (entry.getAllFields().size() == 0)
 431  0
         i.remove();
 432  0
     }
 433  0
   }
 434  
 
 435  
   /**
 436  
          * Tries to import a file by iterating through the available import filters,
 437  
          * and keeping the import that seems most promising.
 438  
          * 
 439  
          * If all fails this method attempts to read this file as bibtex.
 440  
          * 
 441  
          * @throws IOException 
 442  
          */
 443  
         public Pair<String, ParserResult> importUnknownFormat(String filename) throws IOException {
 444  
 
 445  0
                 Pair<String, ParserResult> result = null;
 446  
                 
 447  
                 // Cycle through all importers:
 448  0
                 int bestResult = 0;
 449  
 
 450  0
         for (ImportFormat imFo : getImportFormats()) {
 451  
 
 452  
             try {
 453  
 
 454  0
                 List<BibtexEntry> entries = importFromFile(imFo, filename);
 455  
 
 456  0
                 if (entries != null)
 457  0
                     purgeEmptyEntries(entries);
 458  
 
 459  0
                 int entryCount = ((entries != null) ? entries.size() : 0);
 460  
 
 461  0
                 if (entryCount > bestResult) {
 462  0
                     bestResult = entryCount;
 463  
 
 464  0
                     result = new Pair<String, ParserResult>(imFo.getFormatName(),
 465  
                     new ParserResult(entries));
 466  
                 }
 467  0
             } catch (IOException ex) {
 468  
                 // The import didn't succeed. Go on.
 469  0
             }
 470  
         }
 471  
                 
 472  0
                 if (result != null)
 473  0
                         return result;
 474  
 
 475  
       // Finally, if all else fails, see if it is a BibTeX file:
 476  
       try {
 477  0
           ParserResult pr = OpenDatabaseAction.loadDatabase(new File(filename),
 478  
                   Globals.prefs.get("defaultEncoding"));
 479  0
           if ((pr.getDatabase().getEntryCount() > 0)
 480  
                   || (pr.getDatabase().getStringCount() > 0)) {
 481  0
               pr.setFile(new File(filename));
 482  
 
 483  0
               return new Pair<String, ParserResult>(BIBTEX_FORMAT, pr);
 484  
           }
 485  0
       } catch (RuntimeException ex) {
 486  0
           return null;
 487  0
       }
 488  
 
 489  0
       return null;
 490  
         }
 491  
 }