package org.jabref.logic.importer.fileformat; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import org.jabref.logic.exporter.SavePreferences; import org.jabref.logic.formatter.casechanger.LowerCaseFormatter; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.ParseException; import org.jabref.logic.importer.ParserResult; import org.jabref.logic.util.OS; import org.jabref.model.bibtexkeypattern.AbstractBibtexKeyPattern; import org.jabref.model.bibtexkeypattern.DatabaseBibtexKeyPattern; import org.jabref.model.bibtexkeypattern.GlobalBibtexKeyPattern; import org.jabref.model.cleanup.FieldFormatterCleanup; import org.jabref.model.cleanup.FieldFormatterCleanups; import org.jabref.model.database.BibDatabaseMode; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.BibtexString; import org.jabref.model.entry.EntryType; import org.jabref.model.entry.FieldName; import org.jabref.model.groups.AllEntriesGroup; import org.jabref.model.groups.ExplicitGroup; import org.jabref.model.groups.GroupHierarchyType; import org.jabref.model.groups.GroupTreeNode; import org.jabref.model.groups.RegexKeywordGroup; import org.jabref.model.groups.WordKeywordGroup; import org.jabref.model.metadata.SaveOrderConfig; import org.junit.Before; import org.junit.Test; import org.mockito.Answers; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** * Test the BibtexParser */ public class BibtexParserTest { private ImportFormatPreferences importFormatPreferences; private BibtexParser parser; @Before public void setUp() { importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS); when(importFormatPreferences.getKeywordSeparator()).thenReturn(','); parser = new BibtexParser(importFormatPreferences); } @SuppressWarnings("unused") @Test(expected = NullPointerException.class) public void parseWithNullThrowsNullPointerException() throws Exception { parser.parse(null); } @Test public void fromStringRecognizesEntry() throws ParseException { List<BibEntry> parsed = parser .parseEntries("@article{test,author={Ed von Test}}"); BibEntry expected = new BibEntry(); expected.setType("article"); expected.setCiteKey("test"); expected.setField("author", "Ed von Test"); assertEquals(Collections.singletonList(expected), parsed); } @Test public void fromStringReturnsEmptyListFromEmptyString() throws ParseException { Collection<BibEntry> parsed = parser.parseEntries(""); assertNotNull(parsed); assertEquals(Collections.emptyList(), parsed); } @Test public void fromStringReturnsEmptyListIfNoEntryRecognized() throws ParseException { Collection<BibEntry> parsed = parser .parseEntries("@@article@@{{{{{{}"); assertNotNull(parsed); assertEquals(Collections.emptyList(), parsed); } @Test public void singleFromStringRecognizesEntry() throws ParseException { Optional<BibEntry> parsed = BibtexParser.singleFromString( "@article{canh05," + " author = {Crowston, K. and Annabi, H.},\n" + " title = {Title A}}\n", importFormatPreferences); BibEntry expected = new BibEntry(); expected.setType("article"); expected.setCiteKey("canh05"); expected.setField("author", "Crowston, K. and Annabi, H."); expected.setField("title", "Title A"); assertEquals(Optional.of(expected), parsed); } @Test public void singleFromStringRecognizesEntryInMultiple() throws ParseException { Optional<BibEntry> parsed = BibtexParser.singleFromString( "@article{canh05," + " author = {Crowston, K. and Annabi, H.},\n" + " title = {Title A}}\n" + "@inProceedings{foo," + " author={Norton Bar}}", importFormatPreferences); assertTrue(parsed.get().getCiteKeyOptional().equals(Optional.of("canh05")) || parsed.get().getCiteKeyOptional().equals(Optional.of("foo"))); } @Test public void singleFromStringReturnsEmptyFromEmptyString() throws ParseException { Optional<BibEntry> parsed = BibtexParser.singleFromString("", importFormatPreferences); assertEquals(Optional.empty(), parsed); } @Test public void singleFromStringReturnsEmptyIfNoEntryRecognized() throws ParseException { Optional<BibEntry> parsed = BibtexParser.singleFromString("@@article@@{{{{{{}", importFormatPreferences); assertEquals(Optional.empty(), parsed); } @Test public void parseRecognizesEntry() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={Ed von Test}}")); List<BibEntry> parsed = result.getDatabase().getEntries(); assertEquals(1, parsed.size()); BibEntry e = parsed.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseQuotedEntries() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author=\"Ed von Test\"}")); List<BibEntry> parsed = result.getDatabase().getEntries(); assertEquals(1, parsed.size()); BibEntry e = parsed.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseRecognizesEntryOnlyWithKey() throws IOException { ParserResult result = parser.parse(new StringReader("@article{test}")); List<BibEntry> parsed = result.getDatabase().getEntries(); assertEquals(1, parsed.size()); BibEntry e = parsed.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); } @Test public void parseRecognizesEntryWithWhitespaceAtBegining() throws IOException { ParserResult result = parser .parse(new StringReader(" @article{test,author={Ed von Test}}")); List<BibEntry> parsed = result.getDatabase().getEntries(); assertEquals(1, parsed.size()); BibEntry e = parsed.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseRecognizesEntryWithWhitespace() throws IOException { ParserResult result = parser .parse(new StringReader("@article { test,author={Ed von Test}}")); List<BibEntry> parsed = result.getDatabase().getEntries(); assertEquals(1, parsed.size()); BibEntry e = parsed.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseRecognizesEntryWithNewlines() throws IOException { ParserResult result = parser .parse(new StringReader("@article\n{\ntest,author={Ed von Test}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseRecognizesEntryWithUnknownType() throws IOException { ParserResult result = parser .parse(new StringReader("@unknown{test,author={Ed von Test}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("unknown", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseRecognizesEntryWithVeryLongType() throws IOException { ParserResult result = parser.parse( new StringReader("@thisIsALongStringToTestMaybeItIsToLongWhoKnowsNOTme{test,author={Ed von Test}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("thisisalongstringtotestmaybeitistolongwhoknowsnotme", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseRecognizesEntryInParenthesis() throws IOException { ParserResult result = parser .parse(new StringReader("@article(test,author={Ed von Test})")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } /** * Test for [ 1594123 ] Failure to import big numbers Issue Reported by Ulf Martin. SF Bugs #503, #495 are also * related */ @Test public void parseRecognizesEntryWithBigNumbers() throws IOException { ParserResult result = BibtexParser.parse(new StringReader("@article{canh05," + "isbn = 1234567890123456789,\n" + "isbn2 = {1234567890123456789},\n" + "small = 1234,\n" + "}"), importFormatPreferences); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("canh05"), e.getCiteKeyOptional()); assertEquals(Optional.of("1234567890123456789"), e.getField("isbn")); assertEquals(Optional.of("1234567890123456789"), e.getField("isbn2")); assertEquals(Optional.of("1234"), e.getField("small")); } @Test public void parseRecognizesBibtexKeyWithSpecialCharacters() throws IOException { ParserResult result = parser .parse(new StringReader("@article{te_st:with-special(characters),author={Ed von Test}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("te_st:with-special(characters)"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseRecognizesEntryWhereLastFieldIsFinishedWithComma() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={Ed von Test},}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseRecognizesEntryWithAtInField() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={Ed von T@st}}")); List<BibEntry> parsed = result.getDatabase().getEntries(); BibEntry expected = new BibEntry("article").withField(BibEntry.KEY_FIELD, "test") .withField("author", "Ed von T@st"); assertEquals(Collections.singletonList(expected), parsed); } @Test public void parseRecognizesEntryPrecedingComment() throws IOException { String comment = "@Comment{@article{myarticle,}" + OS.NEWLINE + "@inproceedings{blabla, title={the proceedings of bl@bl@}; }" + OS.NEWLINE + "}"; String entryWithComment = comment + OS.NEWLINE + "@article{test,author={Ed von T@st}}"; ParserResult result = parser.parse(new StringReader(entryWithComment)); List<BibEntry> parsed = result.getDatabase().getEntries(); BibEntry expected = new BibEntry("article").withField(BibEntry.KEY_FIELD, "test") .withField("author", "Ed von T@st"); expected.setCommentsBeforeEntry(comment); assertEquals(Collections.singletonList(expected), parsed); assertEquals(expected.getUserComments(), parsed.get(0).getUserComments()); } @Test public void parseRecognizesMultipleEntries() throws IOException { ParserResult result = BibtexParser.parse( new StringReader("@article{canh05," + " author = {Crowston, K. and Annabi, H.},\n" + " title = {Title A}}\n" + "@inProceedings{foo," + " author={Norton Bar}}"), importFormatPreferences); List<BibEntry> parsed = result.getDatabase().getEntries(); List<BibEntry> expected = new ArrayList<>(); BibEntry firstEntry = new BibEntry(); firstEntry.setType("article"); firstEntry.setCiteKey("canh05"); firstEntry.setField("author", "Crowston, K. and Annabi, H."); firstEntry.setField("title", "Title A"); expected.add(firstEntry); BibEntry secondEntry = new BibEntry(); secondEntry.setType("inproceedings"); secondEntry.setCiteKey("foo"); secondEntry.setField("author", "Norton Bar"); expected.add(secondEntry); assertEquals(expected, parsed); } @Test public void parseSetsParsedSerialization() throws IOException { String firstEntry = "@article{canh05," + " author = {Crowston, K. and Annabi, H.}," + OS.NEWLINE + " title = {Title A}}" + OS.NEWLINE; String secondEntry = "@inProceedings{foo," + " author={Norton Bar}}"; ParserResult result = parser .parse(new StringReader(firstEntry + secondEntry)); for (BibEntry entry : result.getDatabase().getEntries()) { if (entry.getCiteKeyOptional().get().equals("canh05")) { assertEquals(firstEntry, entry.getParsedSerialization()); } else { assertEquals(secondEntry, entry.getParsedSerialization()); } } } @Test public void parseRecognizesMultipleEntriesOnSameLine() throws IOException { ParserResult result = parser .parse(new StringReader("@article{canh05}" + "@inProceedings{foo}")); List<BibEntry> parsed = result.getDatabase().getEntries(); List<BibEntry> expected = new ArrayList<>(); BibEntry firstEntry = new BibEntry(); firstEntry.setType("article"); firstEntry.setCiteKey("canh05"); expected.add(firstEntry); BibEntry secondEntry = new BibEntry(); secondEntry.setType("inproceedings"); secondEntry.setCiteKey("foo"); expected.add(secondEntry); assertEquals(expected, parsed); } @Test public void parseCombinesMultipleAuthorFields() throws IOException { ParserResult result = parser.parse( new StringReader("@article{test,author={Ed von Test},author={Second Author},author={Third Author}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test and Second Author and Third Author"), e.getField("author")); } @Test public void parseCombinesMultipleEditorFields() throws IOException { ParserResult result = parser.parse( new StringReader("@article{test,editor={Ed von Test},editor={Second Author},editor={Third Author}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test and Second Author and Third Author"), e.getField("editor")); } /** * Test for SF Bug #1269 */ @Test public void parseCombinesMultipleKeywordsFields() throws IOException { ParserResult result = parser.parse( new StringReader("@article{test,Keywords={Test},Keywords={Second Keyword},Keywords={Third Keyword}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Test, Second Keyword, Third Keyword"), e.getField("keywords")); } @Test public void parseRecognizesHeaderButIgnoresEncoding() throws IOException { ParserResult result = BibtexParser.parse(new StringReader("This file was created with JabRef 2.1 beta 2." + "\n" + "Encoding: Cp1252" + "\n" + "" + "\n" + "@INPROCEEDINGS{CroAnnHow05," + "\n" + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.}," + "\n" + " title = {Effective work practices for floss development: A model and propositions}," + "\n" + " booktitle = {Hawaii International Conference On System Sciences (HICSS)}," + "\n" + " year = {2005}," + "\n" + " owner = {oezbek}," + "\n" + " timestamp = {2006.05.29}," + "\n" + " url = {http://james.howison.name/publications.html}" + "\n" + "}))"), importFormatPreferences); assertEquals(Optional.empty(), result.getMetaData().getEncoding()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("inproceedings", e.getType()); assertEquals(8, e.getFieldNames().size()); assertEquals(Optional.of("CroAnnHow05"), e.getCiteKeyOptional()); assertEquals(Optional.of("Crowston, K. and Annabi, H. and Howison, J. and Masango, C."), e.getField("author")); assertEquals(Optional.of("Effective work practices for floss development: A model and propositions"), e.getField("title")); assertEquals(Optional.of("Hawaii International Conference On System Sciences (HICSS)"), e.getField("booktitle")); assertEquals(Optional.of("2005"), e.getField("year")); assertEquals(Optional.of("oezbek"), e.getField("owner")); assertEquals(Optional.of("2006.05.29"), e.getField("timestamp")); assertEquals(Optional.of("http://james.howison.name/publications.html"), e.getField("url")); } @Test public void parseRecognizesFormatedEntry() throws IOException { ParserResult result = BibtexParser.parse( new StringReader("" + "@INPROCEEDINGS{CroAnnHow05," + "\n" + " author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.}," + "\n" + " title = {Effective work practices for floss development: A model and propositions}," + "\n" + " booktitle = {Hawaii International Conference On System Sciences (HICSS)}," + "\n" + " year = {2005}," + "\n" + " owner = {oezbek}," + "\n" + " timestamp = {2006.05.29}," + "\n" + " url = {http://james.howison.name/publications.html}" + "\n" + "}))"), importFormatPreferences); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("inproceedings", e.getType()); assertEquals(8, e.getFieldNames().size()); assertEquals(Optional.of("CroAnnHow05"), e.getCiteKeyOptional()); assertEquals(Optional.of("Crowston, K. and Annabi, H. and Howison, J. and Masango, C."), e.getField("author")); assertEquals(Optional.of("Effective work practices for floss development: A model and propositions"), e.getField("title")); assertEquals(Optional.of("Hawaii International Conference On System Sciences (HICSS)"), e.getField("booktitle")); assertEquals(Optional.of("2005"), e.getField("year")); assertEquals(Optional.of("oezbek"), e.getField("owner")); assertEquals(Optional.of("2006.05.29"), e.getField("timestamp")); assertEquals(Optional.of("http://james.howison.name/publications.html"), e.getField("url")); } @Test public void parseRecognizesFieldValuesInQuotationMarks() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author=\"Ed von Test\"}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseRecognizesNumbersWithoutBracketsOrQuotationMarks() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,year = 2005}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("2005"), e.getField("year")); } @Test public void parseRecognizesUppercaseFields() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,AUTHOR={Ed von Test}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } /** * Test for SF Bug #806 */ @Test public void parseRecognizesAbsoluteFile() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,file = {D:\\Documents\\literature\\Tansel-PRL2006.pdf}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("D:\\Documents\\literature\\Tansel-PRL2006.pdf"), e.getField("file")); } /** * Test for SF Bug #48 */ @Test public void parseRecognizesDateFieldWithConcatenation() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,date = {1-4~} # nov}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("1-4~#nov#"), e.getField("date")); } @Test public void parseReturnsEmptyListIfNoEntryRecognized() throws IOException { ParserResult result = BibtexParser.parse( new StringReader(" author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.}," + "\n" + " title = {Effective work practices for floss development: A model and propositions}," + "\n" + " booktitle = {Hawaii International Conference On System Sciences (HICSS)}," + "\n" + " year = {2005}," + "\n" + " owner = {oezbek}," + "\n" + " timestamp = {2006.05.29}," + "\n" + " url = {http://james.howison.name/publications.html}" + "\n" + "}))"), importFormatPreferences); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(0, c.size()); } @Test public void parseReturnsEmptyListIfNoEntryExistent() throws IOException { ParserResult result = parser .parse(new StringReader("This was created with JabRef 2.1 beta 2." + "\n" + "Encoding: Cp1252" + "\n")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(0, c.size()); } @Test public void parseRecognizesDuplicateBibtexKeys() throws IOException { ParserResult result = BibtexParser .parse(new StringReader("@article{canh05," + " author = {Crowston, K. and Annabi, H.},\n" + " title = {Title A}}\n" + "@inProceedings{canh05," + " author={Norton Bar}}"), importFormatPreferences); List<String> duplicateKeys = result.getDuplicateKeys(); assertEquals(1, duplicateKeys.size()); assertEquals("canh05", duplicateKeys.get(0)); } @Test public void parseNotWarnsAboutEntryWithoutBibtexKey() throws IOException { ParserResult result = parser .parse(new StringReader("@article{,author={Ed von Test}}")); assertFalse(result.hasWarnings()); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = new BibEntry(); e.setField("author", "Ed von Test"); e.setType("article"); assertEquals(Collections.singletonList(e), c); } @Test public void parseIgnoresAndWarnsAboutEntryWithUnmatchedOpenBracket() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={author missing bracket}")); assertTrue(result.hasWarnings()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(0, c.size()); } /** * Test for SF bug 482 */ @Test public void parseAddsEscapedOpenBracketToFieldValue() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,review={escaped \\{ bracket}}")); assertFalse(result.hasWarnings()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(Optional.of("escaped \\{ bracket"), e.getField("review")); } @Test public void parseAddsEscapedClosingBracketToFieldValue() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,review={escaped \\} bracket}}")); assertFalse(result.hasWarnings()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(Optional.of("escaped \\} bracket"), e.getField("review")); } @Test public void parseIgnoresAndWarnsAboutEntryWithUnmatchedOpenBracketInQuotationMarks() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author=\"author {missing bracket\"}")); assertTrue(result.hasWarnings()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(0, c.size()); } @Test public void parseIgnoresArbitraryContentAfterEntry() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={author bracket }}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals("Size should be one, but was " + c.size(), 1, c.size()); assertEquals("Epilog should be preserved", "}", result.getDatabase().getEpilog()); } @Test public void parseWarnsAboutUnmatchedContentInEntryWithoutComma() throws IOException { ParserResult result = BibtexParser.parse(new StringReader("@article{test,author={author bracket } too much}"), importFormatPreferences); List<BibEntry> entries = result.getDatabase().getEntries(); assertEquals(Optional.of("author bracket #too##much#"), entries.get(0).getField("author")); } @Test public void parseWarnsAboutUnmatchedContentInEntry() throws IOException { ParserResult result = BibtexParser.parse(new StringReader("@article{test,author={author bracket }, too much}"), importFormatPreferences); assertTrue("There should be warnings", result.hasWarnings()); List<BibEntry> entries = result.getDatabase().getEntries(); assertEquals("Size should be zero, but was " + entries.size(), 0, entries.size()); } @Test public void parseAcceptsEntryWithAtSymbolInBrackets() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={author @ good}}")); List<BibEntry> entries = result.getDatabase().getEntries(); assertEquals(1, entries.size()); assertEquals(Optional.of("author @ good"), entries.get(0).getField("author")); } @Test public void parseRecognizesEntryWithAtSymbolInQuotationMarks() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author=\"author @ good\"}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("author @ good"), e.getField("author")); } @Test public void parseRecognizesFieldsWithBracketsEnclosedInQuotationMarks() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author=\"Test {Ed {von} Test}\"}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Test {Ed {von} Test}"), e.getField("author")); } @Test public void parseRecognizesFieldsWithEscapedQuotationMarks() throws IOException { // Quotes in fields of the form key = "value" have to be escaped by putting them into braces ParserResult result = parser .parse(new StringReader("@article{test,author=\"Test {\" Test}\"}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Test {\" Test}"), e.getField("author")); } @Test public void parseIgnoresAndWarnsAboutEntryWithFieldsThatAreNotSeperatedByComma() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={Ed von Test} year=2005}")); assertTrue(result.hasWarnings()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(0, c.size()); } @Test public void parseIgnoresAndWarnsAboutCorruptedEntryButRecognizeOthers() throws IOException { ParserResult result = BibtexParser.parse( new StringReader( "@article{test,author={author missing bracket}" + "@article{test,author={Ed von Test}}"), importFormatPreferences); assertTrue(result.hasWarnings()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } /** * Test for SF Bug #1283 */ @Test public void parseRecognizesMonthFieldsWithFollowingComma() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={Ed von Test},month={8,}},")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(3, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); assertEquals(Optional.of("8,"), e.getField("month")); } @Test public void parseRecognizesPreamble() throws IOException { ParserResult result = parser .parse(new StringReader("@preamble{some text and \\latex}")); assertEquals(Optional.of("some text and \\latex"), result.getDatabase().getPreamble()); } @Test public void parseRecognizesUppercasePreamble() throws IOException { ParserResult result = parser .parse(new StringReader("@PREAMBLE{some text and \\latex}")); assertEquals(Optional.of("some text and \\latex"), result.getDatabase().getPreamble()); } @Test public void parseRecognizesPreambleWithWhitespace() throws IOException { ParserResult result = parser .parse(new StringReader("@preamble {some text and \\latex}")); assertEquals(Optional.of("some text and \\latex"), result.getDatabase().getPreamble()); } @Test public void parseRecognizesPreambleInParenthesis() throws IOException { ParserResult result = parser .parse(new StringReader("@preamble(some text and \\latex)")); assertEquals(Optional.of("some text and \\latex"), result.getDatabase().getPreamble()); } @Test public void parseRecognizesPreambleWithConcatenation() throws IOException { ParserResult result = parser .parse(new StringReader("@preamble{\"some text\" # \"and \\latex\"}")); assertEquals(Optional.of("\"some text\" # \"and \\latex\""), result.getDatabase().getPreamble()); } @Test public void parseRecognizesString() throws IOException { ParserResult result = parser .parse(new StringReader("@string{bourdieu = {Bourdieu, Pierre}}")); assertEquals(1, result.getDatabase().getStringCount()); BibtexString s = result.getDatabase().getStringValues().iterator().next(); assertEquals("bourdieu", s.getName()); assertEquals("Bourdieu, Pierre", s.getContent()); } @Test public void parseSavesOneNewlineAfterStringInParsedSerialization() throws IOException { String string = "@string{bourdieu = {Bourdieu, Pierre}}" + OS.NEWLINE; ParserResult result = parser .parse(new StringReader(string + OS.NEWLINE + OS.NEWLINE)); assertEquals(1, result.getDatabase().getStringCount()); BibtexString s = result.getDatabase().getStringValues().iterator().next(); assertEquals(string, s.getParsedSerialization()); } @Test public void parseRecognizesStringWithWhitespace() throws IOException { ParserResult result = parser .parse(new StringReader("@string {bourdieu = {Bourdieu, Pierre}}")); assertEquals(1, result.getDatabase().getStringCount()); BibtexString s = result.getDatabase().getStringValues().iterator().next(); assertEquals("bourdieu", s.getName()); assertEquals("Bourdieu, Pierre", s.getContent()); } @Test public void parseRecognizesStringInParenthesis() throws IOException { ParserResult result = parser .parse(new StringReader("@string(bourdieu = {Bourdieu, Pierre})")); assertEquals(1, result.getDatabase().getStringCount()); BibtexString s = result.getDatabase().getStringValues().iterator().next(); assertEquals("bourdieu", s.getName()); assertEquals("Bourdieu, Pierre", s.getContent()); } @Test public void parseRecognizesMultipleStrings() throws IOException { ParserResult result = parser .parse(new StringReader("@string{bourdieu = {Bourdieu, Pierre}}" + "@string{adieu = {Adieu, Pierre}}")); assertEquals(2, result.getDatabase().getStringCount()); Iterator<BibtexString> iterator = result.getDatabase().getStringValues().iterator(); BibtexString s = iterator.next(); BibtexString t = iterator.next(); // Sort them because we can't be sure about the order if (s.getName().equals("adieu")) { BibtexString tmp = s; s = t; t = tmp; } assertEquals("bourdieu", s.getName()); assertEquals("Bourdieu, Pierre", s.getContent()); assertEquals("adieu", t.getName()); assertEquals("Adieu, Pierre", t.getContent()); } @Test public void parseRecognizesStringAndEntry() throws IOException { ParserResult result = BibtexParser.parse( new StringReader("" + "@string{bourdieu = {Bourdieu, Pierre}}" + "@book{bourdieu-2002-questions-sociologie, " + " Address = {Paris}," + " Author = bourdieu," + " Isbn = 2707318256," + " Publisher = {Minuit}," + " Title = {Questions de sociologie}," + " Year = 2002" + "}"), importFormatPreferences); assertEquals(1, result.getDatabase().getStringCount()); BibtexString s = result.getDatabase().getStringValues().iterator().next(); assertEquals("bourdieu", s.getName()); assertEquals("Bourdieu, Pierre", s.getContent()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("book", e.getType()); assertEquals(Optional.of("bourdieu-2002-questions-sociologie"), e.getCiteKeyOptional()); assertEquals(Optional.of("Paris"), e.getField("address")); assertEquals(Optional.of("#bourdieu#"), e.getField("author")); assertEquals(Optional.of("2707318256"), e.getField("isbn")); assertEquals(Optional.of("Minuit"), e.getField("publisher")); assertEquals(Optional.of("Questions de sociologie"), e.getField("title")); assertEquals(Optional.of("2002"), e.getField("year")); } @Test public void parseWarnsAboutStringsWithSameNameAndOnlyKeepsOne() throws IOException { ParserResult result = parser .parse(new StringReader("@string{bourdieu = {Bourdieu, Pierre}}" + "@string{bourdieu = {Other}}")); assertTrue(result.hasWarnings()); assertEquals(1, result.getDatabase().getStringCount()); } @Test public void parseIgnoresComments() throws IOException { ParserResult result = parser .parse(new StringReader("@comment{some text and \\latex}")); assertEquals(0, result.getDatabase().getEntries().size()); } @Test public void parseIgnoresUpercaseComments() throws IOException { ParserResult result = parser .parse(new StringReader("@COMMENT{some text and \\latex}")); assertEquals(0, result.getDatabase().getEntries().size()); } @Test public void parseIgnoresCommentsBeforeEntry() throws IOException { ParserResult result = parser .parse(new StringReader("@comment{some text and \\latex}" + "@article{test,author={Ed von Test}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseIgnoresCommentsAfterEntry() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={Ed von Test}}" + "@comment{some text and \\latex}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseIgnoresText() throws IOException { ParserResult result = parser .parse(new StringReader("comment{some text and \\latex")); assertEquals(0, result.getDatabase().getEntries().size()); } @Test public void parseIgnoresTextBeforeEntry() throws IOException { ParserResult result = parser .parse(new StringReader("comment{some text and \\latex" + "@article{test,author={Ed von Test}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseIgnoresTextAfterEntry() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author={Ed von Test}}" + "comment{some text and \\latex")); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(2, e.getFieldNames().size()); assertEquals(Optional.of("Ed von Test"), e.getField("author")); } @Test public void parseConvertsNewlineToSpace() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,a = {a\nb}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); assertEquals(Optional.of("a b"), e.getField("a")); } @Test public void parseConvertsMultipleNewlinesToSpace() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,a = {a\n\nb}," + "b = {a\n \nb}," + "c = {a \n \n b}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); assertEquals(Optional.of("a b"), e.getField("a")); assertEquals(Optional.of("a b"), e.getField("b")); assertEquals(Optional.of("a b"), e.getField("c")); } @Test public void parseConvertsTabToSpace() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,a = {a\tb}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); assertEquals(Optional.of("a b"), e.getField("a")); } @Test public void parseConvertsMultipleTabsToSpace() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,a = {a\t\tb}," + "b = {a\t \tb}," + "c = {a \t \t b}}")); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); assertEquals(Optional.of("a b"), e.getField("a")); assertEquals(Optional.of("a b"), e.getField("b")); assertEquals(Optional.of("a b"), e.getField("c")); } /** * Test for [2022983] * * @author Uwe Kuehn * @author Andrei Haralevich */ @Test public void parsePreservesMultipleSpacesInNonWrappableField() throws IOException { when(importFormatPreferences.getFieldContentParserPreferences().getNonWrappableFields()) .thenReturn(Collections.singletonList("file")); ParserResult result = parser .parse(new StringReader("@article{canh05,file = {ups sala}}"), importFormatPreferences); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); assertEquals(Optional.of("ups sala"), e.getField("file")); } @Test public void parsePreservesTabsInAbstractField() throws IOException { ParserResult result = BibtexParser.parse(new StringReader("@article{canh05,abstract = {ups \tsala}}"), importFormatPreferences); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); assertEquals(Optional.of("ups \tsala"), e.getField(FieldName.ABSTRACT)); } @Test public void parsePreservesNewlineInAbstractField() throws IOException { ParserResult result = BibtexParser.parse(new StringReader("@article{canh05,abstract = {ups \nsala}}"), importFormatPreferences); Collection<BibEntry> c = result.getDatabase().getEntries(); BibEntry e = c.iterator().next(); assertEquals(Optional.of("ups " + OS.NEWLINE + "sala"), e.getField(FieldName.ABSTRACT)); } /** * Test for #650 */ @Test public void parseHandlesAccentsCorrectly() throws IOException { ParserResult result = parser .parse(new StringReader("@article{test,author = {H\'{e}lne Fiaux}}")); assertFalse(result.hasWarnings()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(Optional.of("H\'{e}lne Fiaux"), e.getField("author")); } /** * Test for #669 */ @Test public void parsePreambleAndEntryWithoutNewLine() throws IOException { ParserResult result = parser .parse(new StringReader("@preamble{some text and \\latex}@article{test,author = {H\'{e}lne Fiaux}}")); assertFalse(result.hasWarnings()); assertEquals(Optional.of("some text and \\latex"), result.getDatabase().getPreamble()); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals("article", e.getType()); assertEquals(Optional.of("test"), e.getCiteKeyOptional()); assertEquals(Optional.of("H\'{e}lne Fiaux"), e.getField("author")); } /** * Test for #669 */ @Test public void parseFileHeaderAndPreambleWithoutNewLine() throws IOException { ParserResult result = parser .parse(new StringReader("% Encoding: US-ASCII@preamble{some text and \\latex}")); assertFalse(result.hasWarnings()); assertEquals(Optional.of("some text and \\latex"), result.getDatabase().getPreamble()); } @Test public void parseSavesEntryInParsedSerialization() throws IOException { String testEntry = "@article{test,author={Ed von Test}}"; ParserResult result = parser.parse(new StringReader(testEntry)); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals(testEntry, e.getParsedSerialization()); } @Test public void parseSavesOneNewlineAfterEntryInParsedSerialization() throws IOException { String testEntry = "@article{test,author={Ed von Test}}"; ParserResult result = parser .parse(new StringReader(testEntry + OS.NEWLINE + OS.NEWLINE)); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals(testEntry + OS.NEWLINE, e.getParsedSerialization()); } @Test public void parseSavesNewlinesBeforeEntryInParsedSerialization() throws IOException { String testEntry = "@article{test,author={Ed von Test}}"; ParserResult result = parser .parse(new StringReader(OS.NEWLINE + OS.NEWLINE + OS.NEWLINE + testEntry)); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals(OS.NEWLINE + OS.NEWLINE + OS.NEWLINE + testEntry, e.getParsedSerialization()); } @Test public void parseRemovesEncodingLineInParsedSerialization() throws IOException { String testEntry = "@article{test,author={Ed von Test}}"; ParserResult result = parser.parse( new StringReader(SavePreferences.ENCODING_PREFIX + OS.NEWLINE + OS.NEWLINE + OS.NEWLINE + testEntry)); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals(OS.NEWLINE + OS.NEWLINE + testEntry, e.getParsedSerialization()); } @Test public void parseSavesNewlinesBetweenEntriesInParsedSerialization() throws IOException { String testEntryOne = "@article{test1,author={Ed von Test}}"; String testEntryTwo = "@article{test2,author={Ed von Test}}"; ParserResult result = parser .parse(new StringReader(testEntryOne + OS.NEWLINE + OS.NEWLINE + OS.NEWLINE + testEntryTwo)); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(2, c.size()); Iterator<BibEntry> i = c.iterator(); BibEntry a = i.next(); BibEntry b = i.next(); // Sort them because we can't be sure about the order if (a.getCiteKeyOptional().equals(Optional.of("test2"))) { BibEntry tmp = a; a = b; b = tmp; } assertEquals(testEntryOne + OS.NEWLINE, a.getParsedSerialization()); assertEquals(OS.NEWLINE + OS.NEWLINE + testEntryTwo, b.getParsedSerialization()); } @Test public void parseIgnoresWhitespaceInEpilogue() throws IOException { ParserResult result = parser.parse(new StringReader(" " + OS.NEWLINE)); assertEquals("", result.getDatabase().getEpilog()); } @Test public void parseIgnoresWhitespaceInEpilogueAfterEntry() throws IOException { String testEntry = "@article{test,author={Ed von Test}}"; ParserResult result = parser .parse(new StringReader(testEntry + OS.NEWLINE + OS.NEWLINE + OS.NEWLINE + " " + OS.NEWLINE)); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals(testEntry + OS.NEWLINE, e.getParsedSerialization()); assertEquals("", result.getDatabase().getEpilog()); } @Test public void parseTrimsWhitespaceInEpilogueAfterEntry() throws IOException { String testEntry = "@article{test,author={Ed von Test}}"; ParserResult result = parser .parse(new StringReader(testEntry + OS.NEWLINE + OS.NEWLINE + OS.NEWLINE + " epilogue " + OS.NEWLINE)); Collection<BibEntry> c = result.getDatabase().getEntries(); assertEquals(1, c.size()); BibEntry e = c.iterator().next(); assertEquals(testEntry + OS.NEWLINE, e.getParsedSerialization()); assertEquals("epilogue", result.getDatabase().getEpilog()); } @Test public void parseRecognizesSaveActionsAfterEntry() throws IOException { BibtexParser parser = this.parser; ParserResult parserResult = parser.parse( new StringReader("@InProceedings{6055279,\n" + " Title = {Educational session 1},\n" + " Booktitle = {Custom Integrated Circuits Conference (CICC), 2011 IEEE},\n" + " Year = {2011},\n" + " Month = {Sept},\n" + " Pages = {1-7},\n" + " Abstract = {Start of the above-titled section of the conference proceedings record.},\n" + " DOI = {10.1109/CICC.2011.6055279},\n" + " ISSN = {0886-5930}\n" + "}\n" + "\n" + "@comment{jabref-meta: saveActions:enabled;title[lower_case]}")); FieldFormatterCleanups saveActions = parserResult.getMetaData().getSaveActions().get(); assertTrue(saveActions.isEnabled()); assertEquals(Collections.singletonList(new FieldFormatterCleanup("title", new LowerCaseFormatter())), saveActions.getConfiguredActions()); } @Test public void integrationTestSaveActions() throws IOException { BibtexParser parser = this.parser; ParserResult parserResult = parser .parse(new StringReader("@comment{jabref-meta: saveActions:enabled;title[lower_case]}")); FieldFormatterCleanups saveActions = parserResult.getMetaData().getSaveActions().get(); assertTrue(saveActions.isEnabled()); assertEquals(Collections.singletonList(new FieldFormatterCleanup("title", new LowerCaseFormatter())), saveActions.getConfiguredActions()); } @Test public void integrationTestCustomEntryType() throws IOException { ParserResult result = parser.parse( new StringReader("@comment{jabref-entrytype: Lecturenotes: req[author;title] opt[language;url]}")); Map<String, EntryType> customEntryTypes = result.getEntryTypes(); assertEquals(1, customEntryTypes.size()); assertEquals("Lecturenotes", customEntryTypes.keySet().toArray()[0]); EntryType entryType = customEntryTypes.get("Lecturenotes"); assertEquals("Lecturenotes", entryType.getName()); assertEquals(Arrays.asList("author", "title"), entryType.getRequiredFields()); assertEquals(Arrays.asList("language", "url"), entryType.getOptionalFields()); } @Test public void integrationTestSaveOrderConfig() throws IOException { ParserResult result = BibtexParser.parse( new StringReader( "@Comment{jabref-meta: saveOrderConfig:specified;author;false;year;true;abstract;false;}"), importFormatPreferences); Optional<SaveOrderConfig> saveOrderConfig = result.getMetaData().getSaveOrderConfig(); assertEquals(new SaveOrderConfig(false, new SaveOrderConfig.SortCriterion("author", false), new SaveOrderConfig.SortCriterion("year", true), new SaveOrderConfig.SortCriterion("abstract", false)), saveOrderConfig.get()); } @Test public void integrationTestCustomKeyPattern() throws IOException { ParserResult result = BibtexParser .parse(new StringReader("@comment{jabref-meta: keypattern_article:articleTest;}" + OS.NEWLINE + "@comment{jabref-meta: keypatterndefault:test;}"), importFormatPreferences); GlobalBibtexKeyPattern pattern = mock(GlobalBibtexKeyPattern.class); AbstractBibtexKeyPattern bibtexKeyPattern = result.getMetaData().getCiteKeyPattern(pattern); AbstractBibtexKeyPattern expectedPattern = new DatabaseBibtexKeyPattern(pattern); expectedPattern.setDefaultValue("test"); expectedPattern.addBibtexKeyPattern("article", "articleTest"); assertEquals(expectedPattern, bibtexKeyPattern); } @Test public void integrationTestBiblatexMode() throws IOException { ParserResult result = parser .parse(new StringReader("@comment{jabref-meta: databaseType:biblatex;}")); Optional<BibDatabaseMode> mode = result.getMetaData().getMode(); assertEquals(BibDatabaseMode.BIBLATEX, mode.get()); } @Test public void integrationTestGroupTree() throws IOException, ParseException { ParserResult result = BibtexParser.parse(new StringReader("@comment{jabref-meta: groupsversion:3;}" + OS.NEWLINE + "@comment{jabref-meta: groupstree:" + OS.NEWLINE + "0 AllEntriesGroup:;" + OS.NEWLINE + "1 KeywordGroup:Fréchet\\;0\\;keywords\\;FrechetSpace\\;0\\;1\\;;" + OS.NEWLINE + "1 KeywordGroup:Invariant theory\\;0\\;keywords\\;GIT\\;0\\;0\\;;" + OS.NEWLINE + "1 ExplicitGroup:TestGroup\\;0\\;Key1\\;Key2\\;;" + "}"), importFormatPreferences); GroupTreeNode root = result.getMetaData().getGroups().get(); assertEquals(new AllEntriesGroup("All entries"), root.getGroup()); assertEquals(3, root.getNumberOfChildren()); assertEquals( new RegexKeywordGroup("Fréchet", GroupHierarchyType.INDEPENDENT, "keywords", "FrechetSpace", false), root.getChildren().get(0).getGroup()); assertEquals( new WordKeywordGroup("Invariant theory", GroupHierarchyType.INDEPENDENT, "keywords", "GIT", false, ',', false), root.getChildren().get(1).getGroup()); assertEquals(Arrays.asList("Key1", "Key2"), ((ExplicitGroup) root.getChildren().get(2).getGroup()).getLegacyEntryKeys()); } @Test public void integrationTestProtectedFlag() throws IOException { ParserResult result = parser .parse(new StringReader("@comment{jabref-meta: protectedFlag:true;}")); assertTrue(result.getMetaData().isProtected()); } @Test public void integrationTestContentSelectors() throws IOException { ParserResult result = BibtexParser.parse( new StringReader("@Comment{jabref-meta: selector_status:approved;captured;received;status;}"), importFormatPreferences); List<String> values = new ArrayList(4); values.add("approved"); values.add("captured"); values.add("received"); values.add("status"); assertEquals(values, result.getMetaData().getContentSelectors().getSelectorValuesForField("status")); } @Test public void parseReallyUnknownType() throws Exception { String bibtexEntry = "@ReallyUnknownType{test," + OS.NEWLINE + " Comment = {testentry}" + OS.NEWLINE + "}"; Collection<BibEntry> entries = parser.parseEntries(bibtexEntry); BibEntry expectedEntry = new BibEntry(); expectedEntry.setType("Reallyunknowntype"); expectedEntry.setCiteKey("test"); expectedEntry.setField("comment", "testentry"); assertEquals(Collections.singletonList(expectedEntry), entries); } @Test public void parseOtherTypeTest() throws Exception { String bibtexEntry = "@Other{test," + OS.NEWLINE + " Comment = {testentry}" + OS.NEWLINE + "}"; Collection<BibEntry> entries = parser.parseEntries(bibtexEntry); BibEntry expectedEntry = new BibEntry(); expectedEntry.setType("Other"); expectedEntry.setCiteKey("test"); expectedEntry.setField("comment", "testentry"); assertEquals(Collections.singletonList(expectedEntry), entries); } @Test public void parseRecognizesDatabaseID() throws Exception { BibtexParser parser = this.parser; String expectedDatabaseID = "q1w2e3r4t5z6"; StringBuilder sharedDatabaseFileContent = new StringBuilder() .append("% DBID: ").append(expectedDatabaseID) .append(OS.NEWLINE) .append("@Article{a}"); ParserResult parserResult = parser.parse(new StringReader(sharedDatabaseFileContent.toString())); String actualDatabaseID = parserResult.getDatabase().getSharedDatabaseID().get(); assertEquals(expectedDatabaseID, actualDatabaseID); } @Test public void parseDoesNotRecognizeDatabaseIDasUserComment() throws Exception { BibtexParser parser = this.parser; StringBuilder sharedDatabaseFileContent = new StringBuilder() .append("% Encoding: UTF-8").append(OS.NEWLINE) .append("% DBID: q1w2e3r4t5z6").append(OS.NEWLINE) .append("@Article{a}"); ParserResult parserResult = parser.parse(new StringReader(sharedDatabaseFileContent.toString())); List<BibEntry> entries = parserResult.getDatabase().getEntries(); assertEquals(1, entries.size()); assertEquals("", entries.get(0).getUserComments()); } @Test public void integrationTestFileDirectories() throws IOException { ParserResult result = BibtexParser.parse( new StringReader("@comment{jabref-meta: fileDirectory:\\\\Literature\\\\;}" + "@comment{jabref-meta: fileDirectory-defaultOwner-user:D:\\\\Documents;}"), importFormatPreferences); assertEquals("\\Literature\\", result.getMetaData().getDefaultFileDirectory().get()); assertEquals("D:\\Documents", result.getMetaData().getUserFileDirectory("defaultOwner-user").get()); } @Test public void parseReturnsEntriesInSameOrder() throws IOException { ParserResult result = parser .parse(new StringReader("@article{a}" + OS.NEWLINE + "@article{b}" + OS.NEWLINE + "@inProceedings{c}")); List<BibEntry> expected = new ArrayList<>(); BibEntry a = new BibEntry(); a.setType("article"); a.setCiteKey("a"); expected.add(a); BibEntry b = new BibEntry(); b.setType("article"); b.setCiteKey("b"); expected.add(b); BibEntry c = new BibEntry(); c.setType("inproceedings"); c.setCiteKey("c"); expected.add(c); assertEquals(expected, result.getDatabase().getEntries()); } @Test public void parsePrecedingComment() throws IOException { // @formatter:off String bibtexEntry = "% Some random comment that should stay here" + OS.NEWLINE + "@Article{test," + OS.NEWLINE + " Author = {Foo Bar}," + OS.NEWLINE + " Journal = {International Journal of Something}," + OS.NEWLINE + " Note = {some note}," + OS.NEWLINE + " Number = {1}" + OS.NEWLINE + "}"; // @formatter:on // read in bibtex string ParserResult result = parser.parse(new StringReader(bibtexEntry)); Collection<BibEntry> entries = result.getDatabase().getEntries(); assertEquals(1, entries.size()); BibEntry entry = entries.iterator().next(); assertEquals(Optional.of("test"), entry.getCiteKeyOptional()); assertEquals(5, entry.getFieldNames().size()); Set<String> fields = entry.getFieldNames(); assertTrue(fields.contains("author")); assertEquals(Optional.of("Foo Bar"), entry.getField("author")); assertEquals(bibtexEntry, entry.getParsedSerialization()); } @Test public void parseCommentAndEntryInOneLine() throws IOException { // @formatter:off String bibtexEntry = "Some random comment that should stay here @Article{test," + OS.NEWLINE + " Author = {Foo Bar}," + OS.NEWLINE + " Journal = {International Journal of Something}," + OS.NEWLINE + " Note = {some note}," + OS.NEWLINE + " Number = {1}" + OS.NEWLINE + "}"; // @formatter:on // read in bibtex string ParserResult result = parser.parse(new StringReader(bibtexEntry)); Collection<BibEntry> entries = result.getDatabase().getEntries(); assertEquals(1, entries.size()); BibEntry entry = entries.iterator().next(); assertEquals(Optional.of("test"), entry.getCiteKeyOptional()); assertEquals(5, entry.getFieldNames().size()); Set<String> fields = entry.getFieldNames(); assertTrue(fields.contains("author")); assertEquals(Optional.of("Foo Bar"), entry.getField("author")); assertEquals(bibtexEntry, entry.getParsedSerialization()); } @Test public void preserveEncodingPrefixInsideEntry() throws ParseException { List<BibEntry> parsed = parser .parseEntries("@article{test,author={" + SavePreferences.ENCODING_PREFIX + "}}"); BibEntry expected = new BibEntry(); expected.setType("article"); expected.setCiteKey("test"); expected.setField("author", SavePreferences.ENCODING_PREFIX); assertEquals(Collections.singletonList(expected), parsed); } @Test public void parseBracketedComment() throws IOException { String commentText = "@Comment{someComment}"; ParserResult result = parser.parse(new StringReader(commentText)); assertEquals(commentText, result.getDatabase().getEpilog()); } @Test public void parseRegularCommentBeforeEntry() throws IOException { // @formatter:off String bibtexEntry = "@Comment{someComment} " + OS.NEWLINE + "@Article{test," + OS.NEWLINE + " Author = {Foo Bar}," + OS.NEWLINE + " Journal = {International Journal of Something}," + OS.NEWLINE + " Note = {some note}," + OS.NEWLINE + " Number = {1}" + OS.NEWLINE + "}"; // @formatter:on ParserResult result = parser.parse(new StringReader(bibtexEntry)); Collection<BibEntry> entries = result.getDatabase().getEntries(); BibEntry entry = entries.iterator().next(); assertEquals(bibtexEntry, entry.getParsedSerialization()); } @Test public void parseCommentWithoutBrackets() throws IOException { String commentText = "@Comment someComment"; ParserResult result = parser.parse(new StringReader(commentText)); assertEquals(commentText, result.getDatabase().getEpilog()); } @Test public void parseCommentWithoutBracketsBeforeEntry() throws IOException { // @formatter:off String bibtexEntry = "@Comment someComment " + OS.NEWLINE + "@Article{test," + OS.NEWLINE + " Author = {Foo Bar}," + OS.NEWLINE + " Journal = {International Journal of Something}," + OS.NEWLINE + " Note = {some note}," + OS.NEWLINE + " Number = {1}" + OS.NEWLINE + "}"; // @formatter:on ParserResult result = parser.parse(new StringReader(bibtexEntry)); Collection<BibEntry> entries = result.getDatabase().getEntries(); BibEntry entry = entries.iterator().next(); assertEquals(bibtexEntry, entry.getParsedSerialization()); } @Test public void parseCommentContainingEntries() throws IOException { // @formatter:off String bibtexEntry = "@Comment{@article{myarticle,}" + OS.NEWLINE + "@inproceedings{blabla, title={the proceedings of blabla}; }" + OS.NEWLINE + "} " + OS.NEWLINE + "@Article{test," + OS.NEWLINE + " Author = {Foo Bar}," + OS.NEWLINE + " Journal = {International Journal of Something}," + OS.NEWLINE + " Note = {some note}," + OS.NEWLINE + " Number = {1}" + OS.NEWLINE + "}"; // @formatter:on ParserResult result = parser.parse(new StringReader(bibtexEntry)); Collection<BibEntry> entries = result.getDatabase().getEntries(); BibEntry entry = entries.iterator().next(); assertEquals(bibtexEntry, entry.getParsedSerialization()); } @Test public void parseCommentContainingEntriesAndAtSymbols() throws IOException { // @formatter:off String bibtexEntry = "@Comment{@article{myarticle,}" + OS.NEWLINE + "@inproceedings{blabla, title={the proceedings of bl@bl@}; }" + OS.NEWLINE + "} " + OS.NEWLINE + "@Article{test," + OS.NEWLINE + " Author = {Foo@Bar}," + OS.NEWLINE + " Journal = {International Journal of Something}," + OS.NEWLINE + " Note = {some note}," + OS.NEWLINE + " Number = {1}" + OS.NEWLINE + "}"; // @formatter:on ParserResult result = parser.parse(new StringReader(bibtexEntry)); Collection<BibEntry> entries = result.getDatabase().getEntries(); BibEntry entry = entries.iterator().next(); assertEquals(bibtexEntry, entry.getParsedSerialization()); } @Test public void parseEmptyPreambleLeadsToEmpty() throws IOException { ParserResult result = parser.parse(new StringReader("@preamble{}")); assertFalse(result.hasWarnings()); assertEquals(Optional.empty(), result.getDatabase().getPreamble()); } @Test public void parseEmptyFileLeadsToPreamble() throws IOException { ParserResult result = parser.parse(new StringReader("")); assertFalse(result.hasWarnings()); assertEquals(Optional.empty(), result.getDatabase().getPreamble()); } }