From 531984df583c36d7610958681703a62119b6840c Mon Sep 17 00:00:00 2001 From: Johannes Manner Date: Wed, 28 Mar 2018 17:48:36 +0200 Subject: [PATCH 1/6] Add Xmp GUI Export Adding a new exporter for xmp export in a .xmp file. --- .../logic/exporter/ExporterFactory.java | 1 + .../jabref/logic/exporter/XmpExporter.java | 40 +++++++++++++++++++ .../java/org/jabref/logic/util/FileType.java | 1 + .../org/jabref/logic/xmp/XmpUtilWriter.java | 32 +++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 src/main/java/org/jabref/logic/exporter/XmpExporter.java diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index 5eb9145f6c5..27e15433496 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -54,6 +54,7 @@ public static ExporterFactory create(Map customFormats exporters.add(new OpenDocumentSpreadsheetCreator()); exporters.add(new MSBibExporter()); exporters.add(new ModsExporter()); + exporters.add(new XmpExporter()); // Now add custom export formats exporters.addAll(customFormats.values()); diff --git a/src/main/java/org/jabref/logic/exporter/XmpExporter.java b/src/main/java/org/jabref/logic/exporter/XmpExporter.java new file mode 100644 index 00000000000..7f679bd5e47 --- /dev/null +++ b/src/main/java/org/jabref/logic/exporter/XmpExporter.java @@ -0,0 +1,40 @@ +package org.jabref.logic.exporter; + +import java.io.BufferedWriter; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; + +import org.jabref.logic.util.FileType; +import org.jabref.logic.xmp.XmpUtilWriter; +import org.jabref.model.database.BibDatabaseContext; +import org.jabref.model.entry.BibEntry; + +/** + * + */ +public class XmpExporter extends Exporter { + + public XmpExporter() { + super("XmpBib", FileType.ENDNOTE_XMP.getDescription(), FileType.ENDNOTE_XMP); + } + + @Override + public void export(BibDatabaseContext databaseContext, Path file, Charset encoding, List entries) throws Exception { + Objects.requireNonNull(databaseContext); + Objects.requireNonNull(entries); + + if (entries.isEmpty()) { + return; + } + + try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { + writer.write(XmpUtilWriter.generateXmpString(entries)); + writer.flush(); + } + } + +} diff --git a/src/main/java/org/jabref/logic/util/FileType.java b/src/main/java/org/jabref/logic/util/FileType.java index cb1de601dc0..101570f8aa6 100644 --- a/src/main/java/org/jabref/logic/util/FileType.java +++ b/src/main/java/org/jabref/logic/util/FileType.java @@ -26,6 +26,7 @@ public enum FileType { DIN_1505(Localization.lang("%0 file", "DIN 1505"), "rtf"), ENDNOTE(Localization.lang("%0 file", "EndNote/Refer"), "ref", "enw"), ENDNOTE_XML(Localization.lang("%0 file", "EndNote XML"), "xml"), + ENDNOTE_XMP(Localization.lang("%0 file", "EndNote Xmp"), "xmp"), ENDNOTE_TXT(Localization.lang("%0 file", "EndNote"), "txt"), //for export FREECITE(Localization.lang("%0 file", "FreeCite"), "txt", "xml"), HARVARD_RTF(Localization.lang("%0 file", "Harvard"), "rtf"), diff --git a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java index 45f10167009..010b4dc5d80 100644 --- a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java +++ b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java @@ -3,6 +3,8 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -13,6 +15,7 @@ import javax.xml.transform.TransformerException; +import org.jabref.Globals; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; @@ -82,6 +85,15 @@ public static void writeXmp(Path file, BibEntry entry, XmpUtilWriter.writeXmp(file, bibEntryList, database, xmpPreferences); } + /** + * Writes the information of the bib entry to the dublin core schema using + * a custom extractor. + * + * @param dcSchema + * @param entry + * @param database + * @param xmpPreferences + */ private static void writeToDCSchema(DublinCoreSchema dcSchema, BibEntry entry, BibDatabase database, XmpPreferences xmpPreferences) { @@ -159,6 +171,26 @@ private static void writeDublinCore(PDDocument document, catalog.setMetadata(metadataStream); } + public static String generateXmpString(List entries) { + XMPMetadata meta = XMPMetadata.createXMPMetadata(); + for (BibEntry entry : entries) { + DublinCoreSchema dcSchema = meta.createAndAddDublinCoreSchema(); + XmpUtilWriter.writeToDCSchema(dcSchema, entry, null, Globals.prefs.getXMPPreferences()); + } + ByteArrayOutputStream os = new ByteArrayOutputStream(); + XmpSerializer serializer = new XmpSerializer(); + try { + serializer.serialize(meta, os, true); + return os.toString(StandardCharsets.UTF_8.name()); + } catch (TransformerException e) { + LOGGER.warn("Tranformation into xmp not possible: " + e.getMessage()); + return ""; + } catch (UnsupportedEncodingException e) { + LOGGER.warn("Unsupported encoding to UTF-8 of bib entries in xmp metadata."); + return ""; + } + } + /** * Try to write the given BibTexEntry in the Document Information (the * properties of the pdf). From 0b44c43e87a51208a68b5649d51bc83fca568594 Mon Sep 17 00:00:00 2001 From: Johannes Manner Date: Wed, 4 Apr 2018 09:04:51 +0200 Subject: [PATCH 2/6] updated code with the requested changes --- .../jabref/logic/exporter/XmpExporter.java | 7 ++-- .../java/org/jabref/logic/util/FileType.java | 2 +- .../org/jabref/logic/xmp/XmpUtilWriter.java | 33 ++++++++++++------- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/XmpExporter.java b/src/main/java/org/jabref/logic/exporter/XmpExporter.java index 7f679bd5e47..df0c53aadaf 100644 --- a/src/main/java/org/jabref/logic/exporter/XmpExporter.java +++ b/src/main/java/org/jabref/logic/exporter/XmpExporter.java @@ -8,13 +8,16 @@ import java.util.List; import java.util.Objects; +import org.jabref.Globals; import org.jabref.logic.util.FileType; import org.jabref.logic.xmp.XmpUtilWriter; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; /** - * + * A custom exporter to write bib entries to a .xmp file for further processing + * in other scenarios and applications. The xmp metadata are written in dublin + * core format. */ public class XmpExporter extends Exporter { @@ -32,7 +35,7 @@ public void export(BibDatabaseContext databaseContext, Path file, Charset encodi } try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { - writer.write(XmpUtilWriter.generateXmpString(entries)); + writer.write(XmpUtilWriter.generateXmpString(entries, Globals.prefs.getXMPPreferences())); writer.flush(); } } diff --git a/src/main/java/org/jabref/logic/util/FileType.java b/src/main/java/org/jabref/logic/util/FileType.java index 101570f8aa6..c0ff7e63dfb 100644 --- a/src/main/java/org/jabref/logic/util/FileType.java +++ b/src/main/java/org/jabref/logic/util/FileType.java @@ -26,7 +26,7 @@ public enum FileType { DIN_1505(Localization.lang("%0 file", "DIN 1505"), "rtf"), ENDNOTE(Localization.lang("%0 file", "EndNote/Refer"), "ref", "enw"), ENDNOTE_XML(Localization.lang("%0 file", "EndNote XML"), "xml"), - ENDNOTE_XMP(Localization.lang("%0 file", "EndNote Xmp"), "xmp"), + ENDNOTE_XMP(Localization.lang("%0 file", "Xmp"), "xmp"), ENDNOTE_TXT(Localization.lang("%0 file", "EndNote"), "txt"), //for export FREECITE(Localization.lang("%0 file", "FreeCite"), "txt", "xml"), HARVARD_RTF(Localization.lang("%0 file", "Harvard"), "rtf"), diff --git a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java index 010b4dc5d80..0547c16ecf1 100644 --- a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java +++ b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java @@ -15,7 +15,6 @@ import javax.xml.transform.TransformerException; -import org.jabref.Globals; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; @@ -89,10 +88,11 @@ public static void writeXmp(Path file, BibEntry entry, * Writes the information of the bib entry to the dublin core schema using * a custom extractor. * - * @param dcSchema - * @param entry - * @param database - * @param xmpPreferences + * @param dcSchema Dublin core schema, which is filled with the bib entry. + * @param entry The entry, which is added to the dublin core metadata. + * @param database maybenull An optional database which the given bibtex entries belong to, which will be used to + * resolve strings. If the database is null the strings will not be resolved. + * @param xmpPreferences The user's xmp preferences. */ private static void writeToDCSchema(DublinCoreSchema dcSchema, BibEntry entry, BibDatabase database, XmpPreferences xmpPreferences) { @@ -103,7 +103,6 @@ private static void writeToDCSchema(DublinCoreSchema dcSchema, BibEntry entry, B dcExtractor.fillDublinCoreSchema(); } - /** * Try to write the given BibTexEntry as a DublinCore XMP Schema * @@ -171,15 +170,24 @@ private static void writeDublinCore(PDDocument document, catalog.setMetadata(metadataStream); } - public static String generateXmpString(List entries) { + /** + * This method generates an xmp metadata string in dublin core format. + *
+ * + * @param entries A list of entries, which are added to the dublin core metadata. + * @param xmpPreferences The user's xmp preferences. + * + * @return If something goes wrong (e.g. an exception is thrown), the method returns an empty string, + * otherwise it returns the xmp metadata as a string in dublin core format. + */ + public static String generateXmpString(List entries, XmpPreferences xmpPreferences) { XMPMetadata meta = XMPMetadata.createXMPMetadata(); for (BibEntry entry : entries) { DublinCoreSchema dcSchema = meta.createAndAddDublinCoreSchema(); - XmpUtilWriter.writeToDCSchema(dcSchema, entry, null, Globals.prefs.getXMPPreferences()); + XmpUtilWriter.writeToDCSchema(dcSchema, entry, null, xmpPreferences); } - ByteArrayOutputStream os = new ByteArrayOutputStream(); - XmpSerializer serializer = new XmpSerializer(); - try { + try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { + XmpSerializer serializer = new XmpSerializer(); serializer.serialize(meta, os, true); return os.toString(StandardCharsets.UTF_8.name()); } catch (TransformerException e) { @@ -188,6 +196,9 @@ public static String generateXmpString(List entries) { } catch (UnsupportedEncodingException e) { LOGGER.warn("Unsupported encoding to UTF-8 of bib entries in xmp metadata."); return ""; + } catch (IOException e) { + LOGGER.warn("IO Exception thrown by closing the output stream."); + return ""; } } From 67cbd43c3037cc28db82fc21429aa4a86ea7cde9 Mon Sep 17 00:00:00 2001 From: Johannes Manner Date: Wed, 4 Apr 2018 17:20:07 +0200 Subject: [PATCH 3/6] XMP export works now for single elements --- .../logic/exporter/ExporterFactory.java | 3 ++- .../jabref/logic/exporter/XmpExporter.java | 11 +++++---- .../java/org/jabref/logic/util/FileType.java | 2 +- .../org/jabref/logic/xmp/XmpUtilWriter.java | 24 +++++++++++++++---- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index 27e15433496..755c3016281 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -8,6 +8,7 @@ import java.util.Objects; import java.util.Optional; +import org.jabref.Globals; import org.jabref.logic.journals.JournalAbbreviationLoader; import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.util.FileType; @@ -54,7 +55,7 @@ public static ExporterFactory create(Map customFormats exporters.add(new OpenDocumentSpreadsheetCreator()); exporters.add(new MSBibExporter()); exporters.add(new ModsExporter()); - exporters.add(new XmpExporter()); + exporters.add(new XmpExporter(Globals.prefs.getXMPPreferences())); // Now add custom export formats exporters.addAll(customFormats.values()); diff --git a/src/main/java/org/jabref/logic/exporter/XmpExporter.java b/src/main/java/org/jabref/logic/exporter/XmpExporter.java index df0c53aadaf..97748e6016d 100644 --- a/src/main/java/org/jabref/logic/exporter/XmpExporter.java +++ b/src/main/java/org/jabref/logic/exporter/XmpExporter.java @@ -8,8 +8,8 @@ import java.util.List; import java.util.Objects; -import org.jabref.Globals; import org.jabref.logic.util.FileType; +import org.jabref.logic.xmp.XmpPreferences; import org.jabref.logic.xmp.XmpUtilWriter; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -21,8 +21,11 @@ */ public class XmpExporter extends Exporter { - public XmpExporter() { - super("XmpBib", FileType.ENDNOTE_XMP.getDescription(), FileType.ENDNOTE_XMP); + private final XmpPreferences xmpPreferences; + + public XmpExporter(XmpPreferences xmpPreferences) { + super("xmp", FileType.PLAIN_XMP.getDescription(), FileType.PLAIN_XMP); + this.xmpPreferences = xmpPreferences; } @Override @@ -35,7 +38,7 @@ public void export(BibDatabaseContext databaseContext, Path file, Charset encodi } try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { - writer.write(XmpUtilWriter.generateXmpString(entries, Globals.prefs.getXMPPreferences())); + writer.write(XmpUtilWriter.generateXmpString(entries, this.xmpPreferences)); writer.flush(); } } diff --git a/src/main/java/org/jabref/logic/util/FileType.java b/src/main/java/org/jabref/logic/util/FileType.java index c0ff7e63dfb..09c9485da41 100644 --- a/src/main/java/org/jabref/logic/util/FileType.java +++ b/src/main/java/org/jabref/logic/util/FileType.java @@ -26,7 +26,6 @@ public enum FileType { DIN_1505(Localization.lang("%0 file", "DIN 1505"), "rtf"), ENDNOTE(Localization.lang("%0 file", "EndNote/Refer"), "ref", "enw"), ENDNOTE_XML(Localization.lang("%0 file", "EndNote XML"), "xml"), - ENDNOTE_XMP(Localization.lang("%0 file", "Xmp"), "xmp"), ENDNOTE_TXT(Localization.lang("%0 file", "EndNote"), "txt"), //for export FREECITE(Localization.lang("%0 file", "FreeCite"), "txt", "xml"), HARVARD_RTF(Localization.lang("%0 file", "Harvard"), "rtf"), @@ -51,6 +50,7 @@ public enum FileType { SILVER_PLATTER(Localization.lang("%0 file", "SilverPlatter"), "dat", "txt"), SIMPLE_HTML(Localization.lang("%0 file", Localization.lang("Simple HTML")), "html"), XMP(Localization.lang("XMP-annotated PDF"), "pdf"), + PLAIN_XMP(Localization.lang("%0 file", "Xmp"), "xmp"), AUX(Localization.lang("%0 file", "AUX"), "aux"), JSTYLE(Localization.lang("Style file"), "jstyle"), diff --git a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java index 0547c16ecf1..9e14464f0b0 100644 --- a/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java +++ b/src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java @@ -99,7 +99,21 @@ private static void writeToDCSchema(DublinCoreSchema dcSchema, BibEntry entry, B BibEntry resolvedEntry = XmpUtilWriter.getDefaultOrDatabaseEntry(entry, database); - DublinCoreExtractor dcExtractor = new DublinCoreExtractor(dcSchema, xmpPreferences, resolvedEntry); + writeToDCSchema(dcSchema, resolvedEntry, xmpPreferences); + } + + /** + * Writes the information of the bib entry to the dublin core schema using + * a custom extractor. + * + * @param dcSchema Dublin core schema, which is filled with the bib entry. + * @param entry The entry, which is added to the dublin core metadata. + * @param xmpPreferences The user's xmp preferences. + */ + private static void writeToDCSchema(DublinCoreSchema dcSchema, BibEntry entry, + XmpPreferences xmpPreferences) { + + DublinCoreExtractor dcExtractor = new DublinCoreExtractor(dcSchema, xmpPreferences, entry); dcExtractor.fillDublinCoreSchema(); } @@ -184,20 +198,20 @@ public static String generateXmpString(List entries, XmpPreferences xm XMPMetadata meta = XMPMetadata.createXMPMetadata(); for (BibEntry entry : entries) { DublinCoreSchema dcSchema = meta.createAndAddDublinCoreSchema(); - XmpUtilWriter.writeToDCSchema(dcSchema, entry, null, xmpPreferences); + XmpUtilWriter.writeToDCSchema(dcSchema, entry, xmpPreferences); } try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { XmpSerializer serializer = new XmpSerializer(); serializer.serialize(meta, os, true); return os.toString(StandardCharsets.UTF_8.name()); } catch (TransformerException e) { - LOGGER.warn("Tranformation into xmp not possible: " + e.getMessage()); + LOGGER.warn("Tranformation into xmp not possible: " + e.getMessage(), e); return ""; } catch (UnsupportedEncodingException e) { - LOGGER.warn("Unsupported encoding to UTF-8 of bib entries in xmp metadata."); + LOGGER.warn("Unsupported encoding to UTF-8 of bib entries in xmp metadata.", e); return ""; } catch (IOException e) { - LOGGER.warn("IO Exception thrown by closing the output stream."); + LOGGER.warn("IO Exception thrown by closing the output stream.", e); return ""; } } From f22de6f22ac1ead45b60f775e7320f7a586f5f0a Mon Sep 17 00:00:00 2001 From: Johannes Manner Date: Wed, 11 Apr 2018 15:01:13 +0200 Subject: [PATCH 4/6] Changed the xmp preference distribution, added a split functionality for generating a single .xmp for every bib entry --- .../org/jabref/cli/ArgumentProcessor.java | 4 +++- .../logic/exporter/ExporterFactory.java | 9 ++++---- .../jabref/logic/exporter/XmpExporter.java | 22 ++++++++++++++++++- .../logic/exporter/CsvExportFormatTest.java | 4 +++- .../jabref/logic/exporter/ExporterTest.java | 4 +++- .../logic/exporter/HtmlExportFormatTest.java | 4 +++- 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jabref/cli/ArgumentProcessor.java b/src/main/java/org/jabref/cli/ArgumentProcessor.java index cd4e96ce523..e15daf1997f 100644 --- a/src/main/java/org/jabref/cli/ArgumentProcessor.java +++ b/src/main/java/org/jabref/cli/ArgumentProcessor.java @@ -41,6 +41,7 @@ import org.jabref.logic.search.SearchQuery; import org.jabref.logic.shared.prefs.SharedDatabasePreferences; import org.jabref.logic.util.OS; +import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.Defaults; import org.jabref.model.EntryTypes; import org.jabref.model.database.BibDatabase; @@ -471,7 +472,8 @@ private void importPreferences() { LayoutFormatterPreferences layoutPreferences = Globals.prefs .getLayoutFormatterPreferences(Globals.journalAbbreviationLoader); SavePreferences savePreferences = SavePreferences.loadForExportFromPreferences(Globals.prefs); - Globals.exportFactory = ExporterFactory.create(customExporters, layoutPreferences, savePreferences); + XmpPreferences xmpPreferences = Globals.prefs.getXMPPreferences(); + Globals.exportFactory = ExporterFactory.create(customExporters, layoutPreferences, savePreferences, xmpPreferences); } catch (JabRefException ex) { LOGGER.error("Cannot import preferences", ex); } diff --git a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java index 755c3016281..efd88ae7ea4 100644 --- a/src/main/java/org/jabref/logic/exporter/ExporterFactory.java +++ b/src/main/java/org/jabref/logic/exporter/ExporterFactory.java @@ -8,10 +8,10 @@ import java.util.Objects; import java.util.Optional; -import org.jabref.Globals; import org.jabref.logic.journals.JournalAbbreviationLoader; import org.jabref.logic.layout.LayoutFormatterPreferences; import org.jabref.logic.util.FileType; +import org.jabref.logic.xmp.XmpPreferences; import org.jabref.preferences.JabRefPreferences; public class ExporterFactory { @@ -30,7 +30,7 @@ private ExporterFactory(List exporters) { } public static ExporterFactory create(Map customFormats, - LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences) { + LayoutFormatterPreferences layoutPreferences, SavePreferences savePreferences, XmpPreferences xmpPreferences) { List exporters = new ArrayList<>(); @@ -55,7 +55,7 @@ public static ExporterFactory create(Map customFormats exporters.add(new OpenDocumentSpreadsheetCreator()); exporters.add(new MSBibExporter()); exporters.add(new ModsExporter()); - exporters.add(new XmpExporter(Globals.prefs.getXMPPreferences())); + exporters.add(new XmpExporter(xmpPreferences)); // Now add custom export formats exporters.addAll(customFormats.values()); @@ -67,7 +67,8 @@ public static ExporterFactory create(JabRefPreferences preferences, JournalAbbre Map customFormats = preferences.customExports.getCustomExportFormats(preferences, abbreviationLoader); LayoutFormatterPreferences layoutPreferences = preferences.getLayoutFormatterPreferences(abbreviationLoader); SavePreferences savePreferences = SavePreferences.loadForExportFromPreferences(preferences); - return create(customFormats, layoutPreferences, savePreferences); + XmpPreferences xmpPreferences = preferences.getXMPPreferences(); + return create(customFormats, layoutPreferences, savePreferences, xmpPreferences); } /** diff --git a/src/main/java/org/jabref/logic/exporter/XmpExporter.java b/src/main/java/org/jabref/logic/exporter/XmpExporter.java index 97748e6016d..db2d6676cdc 100644 --- a/src/main/java/org/jabref/logic/exporter/XmpExporter.java +++ b/src/main/java/org/jabref/logic/exporter/XmpExporter.java @@ -1,10 +1,13 @@ package org.jabref.logic.exporter; import java.io.BufferedWriter; +import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -21,6 +24,8 @@ */ public class XmpExporter extends Exporter { + private static final String XMP_SPLIT_PATTERN = "split"; + private final XmpPreferences xmpPreferences; public XmpExporter(XmpPreferences xmpPreferences) { @@ -31,16 +36,31 @@ public XmpExporter(XmpPreferences xmpPreferences) { @Override public void export(BibDatabaseContext databaseContext, Path file, Charset encoding, List entries) throws Exception { Objects.requireNonNull(databaseContext); + Objects.requireNonNull(file); Objects.requireNonNull(entries); if (entries.isEmpty()) { return; } + // This is a distinction between writing all entries from the supplied list to a single .xmp file, + // or write every entry to a separate file. + if (file.getFileName().toString().trim().equals(XMP_SPLIT_PATTERN)) { + for (BibEntry entry : entries) { + // Avoid situations, where two cite keys are null + Path entryFile = Paths.get(entry.getId() + "_" + entry.getCiteKey() + ".xmp"); + + this.writeBibToXmp(entryFile, Arrays.asList(entry)); + } + } else { + this.writeBibToXmp(file, entries); + } + } + + private void writeBibToXmp(Path file, List entries) throws IOException { try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { writer.write(XmpUtilWriter.generateXmpString(entries, this.xmpPreferences)); writer.flush(); } } - } diff --git a/src/test/java/org/jabref/logic/exporter/CsvExportFormatTest.java b/src/test/java/org/jabref/logic/exporter/CsvExportFormatTest.java index c620578c826..ce7d1058d25 100644 --- a/src/test/java/org/jabref/logic/exporter/CsvExportFormatTest.java +++ b/src/test/java/org/jabref/logic/exporter/CsvExportFormatTest.java @@ -10,6 +10,7 @@ import java.util.Map; import org.jabref.logic.layout.LayoutFormatterPreferences; +import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -36,7 +37,8 @@ public void setUp() { Map customFormats = new HashMap<>(); LayoutFormatterPreferences layoutPreferences = mock(LayoutFormatterPreferences.class, Answers.RETURNS_DEEP_STUBS); SavePreferences savePreferences = mock(SavePreferences.class); - ExporterFactory exporterFactory = ExporterFactory.create(customFormats, layoutPreferences, savePreferences); + XmpPreferences xmpPreferences = mock(XmpPreferences.class); + ExporterFactory exporterFactory = ExporterFactory.create(customFormats, layoutPreferences, savePreferences, xmpPreferences); exportFormat = exporterFactory.getExporterByName("oocsv").get(); diff --git a/src/test/java/org/jabref/logic/exporter/ExporterTest.java b/src/test/java/org/jabref/logic/exporter/ExporterTest.java index 66dfa4ccc00..7f9584dafe7 100644 --- a/src/test/java/org/jabref/logic/exporter/ExporterTest.java +++ b/src/test/java/org/jabref/logic/exporter/ExporterTest.java @@ -12,6 +12,7 @@ import java.util.Map; import org.jabref.logic.layout.LayoutFormatterPreferences; +import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -57,7 +58,8 @@ public static Collection exportFormats() { Map customFormats = new HashMap<>(); LayoutFormatterPreferences layoutPreferences = mock(LayoutFormatterPreferences.class); SavePreferences savePreferences = mock(SavePreferences.class); - ExporterFactory exporterFactory = ExporterFactory.create(customFormats, layoutPreferences, savePreferences); + XmpPreferences xmpPreferences = mock(XmpPreferences.class); + ExporterFactory exporterFactory = ExporterFactory.create(customFormats, layoutPreferences, savePreferences, xmpPreferences); for (Exporter format : exporterFactory.getExporters()) { result.add(new Object[]{format, format.getDisplayName()}); diff --git a/src/test/java/org/jabref/logic/exporter/HtmlExportFormatTest.java b/src/test/java/org/jabref/logic/exporter/HtmlExportFormatTest.java index b3661c61a88..053f16f935a 100644 --- a/src/test/java/org/jabref/logic/exporter/HtmlExportFormatTest.java +++ b/src/test/java/org/jabref/logic/exporter/HtmlExportFormatTest.java @@ -10,6 +10,7 @@ import java.util.Map; import org.jabref.logic.layout.LayoutFormatterPreferences; +import org.jabref.logic.xmp.XmpPreferences; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; @@ -37,7 +38,8 @@ public void setUp() { Map customFormats = new HashMap<>(); LayoutFormatterPreferences layoutPreferences = mock(LayoutFormatterPreferences.class, Answers.RETURNS_DEEP_STUBS); SavePreferences savePreferences = mock(SavePreferences.class); - ExporterFactory exporterFactory = ExporterFactory.create(customFormats, layoutPreferences, savePreferences); + XmpPreferences xmpPreferences = mock(XmpPreferences.class); + ExporterFactory exporterFactory = ExporterFactory.create(customFormats, layoutPreferences, savePreferences, xmpPreferences); exportFormat = exporterFactory.getExporterByName("html").get(); From 9693abcca92f76a281e4536a90f5ea9e1bc3ecac Mon Sep 17 00:00:00 2001 From: Johannes Manner Date: Wed, 11 Apr 2018 15:58:03 +0200 Subject: [PATCH 5/6] Added exporter tests for XmpExporter --- .../jabref/logic/exporter/XmpExporter.java | 18 ++- .../logic/exporter/XmpExporterTest.java | 112 ++++++++++++++++++ 2 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 src/test/java/org/jabref/logic/exporter/XmpExporterTest.java diff --git a/src/main/java/org/jabref/logic/exporter/XmpExporter.java b/src/main/java/org/jabref/logic/exporter/XmpExporter.java index db2d6676cdc..6a08536ec1c 100644 --- a/src/main/java/org/jabref/logic/exporter/XmpExporter.java +++ b/src/main/java/org/jabref/logic/exporter/XmpExporter.java @@ -3,7 +3,6 @@ import java.io.BufferedWriter; import java.io.IOException; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -46,19 +45,26 @@ public void export(BibDatabaseContext databaseContext, Path file, Charset encodi // This is a distinction between writing all entries from the supplied list to a single .xmp file, // or write every entry to a separate file. if (file.getFileName().toString().trim().equals(XMP_SPLIT_PATTERN)) { + for (BibEntry entry : entries) { // Avoid situations, where two cite keys are null - Path entryFile = Paths.get(entry.getId() + "_" + entry.getCiteKey() + ".xmp"); + Path entryFile; + String suffix = entry.getId() + "_" + entry.getCiteKey() + ".xmp"; + if (file.getParent() == null) { + entryFile = Paths.get(suffix); + } else { + entryFile = Paths.get(file.getParent().toString() + "/" + suffix); + } - this.writeBibToXmp(entryFile, Arrays.asList(entry)); + this.writeBibToXmp(entryFile, Arrays.asList(entry), encoding); } } else { - this.writeBibToXmp(file, entries); + this.writeBibToXmp(file, entries, encoding); } } - private void writeBibToXmp(Path file, List entries) throws IOException { - try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) { + private void writeBibToXmp(Path file, List entries, Charset encoding) throws IOException { + try (BufferedWriter writer = Files.newBufferedWriter(file, encoding)) { writer.write(XmpUtilWriter.generateXmpString(entries, this.xmpPreferences)); writer.flush(); } diff --git a/src/test/java/org/jabref/logic/exporter/XmpExporterTest.java b/src/test/java/org/jabref/logic/exporter/XmpExporterTest.java new file mode 100644 index 00000000000..28532bed71d --- /dev/null +++ b/src/test/java/org/jabref/logic/exporter/XmpExporterTest.java @@ -0,0 +1,112 @@ +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.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +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.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.mockito.Answers; + +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; + +public class XmpExporterTest { + + private Exporter exporter; + private BibDatabaseContext databaseContext; + private Charset encoding; + + @Rule public TemporaryFolder testFolder = new TemporaryFolder(); + + @Before + public void setUp() { + Map customFormats = new HashMap<>(); + 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); + + exporter = exporterFactory.getExporterByName("xmp").get(); + + databaseContext = new BibDatabaseContext(); + encoding = StandardCharsets.UTF_8; + } + + @Test + public void exportSingleEntry() throws Exception { + + Path file = testFolder.newFile().toPath(); + + BibEntry entry = new BibEntry(); + entry.setField("author", "Alan Turing"); + + exporter.export(databaseContext, file, encoding, Arrays.asList(entry)); + + List lines = Files.readAllLines(file); + assertTrue(lines.size() == 21); + assertEquals("Alan Turing", lines.get(7).trim()); + } + + @Test + public void writeMutlipleEntriesInASingleFile() throws Exception { + + Path file = testFolder.newFile().toPath(); + + BibEntry entryTuring = new BibEntry(); + entryTuring.setField("author", "Alan Turing"); + + BibEntry entryArmbrust = new BibEntry(); + entryArmbrust.setField("author", "Michael Armbrust"); + entryArmbrust.setCiteKey("Armbrust2010"); + + exporter.export(databaseContext, file, encoding, Arrays.asList(entryTuring, entryArmbrust)); + + List lines = Files.readAllLines(file); + assertTrue(lines.size() == 39); + assertEquals("Alan Turing", lines.get(7).trim()); + assertEquals("Michael Armbrust", lines.get(20).trim()); + } + + @Test + public void writeMultipleEntriesInDifferentFiles() throws Exception { + + Path file = testFolder.newFile("split").toPath(); + + BibEntry entryTuring = new BibEntry(); + entryTuring.setField("author", "Alan Turing"); + + BibEntry entryArmbrust = new BibEntry(); + entryArmbrust.setField("author", "Michael Armbrust"); + entryArmbrust.setCiteKey("Armbrust2010"); + + exporter.export(databaseContext, file, encoding, Arrays.asList(entryTuring, entryArmbrust)); + + List lines = Files.readAllLines(file); + assertTrue(lines.size() == 0); + + Path fileTuring = Paths.get(file.getParent().toString() + "/" + entryTuring.getId() + "_null.xmp"); + List linesTuring = Files.readAllLines(fileTuring); + assertTrue(linesTuring.size() == 21); + assertEquals("Alan Turing", linesTuring.get(7).trim()); + + Path fileArmbrust = Paths.get(file.getParent().toString() + "/" + entryArmbrust.getId() + "_Armbrust2010.xmp"); + List linesArmbrust = Files.readAllLines(fileArmbrust); + assertTrue(linesArmbrust.size() == 26); + assertEquals("Michael Armbrust", linesArmbrust.get(7).trim()); + } +} From bfa34416097e475c0a21765aa53455be68a25092 Mon Sep 17 00:00:00 2001 From: Johannes Manner Date: Thu, 12 Apr 2018 17:08:12 +0200 Subject: [PATCH 6/6] Change xmp file dialog description --- src/main/java/org/jabref/logic/util/FileType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/util/FileType.java b/src/main/java/org/jabref/logic/util/FileType.java index 09c9485da41..400a88540ed 100644 --- a/src/main/java/org/jabref/logic/util/FileType.java +++ b/src/main/java/org/jabref/logic/util/FileType.java @@ -50,7 +50,7 @@ public enum FileType { SILVER_PLATTER(Localization.lang("%0 file", "SilverPlatter"), "dat", "txt"), SIMPLE_HTML(Localization.lang("%0 file", Localization.lang("Simple HTML")), "html"), XMP(Localization.lang("XMP-annotated PDF"), "pdf"), - PLAIN_XMP(Localization.lang("%0 file", "Xmp"), "xmp"), + PLAIN_XMP(Localization.lang("%0 file", "XMP"), "xmp"), AUX(Localization.lang("%0 file", "AUX"), "aux"), JSTYLE(Localization.lang("Style file"), "jstyle"),