package org.jabref.logic.cleanup; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Optional; import org.jabref.logic.formatter.bibtexfields.HtmlToLatexFormatter; import org.jabref.logic.formatter.bibtexfields.LatexCleanupFormatter; import org.jabref.logic.formatter.bibtexfields.NormalizeDateFormatter; import org.jabref.logic.formatter.bibtexfields.NormalizeMonthFormatter; import org.jabref.logic.formatter.bibtexfields.NormalizePagesFormatter; import org.jabref.logic.formatter.bibtexfields.UnitsToLatexFormatter; import org.jabref.logic.formatter.casechanger.ProtectTermsFormatter; import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.protectedterms.ProtectedTermsLoader; import org.jabref.logic.protectedterms.ProtectedTermsPreferences; import org.jabref.model.Defaults; import org.jabref.model.FieldChange; import org.jabref.model.cleanup.FieldFormatterCleanup; import org.jabref.model.cleanup.FieldFormatterCleanups; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FileFieldWriter; import org.jabref.model.entry.LinkedFile; import org.jabref.model.metadata.FileDirectoryPreferences; import org.jabref.model.metadata.MetaData; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class CleanupWorkerTest { @Rule public TemporaryFolder bibFolder = new TemporaryFolder(); private final CleanupPreset emptyPreset = new CleanupPreset(EnumSet.noneOf(CleanupPreset.CleanupStep.class)); private CleanupWorker worker; private File pdfFolder; @Before public void setUp() throws IOException { pdfFolder = bibFolder.newFolder(); MetaData metaData = new MetaData(); metaData.setDefaultFileDirectory(pdfFolder.getAbsolutePath()); BibDatabaseContext context = new BibDatabaseContext(new BibDatabase(), metaData, new Defaults()); context.setDatabaseFile(bibFolder.newFile("test.bib")); FileDirectoryPreferences fileDirPrefs = mock(FileDirectoryPreferences.class); when(fileDirPrefs.isBibLocationAsPrimary()).thenReturn(true); //Biblocation as Primary overwrites all other dirs worker = new CleanupWorker(context, new CleanupPreferences("\\bibtexkey", "", //empty fileDirPattern for backwards compatibility mock(LayoutFormatterPreferences.class), fileDirPrefs)); } @Test(expected = NullPointerException.class) public void cleanupWithNullPresetThrowsException() { worker.cleanup(null, new BibEntry()); } @Test(expected = NullPointerException.class) public void cleanupNullEntryThrowsException() { worker.cleanup(emptyPreset, null); } @Test public void cleanupDoesNothingByDefault() throws IOException { BibEntry entry = new BibEntry(); entry.setCiteKey("Toot"); entry.setField("pdf", "aPdfFile"); entry.setField("some", "1st"); entry.setField("doi", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); entry.setField("month", "01"); entry.setField("pages", "1-2"); entry.setField("date", "01/1999"); entry.setField("pdf", "aPdfFile"); entry.setField("ps", "aPsFile"); entry.setField("file", "link::"); entry.setField("journal", "test"); entry.setField("title", "<b>hallo</b> units 1 A case AlGaAs and latex $\\alpha$$\\beta$"); entry.setField("abstract", "Réflexions"); File tempFile = bibFolder.newFile(); LinkedFile fileField = new LinkedFile("", tempFile.getAbsolutePath(), ""); entry.setField("file", FileFieldWriter.getStringRepresentation(fileField)); List<FieldChange> changes = worker.cleanup(emptyPreset, entry); Assert.assertEquals(Collections.emptyList(), changes); } @Test public void upgradeExternalLinksMoveFromPdfToFile() { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS); BibEntry entry = new BibEntry(); entry.setField("pdf", "aPdfFile"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.empty(), entry.getField("pdf")); Assert.assertEquals(Optional.of("aPdfFile:aPdfFile:PDF"), entry.getField("file")); } @Test public void upgradeExternalLinksMoveFromPsToFile() { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_UPGRADE_EXTERNAL_LINKS); BibEntry entry = new BibEntry(); entry.setField("ps", "aPsFile"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.empty(), entry.getField("pdf")); Assert.assertEquals(Optional.of("aPsFile:aPsFile:PostScript"), entry.getField("file")); } @Test public void cleanupDoiRemovesLeadingHttp() { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_DOI); BibEntry entry = new BibEntry(); entry.setField("doi", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("10.1016/0001-8708(80)90035-3"), entry.getField("doi")); } @Test public void cleanupDoiReturnsChanges() { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_DOI); BibEntry entry = new BibEntry(); entry.setField("doi", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); List<FieldChange> changes = worker.cleanup(preset, entry); FieldChange expectedChange = new FieldChange(entry, "doi", "http://dx.doi.org/10.1016/0001-8708(80)90035-3", "10.1016/0001-8708(80)90035-3"); Assert.assertEquals(Collections.singletonList(expectedChange), changes); } @Test public void cleanupDoiFindsDoiInURLFieldAndMoveItToDOIField() { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_DOI); BibEntry entry = new BibEntry(); entry.setField("url", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("10.1016/0001-8708(80)90035-3"), entry.getField("doi")); Assert.assertEquals(Optional.empty(), entry.getField("url")); } @Test public void cleanupDoiReturnsChangeWhenDoiInURLField() { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CLEAN_UP_DOI); BibEntry entry = new BibEntry(); entry.setField("url", "http://dx.doi.org/10.1016/0001-8708(80)90035-3"); List<FieldChange> changes = worker.cleanup(preset, entry); List<FieldChange> changeList = new ArrayList<>(); changeList.add(new FieldChange(entry, "doi", null, "10.1016/0001-8708(80)90035-3")); changeList.add(new FieldChange(entry, "url", "http://dx.doi.org/10.1016/0001-8708(80)90035-3", null)); Assert.assertEquals(changeList, changes); } @Test public void cleanupMonthChangesNumberToBibtex() { CleanupPreset preset = new CleanupPreset(new FieldFormatterCleanups(true, Collections.singletonList(new FieldFormatterCleanup("month", new NormalizeMonthFormatter())))); BibEntry entry = new BibEntry(); entry.setField("month", "01"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("#jan#"), entry.getField("month")); } @Test public void cleanupPageNumbersConvertsSingleDashToDouble() { CleanupPreset preset = new CleanupPreset(new FieldFormatterCleanups(true, Collections.singletonList(new FieldFormatterCleanup("pages", new NormalizePagesFormatter())))); BibEntry entry = new BibEntry(); entry.setField("pages", "1-2"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("1--2"), entry.getField("pages")); } @Test public void cleanupDatesConvertsToCorrectFormat() { CleanupPreset preset = new CleanupPreset(new FieldFormatterCleanups(true, Collections.singletonList(new FieldFormatterCleanup("date", new NormalizeDateFormatter())))); BibEntry entry = new BibEntry(); entry.setField("date", "01/1999"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("1999-01"), entry.getField("date")); } @Test public void cleanupFixFileLinksMovesSingleDescriptionToLink() { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.FIX_FILE_LINKS); BibEntry entry = new BibEntry(); entry.setField("file", "link::"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of(":link:"), entry.getField("file")); } @Test public void cleanupMoveFilesMovesFileFromSubfolder() throws IOException { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.MOVE_PDF); File subfolder = bibFolder.newFolder(); File tempFile = new File(subfolder, "test.pdf"); tempFile.createNewFile(); BibEntry entry = new BibEntry(); LinkedFile fileField = new LinkedFile("", tempFile.getAbsolutePath(), ""); entry.setField("file", FileFieldWriter.getStringRepresentation(fileField)); worker.cleanup(preset, entry); LinkedFile newFileField = new LinkedFile("", tempFile.getName(), ""); Assert.assertEquals(Optional.of(FileFieldWriter.getStringRepresentation(newFileField)), entry.getField("file")); } @Test public void cleanupRelativePathsConvertAbsoluteToRelativePath() throws IOException { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.MAKE_PATHS_RELATIVE); File tempFile = bibFolder.newFile(); BibEntry entry = new BibEntry(); LinkedFile fileField = new LinkedFile("", tempFile.getAbsolutePath(), ""); entry.setField("file", FileFieldWriter.getStringRepresentation(fileField)); worker.cleanup(preset, entry); LinkedFile newFileField = new LinkedFile("", tempFile.getName(), ""); Assert.assertEquals(Optional.of(FileFieldWriter.getStringRepresentation(newFileField)), entry.getField("file")); } @Test public void cleanupRenamePdfRenamesRelativeFile() throws IOException { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.RENAME_PDF); File tempFile = bibFolder.newFile(); BibEntry entry = new BibEntry(); entry.setCiteKey("Toot"); LinkedFile fileField = new LinkedFile("", tempFile.getAbsolutePath(), ""); entry.setField("file", FileFieldWriter.getStringRepresentation(fileField)); worker.cleanup(preset, entry); LinkedFile newFileField = new LinkedFile("", "Toot.tmp", ""); Assert.assertEquals(Optional.of(FileFieldWriter.getStringRepresentation(newFileField)), entry.getField("file")); } @Test public void cleanupHtmlToLatexConvertsEpsilonToLatex() { CleanupPreset preset = new CleanupPreset(new FieldFormatterCleanups(true, Collections.singletonList(new FieldFormatterCleanup("title", new HtmlToLatexFormatter())))); BibEntry entry = new BibEntry(); entry.setField("title", "Ε"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("{{$\\Epsilon$}}"), entry.getField("title")); } @Test public void cleanupUnitsConvertsOneAmpereToLatex() { CleanupPreset preset = new CleanupPreset(new FieldFormatterCleanups(true, Collections.singletonList(new FieldFormatterCleanup("title", new UnitsToLatexFormatter())))); BibEntry entry = new BibEntry(); entry.setField("title", "1 A"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("1~{A}"), entry.getField("title")); } @Test public void cleanupCasesAddsBracketAroundAluminiumGalliumArsenid() { ProtectedTermsLoader protectedTermsLoader = new ProtectedTermsLoader( new ProtectedTermsPreferences(ProtectedTermsLoader.getInternalLists(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList())); Assert.assertNotEquals(Collections.emptyList(), protectedTermsLoader.getProtectedTerms()); CleanupPreset preset = new CleanupPreset(new FieldFormatterCleanups(true, Collections .singletonList(new FieldFormatterCleanup("title", new ProtectTermsFormatter(protectedTermsLoader))))); BibEntry entry = new BibEntry(); entry.setField("title", "AlGaAs"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("{AlGaAs}"), entry.getField("title")); } @Test public void cleanupLatexMergesTwoLatexMathEnvironments() { CleanupPreset preset = new CleanupPreset(new FieldFormatterCleanups(true, Collections.singletonList(new FieldFormatterCleanup("title", new LatexCleanupFormatter())))); BibEntry entry = new BibEntry(); entry.setField("title", "$\\alpha$$\\beta$"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("$\\alpha\\beta$"), entry.getField("title")); } @Test public void convertToBiblatexMovesAddressToLocation() { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX); BibEntry entry = new BibEntry(); entry.setField("address", "test"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.empty(), entry.getField("address")); Assert.assertEquals(Optional.of("test"), entry.getField("location")); } @Test public void convertToBiblatexMovesJournalToJournalTitle() { CleanupPreset preset = new CleanupPreset(CleanupPreset.CleanupStep.CONVERT_TO_BIBLATEX); BibEntry entry = new BibEntry(); entry.setField("journal", "test"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.empty(), entry.getField("journal")); Assert.assertEquals(Optional.of("test"), entry.getField("journaltitle")); } @Test public void cleanupWithDisabledFieldFormatterChangesNothing() { CleanupPreset preset = new CleanupPreset(new FieldFormatterCleanups(false, Collections.singletonList(new FieldFormatterCleanup("month", new NormalizeMonthFormatter())))); BibEntry entry = new BibEntry(); entry.setField("month", "01"); worker.cleanup(preset, entry); Assert.assertEquals(Optional.of("01"), entry.getField("month")); } }