From 6da7c052d50fd183b544dd6db660b41526dcaca6 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Mon, 12 Oct 2020 14:48:54 +0200 Subject: [PATCH 01/11] added support for exporting CSL in YAML format. --- .../logic/exporter/ExporterFactory.java | 3 +- .../logic/exporter/TemplateExporter.java | 63 +++++++-------- .../jabref/logic/util/StandardFileType.java | 3 +- .../resource/layout/yaml.begin.layout | 2 + .../resources/resource/layout/yaml.end.layout | 1 + .../resources/resource/layout/yaml.layout | 14 ++++ .../logic/exporter/YamlExporterTest.java | 79 +++++++++++++++++++ 7 files changed, 128 insertions(+), 37 deletions(-) create mode 100644 src/main/resources/resource/layout/yaml.begin.layout create mode 100644 src/main/resources/resource/layout/yaml.end.layout create mode 100644 src/main/resources/resource/layout/yaml.layout create mode 100644 src/test/java/org/jabref/logic/exporter/YamlExporterTest.java diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index fbba86a6aa4..157fd843099 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -49,8 +49,9 @@ public static ExporterFactory create(List customFormats, exporters.add(new TemplateExporter("ISO 690", "iso690txt", "iso690", "iso690txt", StandardFileType.TXT, layoutPreferences, savePreferences)); exporters.add(new TemplateExporter("Endnote", "endnote", "EndNote", "endnote", StandardFileType.TXT, layoutPreferences, savePreferences)); exporters.add(new TemplateExporter("OpenOffice/LibreOffice CSV", "oocsv", "openoffice-csv", "openoffice", StandardFileType.CSV, layoutPreferences, savePreferences)); - exporters.add(new TemplateExporter("RIS", "ris", "ris", "ris", StandardFileType.RIS, layoutPreferences, savePreferences).withEncoding(StandardCharsets.UTF_8)); + exporters.add(new TemplateExporter("RIS", "ris", "ris", "ris", StandardFileType.RIS, layoutPreferences, savePreferences, true).withEncoding(StandardCharsets.UTF_8)); exporters.add(new TemplateExporter("MIS Quarterly", "misq", "misq", "misq", StandardFileType.RTF, layoutPreferences, savePreferences)); + exporters.add(new TemplateExporter("CSL YAML", "yaml", "yaml", null, StandardFileType.YAML, layoutPreferences, savePreferences, true)); exporters.add(new BibTeXMLExporter()); exporters.add(new OpenOfficeDocumentCreator()); exporters.add(new OpenDocumentSpreadsheetCreator()); diff --git a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java index af075471e3e..df6fc29efcc 100644 --- a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java +++ b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java @@ -14,7 +14,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.regex.Pattern; import org.jabref.logic.layout.Layout; import org.jabref.logic.layout.LayoutFormatterPreferences; @@ -34,14 +33,6 @@ public class TemplateExporter extends Exporter { private static final String LAYOUT_PREFIX = "/resource/layout/"; - - /** - * A regular expression that matches blank lines - * - * ?m activates "multimode", which makes ^ match line starts/ends. - * \\s simply marks any whitespace character - */ - private static final Pattern BLANK_LINE_MATCHER = Pattern.compile("(?m)^\\s"); private static final String LAYOUT_EXTENSION = ".layout"; private static final String FORMATTERS_EXTENSION = ".formatters"; private static final String BEGIN_INFIX = ".begin"; @@ -58,8 +49,7 @@ public class TemplateExporter extends Exporter { private boolean deleteBlankLines; /** - * Initialize another export format based on templates stored in dir with - * layoutFile lfFilename. + * Initialize another export format based on templates stored in dir with layoutFile lfFilename. * * @param displayName Name to display to the user. * @param consoleName Name to call this format in the console. @@ -72,8 +62,7 @@ public TemplateExporter(String displayName, String consoleName, String lfFileNam } /** - * Initialize another export format based on templates stored in dir with - * layoutFile lfFilename. + * Initialize another export format based on templates stored in dir with layoutFile lfFilename. * * @param name to display to the user and to call this format in the console. * @param lfFileName Name of the main layout file. @@ -87,8 +76,7 @@ public TemplateExporter(String name, String lfFileName, String extension, Layout } /** - * Initialize another export format based on templates stored in dir with - * layoutFile lfFilename. + * Initialize another export format based on templates stored in dir with layoutFile lfFilename. * * @param displayName Name to display to the user. * @param consoleName Name to call this format in the console. @@ -112,27 +100,33 @@ public TemplateExporter(String displayName, String consoleName, String lfFileNam } /** - * Initialize another export format based on templates stored in dir with - * layoutFile lfFilename. - * The display name is automatically derived from the FileType + * Initialize another export format based on templates stored in dir with layoutFile lfFilename. * + * @param displayName Name to display to the user. * @param consoleName Name to call this format in the console. * @param lfFileName Name of the main layout file. * @param directory Directory in which to find the layout file. * @param extension Should contain the . (for instance .txt). * @param layoutPreferences Preferences for layout * @param savePreferences Preferences for saving - * @param deleteBlankLines If blank lines should be remove (default: false) + * @param deleteBlankLines if blank lines should be removed (default: false) */ - public TemplateExporter(String consoleName, String lfFileName, String directory, StandardFileType extension, LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences, boolean deleteBlankLines) { - this(consoleName, consoleName, lfFileName, directory, extension, layoutPreferences, savePreferences); + public TemplateExporter(String displayName, String consoleName, String lfFileName, String directory, FileType extension, + LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences, boolean deleteBlankLines) { + super(consoleName, displayName, extension); + if (Objects.requireNonNull(lfFileName).endsWith(LAYOUT_EXTENSION)) { + this.lfFileName = lfFileName.substring(0, lfFileName.length() - LAYOUT_EXTENSION.length()); + } else { + this.lfFileName = lfFileName; + } + this.directory = directory; + this.layoutPreferences = layoutPreferences; + this.savePreferences = savePreferences; this.deleteBlankLines = deleteBlankLines; } /** - * Indicate whether this is a custom export. A custom export looks for its - * layout files using a normal file path, while a built-in export looks in - * the classpath. + * Indicate whether this is a custom export. A custom export looks for its layout files using a normal file path, while a built-in export looks in the classpath. * * @param custom true to indicate a custom export format. */ @@ -141,8 +135,7 @@ public void setCustomExport(boolean custom) { } /** - * Set an encoding which will be used in preference to the default value - * obtained from the basepanel. + * Set an encoding which will be used in preference to the default value obtained from the basepanel. * * @param encoding The name of the encoding to use. */ @@ -152,11 +145,9 @@ public TemplateExporter withEncoding(Charset encoding) { } /** - * This method should return a reader from which the given layout file can - * be read. + * This method should return a reader from which the given layout file can be read. *

- * Subclasses of TemplateExporter are free to override and provide their own - * implementation. + * Subclasses of TemplateExporter are free to override and provide their own implementation. * * @param filename the filename * @return a newly created reader @@ -278,8 +269,12 @@ public void export(final BibDatabaseContext databaseContext, final Path file, // Write the entry if (layout != null) { if (deleteBlankLines) { - String withoutBlankLines = BLANK_LINE_MATCHER.matcher(layout.doLayout(entry, databaseContext.getDatabase())).replaceAll(""); - ps.write(withoutBlankLines); + String[] lines = layout.doLayout(entry, databaseContext.getDatabase()).split("\n"); + for (String line : lines) { + if (!line.isBlank() && !line.isEmpty()) { + ps.write(line); + } + } } else { ps.write(layout.doLayout(entry, databaseContext.getDatabase())); } @@ -316,9 +311,7 @@ public void export(final BibDatabaseContext databaseContext, final Path file, } /** - * See if there is a name formatter file bundled with this export format. If so, read - * all the name formatters so they can be used by the filter layouts. - * + * See if there is a name formatter file bundled with this export format. If so, read all the name formatters so they can be used by the filter layouts. */ private void readFormatterFile() { File formatterFile = new File(lfFileName + FORMATTERS_EXTENSION); diff --git a/src/main/java/org/jabref/logic/util/StandardFileType.java b/src/main/java/org/jabref/logic/util/StandardFileType.java index 45c48b6cf76..64cbff44d41 100644 --- a/src/main/java/org/jabref/logic/util/StandardFileType.java +++ b/src/main/java/org/jabref/logic/util/StandardFileType.java @@ -41,7 +41,8 @@ public enum StandardFileType implements FileType { JSON("json"), XMP("xmp"), ZIP("zip"), - CSS("css"); + CSS("css"), + YAML("yaml"); private final List extensions; diff --git a/src/main/resources/resource/layout/yaml.begin.layout b/src/main/resources/resource/layout/yaml.begin.layout new file mode 100644 index 00000000000..3d4a00f98c8 --- /dev/null +++ b/src/main/resources/resource/layout/yaml.begin.layout @@ -0,0 +1,2 @@ +--- +references: diff --git a/src/main/resources/resource/layout/yaml.end.layout b/src/main/resources/resource/layout/yaml.end.layout new file mode 100644 index 00000000000..ed97d539c09 --- /dev/null +++ b/src/main/resources/resource/layout/yaml.end.layout @@ -0,0 +1 @@ +--- diff --git a/src/main/resources/resource/layout/yaml.layout b/src/main/resources/resource/layout/yaml.layout new file mode 100644 index 00000000000..28615bdea8c --- /dev/null +++ b/src/main/resources/resource/layout/yaml.layout @@ -0,0 +1,14 @@ +- id: \citationkey +\begin{type} type: \type\end{type} +\begin{author} + author: + - literal: "\author" +\end{author} +\begin{title} title: "\title"\end{title} +\begin{shorttitle} title-short: "\shorttitle"\end{shorttitle} +\begin{date} issued: \date\end{date} +\begin{url} url: \url\end{url} +\begin{doi} doi: \doi\end{doi} +\begin{volume} volume: \volume\end{volume} +\begin{number} number: \number\end{number} +\begin{urldate} accessed: \urldate\end{urldate} diff --git a/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java new file mode 100644 index 00000000000..563227ead6e --- /dev/null +++ b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java @@ -0,0 +1,79 @@ +package org.jabref.logic.exporter; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.jabref.logic.layout.LayoutFormatterPreferences; +import org.jabref.logic.xmp.XmpPreferences; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.entry.types.StandardEntryType; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.Answers; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +public class YamlExporterTest { + + public Charset charset; + private Exporter yamlExporter; + private BibDatabaseContext databaseContext; + + @BeforeEach + public void setUp() throws Exception { + List customFormats = new ArrayList<>(); + LayoutFormatterPreferences layoutPreferences = mock(LayoutFormatterPreferences.class, Answers.RETURNS_DEEP_STUBS); + SavePreferences savePreferences = mock(SavePreferences.class); + XmpPreferences xmpPreferences = mock(XmpPreferences.class); + ExporterFactory exporterFactory = ExporterFactory.create(customFormats, layoutPreferences, savePreferences, xmpPreferences); + + databaseContext = new BibDatabaseContext(); + charset = StandardCharsets.UTF_8; + yamlExporter = exporterFactory.getExporterByName("yaml").get(); + } + + @Test + public final void exportForNoEntriesWritesNothing(@TempDir Path tempFile) throws Exception { + Path file = tempFile.resolve("ThisIsARandomlyNamedFile"); + Files.createFile(file); + yamlExporter.export(databaseContext, tempFile, charset, Collections.emptyList()); + assertEquals(Collections.emptyList(), Files.readAllLines(file)); + } + + @Test + public final void exportCorrectContent(@TempDir Path tempFile) throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.Article); + entry.withCitationKey("test"); + entry.withField(StandardField.AUTHOR, "Test Author"); + entry.withField(StandardField.TITLE, "Test Title"); + entry.withField(StandardField.URL, "http://example.com"); + entry.withField(StandardField.YEAR, "2020"); + + Path file = tempFile.resolve("RandomFileName"); + Files.createFile(file); + yamlExporter.export(databaseContext, file, charset, Collections.singletonList(entry)); + + List lines = new ArrayList<>(); + lines.add("---"); + lines.add("references:"); + lines.add("- id: test"); + lines.add(" author:"); + lines.add(" - literal: \"Test Author\""); + lines.add(" title: \"Test Title\""); + lines.add(" issued: 2020"); + lines.add(" url: http://example.com"); + lines.add("---"); + + assertEquals(lines, Files.readAllLines(file)); + } +} From 4c40d595ef5834959679c67afd81d7915fa2b804 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Mon, 12 Oct 2020 16:36:33 +0200 Subject: [PATCH 02/11] added changes in Changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e09051bff6..0a5294e7c02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We added a query parser and mapping layer to enable conversion of queries formulated in simplified lucene syntax by the user into api queries. [#6799](https://github.com/JabRef/jabref/pull/6799) - We added some basic functionality to customise the look of JabRef by importing a css theme file. [#5790](https://github.com/JabRef/jabref/issues/5790) - We added connection check function in network preference setting [#6560](https://github.com/JabRef/jabref/issues/6560) +- We added support for exporting to YAML. [#6974](https://github.com/JabRef/jabref/issues/6974) ### Changed @@ -48,6 +49,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We fixed an issue where it was impossible to connect to OpenOffice/LibreOffice on Mac OSX. [#6970](https://github.com/JabRef/jabref/pull/6970) - We fixed an issue with the python script used by browser plugins that failed to locate JabRef if not installed in its default location. [#6963](https://github.com/JabRef/jabref/pull/6963/files) - We fixed an issue where identity column header had incorrect foreground color in the Dark theme. [#6796](https://github.com/JabRef/jabref/issues/6796) +- We fixed an issue where the RIS exporter added extra blank lines.[#7007](https://github.com/JabRef/jabref/pull/7007/files) ### Removed From 048259336f0a8b8d2a427a1c0f708f294e416245 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Mon, 12 Oct 2020 16:45:48 +0200 Subject: [PATCH 03/11] Update CHANGELOG.md --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e79a19f1df0..0a5294e7c02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,7 +51,6 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We fixed an issue where identity column header had incorrect foreground color in the Dark theme. [#6796](https://github.com/JabRef/jabref/issues/6796) - We fixed an issue where the RIS exporter added extra blank lines.[#7007](https://github.com/JabRef/jabref/pull/7007/files) - ### Removed ## [5.1] – 2020-08-30 From 34545cb81ed1be05e76b166e59a89d22f3e5dd8d Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Mon, 12 Oct 2020 19:17:54 +0200 Subject: [PATCH 04/11] remove one trailing space --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a5294e7c02..e0427177748 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,7 +48,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve - We fixed an issue where a remove icon was shown for standard entry types in the custom entry types dialog. [#6906](https://github.com/JabRef/jabref/issues/6906) - We fixed an issue where it was impossible to connect to OpenOffice/LibreOffice on Mac OSX. [#6970](https://github.com/JabRef/jabref/pull/6970) - We fixed an issue with the python script used by browser plugins that failed to locate JabRef if not installed in its default location. [#6963](https://github.com/JabRef/jabref/pull/6963/files) -- We fixed an issue where identity column header had incorrect foreground color in the Dark theme. [#6796](https://github.com/JabRef/jabref/issues/6796) +- We fixed an issue where identity column header had incorrect foreground color in the Dark theme. [#6796](https://github.com/JabRef/jabref/issues/6796) - We fixed an issue where the RIS exporter added extra blank lines.[#7007](https://github.com/JabRef/jabref/pull/7007/files) ### Removed From fd22cba7d32f3b181c18a164c878bf004a7ca7d3 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Tue, 13 Oct 2020 07:31:04 +0200 Subject: [PATCH 05/11] Update src/test/java/org/jabref/logic/exporter/YamlExporterTest.java Co-authored-by: Oliver Kopp --- .../org/jabref/logic/exporter/YamlExporterTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java index 563227ead6e..b1287349b55 100644 --- a/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java @@ -52,12 +52,12 @@ public final void exportForNoEntriesWritesNothing(@TempDir Path tempFile) throws @Test public final void exportCorrectContent(@TempDir Path tempFile) throws Exception { - BibEntry entry = new BibEntry(StandardEntryType.Article); - entry.withCitationKey("test"); - entry.withField(StandardField.AUTHOR, "Test Author"); - entry.withField(StandardField.TITLE, "Test Title"); - entry.withField(StandardField.URL, "http://example.com"); - entry.withField(StandardField.YEAR, "2020"); + BibEntry entry = new BibEntry(StandardEntryType.Article) + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "Test Title") + .withField(StandardField.URL, "http://example.com") + .withField(StandardField.YEAR, "2020"); Path file = tempFile.resolve("RandomFileName"); Files.createFile(file); From 27dce7e71ebfbbe9bad655f2c771a78d947cbcc5 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Tue, 13 Oct 2020 07:31:23 +0200 Subject: [PATCH 06/11] Update src/test/java/org/jabref/logic/exporter/YamlExporterTest.java Co-authored-by: Oliver Kopp --- .../logic/exporter/YamlExporterTest.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java index b1287349b55..4015caa3f87 100644 --- a/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java @@ -63,16 +63,16 @@ public final void exportCorrectContent(@TempDir Path tempFile) throws Exception Files.createFile(file); yamlExporter.export(databaseContext, file, charset, Collections.singletonList(entry)); - List lines = new ArrayList<>(); - lines.add("---"); - lines.add("references:"); - lines.add("- id: test"); - lines.add(" author:"); - lines.add(" - literal: \"Test Author\""); - lines.add(" title: \"Test Title\""); - lines.add(" issued: 2020"); - lines.add(" url: http://example.com"); - lines.add("---"); + List lines = List.of( + "---", + "references:", + "- id: test", + " author:", + " - literal: \"Test Author\"", + " title: \"Test Title\"", + " issued: 2020", + " url: http://example.com", + "---"); assertEquals(lines, Files.readAllLines(file)); } From 977bc6e1a1a40ba5ce249d94f3afa7373fd168cb Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Tue, 13 Oct 2020 07:31:41 +0200 Subject: [PATCH 07/11] Update src/main/java/org/jabref/logic/exporter/TemplateExporter.java Co-authored-by: Oliver Kopp --- src/main/java/org/jabref/logic/exporter/TemplateExporter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java index df6fc29efcc..1efcf37ffcc 100644 --- a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java +++ b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java @@ -109,7 +109,7 @@ public TemplateExporter(String displayName, String consoleName, String lfFileNam * @param extension Should contain the . (for instance .txt). * @param layoutPreferences Preferences for layout * @param savePreferences Preferences for saving - * @param deleteBlankLines if blank lines should be removed (default: false) + * @param deleteBlankLines If blank lines should be removed (default: false) */ public TemplateExporter(String displayName, String consoleName, String lfFileName, String directory, FileType extension, LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences, boolean deleteBlankLines) { From 58eea460893e275b3dd6e1f70823675d657f3afa Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Thu, 15 Oct 2020 11:18:19 +0200 Subject: [PATCH 08/11] added conversion from bibtex entrytype to csl type fixed blank line removal --- .../logic/exporter/TemplateExporter.java | 6 +- .../org/jabref/logic/layout/LayoutEntry.java | 3 + .../jabref/logic/layout/format/CSLType.java | 25 ++++++ .../resources/resource/layout/yaml.layout | 2 +- .../logic/exporter/YamlExporterTest.java | 77 +++++++++++++------ 5 files changed, 86 insertions(+), 27 deletions(-) create mode 100644 src/main/java/org/jabref/logic/layout/format/CSLType.java diff --git a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java index 1efcf37ffcc..91bdf450863 100644 --- a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java +++ b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java @@ -19,6 +19,7 @@ import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.layout.LayoutHelper; import org.jabref.logic.util.FileType; +import org.jabref.logic.util.OS; import org.jabref.logic.util.StandardFileType; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -32,6 +33,7 @@ */ public class TemplateExporter extends Exporter { + private static final String BLANK_LINE_PATTERN = "\\r\\n|\\n"; private static final String LAYOUT_PREFIX = "/resource/layout/"; private static final String LAYOUT_EXTENSION = ".layout"; private static final String FORMATTERS_EXTENSION = ".formatters"; @@ -269,10 +271,10 @@ public void export(final BibDatabaseContext databaseContext, final Path file, // Write the entry if (layout != null) { if (deleteBlankLines) { - String[] lines = layout.doLayout(entry, databaseContext.getDatabase()).split("\n"); + String[] lines = layout.doLayout(entry, databaseContext.getDatabase()).split(BLANK_LINE_PATTERN); for (String line : lines) { if (!line.isBlank() && !line.isEmpty()) { - ps.write(line); + ps.write(line + OS.NEWLINE); } } } else { diff --git a/src/main/java/org/jabref/logic/layout/LayoutEntry.java b/src/main/java/org/jabref/logic/layout/LayoutEntry.java index fe5632f9f5b..8a1f6e7349f 100644 --- a/src/main/java/org/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/org/jabref/logic/layout/LayoutEntry.java @@ -32,6 +32,7 @@ import org.jabref.logic.layout.format.AuthorNatBib; import org.jabref.logic.layout.format.AuthorOrgSci; import org.jabref.logic.layout.format.Authors; +import org.jabref.logic.layout.format.CSLType; import org.jabref.logic.layout.format.CompositeFormat; import org.jabref.logic.layout.format.CreateBibORDFAuthors; import org.jabref.logic.layout.format.CreateDocBook4Authors; @@ -539,6 +540,8 @@ private LayoutFormatter getLayoutFormatterByName(String name) { return new WrapFileLinks(prefs.getFileLinkPreferences()); case "Markdown": return new MarkdownFormatter(); + case "CSLType": + return new CSLType(); default: return null; } diff --git a/src/main/java/org/jabref/logic/layout/format/CSLType.java b/src/main/java/org/jabref/logic/layout/format/CSLType.java new file mode 100644 index 00000000000..1507b2bdc0e --- /dev/null +++ b/src/main/java/org/jabref/logic/layout/format/CSLType.java @@ -0,0 +1,25 @@ +package org.jabref.logic.layout.format; + +import java.util.Map; + +import org.jabref.logic.layout.LayoutFormatter; +import org.jabref.model.entry.types.StandardEntryType; + +public class CSLType implements LayoutFormatter { + + @Override + public String format(String value) { + Map map = Map.of(StandardEntryType.Article.getDisplayName(), "article", + StandardEntryType.Book.getDisplayName(), "book", + StandardEntryType.Conference.getDisplayName(), "paper-conference", + StandardEntryType.Report.getDisplayName(), "report", + StandardEntryType.Thesis.getDisplayName(), "thesis", + StandardEntryType.MastersThesis.getDisplayName(), "thesis", + StandardEntryType.PhdThesis.getDisplayName(), "thesis", + StandardEntryType.WWW.getDisplayName(), "webpage", + StandardEntryType.TechReport.getDisplayName(), "report", + StandardEntryType.Online.getDisplayName(), "webpage"); + + return map.getOrDefault(value, "no-type"); + } +} diff --git a/src/main/resources/resource/layout/yaml.layout b/src/main/resources/resource/layout/yaml.layout index 28615bdea8c..94e4f02a9b9 100644 --- a/src/main/resources/resource/layout/yaml.layout +++ b/src/main/resources/resource/layout/yaml.layout @@ -1,5 +1,5 @@ - id: \citationkey -\begin{type} type: \type\end{type} +\begin{entrytype} type: \format[CSLType]{\entrytype}\end{entrytype} \begin{author} author: - literal: "\author" diff --git a/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java index 4015caa3f87..cb5268cf005 100644 --- a/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/YamlExporterTest.java @@ -15,7 +15,7 @@ import org.jabref.model.entry.field.StandardField; import org.jabref.model.entry.types.StandardEntryType; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.mockito.Answers; @@ -25,12 +25,12 @@ public class YamlExporterTest { - public Charset charset; - private Exporter yamlExporter; - private BibDatabaseContext databaseContext; + private static Charset charset; + private static Exporter yamlExporter; + private static BibDatabaseContext databaseContext; - @BeforeEach - public void setUp() throws Exception { + @BeforeAll + static void setUp() { List customFormats = new ArrayList<>(); LayoutFormatterPreferences layoutPreferences = mock(LayoutFormatterPreferences.class, Answers.RETURNS_DEEP_STUBS); SavePreferences savePreferences = mock(SavePreferences.class); @@ -51,29 +51,58 @@ public final void exportForNoEntriesWritesNothing(@TempDir Path tempFile) throws } @Test - public final void exportCorrectContent(@TempDir Path tempFile) throws Exception { + public final void exportsCorrectContent(@TempDir Path tempFile) throws Exception { BibEntry entry = new BibEntry(StandardEntryType.Article) - .withCitationKey("test") - .withField(StandardField.AUTHOR, "Test Author") - .withField(StandardField.TITLE, "Test Title") - .withField(StandardField.URL, "http://example.com") - .withField(StandardField.YEAR, "2020"); + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "Test Title") + .withField(StandardField.URL, "http://example.com") + .withField(StandardField.DATE, "2020-10-14"); Path file = tempFile.resolve("RandomFileName"); Files.createFile(file); yamlExporter.export(databaseContext, file, charset, Collections.singletonList(entry)); - List lines = List.of( - "---", - "references:", - "- id: test", - " author:", - " - literal: \"Test Author\"", - " title: \"Test Title\"", - " issued: 2020", - " url: http://example.com", - "---"); - - assertEquals(lines, Files.readAllLines(file)); + List expected = List.of( + "---", + "references:", + "- id: test", + " type: article", + " author:", + " - literal: \"Test Author\"", + " title: \"Test Title\"", + " issued: 2020-10-14", + " url: http://example.com", + "---"); + + assertEquals(expected, Files.readAllLines(file)); + } + + @Test + public final void formatsContentCorrect(@TempDir Path tempFile) throws Exception { + BibEntry entry = new BibEntry(StandardEntryType.Misc) + .withCitationKey("test") + .withField(StandardField.AUTHOR, "Test Author") + .withField(StandardField.TITLE, "Test Title") + .withField(StandardField.URL, "http://example.com") + .withField(StandardField.DATE, "2020-10-14"); + + Path file = tempFile.resolve("RandomFileName"); + Files.createFile(file); + yamlExporter.export(databaseContext, file, charset, Collections.singletonList(entry)); + + List expected = List.of( + "---", + "references:", + "- id: test", + " type: no-type", + " author:", + " - literal: \"Test Author\"", + " title: \"Test Title\"", + " issued: 2020-10-14", + " url: http://example.com", + "---"); + + assertEquals(expected, Files.readAllLines(file)); } } From 92e45019a6ee094778e716c6b27fad549b8306f8 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Mon, 19 Oct 2020 16:46:29 +0200 Subject: [PATCH 09/11] change deleteBlankLines boolean to use new enum BlankLineBehaviour wrap comments correctly --- CHANGELOG.md | 1 - .../logic/exporter/BlankLineBehaviour.java | 9 +++++++++ .../logic/exporter/ExporterFactory.java | 4 ++-- .../logic/exporter/TemplateExporter.java | 19 ++++++++++++------- 4 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java diff --git a/CHANGELOG.md b/CHANGELOG.md index be265f976e6..a9683dc4d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,7 +54,6 @@ inserting new citations in a OpenOffic/LibreOffice document. [#6957](https://git - We fixed an issue where the RIS exporter added extra blank lines.[#7007](https://github.com/JabRef/jabref/pull/7007/files) - We fixed an issue where clicking on Collapse All button in the Search for Unlinked Local Files expanded the directory structure erroneously [#6848](https://github.com/JabRef/jabref/issues/6848) - ### Removed ## [5.1] – 2020-08-30 diff --git a/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java b/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java new file mode 100644 index 00000000000..46be1803afb --- /dev/null +++ b/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java @@ -0,0 +1,9 @@ +package org.jabref.logic.exporter; + +/** +this enum represents the behaviour for blank lines in {@link TemplateExporter} + */ +public enum BlankLineBehaviour { + KEEP_BLANKS, + DELETE_BLANKS +} diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index 157fd843099..082e284a245 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -49,9 +49,9 @@ public static ExporterFactory create(List customFormats, exporters.add(new TemplateExporter("ISO 690", "iso690txt", "iso690", "iso690txt", StandardFileType.TXT, layoutPreferences, savePreferences)); exporters.add(new TemplateExporter("Endnote", "endnote", "EndNote", "endnote", StandardFileType.TXT, layoutPreferences, savePreferences)); exporters.add(new TemplateExporter("OpenOffice/LibreOffice CSV", "oocsv", "openoffice-csv", "openoffice", StandardFileType.CSV, layoutPreferences, savePreferences)); - exporters.add(new TemplateExporter("RIS", "ris", "ris", "ris", StandardFileType.RIS, layoutPreferences, savePreferences, true).withEncoding(StandardCharsets.UTF_8)); + exporters.add(new TemplateExporter("RIS", "ris", "ris", "ris", StandardFileType.RIS, layoutPreferences, savePreferences, BlankLineBehaviour.DELETE_BLANKS).withEncoding(StandardCharsets.UTF_8)); exporters.add(new TemplateExporter("MIS Quarterly", "misq", "misq", "misq", StandardFileType.RTF, layoutPreferences, savePreferences)); - exporters.add(new TemplateExporter("CSL YAML", "yaml", "yaml", null, StandardFileType.YAML, layoutPreferences, savePreferences, true)); + exporters.add(new TemplateExporter("CSL YAML", "yaml", "yaml", null, StandardFileType.YAML, layoutPreferences, savePreferences, BlankLineBehaviour.DELETE_BLANKS)); exporters.add(new BibTeXMLExporter()); exporters.add(new OpenOfficeDocumentCreator()); exporters.add(new OpenDocumentSpreadsheetCreator()); diff --git a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java index 91bdf450863..8825652dc6d 100644 --- a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java +++ b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java @@ -40,6 +40,7 @@ public class TemplateExporter extends Exporter { private static final String BEGIN_INFIX = ".begin"; private static final String END_INFIX = ".end"; + private static final Logger LOGGER = LoggerFactory.getLogger(TemplateExporter.class); private final String lfFileName; @@ -48,7 +49,7 @@ public class TemplateExporter extends Exporter { private final SavePreferences savePreferences; private Charset encoding; // If this value is set, it will be used to override the default encoding for the getCurrentBasePanel. private boolean customExport; - private boolean deleteBlankLines; + private BlankLineBehaviour blankLineBehaviour; /** * Initialize another export format based on templates stored in dir with layoutFile lfFilename. @@ -111,10 +112,11 @@ public TemplateExporter(String displayName, String consoleName, String lfFileNam * @param extension Should contain the . (for instance .txt). * @param layoutPreferences Preferences for layout * @param savePreferences Preferences for saving - * @param deleteBlankLines If blank lines should be removed (default: false) + * @param blankLineBehaviour how to behave regarding blank lines. */ public TemplateExporter(String displayName, String consoleName, String lfFileName, String directory, FileType extension, - LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences, boolean deleteBlankLines) { + LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences, + BlankLineBehaviour blankLineBehaviour) { super(consoleName, displayName, extension); if (Objects.requireNonNull(lfFileName).endsWith(LAYOUT_EXTENSION)) { this.lfFileName = lfFileName.substring(0, lfFileName.length() - LAYOUT_EXTENSION.length()); @@ -124,11 +126,13 @@ public TemplateExporter(String displayName, String consoleName, String lfFileNam this.directory = directory; this.layoutPreferences = layoutPreferences; this.savePreferences = savePreferences; - this.deleteBlankLines = deleteBlankLines; + this.blankLineBehaviour = blankLineBehaviour; } /** - * Indicate whether this is a custom export. A custom export looks for its layout files using a normal file path, while a built-in export looks in the classpath. + * Indicate whether this is a custom export. + * A custom export looks for its layout files using a normal file path, + * while a built-in export looks in the classpath. * * @param custom true to indicate a custom export format. */ @@ -270,7 +274,7 @@ public void export(final BibDatabaseContext databaseContext, final Path file, // Write the entry if (layout != null) { - if (deleteBlankLines) { + if (blankLineBehaviour == BlankLineBehaviour.DELETE_BLANKS) { String[] lines = layout.doLayout(entry, databaseContext.getDatabase()).split(BLANK_LINE_PATTERN); for (String line : lines) { if (!line.isBlank() && !line.isEmpty()) { @@ -313,7 +317,8 @@ public void export(final BibDatabaseContext databaseContext, final Path file, } /** - * See if there is a name formatter file bundled with this export format. If so, read all the name formatters so they can be used by the filter layouts. + * See if there is a name formatter file bundled with this export format. + * If so, read all the name formatters so they can be used by the filter layouts. */ private void readFormatterFile() { File formatterFile = new File(lfFileName + FORMATTERS_EXTENSION); From 12a366a7e5a52bc53b5bb225e098eb7c23886575 Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Mon, 19 Oct 2020 17:15:31 +0200 Subject: [PATCH 10/11] Update BlankLineBehaviour.java --- src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java b/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java index 46be1803afb..0e8a5a4c090 100644 --- a/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java +++ b/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java @@ -1,7 +1,7 @@ package org.jabref.logic.exporter; /** -this enum represents the behaviour for blank lines in {@link TemplateExporter} + this enum represents the behaviour for blank lines in {@link TemplateExporter} */ public enum BlankLineBehaviour { KEEP_BLANKS, From a1107ed890bb562ca6f5b64f26ae7aecceb6f92d Mon Sep 17 00:00:00 2001 From: Johannes Theiner Date: Wed, 21 Oct 2020 10:12:06 +0200 Subject: [PATCH 11/11] small updates --- .../logic/exporter/BlankLineBehaviour.java | 2 +- .../logic/exporter/TemplateExporter.java | 1 - .../jabref/logic/layout/format/CSLType.java | 22 ++++++++----------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java b/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java index 0e8a5a4c090..96957869a27 100644 --- a/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java +++ b/src/main/java/org/jabref/logic/exporter/BlankLineBehaviour.java @@ -1,7 +1,7 @@ package org.jabref.logic.exporter; /** - this enum represents the behaviour for blank lines in {@link TemplateExporter} + * This enum represents the behaviour for blank lines in {@link TemplateExporter} */ public enum BlankLineBehaviour { KEEP_BLANKS, diff --git a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java index 8825652dc6d..4e3230e509d 100644 --- a/src/main/java/org/jabref/logic/exporter/TemplateExporter.java +++ b/src/main/java/org/jabref/logic/exporter/TemplateExporter.java @@ -40,7 +40,6 @@ public class TemplateExporter extends Exporter { private static final String BEGIN_INFIX = ".begin"; private static final String END_INFIX = ".end"; - private static final Logger LOGGER = LoggerFactory.getLogger(TemplateExporter.class); private final String lfFileName; diff --git a/src/main/java/org/jabref/logic/layout/format/CSLType.java b/src/main/java/org/jabref/logic/layout/format/CSLType.java index 1507b2bdc0e..aac863567fe 100644 --- a/src/main/java/org/jabref/logic/layout/format/CSLType.java +++ b/src/main/java/org/jabref/logic/layout/format/CSLType.java @@ -1,7 +1,5 @@ package org.jabref.logic.layout.format; -import java.util.Map; - import org.jabref.logic.layout.LayoutFormatter; import org.jabref.model.entry.types.StandardEntryType; @@ -9,17 +7,15 @@ public class CSLType implements LayoutFormatter { @Override public String format(String value) { - Map map = Map.of(StandardEntryType.Article.getDisplayName(), "article", - StandardEntryType.Book.getDisplayName(), "book", - StandardEntryType.Conference.getDisplayName(), "paper-conference", - StandardEntryType.Report.getDisplayName(), "report", - StandardEntryType.Thesis.getDisplayName(), "thesis", - StandardEntryType.MastersThesis.getDisplayName(), "thesis", - StandardEntryType.PhdThesis.getDisplayName(), "thesis", - StandardEntryType.WWW.getDisplayName(), "webpage", - StandardEntryType.TechReport.getDisplayName(), "report", - StandardEntryType.Online.getDisplayName(), "webpage"); + return switch (StandardEntryType.valueOf(value)) { + case Article -> "article"; + case Book -> "book"; + case Conference -> "paper-conference"; + case Report, TechReport -> "report"; + case Thesis, MastersThesis, PhdThesis -> "thesis"; + case WWW, Online -> "webpage"; - return map.getOrDefault(value, "no-type"); + default -> "no-type"; + }; } }