package org.jabref.logic.search.rules.describer;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.search.rules.GrammarBasedSearchRule;
import org.jabref.model.strings.StringUtil;
import org.jabref.search.SearchBaseVisitor;
import org.jabref.search.SearchParser;
import org.antlr.v4.runtime.tree.ParseTree;
public class GrammarBasedSearchRuleDescriber implements SearchDescriber {
private final boolean caseSensitive;
private final boolean regExp;
private final ParseTree parseTree;
public GrammarBasedSearchRuleDescriber(boolean caseSensitive, boolean regExp, ParseTree parseTree) {
this.caseSensitive = caseSensitive;
this.regExp = regExp;
this.parseTree = Objects.requireNonNull(parseTree);
}
@Override
public String getDescription() {
StringBuilder stringBuilder = new StringBuilder();
// describe advanced search expression
stringBuilder.append(Localization.lang("This search contains entries in which")).append(' ')
.append(new SearchBaseVisitor<String>() {
@Override
public String visitStart(SearchParser.StartContext context) {
return visit(context.expression());
}
@Override
public String visitUnaryExpression(SearchParser.UnaryExpressionContext context) {
return String.format("%s %s", Localization.lang("not"), visit(context.expression()));
}
@Override
public String visitParenExpression(SearchParser.ParenExpressionContext context) {
return String.format("%s", context.expression());
}
@Override
public String visitBinaryExpression(SearchParser.BinaryExpressionContext context) {
if ("AND".equalsIgnoreCase(context.operator.getText())) {
return String.format("(%s %s %s)", visit(context.left), Localization.lang("and"), visit(context.right));
} else {
return String.format("(%s %s %s)", visit(context.left), Localization.lang("or"), visit(context.right));
}
}
@Override
public String visitComparison(SearchParser.ComparisonContext context) {
final Optional<SearchParser.NameContext> fieldDescriptor = Optional.ofNullable(context.left);
final String value = StringUtil.unquote(context.right.getText(), '"');
if (!fieldDescriptor.isPresent()) {
return new ContainsAndRegexBasedSearchRuleDescriber(caseSensitive, regExp, value).getDescription();
}
final String field = StringUtil.unquote(fieldDescriptor.get().getText(), '"');
final GrammarBasedSearchRule.ComparisonOperator operator = GrammarBasedSearchRule.ComparisonOperator.build(context.operator.getText());
final boolean regExpFieldSpec = !Pattern.matches("\\w+", field);
final String termQuoted = StringUtil.quoteForHTML(value);
final String fieldSpecQuoted = regExpFieldSpec ? Localization.lang(
"any field that matches the regular expression <b>%0</b>",
StringUtil.quoteForHTML(field)) : Localization.lang("the field <b>%0</b>",
StringUtil.quoteForHTML(field));
if (operator == GrammarBasedSearchRule.ComparisonOperator.CONTAINS) {
if (regExp) {
return Localization.lang("%0 contains the regular expression <b>%1</b>", fieldSpecQuoted,
termQuoted);
}
return Localization.lang("%0 contains the term <b>%1</b>", fieldSpecQuoted, termQuoted);
} else if (operator == GrammarBasedSearchRule.ComparisonOperator.EXACT) {
if (regExp) {
return Localization.lang("%0 matches the regular expression <b>%1</b>",
fieldSpecQuoted, termQuoted);
}
return Localization.lang("%0 matches the term <b>%1</b>",
fieldSpecQuoted,
termQuoted);
} else if (operator == GrammarBasedSearchRule.ComparisonOperator.DOES_NOT_CONTAIN) {
if (regExp) {
return Localization.lang("%0 doesn't contain the regular expression <b>%1</b>",
fieldSpecQuoted, termQuoted);
}
return Localization.lang("%0 doesn't contain the term <b>%1</b>", fieldSpecQuoted,
termQuoted);
} else {
throw new IllegalStateException("CANNOT HAPPEN!");
}
}
}.visit(parseTree));
stringBuilder.append(". ");
stringBuilder.append(caseSensitive ? Localization
.lang("The search is case sensitive.") :
Localization.lang("The search is case insensitive."));
return stringBuilder.toString();
}
}