package org.jabref.logic.layout.format; import java.nio.file.Paths; import java.util.List; import java.util.stream.Collectors; import org.jabref.logic.layout.ParamLayoutFormatter; import org.jabref.model.entry.FileFieldParser; import org.jabref.model.entry.LinkedFile; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Export formatter that handles the file link list of JabRef 2.3 and later, by * selecting the first file link, if any, specified by the field. */ public class FileLink implements ParamLayoutFormatter { private static final Log LOGGER = LogFactory.getLog(FileLink.class); private final FileLinkPreferences prefs; private String fileType; public FileLink(FileLinkPreferences fileLinkPreferences) { this.prefs = fileLinkPreferences; } @Override public String format(String field) { if (field == null) { return ""; } List<LinkedFile> fileList = FileFieldParser.parse(field); LinkedFile link = null; if (fileType == null) { // No file type specified. Simply take the first link. if (!(fileList.isEmpty())) { link = fileList.get(0); } } else { // A file type is specified: for (LinkedFile flEntry : fileList) { if (flEntry.getFileType().equalsIgnoreCase(fileType)) { link = flEntry; break; } } } if (link == null) { return ""; } List<String> dirs; // We need to resolve the file directory from the database's metadata, // but that is not available from a formatter. Therefore, as an // ugly hack, the export routine has set a global variable before // starting the export, which contains the database's file directory: if (prefs.getFileDirForDatabase() == null) { dirs = prefs.getGeneratedDirForDatabase(); } else { dirs = prefs.getFileDirForDatabase(); } return link.findIn(dirs.stream().map(Paths::get).collect(Collectors.toList())) .map(path -> path.normalize().toString()) .orElse(link.getLink()); } /** * This method is called if the layout file specifies an argument for this * formatter. We use it as an indicator of which file type we should look for. * @param arg The file type. */ @Override public void setArgument(String arg) { fileType = arg; } }