예제 #1
0
  public void checkEntryTypes(ParserResult _pr) {

    for (BibtexEntry be : _db.getEntries()) {
      if (be.getType() instanceof UnknownEntryType) {
        // Look up the unknown type name in our map of parsed types:

        Object o = entryTypes.get(be.getType().getName().toLowerCase());
        if (o != null) {
          BibtexEntryType type = (BibtexEntryType) o;
          be.setType(type);
        } else {
          // System.out.println("Unknown entry type:
          // "+be.getType().getName());
          _pr.addWarning(
              Globals.lang("unknown entry type")
                  + ": "
                  + be.getType().getName()
                  + ". "
                  + Globals.lang("Type set to 'other'")
                  + ".");
          be.setType(BibtexEntryType.OTHER);
        }
      }
    }
  }
예제 #2
0
  /**
   * Tries to restore the key
   *
   * @return rest of key on success, otherwise empty string
   * @throws IOException on Reader-Error
   */
  private String fixKey() throws IOException {
    StringBuilder key = new StringBuilder();
    int lookahead_used = 0;
    char currentChar;

    // Find a char which ends key (','&&'\n') or entryfield ('='):
    do {
      currentChar = (char) read();
      key.append(currentChar);
      lookahead_used++;
    } while ((currentChar != ',' && currentChar != '\n' && currentChar != '=')
        && (lookahead_used < LOOKAHEAD));

    // Consumed a char too much, back into reader and remove from key:
    unread(currentChar);
    key.deleteCharAt(key.length() - 1);

    // Restore if possible:
    switch (currentChar) {
      case '=':

        // Get entryfieldname, push it back and take rest as key
        key = key.reverse();

        boolean matchedAlpha = false;
        for (int i = 0; i < key.length(); i++) {
          currentChar = key.charAt(i);

          /// Skip spaces:
          if (!matchedAlpha && currentChar == ' ') {
            continue;
          }
          matchedAlpha = true;

          // Begin of entryfieldname (e.g. author) -> push back:
          unread(currentChar);
          if (currentChar == ' ' || currentChar == '\n') {

            /*
             * found whitespaces, entryfieldname completed -> key in
             * keybuffer, skip whitespaces
             */
            StringBuilder newKey = new StringBuilder();
            for (int j = i; j < key.length(); j++) {
              currentChar = key.charAt(j);
              if (!Character.isWhitespace(currentChar)) {
                newKey.append(currentChar);
              }
            }

            // Finished, now reverse newKey and remove whitespaces:
            _pr.addWarning(
                Globals.lang("Line %0: Found corrupted BibTeX-key.", String.valueOf(line)));
            key = newKey.reverse();
          }
        }
        break;

      case ',':
        _pr.addWarning(
            Globals.lang(
                "Line %0: Found corrupted BibTeX-key (contains whitespaces).",
                String.valueOf(line)));

      case '\n':
        _pr.addWarning(
            Globals.lang(
                "Line %0: Found corrupted BibTeX-key (comma missing).", String.valueOf(line)));

        break;

      default:

        // No more lookahead, give up:
        unreadBuffer(key);
        return "";
    }

    return removeWhitespaces(key).toString();
  }
예제 #3
0
  /**
   * Will parse the BibTex-Data found when reading from reader.
   *
   * <p>The reader will be consumed.
   *
   * <p>Multiple calls to parse() return the same results
   *
   * @return ParserResult
   * @throws IOException
   */
  public ParserResult parse() throws IOException {

    // If we already parsed this, just return it.
    if (_pr != null) return _pr;

    _db = new BibtexDatabase(); // Bibtex related contents.
    _meta = new HashMap<String, String>(); // Metadata in comments for Bibkeeper.
    entryTypes = new HashMap<String, BibtexEntryType>(); // To store custem entry types parsed.
    _pr = new ParserResult(_db, _meta, entryTypes);

    // First see if we can find the version number of the JabRef version that
    // wrote the file:
    String versionNum = readJabRefVersionNumber();
    if (versionNum != null) {
      _pr.setJabrefVersion(versionNum);
      setMajorMinorVersions();
    } else {
      // No version number found. However, we have only
    }

    skipWhitespace();

    try {
      while (!_eof) {
        boolean found = consumeUncritically('@');
        if (!found) break;
        skipWhitespace();
        String entryType = parseTextToken();
        BibtexEntryType tp = BibtexEntryType.getType(entryType);
        boolean isEntry = (tp != null);
        // Util.pr(tp.getName());
        if (!isEntry) {
          // The entry type name was not recognized. This can mean
          // that it is a string, preamble, or comment. If so,
          // parse and set accordingly. If not, assume it is an entry
          // with an unknown type.
          if (entryType.toLowerCase().equals("preamble")) {
            _db.setPreamble(parsePreamble());
          } else if (entryType.toLowerCase().equals("string")) {
            BibtexString bs = parseString();
            try {
              _db.addString(bs);
            } catch (KeyCollisionException ex) {
              _pr.addWarning(Globals.lang("Duplicate string name") + ": " + bs.getName());
              // ex.printStackTrace();
            }
          } else if (entryType.toLowerCase().equals("comment")) {
            StringBuffer commentBuf = parseBracketedTextExactly();
            /**
             * Metadata are used to store Bibkeeper-specific information in .bib files.
             *
             * <p>Metadata are stored in bibtex files in the format
             *
             * @comment{jabref-meta: type:data0;data1;data2;...}
             *     <p>Each comment that starts with the META_FLAG is stored in the meta HashMap,
             *     with type as key. Unluckily, the old META_FLAG bibkeeper-meta: was used in JabRef
             *     1.0 and 1.1, so we need to support it as well. At least for a while. We'll always
             *     save with the new one.
             */
            String comment = commentBuf.toString().replaceAll("[\\x0d\\x0a]", "");
            if (comment
                    .substring(0, Math.min(comment.length(), GUIGlobals.META_FLAG.length()))
                    .equals(GUIGlobals.META_FLAG)
                || comment
                    .substring(0, Math.min(comment.length(), GUIGlobals.META_FLAG_OLD.length()))
                    .equals(GUIGlobals.META_FLAG_OLD)) {

              String rest;
              if (comment.substring(0, GUIGlobals.META_FLAG.length()).equals(GUIGlobals.META_FLAG))
                rest = comment.substring(GUIGlobals.META_FLAG.length());
              else rest = comment.substring(GUIGlobals.META_FLAG_OLD.length());

              int pos = rest.indexOf(':');

              if (pos > 0) _meta.put(rest.substring(0, pos), rest.substring(pos + 1));
              // We remove all line breaks in the metadata - these
              // will have been inserted
              // to prevent too long lines when the file was
              // saved, and are not part of the data.
            }

            /**
             * A custom entry type can also be stored in a
             *
             * @comment:
             */
            if (comment
                .substring(0, Math.min(comment.length(), GUIGlobals.ENTRYTYPE_FLAG.length()))
                .equals(GUIGlobals.ENTRYTYPE_FLAG)) {

              CustomEntryType typ = CustomEntryType.parseEntryType(comment);
              entryTypes.put(typ.getName().toLowerCase(), typ);
            }
          } else {
            // The entry type was not recognized. This may mean that
            // it is a custom entry type whose definition will
            // appear
            // at the bottom of the file. So we use an
            // UnknownEntryType
            // to remember the type name by.
            tp = new UnknownEntryType(entryType.toLowerCase());
            // System.out.println("unknown type: "+entryType);
            isEntry = true;
          }
        }

        if (isEntry) // True if not comment, preamble or string.
        {
          /**
           * Morten Alver 13 Aug 2006: Trying to make the parser more robust. If an exception is
           * thrown when parsing an entry, drop the entry and try to resume parsing. Add a warning
           * for the user.
           *
           * <p>An alternative solution is to try rescuing the entry for which parsing failed, by
           * returning the entry with the exception and adding it before parsing is continued.
           */
          try {
            BibtexEntry be = parseEntry(tp);

            boolean duplicateKey = _db.insertEntry(be);
            if (duplicateKey) // JZTODO lyrics
            _pr.addWarning(
                  Globals.lang("duplicate BibTeX key")
                      + ": "
                      + be.getCiteKey()
                      + " ("
                      + Globals.lang("grouping may not work for this entry")
                      + ")");
            else if (be.getCiteKey() == null || be.getCiteKey().equals("")) {
              _pr.addWarning(
                  Globals.lang("empty BibTeX key")
                      + ": "
                      + be.getAuthorTitleYear(40)
                      + " ("
                      + Globals.lang("grouping may not work for this entry")
                      + ")");
            }
          } catch (IOException ex) {
            ex.printStackTrace();
            _pr.addWarning(
                Globals.lang("Error occured when parsing entry")
                    + ": '"
                    + ex.getMessage()
                    + "'. "
                    + Globals.lang("Skipped entry."));
          }
        }

        skipWhitespace();
      }

      // Before returning the database, update entries with unknown type
      // based on parsed type definitions, if possible.
      checkEntryTypes(_pr);

      return _pr;
    } catch (KeyCollisionException kce) {
      // kce.printStackTrace();
      throw new IOException("Duplicate ID in bibtex file: " + kce.toString());
    }
  }