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

Feature/add abstract field to complex search #7079

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public WebSearchPaneViewModel(ImportFormatPreferences importPreferences, JabRefF
preferences.putInt(JabRefPreferences.SELECTED_FETCHER_INDEX, newIndex);
});

String allowedFields = "((author|journal|title|year|year-range):\\s?)?";
String allowedFields = "((author|abstract|journal|title|year|year-range):\\s?)?";
// Either a single word, or a phrase with quotes, or a year-range
String allowedTermText = "(((\\d{4}-\\d{4})|(\\w+)|(\"\\w+[^\"]*\"))\\s?)+";
queryPattern = Pattern.compile("^(" + allowedFields + allowedTermText + ")+$");
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/jabref/logic/importer/fetcher/ArXiv.java
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ public List<BibEntry> performComplexSearch(ComplexSearchQuery complexSearchQuery
List<String> searchTerms = new ArrayList<>();
complexSearchQuery.getAuthors().forEach(author -> searchTerms.add("au:" + author));
complexSearchQuery.getTitlePhrases().forEach(title -> searchTerms.add("ti:" + title));
complexSearchQuery.getTitlePhrases().forEach(abstr -> searchTerms.add("abs:" + abstr));
complexSearchQuery.getJournal().ifPresent(journal -> searchTerms.add("jr:" + journal));
// Since ArXiv API does not support year search, we ignore the year related terms
complexSearchQuery.getToYear().ifPresent(year -> searchTerms.add(year.toString()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.StringJoiner;

import org.jabref.model.strings.StringUtil;

Expand All @@ -15,15 +16,17 @@ public class ComplexSearchQuery {
private final List<String> defaultField;
private final List<String> authors;
private final List<String> titlePhrases;
private final List<String> abstractPhrases;
private final Integer fromYear;
private final Integer toYear;
private final Integer singleYear;
private final String journal;

private ComplexSearchQuery(List<String> defaultField, List<String> authors, List<String> titlePhrases, Integer fromYear, Integer toYear, Integer singleYear, String journal) {
private ComplexSearchQuery(List<String> defaultField, List<String> authors, List<String> titlePhrases, List<String> abstractPhrases, Integer fromYear, Integer toYear, Integer singleYear, String journal) {
this.defaultField = defaultField;
this.authors = authors;
this.titlePhrases = titlePhrases;
this.abstractPhrases = abstractPhrases;
this.fromYear = fromYear;
// Some APIs do not support, or not fully support, year based search. In these cases, the non applicable parameters are ignored.
this.toYear = toYear;
Expand All @@ -38,6 +41,7 @@ public static ComplexSearchQuery fromTerms(Collection<Term> terms) {
switch (term.field().toLowerCase()) {
case "author" -> builder.author(termText);
case "title" -> builder.titlePhrase(termText);
case "abstract" -> builder.abstractPhrase(termText);
case "journal" -> builder.journal(termText);
case "year" -> builder.singleYear(Integer.valueOf(termText));
case "year-range" -> builder.parseYearRange(termText);
Expand All @@ -60,6 +64,10 @@ public List<String> getTitlePhrases() {
return titlePhrases;
}

public List<String> getAbstractPhrases() {
return abstractPhrases;
}

public Optional<Integer> getFromYear() {
return Optional.ofNullable(fromYear);
}
Expand Down Expand Up @@ -101,6 +109,9 @@ public boolean equals(Object o) {
if (!(getTitlePhrases().containsAll(that.getTitlePhrases()) && that.getTitlePhrases().containsAll(getTitlePhrases()))) {
return false;
}
if (!(getAbstractPhrases().containsAll(that.getAbstractPhrases()) && that.getAbstractPhrases().containsAll(getAbstractPhrases()))) {
return false;
}
if (getFromYear().isPresent() ? !getFromYear().equals(that.getFromYear()) : that.getFromYear().isPresent()) {
return false;
}
Expand All @@ -115,33 +126,30 @@ public boolean equals(Object o) {

@Override
public int hashCode() {
int result = defaultField != null ? defaultField.hashCode() : 0;
result = 31 * result + (getAuthors() != null ? getAuthors().hashCode() : 0);
result = 31 * result + (getTitlePhrases() != null ? getTitlePhrases().hashCode() : 0);
result = 31 * result + (getFromYear().isPresent() ? getFromYear().hashCode() : 0);
result = 31 * result + (getToYear().isPresent() ? getToYear().hashCode() : 0);
result = 31 * result + (getSingleYear().isPresent() ? getSingleYear().hashCode() : 0);
result = 31 * result + (getJournal().isPresent() ? getJournal().hashCode() : 0);
return result;
return Objects.hash(defaultField, getAuthors(), getSingleYear(), getAbstractPhrases(), getFromYear(), getToYear(), getTitlePhrases(), getJournal());
}

@Override
public String toString() {
StringBuilder stringRepresentation = new StringBuilder();
getSingleYear().ifPresent(singleYear -> stringRepresentation.append(singleYear).append(" "));
getFromYear().ifPresent(fromYear -> stringRepresentation.append(fromYear).append(" "));
getToYear().ifPresent(toYear -> stringRepresentation.append(toYear).append(" "));
getJournal().ifPresent(journal -> stringRepresentation.append(journal).append(" "));
stringRepresentation.append(String.join(" ", getTitlePhrases()))
.append(String.join(" ", getDefaultFieldPhrases()))
.append(String.join(" ", getAuthors()));
return stringRepresentation.toString();
StringJoiner stringJoiner = new StringJoiner(" ");

getSingleYear().ifPresent(singleYear -> stringJoiner.add(singleYear.toString()));
getFromYear().ifPresent(fromYear -> stringJoiner.add(fromYear.toString()));
getToYear().ifPresent(toYear -> stringJoiner.add(toYear.toString()));
getJournal().ifPresent(stringJoiner::add);
stringJoiner.add(String.join(" ", getTitlePhrases()))
.add(String.join(" ", getDefaultFieldPhrases()))
.add(String.join(" ", getAuthors()))
.add(String.join(" ", getAbstractPhrases()));

return stringJoiner.toString();
}

public static class ComplexSearchQueryBuilder {
private List<String> defaultFieldPhrases = new ArrayList<>();
private List<String> authors = new ArrayList<>();
private List<String> titlePhrases = new ArrayList<>();
private List<String> abstractPhrases = new ArrayList<>();
private String journal;
private Integer fromYear;
private Integer toYear;
Expand Down Expand Up @@ -183,6 +191,18 @@ public ComplexSearchQueryBuilder titlePhrase(String titlePhrase) {
return this;
}

/**
* Adds abstract phrase and wraps it in quotes
*/
public ComplexSearchQueryBuilder abstractPhrase(String abstractPhrase) {
if (Objects.requireNonNull(abstractPhrase).isBlank()) {
throw new IllegalArgumentException("Parameter must not be blank");
}
// Strip all quotes before wrapping
this.titlePhrases.add(String.format("\"%s\"", abstractPhrase.replace("\"", "")));
return this;
}

public ComplexSearchQueryBuilder fromYearAndToYear(Integer fromYear, Integer toYear) {
if (Objects.nonNull(singleYear)) {
throw new IllegalArgumentException("You can not use single year and year range search.");
Expand Down Expand Up @@ -214,6 +234,7 @@ public ComplexSearchQueryBuilder terms(Collection<Term> terms) {
switch (term.field().toLowerCase()) {
case "author" -> this.author(termText);
case "title" -> this.titlePhrase(termText);
case "abstract" -> this.abstractPhrase(termText);
case "journal" -> this.journal(termText);
case "year" -> this.singleYear(Integer.valueOf(termText));
case "year-range" -> this.parseYearRange(termText);
Expand All @@ -235,7 +256,7 @@ public ComplexSearchQuery build() throws IllegalStateException {
if (textSearchFieldsAndYearFieldsAreEmpty()) {
throw new IllegalStateException("At least one text field has to be set");
}
return new ComplexSearchQuery(defaultFieldPhrases, authors, titlePhrases, fromYear, toYear, singleYear, journal);
return new ComplexSearchQuery(defaultFieldPhrases, authors, titlePhrases, abstractPhrases, fromYear, toYear, singleYear, journal);
}

void parseYearRange(String termText) {
Expand All @@ -259,7 +280,7 @@ void parseYearRange(String termText) {

private boolean textSearchFieldsAndYearFieldsAreEmpty() {
return this.stringListIsBlank(defaultFieldPhrases) && this.stringListIsBlank(titlePhrases) &&
this.stringListIsBlank(authors) && StringUtil.isBlank(journal) && yearFieldsAreEmpty();
this.stringListIsBlank(authors) && this.stringListIsBlank(abstractPhrases) && StringUtil.isBlank(journal) && yearFieldsAreEmpty();
}

private boolean yearFieldsAreEmpty() {
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/org/jabref/logic/importer/fetcher/IEEE.java
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,10 @@ public URL getComplexQueryURL(ComplexSearchQuery complexSearchQuery) throws URIS
if (!complexSearchQuery.getAuthors().isEmpty()) {
uriBuilder.addParameter("author", String.join(" AND ", complexSearchQuery.getAuthors()));
}
if (!complexSearchQuery.getAuthors().isEmpty()) {
if (!complexSearchQuery.getAbstractPhrases().isEmpty()) {
uriBuilder.addParameter("abstract", String.join(" AND ", complexSearchQuery.getAbstractPhrases()));
}
if (!complexSearchQuery.getTitlePhrases().isEmpty()) {
uriBuilder.addParameter("article_title", String.join(" AND ", complexSearchQuery.getTitlePhrases()));
}
complexSearchQuery.getJournal().ifPresent(journalTitle -> uriBuilder.addParameter("publication_title", journalTitle));
Expand Down