Verified Owner
Top Description Inners Fields Constructors Methods
org.jabref.logic.importer.fileformat

public Class BibtexParser

extends Object
implements Parser
Class Inheritance
All Implemented Interfaces
org.jabref.logic.importer.Parser
Imports
java.io.ByteArrayInputStream, .IOException, .InputStream, .PushbackReader, .Reader, .StringWriter, java.nio.file.Path, java.util.ArrayDeque, .Base64, .Collection, .Deque, .HashMap, .HashSet, .LinkedHashMap, .LinkedList, .List, .Locale, .Map, .Optional, .Set, java.util.function.Predicate, java.util.regex.Pattern, javax.xml.parsers.DocumentBuilderFactory, .ParserConfigurationException, org.jabref.logic.bibtex.FieldWriter, org.jabref.logic.exporter.BibDatabaseWriter, .SaveConfiguration, org.jabref.logic.groups.GroupsFactory, org.jabref.logic.importer.ImportFormatPreferences, .Importer, .KeywordImportNormalizer, .ParseException, .Parser, .ParserResult, org.jabref.logic.importer.util.MetaDataParser, org.jabref.logic.l10n.Localization, org.jabref.logic.os.OS, org.jabref.model.database.BibDatabase, .KeyCollisionException, org.jabref.model.entry.BibEntry, .BibEntryType, .BibtexString, .LinkedFile, org.jabref.model.entry.field.Field, .FieldFactory, .FieldProperty, .InternalField, .StandardField, org.jabref.model.entry.types.EntryTypeFactory, org.jabref.model.groups.ExplicitGroup, .GroupHierarchyType, .GroupTreeNode, org.jabref.model.metadata.MetaData, org.jabref.model.util.DummyFileUpdateMonitor, .FileUpdateMonitor, com.dd.plist.BinaryPropertyListParser, .NSArray, .NSDictionary, .NSString, org.jspecify.annotations.NonNull, org.slf4j.Logger, .LoggerFactory, org.w3c.dom.Document, .Element, .NodeList, org.xml.sax.SAXException

Class for importing BibTeX files.

Usage

BibtexParser parser = new BibtexParser(importFormatPreferences); ParserResult result = parser.parse();
BibtexParser parser = new BibtexParser(importFormatPreferences);
ParserResult result = parser.parse();

Can be used standalone.

Main using method: `OpenDatabase.loadDatabase`(org.jabref.logic.importer.OpenDatabase#loadDatabase(java.nio.file.Path, org.jabref.logic.importer.ImportFormatPreferences, org.jabref.model.util.FileUpdateMonitor))

Opposite class: BibDatabaseWriter

FIXME: This class relies on char, but should use java.lang.Character to be fully Unicode compliant.

Nested and Inner Type Summary

Modifier and TypeClass and Description
private static class
BibtexParser.ConflictMarkerFoundException

Thrown as soon as an unresolved version control conflict marker is read, which makes the rest of the file meaningless.

Field Summary

Modifier and TypeField and Description
private static final String
private GroupTreeNode
private int
private static final int
CONFLICT_MARKER_LENGTH

Git writes conflict markers as seven characters at the start of a line, but a botched merge can produce longer runs (https://github.com/JabRef/jabref/issues/9167).

private char
conflictMarkerCharacter

0 while the current line does not start with a run of conflict marker characters

private BibDatabase
private static final DocumentBuilderFactory
private Set<BibEntryType>
private boolean
private static final Pattern
private final Deque<Integer>
private final ImportFormatPreferences
private static final int
private int
private static final Logger
private static final int
private final MetaDataParser
private final Map<String, String>
private ParserResult
private final Deque<Character>
private PushbackReader

Constructor Summary

AccessConstructor and Description
public
BibtexParser(@NonNull ImportFormatPreferences importFormatPreferences, FileUpdateMonitor fileMonitor)

public
BibtexParser(ImportFormatPreferences importFormatPreferences)

Method Summary

Modifier and TypeMethod and Description
private void
addBibDeskGroupEntriesToJabRefGroups(Character keywordSeparator)

Adds BibDesk group entries to the JabRef database

private void
private void
checkForConflictMarker(int character)

Detects a run of conflict marker characters at the start of a line.

private void
consume(char expected)

private void
consume(Field field, char expected)

private void
consume(char firstOption, char secondOption)

private boolean
consumeUncritically(char expected)

private void
private String
private String

Returns:

the text read so far
dumpTextReadSoFarToString
()

Puts all text that has been read from the reader, including newlines, etc., since the last call of this method into a string.

private String

Returns:

rest of key on success, otherwise empty string
fixKey
()

Tries to restore the key

private String
public Collection<BibtexString>
private void
initializeParserResult(String newLineSeparator)

private boolean
private boolean
private boolean
isEOFCharacter(int character)

private boolean
isEscapeSymbol(char character)

public ParserResult
parse(@NonNull Reader in)

Parses BibTeX data found when reading from reader.

private void
private void
parseBibDeskComment(String comment, Map<String, String> meta)

Parses comment types found in BibDesk, to migrate BibDesk Static Groups to JabRef.

private void
private StringBuilder
parseBracketedFieldContent(boolean recoverAtEntryStart)

This is called if a field in the form of field = {content} is parsed.

private String
private void
public List<BibEntry>
private BibEntry
parseEntry(String entryType)

private void
private String
private ParserResult
private void
private String
parseKey()

This method is used to parse the citation key of an entry.

private String
private StringBuilder
private void
public Optional<BibEntry>
parseSingleEntry(String bibtexString)

private BibtexString
private String
parseTextToken()

This method is used to parse string labels, field names, entry type and numbers outside brackets.

private int
peek()

private char[]
private String

Returns:

a stripped version of the context
purge
(String context, String stringToPurge)

Purges the given stringToPurge (if it exists) from the given context

private String

Returns:

a String without eof characters
purgeEOFCharacters
(String input)

Removes all eof characters from a StringBuilder and returns a new String with the resulting content

private int
read()

private StringBuilder
removeWhitespaces(StringBuilder toRemove)

returns a new StringBuilder which corresponds to toRemove without whitespaces

public static Optional<BibEntry>

Returns:

An Optional<BibEntry>. Optional.empty() if non was found or an error occurred.
singleFromString
(String bibtexString, ImportFormatPreferences importFormatPreferences)

Parses BibtexEntries from the given string and returns one entry found (or null if none found)

It is undetermined which entry is returned, so use this in case you know there is only one entry in the string.

private String
skipAndRecordWhitespace(int character)

private void
private void
private void
private void
unread(int character)

private void
unreadBuffer(StringBuilder stringBuilder)

pushes buffer back into input

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

BIB_DESK_ROOT_GROUP_NAMEback to summary
private static final String BIB_DESK_ROOT_GROUP_NAME
bibDeskGroupTreeNodeback to summary
private GroupTreeNode bibDeskGroupTreeNode
columnback to summary
private int column
CONFLICT_MARKER_LENGTHback to summary
private static final int CONFLICT_MARKER_LENGTH

Git writes conflict markers as seven characters at the start of a line, but a botched merge can produce longer runs (https://github.com/JabRef/jabref/issues/9167).

conflictMarkerCharacterback to summary
private char conflictMarkerCharacter

0 while the current line does not start with a run of conflict marker characters

databaseback to summary
private BibDatabase database
DOCUMENT_BUILDER_FACTORYback to summary
private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY
entryTypesback to summary
private Set<BibEntryType> entryTypes
eofback to summary
private boolean eof
EPILOG_PATTERNback to summary
private static final Pattern EPILOG_PATTERN
highestColumnsback to summary
private final Deque<Integer> highestColumns
importFormatPreferencesback to summary
private final ImportFormatPreferences importFormatPreferences
INDEX_RELATIVE_PATH_IN_PLISTback to summary
private static final int INDEX_RELATIVE_PATH_IN_PLIST
lineback to summary
private int line
LOGGERback to summary
private static final Logger LOGGER
LOOKAHEADback to summary
private static final int LOOKAHEAD
metaDataParserback to summary
private final MetaDataParser metaDataParser
parsedBibDeskGroupsback to summary
private final Map<String, String> parsedBibDeskGroups
parserResultback to summary
private ParserResult parserResult
pureTextFromFileback to summary
private final Deque<Character> pureTextFromFile
pushbackReaderback to summary
private PushbackReader pushbackReader

Constructor Detail

BibtexParserback to summary
public BibtexParser(@NonNull ImportFormatPreferences importFormatPreferences, FileUpdateMonitor fileMonitor)
BibtexParserback to summary
public BibtexParser(ImportFormatPreferences importFormatPreferences)

Method Detail

addBibDeskGroupEntriesToJabRefGroupsback to summary
private void addBibDeskGroupEntriesToJabRefGroups(Character keywordSeparator)

Adds BibDesk group entries to the JabRef database

checkEpilogback to summary
private void checkEpilog()
checkForConflictMarkerback to summary
private void checkForConflictMarker(int character)

Detects a run of conflict marker characters at the start of a line. column still holds the column of the just-read character.

The state is keyed on column (which unread(int) restores) instead of on a counter: lookahead reads a character, unreads it and reads it again, and each physical character must be counted once only.

Only < and > are looked for. A line of = or | also appears as a decorative rule in comments and field values, and looking for them buys nothing: the ======= separator and the ||||||| base line of a diff3 style conflict are always preceded by a <<<<<<< line, which is reported first anyway.

consumeback to summary
private void consume(char expected) throws IOException
consumeback to summary
private void consume(Field field, char expected) throws IOException
consumeback to summary
private void consume(char firstOption, char secondOption) throws IOException
consumeUncriticallyback to summary
private boolean consumeUncritically(char expected) throws IOException
createBibDeskGroupTreeback to summary
private void createBibDeskGroupTree(Character keywordSeparator)
determineNewLineSeparatorback to summary
private String determineNewLineSeparator() throws IOException
dumpTextReadSoFarToStringback to summary
private String dumpTextReadSoFarToString()

Puts all text that has been read from the reader, including newlines, etc., since the last call of this method into a string. Removes the JabRef file header, if it is found

Returns:String

the text read so far

fixKeyback to summary
private String fixKey() throws IOException

Tries to restore the key

Returns:String

rest of key on success, otherwise empty string

Exceptions
IOException:
on Reader-Error
getPureTextFromFileback to summary
private String getPureTextFromFile()
getStringValuesback to summary
public Collection<BibtexString> getStringValues()
initializeParserResultback to summary
private void initializeParserResult(String newLineSeparator)
isClosingBracketNextback to summary
private boolean isClosingBracketNext()
isEntryStartback to summary
private boolean isEntryStart() throws IOException
isEOFCharacterback to summary
private boolean isEOFCharacter(int character)
isEscapeSymbolback to summary
private boolean isEscapeSymbol(char character)
parseback to summary
public ParserResult parse(@NonNull Reader in) throws IOException

Parses BibTeX data found when reading from reader.

The reader will be consumed.

Multiple calls to parse() return the same results

Handling of encoding is done at BibtexImporter

parseAndAddEntryback to summary
private void parseAndAddEntry(String type)
parseBibDeskCommentback to summary
private void parseBibDeskComment(String comment, Map<String, String> meta) throws ParseException

Parses comment types found in BibDesk, to migrate BibDesk Static Groups to JabRef.

parseBibtexStringback to summary
private void parseBibtexString() throws IOException
parseBracketedFieldContentback to summary
private StringBuilder parseBracketedFieldContent(boolean recoverAtEntryStart) throws IOException

This is called if a field in the form of field = {content} is parsed. The global variable character contains {.

parseBracketedTextback to summary
private String parseBracketedText() throws IOException
parseDatabaseIDback to summary
private void parseDatabaseID() throws IOException
parseEntriesback to summary
public List<BibEntry> parseEntries(InputStream inputStream) throws ParseException

Implements org.jabref.logic.importer.Parser.parseEntries.

Annotations
@Override
parseEntryback to summary
private BibEntry parseEntry(String entryType) throws IOException
parseFieldback to summary
private void parseField(BibEntry entry) throws IOException
parseFieldContentback to summary
private String parseFieldContent(Field field) throws IOException
parseFileContentback to summary
private ParserResult parseFileContent() throws IOException
parseJabRefCommentback to summary
private void parseJabRefComment(Map<String, String> meta)
parseKeyback to summary
private String parseKey() throws IOException

This method is used to parse the citation key of an entry.

parsePreambleback to summary
private String parsePreamble() throws IOException
parseQuotedFieldExactlyback to summary
private StringBuilder parseQuotedFieldExactly() throws IOException
parseRemainingContentback to summary
private void parseRemainingContent()
parseSingleEntryback to summary
public Optional<BibEntry> parseSingleEntry(String bibtexString) throws ParseException
parseStringback to summary
private BibtexString parseString() throws IOException
parseTextTokenback to summary
private String parseTextToken() throws IOException

This method is used to parse string labels, field names, entry type and numbers outside brackets.

peekback to summary
private int peek() throws IOException
peekTwoCharactersback to summary
private char[] peekTwoCharacters() throws IOException
purgeback to summary
private String purge(String context, String stringToPurge)

Purges the given stringToPurge (if it exists) from the given context

Returns:String

a stripped version of the context

purgeEOFCharactersback to summary
private String purgeEOFCharacters(String input)

Removes all eof characters from a StringBuilder and returns a new String with the resulting content

Returns:String

a String without eof characters

readback to summary
private int read() throws IOException
removeWhitespacesback to summary
private StringBuilder removeWhitespaces(StringBuilder toRemove)

returns a new StringBuilder which corresponds to toRemove without whitespaces

singleFromStringback to summary
public static Optional<BibEntry> singleFromString(String bibtexString, ImportFormatPreferences importFormatPreferences) throws ParseException

Parses BibtexEntries from the given string and returns one entry found (or null if none found)

It is undetermined which entry is returned, so use this in case you know there is only one entry in the string.

Returns:Optional<BibEntry>

An Optional<BibEntry>. Optional.empty() if non was found or an error occurred.

skipAndRecordWhitespaceback to summary
private String skipAndRecordWhitespace(int character) throws IOException
skipOneNewlineback to summary
private void skipOneNewline() throws IOException
skipSpaceback to summary
private void skipSpace() throws IOException
skipWhitespaceback to summary
private void skipWhitespace() throws IOException
unreadback to summary
private void unread(int character) throws IOException
unreadBufferback to summary
private void unreadBuffer(StringBuilder stringBuilder) throws IOException

pushes buffer back into input

Exceptions
IOException:
can be thrown if buffer is bigger than LOOKAHEAD
org.jabref.logic.importer.fileformat back to summary

private Class BibtexParser.ConflictMarkerFoundException

extends RuntimeException
Class Inheritance

Thrown as soon as an unresolved version control conflict marker is read, which makes the rest of the file meaningless.

Unchecked on purpose: the parser recovers from IOException in several places (e.g., isClosingBracketNext()), and a conflict marker must not be recoverable.

impl->req~import.bibtex.merge-conflict-markers~1

Constructor Summary

AccessConstructor and Description
pack-priv

Constructor Detail

ConflictMarkerFoundExceptionback to summary
pack-priv ConflictMarkerFoundException(int line)