package org.jabref.logic.importer; import java.io.BufferedInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.util.List; import java.util.Objects; import java.util.Optional; import org.jabref.model.cleanup.Formatter; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.identifier.Identifier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Provides a convenient interface for {@link IdFetcher}, which follow the usual three-step procedure: * 1. Open a URL based on the search query * 2. Parse the response to get a list of {@link BibEntry} * 3. Extract identifier */ public interface IdParserFetcher<T extends Identifier> extends IdFetcher<T> { Log LOGGER = LogFactory.getLog(IdParserFetcher.class); /** * Constructs a URL based on the {@link BibEntry}. * * @param entry the entry to look information for */ URL getURLForEntry(BibEntry entry) throws URISyntaxException, MalformedURLException, FetcherException; /** * Returns the parser used to convert the response to a list of {@link BibEntry}. */ Parser getParser(); /** * Performs a cleanup of the fetched entry. * * Only systematic errors of the fetcher should be corrected here * (i.e. if information is consistently contained in the wrong field or the wrong format) * but not cosmetic issues which may depend on the user's taste (for example, LateX code vs HTML in the abstract). * * Try to reuse existing {@link Formatter} for the cleanup. For example, * {@code new FieldFormatterCleanup(FieldName.TITLE, new RemoveBracesFormatter()).cleanup(entry);} * * By default, no cleanup is done. * * @param entry the entry to be cleaned-up */ default void doPostCleanup(BibEntry entry) { // Do nothing by default } /** * Extracts the identifier from the list of fetched entries. * * @param inputEntry the entry for which we are searching the identifier (can be used to find closest match in * the result) * @param fetchedEntries list of entries returned by the web service */ Optional<T> extractIdentifier(BibEntry inputEntry, List<BibEntry> fetchedEntries) throws FetcherException; @Override default Optional<T> findIdentifier(BibEntry entry) throws FetcherException { Objects.requireNonNull(entry); try (InputStream stream = new BufferedInputStream(getURLForEntry(entry).openStream())) { List<BibEntry> fetchedEntries = getParser().parseEntries(stream); if (fetchedEntries.isEmpty()) { return Optional.empty(); } // Post-cleanup fetchedEntries.forEach(this::doPostCleanup); return extractIdentifier(entry, fetchedEntries); } catch (URISyntaxException e) { throw new FetcherException("Search URI is malformed", e); } catch (FileNotFoundException e) { LOGGER.debug("Id not found"); return Optional.empty(); } catch (IOException e) { // TODO: Catch HTTP Response 401 errors and report that user has no rights to access resource // TODO catch 503 service unavailable and alert user throw new FetcherException("An I/O exception occurred", e); } catch (ParseException e) { throw new FetcherException("An internal parser error occurred", e); } } }