-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Add a new field for citation count #13531
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
base: main
Are you sure you want to change the base?
Changes from all commits
dcc6076
1a76c57
aaef2ce
150bc2c
fe6b48d
23fbd53
b37475d
f4fa327
1193823
44de54c
05aa416
15baed1
19923b8
db2ffd2
cd836e7
a90024c
9c3facb
84af44f
1d265d3
8bfc988
83709c9
4333732
18f9de0
91c8c62
0cf3850
e4fdd97
e1928d8
18e51bd
d12e8e4
1f7f5cf
ba09528
25e3649
4e0c1af
1accb7c
85190f9
371f9f6
3074fde
41deb2b
fa1297f
4f1250d
49d6d47
827b4a7
0630f86
f8a9733
5bd1d5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package org.jabref.gui.fieldeditors; | ||
|
||
import javax.swing.undo.UndoManager; | ||
|
||
import javafx.fxml.FXML; | ||
import javafx.scene.Parent; | ||
import javafx.scene.control.Button; | ||
import javafx.scene.control.Tooltip; | ||
import javafx.scene.layout.HBox; | ||
|
||
import org.jabref.gui.DialogService; | ||
import org.jabref.gui.StateManager; | ||
import org.jabref.gui.autocompleter.SuggestionProvider; | ||
import org.jabref.gui.fieldeditors.contextmenu.DefaultMenu; | ||
import org.jabref.gui.preferences.GuiPreferences; | ||
import org.jabref.logic.citation.SearchCitationsRelationsService; | ||
import org.jabref.logic.integrity.FieldCheckers; | ||
import org.jabref.logic.l10n.Localization; | ||
import org.jabref.logic.util.TaskExecutor; | ||
import org.jabref.model.entry.BibEntry; | ||
import org.jabref.model.entry.field.Field; | ||
|
||
import com.airhacks.afterburner.injection.Injector; | ||
import com.airhacks.afterburner.views.ViewLoader; | ||
import jakarta.inject.Inject; | ||
|
||
public class CitationCountEditor extends HBox implements FieldEditorFX { | ||
@FXML private CitationCountEditorViewModel viewModel; | ||
@FXML private EditorTextField textField; | ||
@FXML private Button fetchCitationCountButton; | ||
|
||
@Inject private DialogService dialogService; | ||
@Inject private GuiPreferences preferences; | ||
@Inject private UndoManager undoManager; | ||
@Inject private TaskExecutor taskExecutor; | ||
@Inject private StateManager stateManager; | ||
@Inject private SearchCitationsRelationsService searchCitationsRelationsService; | ||
|
||
public CitationCountEditor(Field field, | ||
SuggestionProvider<?> suggestionProvider, | ||
FieldCheckers fieldCheckers) { | ||
Injector.registerExistingAndInject(this); | ||
this.viewModel = new CitationCountEditorViewModel( | ||
field, | ||
suggestionProvider, | ||
fieldCheckers, | ||
taskExecutor, | ||
dialogService, | ||
undoManager, | ||
stateManager, | ||
preferences, | ||
searchCitationsRelationsService); | ||
|
||
ViewLoader.view(this) | ||
.root(this) | ||
.load(); | ||
|
||
textField.textProperty().bindBidirectional(viewModel.textProperty()); | ||
|
||
fetchCitationCountButton.setTooltip( | ||
new Tooltip(Localization.lang("Look up %0", field.getDisplayName()))); | ||
textField.initContextMenu(new DefaultMenu(textField), preferences.getKeyBindingRepository()); | ||
new EditorValidator(preferences).configureValidation(viewModel.getFieldValidator().getValidationStatus(), textField); | ||
} | ||
|
||
@FXML | ||
private void fetchCitationCount() { | ||
viewModel.getCitationCount(); | ||
} | ||
|
||
public CitationCountEditorViewModel getViewModel() { | ||
return viewModel; | ||
} | ||
|
||
@Override | ||
public void bindToEntry(BibEntry entry) { | ||
viewModel.bindToEntry(entry); | ||
} | ||
|
||
@Override | ||
public Parent getNode() { | ||
return this; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package org.jabref.gui.fieldeditors; | ||
|
||
import java.util.Optional; | ||
|
||
import javax.swing.undo.UndoManager; | ||
|
||
import javafx.beans.property.BooleanProperty; | ||
import javafx.beans.property.SimpleBooleanProperty; | ||
|
||
import org.jabref.gui.DialogService; | ||
import org.jabref.gui.StateManager; | ||
import org.jabref.gui.autocompleter.SuggestionProvider; | ||
import org.jabref.gui.preferences.GuiPreferences; | ||
import org.jabref.logic.citation.SearchCitationsRelationsService; | ||
import org.jabref.logic.integrity.FieldCheckers; | ||
import org.jabref.logic.l10n.Localization; | ||
import org.jabref.logic.util.BackgroundTask; | ||
import org.jabref.logic.util.TaskExecutor; | ||
import org.jabref.model.entry.field.Field; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class CitationCountEditorViewModel extends AbstractEditorViewModel { | ||
private static final Logger LOGGER = LoggerFactory.getLogger(CitationCountEditorViewModel.class); | ||
|
||
protected final BooleanProperty fetchCitationCountInProgress = new SimpleBooleanProperty(false); | ||
private final TaskExecutor taskExecutor; | ||
private final DialogService dialogService; | ||
private final UndoManager undoManager; | ||
private final StateManager stateManager; | ||
private final GuiPreferences preferences; | ||
SalvadorRomo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private final SearchCitationsRelationsService searchCitationsRelationsService; | ||
public CitationCountEditorViewModel( | ||
Field field, | ||
SuggestionProvider<?> suggestionProvider, | ||
FieldCheckers fieldCheckers, | ||
TaskExecutor taskExecutor, | ||
DialogService dialogService, | ||
UndoManager undoManager, | ||
StateManager stateManager, | ||
GuiPreferences preferences, | ||
SearchCitationsRelationsService searchCitationsRelationsService) { | ||
super(field, suggestionProvider, fieldCheckers, undoManager); | ||
this.taskExecutor = taskExecutor; | ||
this.dialogService = dialogService; | ||
this.undoManager = undoManager; | ||
this.stateManager = stateManager; | ||
this.preferences = preferences; | ||
this.searchCitationsRelationsService = searchCitationsRelationsService; | ||
} | ||
|
||
public BooleanProperty fetchCitationCountInProgressProperty() { | ||
return fetchCitationCountInProgress; | ||
} | ||
|
||
public boolean getFetchCitationCountInProgress() { | ||
return fetchCitationCountInProgress.get(); | ||
} | ||
|
||
public void getCitationCount() { | ||
Optional<String> fieldContent = entry.getField(field); | ||
BackgroundTask.wrap(() -> searchCitationsRelationsService.getCitationCount(this.entry, fieldContent)) | ||
.onRunning(() -> fetchCitationCountInProgress.setValue(true)) | ||
.onFinished(() -> fetchCitationCountInProgress.setValue(false)) | ||
.onFailure(e -> { | ||
dialogService.notify(Localization.lang("Error occurred when getting citation count, please try again or check the identifier.")); | ||
LOGGER.error("Error while fetching citation count", e); | ||
}) | ||
.onSuccess(identifier -> { | ||
entry.setField(field, String.valueOf(identifier)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using setField instead of withField violates the immutability principle for BibEntry objects as specified in JabRef's conventions |
||
}).executeWith(taskExecutor); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<?import javafx.scene.control.Button?> | ||
<?import javafx.scene.control.ProgressIndicator?> | ||
<?import javafx.scene.control.Tooltip?> | ||
<?import javafx.scene.layout.HBox?> | ||
<?import javafx.scene.layout.StackPane?> | ||
<?import org.jabref.gui.fieldeditors.EditorTextField?> | ||
<?import org.jabref.gui.icon.JabRefIconView?> | ||
<fx:root xmlns:fx="http://javafx.com/fxml/1" type="HBox" xmlns="http://javafx.com/javafx/8.0.112" | ||
fx:controller="org.jabref.gui.fieldeditors.CitationCountEditor"> | ||
<EditorTextField fx:id="textField" prefHeight="0.0" HBox.hgrow="ALWAYS"/> | ||
<Button fx:id="fetchCitationCountButton" onAction="#fetchCitationCount" styleClass="icon-button"> | ||
<graphic> | ||
<StackPane> | ||
<JabRefIconView glyph="LOOKUP_IDENTIFIER" | ||
visible="${!controller.viewModel.fetchCitationCountInProgress}"/> | ||
<ProgressIndicator maxHeight="12.0" maxWidth="12.0" | ||
visible="${controller.viewModel.fetchCitationCountInProgress}"/> | ||
</StackPane> | ||
</graphic> | ||
</Button> | ||
</fx:root> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
import java.net.MalformedURLException; | ||
import java.net.URL; | ||
import java.util.List; | ||
import java.util.Optional; | ||
|
||
import org.jabref.logic.importer.FetcherException; | ||
import org.jabref.logic.importer.ImporterPreferences; | ||
|
@@ -33,6 +34,12 @@ public String getAPIUrl(String entry_point, BibEntry entry) { | |
+ "&limit=1000"; | ||
} | ||
|
||
public String getUrlForCitationCount(BibEntry entry) { | ||
return SEMANTIC_SCHOLAR_API + "paper/" + "DOI:" + entry.getDOI().orElseThrow().asString() | ||
+ "?fields=" + "citationCount" | ||
+ "&limit=1"; | ||
} | ||
|
||
@Override | ||
public List<BibEntry> searchCitedBy(BibEntry entry) throws FetcherException { | ||
if (entry.getDOI().isEmpty()) { | ||
|
@@ -84,6 +91,27 @@ public List<BibEntry> searchCitedBy(BibEntry entry) throws FetcherException { | |
.map(referenceDataItem -> referenceDataItem.getCitedPaper().toBibEntry()).toList(); | ||
} | ||
|
||
@Override | ||
public Optional<Integer> searchCitationCount(BibEntry entry) throws FetcherException { | ||
if (entry.getDOI().isEmpty()) { | ||
return Optional.empty(); | ||
} | ||
URL referencesUrl; | ||
try { | ||
referencesUrl = URLUtil.create(getUrlForCitationCount(entry)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Variable name 'referencesUrl' is misleading as it's used for citation count URL, not references. This reduces code readability and maintainability. |
||
} catch (MalformedURLException e) { | ||
throw new FetcherException("Malformed URL", e); | ||
} | ||
URLDownload urlDownload = new URLDownload(referencesUrl); | ||
importerPreferences.getApiKey(getName()).ifPresent(apiKey -> urlDownload.addHeader("x-api-key", apiKey)); | ||
PaperDetails paperDetails = GSON.fromJson(urlDownload.asString(), PaperDetails.class); | ||
|
||
if (paperDetails == null) { | ||
return Optional.empty(); | ||
} | ||
return Optional.of(paperDetails.getCitationCount()); | ||
koppor marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
@Override | ||
public String getName() { | ||
return FETCHER_NAME; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -136,6 +136,7 @@ public enum StandardField implements Field { | |
// JabRef-specific fields | ||
GROUPS("groups"), | ||
OWNER("owner"), | ||
CITATIONCOUNT("Citation count"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Field name should be in lowercase with underscores for consistency with other field names. The display name should be sentence case as per UI text guidelines. |
||
TIMESTAMP("timestamp", FieldProperty.DATE), | ||
CREATIONDATE("creationdate", FieldProperty.DATE), | ||
MODIFICATIONDATE("modificationdate", FieldProperty.DATE); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using Swing components in a JavaFX application violates the architectural decision to use only JavaFX. The UndoManager should be replaced with a JavaFX-specific implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JabRef uses this - which is OK.