Skip to content

Commit

Permalink
Add search by author to return article and books JabRef#8539
Browse files Browse the repository at this point in the history
implemented tests
  • Loading branch information
Jonathan-Oliveira committed Apr 15, 2022
1 parent dbf921e commit 5ba7adb
Show file tree
Hide file tree
Showing 10 changed files with 552 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/workflows/deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ env:
SpringerNatureAPIKey: ${{ secrets.SpringerNatureAPIKey }}
AstrophysicsDataSystemAPIKey: ${{ secrets.AstrophysicsDataSystemAPIKey }}
IEEEAPIKey: ${{ secrets.IEEEAPIKey }}
BiodiversityHeritageApiKey: ${{ secrets.BiodiversityHeritageApiKey}}
OSXCERT: ${{ secrets.OSX_SIGNING_CERT }}
GRADLE_OPTS: -Xmx4g -Dorg.gradle.daemon=false -Dorg.gradle.vfs.watch=false
JAVA_OPTS: -Xmx4g
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tests-fetchers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ env:
SpringerNatureAPIKey: ${{ secrets.SPRINGERNATUREAPIKEY_FOR_TESTS }}
AstrophysicsDataSystemAPIKey: ${{ secrets.AstrophysicsDataSystemAPIKey_FOR_TESTS }}
IEEEAPIKey: ${{ secrets.IEEEAPIKey_FOR_TESTS }}
BiodiversityHeritageApiKey: ${{ secrets.BiodiversityHeritageApiKey_FOR_TESTS}}

concurrency:
group: fetcher-tests-${{ github.head_ref }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ env:
SpringerNatureAPIKey: ${{ secrets.SpringerNatureAPIKey }}
AstrophysicsDataSystemAPIKey: ${{ secrets.AstrophysicsDataSystemAPIKey }}
IEEEAPIKey: ${{ secrets.IEEEAPIKey }}
BiodiversityHeritageApiKey: ${{ secrets.BiodiversityHeritageApiKey}}
GRADLE_OPTS: -Xmx4g
JAVA_OPTS: -Xmx4g

Expand Down
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ processResources {
"springerNatureAPIKey": System.getenv('SpringerNatureAPIKey') ? System.getenv('SpringerNatureAPIKey') : '',
"astrophysicsDataSystemAPIKey": System.getenv('AstrophysicsDataSystemAPIKey') ? System.getenv('AstrophysicsDataSystemAPIKey') : '',
"ieeeAPIKey": System.getenv('IEEEAPIKey') ? System.getenv('IEEEAPIKey') : '',
"scienceDirectApiKey": System.getenv('SCIENCEDIRECTAPIKEY') ? System.getenv('SCIENCEDIRECTAPIKEY') : ''
"scienceDirectApiKey": System.getenv('SCIENCEDIRECTAPIKEY') ? System.getenv('SCIENCEDIRECTAPIKEY') : '',
"biodiversityHeritageApiKey": System.getenv('BiodiversityHeritageApiKey')?System.getenv('BiodiversityHeritageApiKey'):''
)
filteringCharset = 'UTF-8'
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/jabref/logic/importer/WebFetchers.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.jabref.logic.importer.fetcher.ApsFetcher;
import org.jabref.logic.importer.fetcher.ArXiv;
import org.jabref.logic.importer.fetcher.AstrophysicsDataSystem;
import org.jabref.logic.importer.fetcher.BiodiversityLibrary;
import org.jabref.logic.importer.fetcher.CiteSeer;
import org.jabref.logic.importer.fetcher.CollectionOfComputerScienceBibliographiesFetcher;
import org.jabref.logic.importer.fetcher.CompositeSearchBasedFetcher;
Expand Down Expand Up @@ -111,6 +112,7 @@ public static SortedSet<SearchBasedFetcher> getSearchBasedFetchers(ImportFormatP
// set.add(new JstorFetcher(importFormatPreferences));
set.add(new SemanticScholar());
set.add(new ResearchGate(importFormatPreferences));
set.add(new BiodiversityLibrary());
return set;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
package org.jabref.logic.importer.fetcher;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.ParseException;
import org.jabref.logic.importer.Parser;
import org.jabref.logic.importer.SearchBasedParserFetcher;
import org.jabref.logic.importer.fetcher.transformers.BiodiversityLibraryTransformer;
import org.jabref.logic.importer.util.JsonReader;
import org.jabref.logic.net.URLDownload;
import org.jabref.logic.util.BuildInfo;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.types.StandardEntryType;

import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONException;
import kong.unirest.json.JSONObject;
import org.apache.http.client.utils.URIBuilder;
import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Fetches data from the Biodiversity Heritage Library
*
* @implNote <a href="https://www.biodiversitylibrary.org/docs/api3.html">API documentation</a>
*/

public class BiodiversityLibrary implements SearchBasedParserFetcher {

private static final Logger LOGGER = LoggerFactory.getLogger(BiodiversityLibrary.class);
private static final String API_KEY = new BuildInfo().biodiversityHeritageApiKey;
private static final String BASE_URL = "https://www.biodiversitylibrary.org/api3";
private static final String RESPONSE_FORMAT = "json";

public BiodiversityLibrary() {
}

public URL getBaseURL() throws URISyntaxException, MalformedURLException {
URIBuilder baseURI = new URIBuilder(BASE_URL);
baseURI.addParameter("apikey", API_KEY);
baseURI.addParameter("format", RESPONSE_FORMAT);

return baseURI.build().toURL();
}

@Override
public String getName() {
return "Biodiversity Heritage";
}

public URL getItemMetadataURL(String identifier) throws URISyntaxException, MalformedURLException {
URIBuilder uriBuilder = new URIBuilder(getBaseURL().toURI());
uriBuilder.addParameter("op", "GetItemMetadata");
uriBuilder.addParameter("pages", "f");
uriBuilder.addParameter("ocr", "f");
uriBuilder.addParameter("ocr", "f");
uriBuilder.addParameter("id", identifier);

return uriBuilder.build().toURL();

}

public URL getPartMetadataURL(String identifier) throws URISyntaxException, MalformedURLException {
URIBuilder uriBuilder = new URIBuilder(getBaseURL().toURI());
uriBuilder.addParameter("op", "GetPartMetadata");
uriBuilder.addParameter("pages", "f");
uriBuilder.addParameter("names", "f");
uriBuilder.addParameter("id", identifier);

return uriBuilder.build().toURL();

}

public JSONObject getDetails(URL url) throws IOException {

URLDownload download = new URLDownload(url);
String response = download.asString();
return new JSONObject(response).getJSONArray("Result").getJSONObject(0);
}

public BibEntry getMostDetails(JSONObject item, BibEntry entry) throws IOException, URISyntaxException {

if (item.has("BHLType")) {
if (item.getString("BHLType").equals("Part")) {
URL url = getPartMetadataURL(item.getString("PartID"));
JSONObject itemsDetails = getDetails(url);
// Language
if (itemsDetails.has("Language")) {
entry.setField(StandardField.LANGUAGE, itemsDetails.getString("Language"));
}
// DOI
if (itemsDetails.has("Doi")) {
entry.setField(StandardField.DOI, itemsDetails.getString("Doi"));
}
// Publisher
if (itemsDetails.has("PublisherName")) {
entry.setField(StandardField.PUBLISHER, itemsDetails.getString("PublisherName"));
}
// Volume
if (itemsDetails.has("Volume") && !entry.hasField(StandardField.VOLUME)) {
entry.setField(StandardField.VOLUME, itemsDetails.getString("Volume"));
}
// Date
if (itemsDetails.has("Date") && !entry.hasField(StandardField.DATE) && !entry.hasField(StandardField.YEAR)) {
entry.setField(StandardField.DATE, itemsDetails.getString("Date"));
}
// Link
if (itemsDetails.has("PartUrl")) {
entry.setField(StandardField.URL, itemsDetails.getString("PartUrl"));
}

}

if (item.getString("BHLType").equals("Item")) {
URL url = getItemMetadataURL(item.getString("ItemID"));
JSONObject itemsDetails = getDetails(url);
// Editor
if (itemsDetails.has("Sponsor")) {
entry.setField(StandardField.EDITOR, itemsDetails.getString("Sponsor"));
}
// Publisher
if (itemsDetails.has("HoldingInstitution")) {
entry.setField(StandardField.PUBLISHER, itemsDetails.getString("HoldingInstitution"));
}
// Language
if (itemsDetails.has("Language")) {
entry.setField(StandardField.LANGUAGE, itemsDetails.getString("Language"));
}
// Link
if (itemsDetails.has("ItemUrl")) {
entry.setField(StandardField.URL, itemsDetails.getString("ItemUrl"));
}
// Date
if (itemsDetails.has("Date") && !entry.hasField(StandardField.DATE) && !entry.hasField(StandardField.YEAR)) {
entry.setField(StandardField.DATE, itemsDetails.getString("Date"));
}

}

}
return entry;
}

public BibEntry jsonResultToBibEntry(JSONObject item) {
BibEntry entry = new BibEntry();

if ("Book".equals(item.optString("Genre"))) {
entry.setType(StandardEntryType.Book);
} else {
entry.setType(StandardEntryType.Article);
}

// Title
if (item.has("Title")) {
entry.setField(StandardField.TITLE, item.optString("Title"));
}
// Authors
if (item.has("Authors")) {
JSONArray authors = item.getJSONArray("Authors");
List<String> authorList = new ArrayList<>();
for (int i = 0; i < authors.length(); i++) {
if (authors.getJSONObject(i).has("Name")) {
authorList.add(authors.getJSONObject(i).getString("Name"));
} else {
LOGGER.debug("Empty author name.");
}
}
entry.setField(StandardField.AUTHOR, String.join(" and ", authorList));
} else {
LOGGER.debug("Empty author name");
}
// Pages
if (item.has("PageRange")) {
entry.setField(StandardField.PAGES, item.getString("PageRange"));
} else {
LOGGER.debug("Empty pages number");
}

// Publisher Place
if (item.has("PublisherPlace")) {
entry.setField(StandardField.PUBSTATE, item.getString("PublisherPlace"));
} else {
LOGGER.debug("Empty Publisher Place");
}
// Publisher Name
if (item.has("PublisherName")) {
entry.setField(StandardField.PUBLISHER, item.getString("PublisherName"));
} else {
LOGGER.debug("Empty Publisher Name");
}

// Date
if (item.has("Date")) {
entry.setField(StandardField.DATE, item.getString("Date"));
} else if (item.has("PublicationDate")) {
entry.setField(StandardField.YEAR, item.getString("PublicationDate"));
} else {
LOGGER.debug("Empty date");
}

// Journal Title
if (item.has("ContainerTitle")) {
entry.setField(StandardField.JOURNALTITLE, item.getString("ContainerTitle"));
} else {
LOGGER.debug("Empty journal name");
}

// Volumes
if (item.has("Volume")) {
entry.setField(StandardField.VOLUME, item.getString("Volume"));
} else {
LOGGER.debug("Empty volume number");
}
return entry;

}

@Override
public Parser getParser() {
return inputStream -> {
JSONObject response = JsonReader.toJsonObject(inputStream);
if (response.isEmpty()) {
return Collections.emptyList();
}
String errorMessage = response.getString("ErrorMessage");
if (!errorMessage.isBlank()) {
return Collections.emptyList();
}

JSONArray items = response.getJSONArray("Result");
List<BibEntry> entries = new ArrayList<>(items.length());
for (int i = 0; i < items.length(); i++) {
JSONObject item = items.getJSONObject(i);
BibEntry entry = jsonResultToBibEntry(item);
try {
entry = getMostDetails(item, entry);
} catch (JSONException | IOException | URISyntaxException exception) {
throw new ParseException("Error when parse entry", exception);
}
entries.add(entry);
}
return entries;
};
}

@Override
public URL getURLForQuery(QueryNode luceneQuery) throws URISyntaxException, MalformedURLException, FetcherException {
URIBuilder uriBuilder = new URIBuilder(getBaseURL().toURI());
BiodiversityLibraryTransformer transformer = new BiodiversityLibraryTransformer();
transformer.transformLuceneQuery(luceneQuery).orElse("");
uriBuilder.addParameter("op", "PublicationSearchAdvanced");

if (transformer.getAuthor().isPresent()) {
uriBuilder.addParameter("authorname", transformer.getAuthor().get());
}

if (transformer.getTitle().isPresent()) {
uriBuilder.addParameter("title", transformer.getTitle().get());
uriBuilder.addParameter("titleop", "all");
}
if (transformer.getTitle().isEmpty() && transformer.getAuthor().isEmpty()) {
throw new FetcherException("Must add author or title");
}
return uriBuilder.build().toURL();

}
}
Loading

0 comments on commit 5ba7adb

Please sign in to comment.