package org.jabref.logic.importer;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Objects;
import org.jabref.logic.util.FileExtensions;
/**
* Role of an importer for JabRef.
*/
public abstract class Importer implements Comparable<Importer> {
/**
* Check whether the source is in the correct format for this importer.
*
* The effect of this method is primarily to avoid unnecessary processing of
* files when searching for a suitable import format. If this method returns
* false, the import routine will move on to the next import format.
*
* Thus the correct behaviour is to return false if it is certain that the file is
* not of the suitable type, and true otherwise. Returning true is the safe choice if not certain.
*/
public abstract boolean isRecognizedFormat(BufferedReader input) throws IOException;
public boolean isRecognizedFormat(Path filePath, Charset encoding) throws IOException {
try (BufferedReader bufferedReader = getReader(filePath, encoding)) {
return isRecognizedFormat(bufferedReader);
}
}
/**
* Parse the database in the source.
*
* This method can be called in two different contexts - either when importing in
* a specified format, or when importing in unknown format. In the latter case,
* JabRef cycles through all available import formats. No error messages or feedback
* is displayed from individual import formats in this case.
*
* If importing in a specified format and an empty library is returned, JabRef reports
* that no entries were found.
*
* This method should never return null.
*
* @param input the input to read from
*/
public abstract ParserResult importDatabase(BufferedReader input) throws IOException ;
/**
* Parse the database in the specified file.
*
* Importer having the facilities to detect the correct encoding of a file should overwrite this method,
* determine the encoding and then call {@link #importDatabase(BufferedReader)}.
*
* @param filePath the path to the file which should be imported
* @param encoding the encoding used to decode the file
*/
public ParserResult importDatabase(Path filePath, Charset encoding) throws IOException {
try (BufferedReader bufferedReader = getReader(filePath, encoding)) {
ParserResult parserResult = importDatabase(bufferedReader);
parserResult.getMetaData().setEncoding(encoding);
parserResult.setFile(filePath.toFile());
return parserResult;
}
}
protected static BufferedReader getUTF8Reader(Path filePath) throws IOException {
return getReader(filePath, StandardCharsets.UTF_8);
}
protected static BufferedReader getUTF16Reader(Path filePath) throws IOException {
return getReader(filePath, StandardCharsets.UTF_16);
}
public static BufferedReader getReader(Path filePath, Charset encoding)
throws IOException {
InputStream stream = new FileInputStream(filePath.toFile());
return new BufferedReader(new InputStreamReader(stream, encoding));
}
/**
* Returns the name of this import format.
*
* <p>The name must be unique.</p>
*
* @return format name, must be unique and not <code>null</code>
*/
public abstract String getName();
/**
* Returns the file extensions that this importer can read
* @return {@link FileExtensions} correspoding to the importer
*/
public abstract FileExtensions getExtensions();
/**
* Returns a one-word ID which identifies this import format.
* Used for example, to identify the format when used from the command line.
*
* @return ID, must be unique and not <code>null</code>
*/
public String getId() {
String id = getName();
StringBuilder result = new StringBuilder(id.length());
for (int i = 0; i < id.length(); i++) {
char c = id.charAt(i);
if (Character.isLetterOrDigit(c)) {
result.append(Character.toLowerCase(c));
}
}
return result.toString();
}
/**
* Returns the description of the import format.
*
* The description should specify
* <ul><li>
* what kind of entries from what sources and based on what specification it is able to import
* </li><li>
* by what criteria it {@link #isRecognizedFormat(BufferedReader) recognizes} an import format
* </li></ul>
*
* @return description of the import format
*/
public abstract String getDescription();
@Override
public int hashCode() {
return getName().hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Importer)) {
return false;
}
Importer other = (Importer)obj;
return Objects.equals(this.getName(), other.getName());
}
@Override
public String toString() {
return getName();
}
@Override
public int compareTo(Importer o) {
return getName().compareTo(o.getName());
}
}