Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add XMP Exporter #3895

Merged
merged 6 commits into from
Apr 12, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public static ExporterFactory create(Map<String, TemplateExporter> 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());
Expand Down
43 changes: 43 additions & 0 deletions src/main/java/org/jabref/logic/exporter/XmpExporter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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.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 {

public XmpExporter() {
super("XmpBib", FileType.ENDNOTE_XMP.getDescription(), FileType.ENDNOTE_XMP);
}

@Override
public void export(BibDatabaseContext databaseContext, Path file, Charset encoding, List<BibEntry> 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, Globals.prefs.getXMPPreferences()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please pass the Globals.prefs.getXMPPreferences() dependency as a constructor argument. We are currently trying to reduce the number of calls to Globals.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please pass the Globals.prefs.getXMPPreferences() dependency as a constructor argument. We are currently trying to reduce the number of calls to Globals.

writer.flush();
}
}

}
1 change: 1 addition & 0 deletions src/main/java/org/jabref/logic/util/FileType.java
Original file line number Diff line number Diff line change
Expand Up @@ -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", "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"),
Expand Down
45 changes: 44 additions & 1 deletion src/main/java/org/jabref/logic/xmp/XmpUtilWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -82,6 +84,16 @@ 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 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) {

Expand All @@ -91,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
*
Expand Down Expand Up @@ -159,6 +170,38 @@ private static void writeDublinCore(PDDocument document,
catalog.setMetadata(metadataStream);
}

/**
* This method generates an xmp metadata string in dublin core format.
* <br/>
*
* @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<BibEntry> entries, XmpPreferences xmpPreferences) {
XMPMetadata meta = XMPMetadata.createXMPMetadata();
for (BibEntry entry : entries) {
DublinCoreSchema dcSchema = meta.createAndAddDublinCoreSchema();
XmpUtilWriter.writeToDCSchema(dcSchema, entry, null, xmpPreferences);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to add an additional method writeToDCSchema with 3 parameters. We should avoid null parameters.

}
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());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not logging the exception itself, too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the stack trace of the exception?
Is there a smart solution in JabRef to print the stack trace with the logger (maybe an utility method)?

Otherwise, I would use something like this:
Arrays.asList(exception.getStackTrace())
.stream()
.map(Objects::toString)
.collect(Collectors.joining("\n"))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logger methods have a second parameter which accepts a throwable /exception.
The stack trace will then automatically be printed (handled by the logger itself)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code usually looks something like LOGGER.warn("Transformation in xmp not possible", e).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I would wrap these Exceptions in an IOException and then rethrow.

return "";
} 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 "";
}
}

/**
* Try to write the given BibTexEntry in the Document Information (the
* properties of the pdf).
Expand Down