package org.jabref.model.util;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.metadata.FileDirectoryPreferences;
public class FileHelper {
/**
* Returns the extension of a file or Optional.empty() if the file does not have one (no . in name).
*
* @param file
* @return The extension, trimmed and in lowercase.
*/
public static Optional<String> getFileExtension(Path file) {
return getFileExtension(file.toString());
}
/**
* Returns the extension of a file name or Optional.empty() if the file does not have one (no "." in name).
*
* @param fileName
* @return The extension (without leading dot), trimmed and in lowercase.
*/
public static Optional<String> getFileExtension(String fileName) {
int dotPosition = fileName.lastIndexOf('.');
if ((dotPosition > 0) && (dotPosition < (fileName.length() - 1))) {
return Optional.of(fileName.substring(dotPosition + 1).trim().toLowerCase(Locale.ROOT));
} else {
return Optional.empty();
}
}
/**
* Converts a relative filename to an absolute one, if necessary. Returns an empty optional if the file does not
* exist.<br/>
* <p>
* Uses <ul>
* <li>the default directory associated with the extension of the file</li>
* <li>the standard file directory</li>
* <li>the directory of the BIB file</li>
* </ul>
*
* @param databaseContext The database this file belongs to.
* @param name The filename, may also be a relative path to the file
*/
public static Optional<Path> expandFilename(final BibDatabaseContext databaseContext, String name,
FileDirectoryPreferences fileDirectoryPreferences) {
Optional<String> extension = getFileExtension(name);
// Find the default directory for this field type, if any:
List<String> directories = databaseContext.getFileDirectories(extension.orElse(null), fileDirectoryPreferences);
// Include the standard "file" directory:
List<String> fileDir = databaseContext.getFileDirectories(fileDirectoryPreferences);
List<String> searchDirectories = new ArrayList<>();
for (String dir : directories) {
if (!searchDirectories.contains(dir)) {
searchDirectories.add(dir);
}
}
for (String aFileDir : fileDir) {
if (!searchDirectories.contains(aFileDir)) {
searchDirectories.add(aFileDir);
}
}
return expandFilename(name, searchDirectories);
}
/**
* Converts a relative filename to an absolute one, if necessary. Returns
* null if the file does not exist.
* <p>
* Will look in each of the given dirs starting from the beginning and
* returning the first found file to match if any.
*
* @deprecated use {@link #expandFilenameAsPath(String, List)} instead
*/
@Deprecated
public static Optional<Path> expandFilename(String name, List<String> directories) {
for (String dir : directories) {
Optional<Path> result = expandFilename(name, Paths.get(dir));
if (result.isPresent()) {
return result;
}
}
return Optional.empty();
}
public static Optional<Path> expandFilenameAsPath(String name, List<Path> directories) {
for (Path directory : directories) {
Optional<Path> result = expandFilename(name, directory);
if (result.isPresent()) {
return result;
}
}
return Optional.empty();
}
/**
* Converts a relative filename to an absolute one, if necessary. Returns
* an empty optional if the file does not exist.
*/
private static Optional<Path> expandFilename(String filename, Path directory) {
Objects.requireNonNull(filename);
Objects.requireNonNull(directory);
Path file = Paths.get(filename);
if (Files.exists(file)) {
return Optional.of(file);
}
Path resolvedFile = directory.resolve(file);
if (Files.exists(resolvedFile)) {
return Optional.of(resolvedFile);
} else {
return Optional.empty();
}
}
}