Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve citation relations #11016

Merged
merged 12 commits into from
Mar 18, 2024
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
- We enhanced the dialog for adding new fields in the content selector with a selection box containing a list of standard fields. [#10912](https://github.com/JabRef/jabref/pull/10912)
- We store the citation relations in an LRU cache to avoid bloating the memory and out-of-memory exceptions. [#10958](https://github.com/JabRef/jabref/issues/10958)
- Keywords filed are now displayed as tags. [#10910](https://github.com/JabRef/jabref/pull/10910)
- Citation relations now get more information, and have quick access to view the articles in a browser without adding them to the library [#10869](https://github.com/JabRef/jabref/issues/10869)

### Fixed

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.jabref.gui.entryeditor.citationrelationtab;

import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -28,6 +30,7 @@
import org.jabref.gui.Globals;
import org.jabref.gui.LibraryTab;
import org.jabref.gui.StateManager;
import org.jabref.gui.desktop.JabRefDesktop;
import org.jabref.gui.entryeditor.EntryEditorPreferences;
import org.jabref.gui.entryeditor.EntryEditorTab;
import org.jabref.gui.entryeditor.citationrelationtab.semanticscholar.CitationFetcher;
Expand All @@ -40,6 +43,9 @@
import org.jabref.logic.l10n.Localization;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.identifier.DOI;
import org.jabref.model.strings.StringUtil;
import org.jabref.model.util.FileUpdateMonitor;
import org.jabref.preferences.PreferencesService;

Expand Down Expand Up @@ -201,6 +207,8 @@ private void styleFetchedListView(CheckListView<CitationRelationItem> listView)
HBox hContainer = new HBox();
hContainer.prefWidthProperty().bind(listView.widthProperty().subtract(25));

VBox vContainer = new VBox();

if (entry.isLocal()) {
Button jumpTo = IconTheme.JabRefIcons.LINK.asButton();
jumpTo.setTooltip(new Tooltip(Localization.lang("Jump to entry in library")));
Expand All @@ -211,7 +219,7 @@ private void styleFetchedListView(CheckListView<CitationRelationItem> listView)
citingTask.cancel();
citedByTask.cancel();
});
hContainer.getChildren().addAll(entryNode, separator, jumpTo);
vContainer.getChildren().add(jumpTo);
} else {
ToggleButton addToggle = IconTheme.JabRefIcons.ADD.asToggleButton();
addToggle.setTooltip(new Tooltip(Localization.lang("Select entry")));
Expand All @@ -224,8 +232,28 @@ private void styleFetchedListView(CheckListView<CitationRelationItem> listView)
});
addToggle.getStyleClass().add("addEntryButton");
addToggle.selectedProperty().bindBidirectional(listView.getItemBooleanProperty(entry));
hContainer.getChildren().addAll(entryNode, separator, addToggle);
vContainer.getChildren().add(addToggle);
}

if (entry.entry().getDOI().isPresent() || entry.entry().getField(StandardField.URL).isPresent()) {
Button openWeb = IconTheme.JabRefIcons.OPEN_LINK.asButton();
openWeb.setTooltip(new Tooltip(Localization.lang("Open URL or DOI")));
openWeb.setOnMouseClicked(event -> {
String url = entry.entry().getDOI().flatMap(DOI::getExternalURI).map(URI::toString)
.or(() -> entry.entry().getField(StandardField.URL)).orElse("");
if (StringUtil.isNullOrEmpty(url)) {
return;
}
try {
JabRefDesktop.openBrowser(url, preferencesService.getFilePreferences());
} catch (IOException ex) {
dialogService.notify(Localization.lang("Unable to open link."));
}
});
vContainer.getChildren().addLast(openWeb);
}

hContainer.getChildren().addAll(entryNode, separator, vContainer);
hContainer.getStyleClass().add("entry-container");

return hContainer;
Expand Down Expand Up @@ -392,8 +420,6 @@ private void showNodes(Node... nodes) {
Arrays.stream(nodes).forEach(node -> node.setVisible(true));
}

// Absolute-phase phenomena in photoionization with few-cycle laser pulses

/**
* Function to import selected entries to the database. Also writes the entries to import to the CITING/CITED field
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
package org.jabref.gui.entryeditor.citationrelationtab.semanticscholar;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.types.StandardEntryType;

import com.google.gson.annotations.SerializedName;

public class PaperDetails {
private String paperId;
private String title;
private String year;

@SerializedName("abstract")
private String abstr;
private String url;
private int citationCount;
private int referenceCount;
private List<AuthorResponse> authors;
private List<String> publicationTypes;
private Map<String, String> externalIds;

public String getPaperId() {
return paperId;
Expand All @@ -38,6 +48,22 @@ public void setYear(String year) {
this.year = year;
}

public String getAbstract() {
return abstr;
}

public void setAbstract(String abstr) {
this.abstr = abstr;
}

public String getURL() {
return url;
}

public void setURL(String url) {
this.url = url;
}

public int getCitationCount() {
return citationCount;
}
Expand All @@ -58,6 +84,56 @@ public List<AuthorResponse> getAuthors() {
return authors;
}

public String getPublicationType() {
if (publicationTypes == null || publicationTypes.isEmpty()) {
return "Misc";
}
if (publicationTypes.contains("Conference")) {
return "InProceedings";
} else if (publicationTypes.contains("JournalArticle")) {
return "Article";
} else {
return switch (publicationTypes.getFirst()) {
case "Review" ->
"Misc";
case "CaseReport" ->
"Report";
case "ClinicalTrial" ->
"Report";
case "Dataset" ->
"Dataset";
case "Editorial" ->
"Misc";
case "LettersAndComments" ->
"Misc";
case "MetaAnalysis" ->
"Article";
case "News" ->
"Misc";
case "Study" ->
"Article";
case "Book" ->
"Book";
case "BookSection" ->
"InBook";
default ->
"Misc";
};
}
}

public String getDOI() {
if (externalIds != null) {
if (externalIds.containsKey("DOI")) {
return externalIds.get("DOI");
} else if (externalIds.containsKey("ArXiv")) {
// Some ArXiv articles don't return the DOI, even though it's easy to obtain from the ArXiv ID
return "10.48550/arXiv." + externalIds.get("ArXiv");
}
}
return "";
}

public BibEntry toBibEntry() {
BibEntry bibEntry = new BibEntry();
bibEntry.setField(StandardField.TITLE, getTitle());
Expand All @@ -70,6 +146,20 @@ public BibEntry toBibEntry() {
.collect(Collectors.joining(" and "));
bibEntry.setField(StandardField.AUTHOR, authors);

bibEntry.setType(StandardEntryType.valueOf(getPublicationType()));

if (getDOI() != null) {
bibEntry.setField(StandardField.DOI, getDOI());
}

if (getURL() != null) {
bibEntry.setField(StandardField.URL, getURL());
}

if (getAbstract() != null) {
bibEntry.setField(StandardField.ABSTRACT, getAbstract());
}

return bibEntry;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ public SemanticScholarFetcher(ImporterPreferences importerPreferences) {
this.importerPreferences = importerPreferences;
}

public String getAPIUrl(String entry_point, BibEntry entry) {
return SEMANTIC_SCHOLAR_API + "paper/" + "DOI:" + entry.getDOI().orElseThrow().getDOI() + "/" + entry_point
+ "?fields=" + "title,authors,year,citationCount,referenceCount,externalIds,publicationTypes,abstract,url"
+ "&limit=1000";
}

@Override
public List<BibEntry> searchCitedBy(BibEntry entry) throws FetcherException {
if (entry.getDOI().isPresent()) {
StringBuilder urlBuilder = new StringBuilder(SEMANTIC_SCHOLAR_API)
.append("paper/")
.append("DOI:").append(entry.getDOI().get().getDOI())
.append("/citations")
.append("?fields=").append("title,authors,year,citationCount,referenceCount")
.append("&limit=1000");
try {
URL citationsUrl = URI.create(urlBuilder.toString()).toURL();
URL citationsUrl = URI.create(getAPIUrl("citations", entry)).toURL();
URLDownload urlDownload = new URLDownload(citationsUrl);

String apiKey = getApiKey();
Expand All @@ -58,15 +58,8 @@ public List<BibEntry> searchCitedBy(BibEntry entry) throws FetcherException {
@Override
public List<BibEntry> searchCiting(BibEntry entry) throws FetcherException {
if (entry.getDOI().isPresent()) {
StringBuilder urlBuilder = new StringBuilder(SEMANTIC_SCHOLAR_API)
.append("paper/")
.append("DOI:").append(entry.getDOI().get().getDOI())
.append("/references")
.append("?fields=")
.append("title,authors,year,citationCount,referenceCount")
.append("&limit=1000");
try {
URL referencesUrl = URI.create(urlBuilder.toString()).toURL();
URL referencesUrl = URI.create(getAPIUrl("references", entry)).toURL();
URLDownload urlDownload = new URLDownload(referencesUrl);
String apiKey = getApiKey();
if (!apiKey.isEmpty()) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/jabref/model/entry/BibEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ public void setField(Map<Field, String> fields) {
*/
public Optional<FieldChange> setField(Field field, String value, EntriesEventSource eventSource) {
Objects.requireNonNull(field, "field name must not be null");
Objects.requireNonNull(value, "field value must not be null");
Objects.requireNonNull(value, "field value for field " + field.getName() + " must not be null");
Objects.requireNonNull(eventSource, "field eventSource must not be null");

if (value.isEmpty()) {
Expand Down
Loading