Skip to content

Commit

Permalink
Migrate search groups flags to new syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
LoayGhreeb committed Oct 4, 2024
1 parent 6ab8f55 commit 4fc088f
Show file tree
Hide file tree
Showing 19 changed files with 304 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,14 @@ public AbstractGroup resultConverter(ButtonType button) {
// Otherwise, it means that the user did not accept the migration to the new version.
Optional<GroupTreeNode> groups = currentDatabase.getMetaData().getGroups();
if (groups.filter(this::groupOrSubgroupIsSearchGroup).isEmpty()) {
currentDatabase.getMetaData().setGroupSearchSyntaxVersion(SearchGroupsMigrationAction.VERSION_6_0_ALPHA);
currentDatabase.getMetaData().setGroupSearchSyntaxVersion(SearchGroupsMigrationAction.VERSION_6_0_ALPHA_1);
}
}

Optional<IndexManager> indexManager = stateManager.getIndexManager(currentDatabase);
if (indexManager.isPresent()) {
SearchGroup searchGroup = (SearchGroup) resultingGroup;
// TODO: search should be done in a background thread
searchGroup.setMatchedEntries(indexManager.get().search(searchGroup.getSearchQuery()).getMatchedEntries());
}
} else if (typeAutoProperty.getValue()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
public class CheckForNewEntryTypesAction implements GUIPostOpenAction {

@Override
public boolean isActionNecessary(ParserResult parserResult, CliPreferences preferences) {
public boolean isActionNecessary(ParserResult parserResult, DialogService dialogService, CliPreferences preferences) {
return !getListOfUnknownAndUnequalCustomizations(parserResult, preferences.getLibraryPreferences()).isEmpty();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* opening a BIB file into JabRef. This can for instance be file upgrade actions
* that should be offered due to new features in JabRef, and may depend on e.g.
* which JabRef version the file was last written by.
*
* <p>
* This interface is introduced in an attempt to add such functionality in a
* flexible manner.
*/
Expand All @@ -22,12 +22,12 @@ public interface GUIPostOpenAction {
* @param pr The result of the BIB parse operation.
* @return true if the action should be called, false otherwise.
*/
boolean isActionNecessary(ParserResult pr, CliPreferences preferences);
boolean isActionNecessary(ParserResult pr, DialogService dialogService, CliPreferences preferences);

/**
* This method is called after the new database has been added to the GUI, if
* the isActionNecessary() method returned true.
*
* <p>
* Note: if several such methods need to be called sequentially, it is
* important that all implementations of this method do not return
* until the operation is finished.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public class MergeReviewIntoCommentAction implements GUIPostOpenAction {

@Override
public boolean isActionNecessary(ParserResult parserResult, CliPreferences preferences) {
public boolean isActionNecessary(ParserResult parserResult, DialogService dialogService, CliPreferences preferences) {
return MergeReviewIntoCommentMigration.needsMigration(parserResult);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public OpenDatabaseAction(LibraryTabContainer tabContainer,

public static void performPostOpenActions(ParserResult result, DialogService dialogService, CliPreferences preferences) {
for (GUIPostOpenAction action : OpenDatabaseAction.POST_OPEN_ACTIONS) {
if (action.isActionNecessary(result, preferences)) {
if (action.isActionNecessary(result, dialogService, preferences)) {
action.performAction(result, dialogService, preferences);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
import org.jabref.logic.importer.ParserResult;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.preferences.CliPreferences;
import org.jabref.logic.search.query.SearchQueryConversion;
import org.jabref.logic.util.Version;
import org.jabref.migrations.SearchToLuceneMigration;
import org.jabref.model.groups.GroupTreeNode;
import org.jabref.model.groups.SearchGroup;
import org.jabref.model.search.SearchFlags;

import org.antlr.v4.runtime.misc.ParseCancellationException;

Expand All @@ -24,11 +23,17 @@ public class SearchGroupsMigrationAction implements GUIPostOpenAction {
// We cannot have this constant in `Version.java` because of recursion errors
// Thus, we keep it here, because it is (currently) used only in the context of groups migration.
public static final Version VERSION_6_0_ALPHA = Version.parse("6.0-alpha");
public static final Version VERSION_6_0_ALPHA_1 = Version.parse("6.0-alpha_1");

@Override
public boolean isActionNecessary(ParserResult parserResult, CliPreferences preferences) {
if (parserResult.getMetaData().getGroupSearchSyntaxVersion().isPresent()) {
// Currently the presence of any version is enough to know that no migration is necessary
public boolean isActionNecessary(ParserResult parserResult, DialogService dialogService, CliPreferences preferences) {
Optional<Version> currentVersion = parserResult.getMetaData().getGroupSearchSyntaxVersion();
if (currentVersion.isPresent()) {
if (currentVersion.get().equals(VERSION_6_0_ALPHA)) {
dialogService.showErrorDialogAndWait(Localization.lang("Search groups migration"),
Localization.lang("The search groups syntax has been reverted to the old one. "
+ "Please use the backup you made before migrating to 6.0-alpha."));
}
return false;
}

Expand Down Expand Up @@ -57,21 +62,22 @@ public void performAction(ParserResult parserResult, DialogService dialogService
}

parserResult.getMetaData().getGroups().ifPresent(groupTreeNode -> migrateGroups(groupTreeNode, dialogService));
parserResult.getMetaData().setGroupSearchSyntaxVersion(VERSION_6_0_ALPHA);
parserResult.getMetaData().setGroupSearchSyntaxVersion(VERSION_6_0_ALPHA_1);
parserResult.setChangedOnMigration(true);
}

private void migrateGroups(GroupTreeNode node, DialogService dialogService) {
if (node.getGroup() instanceof SearchGroup searchGroup) {
try {
String luceneSearchExpression = SearchToLuceneMigration.migrateToLuceneSyntax(searchGroup.getSearchExpression(), searchGroup.getSearchFlags().contains(SearchFlags.REGULAR_EXPRESSION));
searchGroup.setSearchExpression(luceneSearchExpression);
String newSearchExpression = SearchQueryConversion.flagsToSearchExpression(searchGroup.getSearchExpression(), searchGroup.getSearchFlags());
searchGroup.setSearchExpression(newSearchExpression);
} catch (ParseCancellationException e) {
Optional<String> luceneSearchExpression = dialogService.showInputDialogWithDefaultAndWait(
Optional<String> newSearchExpression = dialogService.showInputDialogWithDefaultAndWait(
Localization.lang("Search group migration failed"),
Localization.lang("The search group '%0' could not be migrated. Please enter the new search expression.", searchGroup.getName()),
Localization.lang("The search group '%0' could not be migrated. Please enter the new search expression.",
searchGroup.getName()),
searchGroup.getSearchExpression());
luceneSearchExpression.ifPresent(searchGroup::setSearchExpression);
newSearchExpression.ifPresent(searchGroup::setSearchExpression);
}
}
for (GroupTreeNode child : node.getChildren()) {
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/org/jabref/logic/search/IndexManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,18 +222,17 @@ public AutoCloseable blockLinkedFileIndexer() {

public SearchResults search(SearchQuery query) {
SearchResults searchResults = new SearchResults();

searchResults.mergeSearchResults(bibFieldsSearcher.search(query));
// if (query.isValid()) {
// query.setSearchResults(linkedFilesSearcher.search(query.getParsedQuery(), query.getSearchFlags()));
// } else {
// query.setSearchResults(new SearchResults());
// }
if (query.getSearchFlags().contains(SearchFlags.FULLTEXT)) {
// TODO: merge results from lucene and postgres
} else {
query.setSearchResults(bibFieldsSearcher.search(query));
}
return query.getSearchResults();
query.setSearchResults(searchResults);
return searchResults;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.jabref.logic.search.query;

import java.util.EnumSet;
import java.util.Optional;

import org.jabref.model.search.SearchFlags;
import org.jabref.model.search.query.SearchTermFlag;
import org.jabref.search.SearchBaseVisitor;
import org.jabref.search.SearchParser;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.jabref.model.search.query.SearchTermFlag.CASE_INSENSITIVE;
import static org.jabref.model.search.query.SearchTermFlag.CASE_SENSITIVE;
import static org.jabref.model.search.query.SearchTermFlag.EXACT_MATCH;
import static org.jabref.model.search.query.SearchTermFlag.INEXACT_MATCH;
import static org.jabref.model.search.query.SearchTermFlag.NEGATION;
import static org.jabref.model.search.query.SearchTermFlag.REGULAR_EXPRESSION;

public class SearchFlagsToExpressionVisitor extends SearchBaseVisitor<String> {

private static final Logger LOGGER = LoggerFactory.getLogger(SearchFlagsToExpressionVisitor.class);

private final boolean isCaseSensitive;
private final boolean isRegularExpression;

public SearchFlagsToExpressionVisitor(EnumSet<SearchFlags> searchFlags) {
LOGGER.debug("Converting search flags to search expression: {}", searchFlags);
this.isCaseSensitive = searchFlags.contains(SearchFlags.CASE_SENSITIVE);
this.isRegularExpression = searchFlags.contains(SearchFlags.REGULAR_EXPRESSION);
}

@Override
public String visitStart(SearchParser.StartContext context) {
return visit(context.expression());
}

@Override
public String visitParenExpression(SearchParser.ParenExpressionContext ctx) {
return "(" + visit(ctx.expression()) + ")";
}

@Override
public String visitUnaryExpression(SearchParser.UnaryExpressionContext ctx) {
return "NOT " + visit(ctx.expression());
}

@Override
public String visitBinaryExpression(SearchParser.BinaryExpressionContext ctx) {
return visit(ctx.left) + " " + ctx.operator.getText() + " " + visit(ctx.right);
}

public String visitComparison(SearchParser.ComparisonContext context) {
String right = context.right.getText();

Optional<SearchParser.NameContext> fieldDescriptor = Optional.ofNullable(context.left);
EnumSet<SearchTermFlag> termFlags = EnumSet.noneOf(SearchTermFlag.class);

if (fieldDescriptor.isPresent()) {
String field = fieldDescriptor.get().getText();

termFlags.add(isCaseSensitive ? CASE_SENSITIVE : CASE_INSENSITIVE);
if (context.NEQUAL() != null) {
termFlags.add(NEGATION);
}

if (isRegularExpression) {
termFlags.add(REGULAR_EXPRESSION);
} else {
if (context.EQUAL() != null || context.CONTAINS() != null || context.NEQUAL() != null) {
termFlags.add(INEXACT_MATCH);
} else if (context.EEQUAL() != null || context.MATCHES() != null) {
termFlags.add(EXACT_MATCH);
}
}
return getFieldQueryNode(field, right, termFlags);
} else {
termFlags.add(isCaseSensitive ? CASE_SENSITIVE : CASE_INSENSITIVE);
if (isRegularExpression) {
termFlags.add(REGULAR_EXPRESSION);
} else {
termFlags.add(INEXACT_MATCH);
}
return getFieldQueryNode("any", right, termFlags);
}
}

private String getFieldQueryNode(String field, String term, EnumSet<SearchTermFlag> searchFlags) {
String operator = getOperator(searchFlags);
return field + " " + operator + " " + term;
}

private static String getOperator(EnumSet<SearchTermFlag> searchFlags) {
StringBuilder operator = new StringBuilder();

if (searchFlags.contains(NEGATION)) {
operator.append("!");
}

if (searchFlags.contains(INEXACT_MATCH)) {
operator.append("=");
} else if (searchFlags.contains(EXACT_MATCH)) {
operator.append("==");
} else if (searchFlags.contains(REGULAR_EXPRESSION)) {
operator.append("=~");
}

if (searchFlags.contains(CASE_SENSITIVE)) {
operator.append("!");
}

return operator.toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.jabref.logic.search.query;

import java.util.EnumSet;

import org.jabref.model.search.SearchFlags;
import org.jabref.model.search.ThrowingErrorListener;
import org.jabref.search.SearchLexer;
import org.jabref.search.SearchParser;
Expand All @@ -10,8 +13,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SearchToSqlConversion {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchToSqlConversion.class);
public class SearchQueryConversion {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchQueryConversion.class);

public static String searchToSql(String table, String searchExpression) {
LOGGER.debug("Converting search expression to SQL: {}", searchExpression);
Expand All @@ -20,6 +23,17 @@ public static String searchToSql(String table, String searchExpression) {
return searchToSqlVisitor.visit(context);
}

public static String flagsToSearchExpression(String searchExpression, EnumSet<SearchFlags> searchFlags) {
LOGGER.debug("Converting search flags to search expression: {}, flags {}", searchExpression, searchFlags);
SearchParser.StartContext context = getStartContext(searchExpression);
return new SearchFlagsToExpressionVisitor(searchFlags).visit(context);
}

public static String searchToLucene(String searchExpression) {
LOGGER.debug("Converting search expression to Lucene: {}", searchExpression);
return "";
}

private static SearchParser.StartContext getStartContext(String searchExpression) {
SearchLexer lexer = new SearchLexer(CharStreams.fromString(searchExpression));
lexer.removeErrorListeners(); // no infos on file system
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.jabref.migrations;
package org.jabref.logic.search.query;

import java.util.List;
import java.util.Optional;
Expand All @@ -21,7 +21,7 @@

/**
* Converts to a Lucene index with the assumption that the ngram analyzer is used.
*
* <p>
* Tests are located in {@link org.jabref.migrations.SearchToLuceneMigrationTest}.
*/
public class SearchToLuceneVisitor extends SearchBaseVisitor<QueryNode> {
Expand Down
Loading

0 comments on commit 4fc088f

Please sign in to comment.