Skip to content

Commit

Permalink
Add entry based on ISSN number JabRef#10124 (JabRef#10178)
Browse files Browse the repository at this point in the history
* Add: implementing the ISSN Fetcher

* Add: implementing methods of IssnFetcher class

* Substantially changes on IssnFetcher class

* Substantial changes of IssnFetcher

* Implementing the performSearchById method for IssnFetcher class

* Saving changes for branch updating

* Started to implement the ISSN search logic

* Refactor the performSearchById method

* Add the IssnFetcher on WebFetcher class and add unit tests

* Implement search based on the ISSN number

* Change the ISSN Checker validation of a valid checksum

* refactor to use exiting journal info fetcher

* reafactor

* add button next to journal field

* fix tests and checkstyle

* arch test

* Fuuu checkstyle

---------

Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>
  • Loading branch information
guipmenezes and Siedlerchr committed Nov 4, 2023
1 parent 5b34fe8 commit 86870cb
Show file tree
Hide file tree
Showing 16 changed files with 225 additions and 45 deletions.
4 changes: 2 additions & 2 deletions src/main/java/org/jabref/gui/fieldeditors/FieldEditors.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public static FieldEditorFX getForField(final Field field,
return new JournalEditor(field, suggestionProvider, fieldCheckers);
} else if (fieldProperties.contains(FieldProperty.DOI) || fieldProperties.contains(FieldProperty.EPRINT) || fieldProperties.contains(FieldProperty.ISBN)) {
return new IdentifierEditor(field, suggestionProvider, fieldCheckers);
} else if (fieldProperties.contains(FieldProperty.ISSN)) {
return new ISSNEditor(field, suggestionProvider, fieldCheckers);
} else if (field == StandardField.OWNER) {
return new OwnerEditor(field, suggestionProvider, fieldCheckers);
} else if (field == StandardField.GROUPS) {
Expand Down Expand Up @@ -97,8 +99,6 @@ public static FieldEditorFX getForField(final Field field,
return new KeywordsEditor(field, suggestionProvider, fieldCheckers, preferences, undoManager);
} else if (field == InternalField.KEY_FIELD) {
return new CitationKeyEditor(field, suggestionProvider, fieldCheckers, databaseContext);
} else if (field == StandardField.ISSN) {
return new ISSNEditor(field, suggestionProvider, fieldCheckers);
} else {
// default
return new SimpleEditor(field, suggestionProvider, fieldCheckers, preferences, isMultiLine, undoManager);
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/org/jabref/gui/fieldeditors/ISSNEditor.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.layout.HBox?>
<?import org.jabref.gui.icon.JabRefIconView?>
<?import javafx.scene.layout.VBox?>
<?import org.jabref.gui.fieldeditors.EditorTextArea?>
<?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.ISSNEditor">
<EditorTextArea fx:id="textArea"/>
<VBox>
<Button fx:id="journalInfoButton"
onAction="#showJournalInfo"
styleClass="icon-button">
Expand All @@ -20,5 +18,11 @@
<Tooltip text="%View journal info"/>
</tooltip>
</Button>
</VBox>
<Button fx:id="fetchInformationByIdentifierButton"
onAction="#fetchInformationByIdentifier"
styleClass="icon-button">
<graphic>
<JabRefIconView glyph="FETCH_BY_IDENTIFIER"/>
</graphic>
</Button>
</fx:root>
16 changes: 15 additions & 1 deletion src/main/java/org/jabref/gui/fieldeditors/ISSNEditor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.jabref.gui.fieldeditors;

import java.util.Optional;

import javax.swing.undo.UndoManager;

import javafx.fxml.FXML;
Expand All @@ -8,6 +10,7 @@
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.util.TaskExecutor;
Expand All @@ -23,11 +26,14 @@ public class ISSNEditor extends HBox implements FieldEditorFX {
@FXML private ISSNEditorViewModel viewModel;
@FXML private EditorTextArea textArea;
@FXML private Button journalInfoButton;
@FXML private Button fetchInformationByIdentifierButton;

@Inject private DialogService dialogService;
@Inject private PreferencesService preferencesService;
@Inject private UndoManager undoManager;
@Inject private TaskExecutor taskExecutor;
@Inject private StateManager stateManager;
private Optional<BibEntry> entry = Optional.empty();

public ISSNEditor(Field field,
SuggestionProvider<?> suggestionProvider,
Expand All @@ -43,7 +49,9 @@ public ISSNEditor(Field field,
fieldCheckers,
taskExecutor,
dialogService,
undoManager);
undoManager,
stateManager,
preferencesService);

textArea.textProperty().bindBidirectional(viewModel.textProperty());
textArea.initContextMenu(new DefaultMenu(textArea));
Expand All @@ -57,6 +65,7 @@ public ISSNEditorViewModel getViewModel() {

@Override
public void bindToEntry(BibEntry entry) {
this.entry = Optional.of(entry);
viewModel.bindToEntry(entry);
}

Expand All @@ -70,6 +79,11 @@ public void requestFocus() {
textArea.requestFocus();
}

@FXML
private void fetchInformationByIdentifier() {
entry.ifPresent(viewModel::fetchBibliographyInformation);
}

@FXML
private void showJournalInfo() {
if (JournalInfoOptInDialogHelper.isJournalInfoEnabled(dialogService, preferencesService.getEntryEditorPreferences())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,50 @@
import javafx.scene.control.Button;

import org.jabref.gui.DialogService;
import org.jabref.gui.StateManager;
import org.jabref.gui.autocompleter.SuggestionProvider;
import org.jabref.gui.mergeentries.FetchAndMergeEntry;
import org.jabref.gui.util.TaskExecutor;
import org.jabref.logic.integrity.FieldCheckers;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.StandardField;
import org.jabref.preferences.PreferencesService;

public class ISSNEditorViewModel extends AbstractEditorViewModel {
private final TaskExecutor taskExecutor;
private final DialogService dialogService;
private final UndoManager undoManager;
private final StateManager stateManager;
private final PreferencesService preferencesService;

public ISSNEditorViewModel(
Field field,
SuggestionProvider<?> suggestionProvider,
FieldCheckers fieldCheckers,
TaskExecutor taskExecutor,
DialogService dialogService,
UndoManager undoManager) {
UndoManager undoManager,
StateManager stateManager,
PreferencesService preferencesService) {
super(field, suggestionProvider, fieldCheckers, undoManager);
this.taskExecutor = taskExecutor;
this.dialogService = dialogService;
this.undoManager = undoManager;
this.stateManager = stateManager;
this.preferencesService = preferencesService;
}

public void showJournalInfo(Button journalInfoButton) {
PopOverUtil.showJournalInfo(journalInfoButton, entry, dialogService, taskExecutor);
}

public void fetchBibliographyInformation(BibEntry bibEntry) {
stateManager.getActiveDatabase().ifPresentOrElse(
databaseContext -> new FetchAndMergeEntry(databaseContext, taskExecutor, preferencesService, dialogService, undoManager)
.fetchAndMerge(bibEntry, StandardField.ISSN),
() -> dialogService.notify(Localization.lang("No library selected"))
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@
import org.jabref.logic.l10n.Localization;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.StandardField;
import org.jabref.preferences.PreferencesService;

import com.airhacks.afterburner.injection.Injector;
import com.airhacks.afterburner.views.ViewLoader;
import jakarta.inject.Inject;

import static org.jabref.model.entry.field.StandardField.DOI;
import static org.jabref.model.entry.field.StandardField.EPRINT;
import static org.jabref.model.entry.field.StandardField.ISBN;

public class IdentifierEditor extends HBox implements FieldEditorFX {

@FXML private BaseIdentifierEditorViewModel<?> viewModel;
Expand All @@ -53,14 +56,18 @@ public IdentifierEditor(Field field,
// but we need the injected vars to create the viewmodels.
Injector.registerExistingAndInject(this);

if (StandardField.DOI == field) {
this.viewModel = new DoiIdentifierEditorViewModel(suggestionProvider, fieldCheckers, dialogService, taskExecutor, preferencesService, undoManager, stateManager);
} else if (StandardField.ISBN == field) {
this.viewModel = new ISBNIdentifierEditorViewModel(suggestionProvider, fieldCheckers, dialogService, taskExecutor, preferencesService, undoManager, stateManager);
} else if (StandardField.EPRINT == field) {
this.viewModel = new EprintIdentifierEditorViewModel(suggestionProvider, fieldCheckers, dialogService, taskExecutor, preferencesService, undoManager);
} else {
throw new IllegalStateException(String.format("Unable to instantiate a view model for identifier field editor '%s'", field.getDisplayName()));
switch (field) {
case DOI ->
this.viewModel = new DoiIdentifierEditorViewModel(suggestionProvider, fieldCheckers, dialogService, taskExecutor, preferencesService, undoManager, stateManager);
case ISBN ->
this.viewModel = new ISBNIdentifierEditorViewModel(suggestionProvider, fieldCheckers, dialogService, taskExecutor, preferencesService, undoManager, stateManager);
case EPRINT ->
this.viewModel = new EprintIdentifierEditorViewModel(suggestionProvider, fieldCheckers, dialogService, taskExecutor, preferencesService, undoManager);

case null, default -> {
assert field != null;
throw new IllegalStateException(String.format("Unable to instantiate a view model for identifier field editor '%s'", field.getDisplayName()));
}
}

ViewLoader.view(this)
Expand All @@ -74,7 +81,7 @@ public IdentifierEditor(Field field,
lookupIdentifierButton.setTooltip(
new Tooltip(Localization.lang("Look up %0", field.getDisplayName())));

if (field.equals(StandardField.DOI)) {
if (field.equals(DOI)) {
textArea.initContextMenu(EditorMenus.getDOIMenu(textArea, dialogService, preferencesService));
} else {
textArea.initContextMenu(new DefaultMenu(textArea));
Expand All @@ -89,7 +96,6 @@ public BaseIdentifierEditorViewModel<?> getViewModel() {

@Override
public void bindToEntry(BibEntry entry) {
this.entry = Optional.of(entry);
viewModel.bindToEntry(entry);
}

Expand Down
28 changes: 17 additions & 11 deletions src/main/java/org/jabref/logic/importer/WebFetchers.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.jabref.logic.importer.fetcher.IEEE;
import org.jabref.logic.importer.fetcher.INSPIREFetcher;
import org.jabref.logic.importer.fetcher.IacrEprintFetcher;
import org.jabref.logic.importer.fetcher.IssnFetcher;
import org.jabref.logic.importer.fetcher.LOBIDFetcher;
import org.jabref.logic.importer.fetcher.LibraryOfCongress;
import org.jabref.logic.importer.fetcher.MathSciNet;
Expand All @@ -51,8 +52,10 @@
import org.jabref.model.entry.identifier.Identifier;
import org.jabref.preferences.FilePreferences;

import static org.jabref.model.entry.field.StandardField.DOI;
import static org.jabref.model.entry.field.StandardField.EPRINT;
import static org.jabref.model.entry.field.StandardField.ISBN;
import static org.jabref.model.entry.field.StandardField.ISSN;

public class WebFetchers {

Expand All @@ -62,16 +65,18 @@ private WebFetchers() {
public static Optional<IdBasedFetcher> getIdBasedFetcherForField(Field field, ImportFormatPreferences importFormatPreferences) {
IdBasedFetcher fetcher;

if (field == StandardField.DOI) {
fetcher = new DoiFetcher(importFormatPreferences);
} else if (field == ISBN) {
fetcher = new IsbnFetcher(importFormatPreferences);
// .addRetryFetcher(new EbookDeIsbnFetcher(importFormatPreferences));
// .addRetryFetcher(new DoiToBibtexConverterComIsbnFetcher(importFormatPreferences));
} else if (field == EPRINT) {
fetcher = new ArXivFetcher(importFormatPreferences);
} else {
return Optional.empty();
switch (field) {
case DOI ->
fetcher = new DoiFetcher(importFormatPreferences);
case ISBN ->
fetcher = new IsbnFetcher(importFormatPreferences);
case EPRINT ->
fetcher = new ArXivFetcher(importFormatPreferences);
case ISSN ->
fetcher = new IssnFetcher();
case null, default -> {
return Optional.empty();
}
}
return Optional.of(fetcher);
}
Expand Down Expand Up @@ -162,7 +167,8 @@ public static SortedSet<EntryBasedFetcher> getEntryBasedFetchers(ImporterPrefere
set.add(new AstrophysicsDataSystem(importFormatPreferences, importerPreferences));
set.add(new DoiFetcher(importFormatPreferences));
set.add(new IsbnFetcher(importFormatPreferences));
// .addRetryFetcher(new EbookDeIsbnFetcher(importFormatPreferences)));
set.add(new IssnFetcher());
// .addRetryFetcher(new EbookDeIsbnFetcher(importFormatPreferences)));
// .addRetryFetcher(new DoiToBibtexConverterComIsbnFetcher(importFormatPreferences)));
set.add(new MathSciNet(importFormatPreferences));
set.add(new CrossRef());
Expand Down
11 changes: 4 additions & 7 deletions src/main/java/org/jabref/logic/importer/fetcher/DOAJFetcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ public DOAJFetcher(ImportFormatPreferences preferences) {
*/
public static BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry, Character keywordSeparator) {
// Fields that are directly accessible at the top level BibJson object
Field[] singleFields = {StandardField.YEAR, StandardField.TITLE, StandardField.ABSTRACT, StandardField.MONTH};
List<Field> singleFields = List.of(StandardField.YEAR, StandardField.TITLE, StandardField.ABSTRACT, StandardField.MONTH);

// Fields that are accessible in the journal part of the BibJson object
Field[] journalSingleFields = {StandardField.PUBLISHER, StandardField.NUMBER, StandardField.VOLUME};
List<Field> journalSingleFields = List.of(StandardField.PUBLISHER, StandardField.NUMBER, StandardField.VOLUME);

BibEntry entry = new BibEntry(StandardEntryType.Article);

Expand Down Expand Up @@ -155,13 +155,10 @@ public static BibEntry parseBibJSONtoBibtex(JSONObject bibJsonEntry, Character k
return entry;
}

public static URIBuilder addPath(URIBuilder base, String subPath) {
public static void addPath(URIBuilder base, String subPath) {
// slightly altered version based on https://gist.github.com/enginer/230e2dc2f1d213a825d5
if (StringUtil.isBlank(subPath) || "/".equals(subPath)) {
return base;
} else {
if (!StringUtil.isBlank(subPath) && !"/".equals(subPath)) {
base.setPath(appendSegmentToPath(base.getPath(), subPath));
return base;
}
}

Expand Down
52 changes: 52 additions & 0 deletions src/main/java/org/jabref/logic/importer/fetcher/IssnFetcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.jabref.logic.importer.fetcher;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.jabref.logic.importer.EntryBasedFetcher;
import org.jabref.logic.importer.FetcherException;
import org.jabref.logic.importer.IdBasedFetcher;
import org.jabref.logic.journals.JournalInformation;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.StandardField;

/**
* Fetcher to generate the BibTex entry from an ISSN.
* As an ISSN ist just a journal identifier, so we only return journal title and publisher
* The idea is to use the {@link JournalInformationFetcher} to do a request for a given ISSN.
*/

public class IssnFetcher implements EntryBasedFetcher, IdBasedFetcher {

private final JournalInformationFetcher journalInformationFetcher;

public IssnFetcher() {
this.journalInformationFetcher = new JournalInformationFetcher();
}

@Override
public List<BibEntry> performSearch(BibEntry entry) throws FetcherException {
Optional<String> issn = entry.getField(StandardField.ISSN);
if (issn.isPresent()) {
Optional<JournalInformation> journalInformation = journalInformationFetcher.getJournalInformation(issn.get(), "");
return journalInformation.map(journalInfo -> journalInformationToBibEntry(journalInfo, issn.get())).stream().toList();
}
return Collections.emptyList();
}

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

@Override
public Optional<BibEntry> performSearchById(String identifier) throws FetcherException {
Optional<JournalInformation> journalInformation = journalInformationFetcher.getJournalInformation(identifier, "");
return journalInformation.map(journalInfo -> journalInformationToBibEntry(journalInfo, identifier));
}

private BibEntry journalInformationToBibEntry(JournalInformation journalInfo, String issn) {
return new BibEntry().withField(StandardField.JOURNALTITLE, journalInfo.title()).withField(StandardField.PUBLISHER, journalInfo.publisher()).withField(StandardField.ISSN, issn);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
public class JournalInformationFetcher implements WebFetcher {
public static final String NAME = "Journal Information";
private static final Logger LOGGER = LoggerFactory.getLogger(JournalInformationFetcher.class);
// Uses JabRef Online APIs
private static final String API_URL = "https://jabref.org/api";
private static final Pattern QUOTES_BRACKET_PATTERN = Pattern.compile("[\"\\[\\]]");

Expand Down Expand Up @@ -90,7 +91,7 @@ private JournalInformation parseResponse(JSONObject responseJsonObject) throws F
try {
if (responseJsonObject.has("errors")) {
JSONArray errors = responseJsonObject.optJSONArray("errors");
if (errors != null && errors.length() > 0) {
if (errors != null && !errors.isEmpty()) {
JSONObject error = errors.getJSONObject(0);
String errorMessage = error.optString("message", "");
LOGGER.error("Error accessing catalog: {}", errorMessage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ public class IsbnFetcher implements EntryBasedFetcher, IdBasedFetcher {
private static final Logger LOGGER = LoggerFactory.getLogger(IsbnFetcher.class);
private static final Pattern NEWLINE_SPACE_PATTERN = Pattern.compile("\\n|\\r\\n|\\s");
protected final ImportFormatPreferences importFormatPreferences;
private final OpenLibraryIsbnFetcher openLibraryIsbnFetcher;
private final List<AbstractIsbnFetcher> retryIsbnFetcher;
private final GvkFetcher gvkIbsnFetcher;

public IsbnFetcher(ImportFormatPreferences importFormatPreferences) {
this.importFormatPreferences = importFormatPreferences;
this.openLibraryIsbnFetcher = new OpenLibraryIsbnFetcher(importFormatPreferences);
OpenLibraryIsbnFetcher openLibraryIsbnFetcher = new OpenLibraryIsbnFetcher(importFormatPreferences);
this.gvkIbsnFetcher = new GvkFetcher(importFormatPreferences);
this.retryIsbnFetcher = new ArrayList<>();
this.addRetryFetcher(openLibraryIsbnFetcher);
Expand Down
Loading

0 comments on commit 86870cb

Please sign in to comment.