package org.jabref.logic.importer.fetcher; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import org.jabref.logic.cleanup.MoveFieldCleanup; import org.jabref.logic.formatter.bibtexfields.ClearFormatter; import org.jabref.logic.importer.EntryBasedParserFetcher; import org.jabref.logic.importer.FetcherException; import org.jabref.logic.importer.IdBasedParserFetcher; import org.jabref.logic.importer.ImportFormatPreferences; import org.jabref.logic.importer.Parser; import org.jabref.logic.importer.SearchBasedParserFetcher; import org.jabref.logic.importer.fileformat.BibtexParser; import org.jabref.logic.util.OS; import org.jabref.model.cleanup.FieldFormatterCleanup; import org.jabref.model.entry.BibEntry; import org.jabref.model.entry.FieldName; import org.apache.http.client.utils.URIBuilder; /** * Fetches data from the MathSciNet (http://www.ams.org/mathscinet) */ public class MathSciNet implements SearchBasedParserFetcher, EntryBasedParserFetcher, IdBasedParserFetcher { private final ImportFormatPreferences preferences; public MathSciNet(ImportFormatPreferences preferences) { this.preferences = Objects.requireNonNull(preferences); } @Override public String getName() { return "MathSciNet"; } /** * We use MR Lookup (http://www.ams.org/mrlookup) instead of the usual search since this tool is also available * without subscription and, moreover, is optimized for finding a publication based on partial information. */ @Override public URL getURLForEntry(BibEntry entry) throws URISyntaxException, MalformedURLException, FetcherException { URIBuilder uriBuilder = new URIBuilder("http://www.ams.org/mrlookup"); uriBuilder.addParameter("format", "bibtex"); entry.getFieldOrAlias(FieldName.TITLE).ifPresent(title -> uriBuilder.addParameter("ti", title)); entry.getFieldOrAlias(FieldName.AUTHOR).ifPresent(author -> uriBuilder.addParameter("au", author)); entry.getFieldOrAlias(FieldName.JOURNAL).ifPresent(journal -> uriBuilder.addParameter("jrnl", journal)); entry.getFieldOrAlias(FieldName.YEAR).ifPresent(year -> uriBuilder.addParameter("year", year)); return uriBuilder.build().toURL(); } @Override public URL getURLForQuery(String query) throws URISyntaxException, MalformedURLException, FetcherException { URIBuilder uriBuilder = new URIBuilder("http://www.ams.org/mathscinet/search/publications.html"); uriBuilder.addParameter("pg7", "ALLF"); // search all fields uriBuilder.addParameter("s7", query); // query uriBuilder.addParameter("r", "1"); // start index uriBuilder.addParameter("extend", "1"); // should return up to 100 items (instead of default 10) uriBuilder.addParameter("fmt", "bibtex"); // BibTeX format return uriBuilder.build().toURL(); } @Override public URL getURLForID(String identifier) throws URISyntaxException, MalformedURLException, FetcherException { URIBuilder uriBuilder = new URIBuilder("http://www.ams.org/mathscinet/search/publications.html"); uriBuilder.addParameter("pg1", "MR"); // search MR number uriBuilder.addParameter("s1", identifier); // identifier uriBuilder.addParameter("fmt", "bibtex"); // BibTeX format return uriBuilder.build().toURL(); } @Override public Parser getParser() { // MathSciNet returns the BibTeX result embedded in HTML // So we extract the BibTeX string from the <pre>bibtex</pre> tags and pass the content to the BibTeX parser return inputStream -> { String response = new BufferedReader(new InputStreamReader(inputStream)).lines().collect( Collectors.joining(OS.NEWLINE)); List<BibEntry> entries = new ArrayList<>(); BibtexParser bibtexParser = new BibtexParser(preferences); Pattern pattern = Pattern.compile("<pre>(?s)(.*)</pre>"); Matcher matcher = pattern.matcher(response); while (matcher.find()) { String bibtexEntryString = matcher.group(); entries.addAll(bibtexParser.parseEntries(bibtexEntryString)); } return entries; }; } @Override public void doPostCleanup(BibEntry entry) { new MoveFieldCleanup("fjournal", FieldName.JOURNAL).cleanup(entry); new MoveFieldCleanup("mrclass", FieldName.KEYWORDS).cleanup(entry); new FieldFormatterCleanup("mrreviewer", new ClearFormatter()).cleanup(entry); new FieldFormatterCleanup(FieldName.URL, new ClearFormatter()).cleanup(entry); } }