/*
* Copyright 2011 Luke Usherwood.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.bettyluke.tracinstant.ui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/** One of a user's search term, in the format: <code>[-][field:][-]pattern</code> */
final class SearchTerm {
private static final Pattern EMPTY_STRING_PATTERN = Pattern.compile("^$");
public SearchTerm(String field, Pattern pattern, boolean exclude) {
this.field = field;
this.pattern = pattern;
this.exclude = exclude;
}
/** The optional field name; null to search all fields. */
public String field;
/** The search pattern */
public Pattern pattern;
/**
* If true, the Ticket will only be matched if the pattern is NOT found in the
* ticket's field(s)
*/
public boolean exclude;
@Override
public String toString() {
return "SearchTerm [field=" + field + ", pattern=" + pattern + ", exclude="
+ exclude + "]";
}
public static SearchTerm[] parseSearchString(String searchText) {
if (searchText.trim().isEmpty()) {
return TableRowFilterComputer.EMPTY_SEARCH_TERMS;
}
List<SearchTerm> terms = new ArrayList<>();
final String[] words = searchText.split("\\s");
try {
for (String word : words) {
SearchTerm term = parseTerm(word);
if (term != null) {
terms.add(term);
}
}
} catch (PatternSyntaxException ex) {
return TableRowFilterComputer.EMPTY_SEARCH_TERMS;
}
// Do what we can for filtering speed - apply a partial sorting
// to make terms with specific fields come first.
SearchTerm[] result = terms.toArray(new SearchTerm[0]);
Arrays.sort(result, (t1, t2) -> {
int len1 = t1.field == null ? 0 : t1.field.length();
int len2 = t2.field == null ? 0 : t2.field.length();
return len2 - len1;
});
return result;
}
/** @return a SearchTerm, or null if the search pattern would be empty. */
public static SearchTerm parseTerm(String word) {
boolean exclude = word.startsWith("-");
if (exclude) {
word = word.substring(1);
}
String field = null;
int colon = word.indexOf(':');
if (colon != -1) {
field = word.substring(0, colon);
word = word.substring(colon + 1);
}
if (word.startsWith("-")) {
exclude = true;
word = word.substring(1);
}
if (word.isEmpty()) {
if (field == null) {
return null;
} else {
return new SearchTerm(field, EMPTY_STRING_PATTERN, exclude);
}
}
Pattern regex = Pattern.compile(word, Pattern.CASE_INSENSITIVE);
return new SearchTerm(field, regex, exclude);
}
}