Skip to content

Commit

Permalink
Add ShortScience integration (JabRef#6018)
Browse files Browse the repository at this point in the history
  • Loading branch information
stevensdavid committed Mar 6, 2020
1 parent c0abdce commit 7fda4cc
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#
- Filenames of external files can no longer contain curly braces. [#5926](https://github.com/JabRef/jabref/pull/5926)
- We made the filters more easily accessible in the integrity check dialog. [#5955](https://github.com/JabRef/jabref/pull/5955)
- We reimplemented and improved the dialog "Customize entry types" [#4719](https://github.com/JabRef/jabref/issues/4719)
- We added support for searching ShortScience for an entry through the user's browser. [#6018](https://github.com/JabRef/jabref/pull/6018)

### Fixed

Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/jabref/gui/actions/StandardActions.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public enum StandardActions implements Action {
SEND_AS_EMAIL(Localization.lang("Send as email"), IconTheme.JabRefIcons.EMAIL),
OPEN_EXTERNAL_FILE(Localization.lang("Open file"), IconTheme.JabRefIcons.FILE, KeyBinding.OPEN_FILE),
OPEN_URL(Localization.lang("Open URL or DOI"), IconTheme.JabRefIcons.WWW, KeyBinding.OPEN_URL_OR_DOI),
SEARCH_SHORTSCIENCE(Localization.lang("Search ShortScience")),
MERGE_WITH_FETCHED_ENTRY(Localization.lang("Get BibTeX data from %0", "DOI/ISBN/...")),
ATTACH_FILE(Localization.lang("Attach file"), IconTheme.JabRefIcons.ATTACH_FILE),
PRIORITY(Localization.lang("Priority"), IconTheme.JabRefIcons.PRIORITY),
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/jabref/gui/maintable/RightClickMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public static ContextMenu create(BibEntryTableViewModel entry, KeyBindingReposit
contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_FOLDER, new OpenFolderAction(dialogService, stateManager, preferencesService)));
contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_EXTERNAL_FILE, new OpenExternalFileAction(dialogService, stateManager, preferencesService)));
contextMenu.getItems().add(factory.createMenuItem(StandardActions.OPEN_URL, new OpenUrlAction(dialogService, stateManager)));
contextMenu.getItems().add(factory.createMenuItem(StandardActions.SEARCH_SHORTSCIENCE, new SearchShortScienceAction(dialogService, stateManager)));

contextMenu.getItems().add(new SeparatorMenuItem());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.jabref.gui.maintable;

import java.io.IOException;
import java.util.List;

import javafx.beans.binding.BooleanExpression;

import org.jabref.gui.DialogService;
import org.jabref.gui.StateManager;
import org.jabref.gui.actions.SimpleCommand;
import org.jabref.gui.desktop.JabRefDesktop;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.util.ExternalLinkCreator;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.StandardField;

import static org.jabref.gui.actions.ActionHelper.isFieldSetForSelectedEntry;
import static org.jabref.gui.actions.ActionHelper.needsEntriesSelected;

public class SearchShortScienceAction extends SimpleCommand {
private final DialogService dialogService;
private final StateManager stateManager;

public SearchShortScienceAction(DialogService dialogService, StateManager stateManager) {
this.dialogService = dialogService;
this.stateManager = stateManager;

BooleanExpression fieldIsSet = isFieldSetForSelectedEntry(StandardField.TITLE, stateManager);
this.executable.bind(needsEntriesSelected(1, stateManager).and(fieldIsSet));
}

@Override
public void execute() {
stateManager.getActiveDatabase().ifPresent(databaseContext -> {
final List<BibEntry> bibEntries = stateManager.getSelectedEntries();

if (bibEntries.size() != 1) {
dialogService.notify(Localization.lang("This operation requires exactly one item to be selected."));
return;
}
ExternalLinkCreator.getShortScienceSearchURL(bibEntries.get(0)).ifPresent(url -> {
try {
JabRefDesktop.openExternalViewer(databaseContext, url, StandardField.URL);
} catch (IOException ex) {
dialogService.showErrorDialogAndWait(Localization.lang("Unable to open ShortScience."), ex);
}
});
});
}
}
34 changes: 34 additions & 0 deletions src/main/java/org/jabref/logic/util/ExternalLinkCreator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.jabref.logic.util;

import java.net.URISyntaxException;
import java.util.Optional;

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

import org.apache.http.client.utils.URIBuilder;

public class ExternalLinkCreator {
private static final String SHORTSCIENCE_SEARCH_URL = "https://www.shortscience.org/internalsearch";

/**
* Get a URL to the search results of ShortScience for the BibEntry's title
*
* @param entry The entry to search for. Expects the BibEntry's title to be set for successful return.
* @return The URL if it was successfully created
*/
public static Optional<String> getShortScienceSearchURL(BibEntry entry) {
return entry.getField(StandardField.TITLE).map(title -> {
URIBuilder uriBuilder;
try {
uriBuilder = new URIBuilder(SHORTSCIENCE_SEARCH_URL);
} catch (URISyntaxException e) {
// This should never be able to happen as it would require the field to be misconfigured.
throw new AssertionError("ShortScience URL is invalid.", e);
}
// Direct the user to the search results for the title.
uriBuilder.addParameter("q", title);
return uriBuilder.toString();
});
}
}
4 changes: 4 additions & 0 deletions src/main/resources/l10n/JabRef_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2114,5 +2114,9 @@ Optional=Optional
Required=Required
Entry\ type\ cannot\ be\ empty.\ Please\ enter\ a\ name.=Entry type cannot be empty. Please enter a name.
Field\ cannot\ be\ empty.\ Please\ enter\ a\ name.=Field cannot be empty. Please enter a name.
Search\ ShortScience=Search ShortScience
Unable\ to\ open\ ShortScience.=Unable to open ShortScience.
Shared\ database=Shared database
Lookup=Lookup
56 changes: 56 additions & 0 deletions src/test/java/org/jabref/logic/util/ExternalLinkCreatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.jabref.logic.util;

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Optional;

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

import org.junit.jupiter.api.Test;

import static org.jabref.logic.util.ExternalLinkCreator.getShortScienceSearchURL;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class ExternalLinkCreatorTest {

/**
* Validates URL conformance to RFC2396. Does not perform complex checks such as opening connections.
*/
private boolean urlIsValid(String url) {
try {
// This will throw on non-compliance to RFC2396.
new URL(url).toURI();
return true;
} catch (MalformedURLException | URISyntaxException e) {
return false;
}
}

@Test
void getShortScienceSearchURLEncodesSpecialCharacters() {
BibEntry entry = new BibEntry();
String rfc3986ReservedCharacters = "!*'();:@&=+$,/?#[]";
entry.setField(StandardField.TITLE, rfc3986ReservedCharacters);
Optional<String> url = getShortScienceSearchURL(entry);
assertTrue(url.isPresent());
assertTrue(urlIsValid(url.get()));
}

@Test
void getShortScienceSearchURLReturnsEmptyOnMissingTitle() {
BibEntry entry = new BibEntry();
assertEquals(Optional.empty(), getShortScienceSearchURL(entry));
}

@Test
void getShortScienceSearchURLLinksToSearchResults() {
// Take an arbitrary article name
BibEntry entry = new BibEntry().withField(StandardField.TITLE, "JabRef bibliography management");
Optional<String> url = getShortScienceSearchURL(entry);
// Expected behaviour is to link to the search results page, /internalsearch
assertEquals(Optional.of("https://www.shortscience.org/internalsearch?q=JabRef+bibliography+management"), url);
}
}

0 comments on commit 7fda4cc

Please sign in to comment.