package org.jabref.logic.util.io;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.metadata.FileDirectoryPreferences;
/**
* Search class for files. <br>
* <br>
* This class provides some functionality to search in a {@link BibDatabase} for
* files. <br>
*/
public class DatabaseFileLookup {
private final Set<Path> fileCache = new HashSet<>();
private final List<Path> possibleFilePaths;
/**
* Creates an instance by passing a {@link BibDatabase} which will be used for the searches.
*/
public DatabaseFileLookup(BibDatabaseContext databaseContext, FileDirectoryPreferences fileDirectoryPreferences) {
Objects.requireNonNull(databaseContext);
possibleFilePaths = Optional.ofNullable(databaseContext.getFileDirectoriesAsPaths(fileDirectoryPreferences))
.orElse(new ArrayList<>());
for (BibEntry entry : databaseContext.getDatabase().getEntries()) {
fileCache.addAll(parseFileField(entry));
}
}
/**
* Returns whether the File <code>file</code> is present in the database
* as an attached File to an {@link BibEntry}. <br>
* <br>
* To do this, the field specified by the key <b>file</b> will be searched
* for the provided file for every {@link BibEntry} in the database. <br>
* <br>
* For the matching, the absolute file paths will be used.
*
* @param file
* A {@link File} Object.
* @return <code>true</code>, if the file Object is stored in at least one
* entry in the database, otherwise <code>false</code>.
*/
public boolean lookupDatabase(File file) {
return fileCache.contains(file.toPath());
}
private List<Path> parseFileField(BibEntry entry) {
Objects.requireNonNull(entry);
return entry.getFiles().stream()
.filter(file -> !file.isOnlineLink()) // Do not query external file links (huge performance leak)
.map(file -> file.findIn(possibleFilePaths))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}
}