Refactored keyword filter logic from AbstractListFilter to a newly

introduced KeywordMatcher
This commit is contained in:
Steffen Schaefer committed 2016-10-24 11:58:03 +02:00
1 parent 5428f541a2
commit 2e7d48c687
2 files changed
+67 -42

No files matched your search

@@ -3,7 +3,7 @@ package com.sap.sse.common.filter;
import java.util.ArrayList;
import java.util.List;
import com.sap.sse.common.Util;
import com.sap.sse.common.filter.impl.KeywordMatcher;
/**
* Matches a list of keywords in a list of strings. A match is recognized if each of the keywords is contained in at least
@@ -17,14 +17,16 @@ import com.sap.sse.common.Util;
* @param <T>
*/
public abstract class AbstractListFilter<T> {
private final KeywordMatcher<T> matcher = new KeywordMatcher<T>() {
@Override
public Iterable<String> getStrings(T t) {
return AbstractListFilter.this.getStrings(t);
}
};
/**
* Subclasses must implement this to extract the strings from an object of type <code>T</code> based on which the
* filter performs its filtering
*
* @param t
* the object from which to extract the searchable strings
* @return the searchable strings
* @see KeywordMatcher#getStrings(Object)
*/
public abstract Iterable<String> getStrings(T t);
@@ -34,46 +36,13 @@ public abstract class AbstractListFilter<T> {
public Iterable<T> applyFilter(Iterable<String> keywords, Iterable<T> all) {
List<T> sortedList = new ArrayList<T>();
if (all != null) {
if (keywords != null && !Util.isEmpty(keywords)) {
for (T t : all) {
if (containsText(t, keywords)) {
sortedList.add(t);
}
}
} else {
for (T t : all) {
for (T t : all) {
if (matcher.matches(keywords, t)) {
sortedList.add(t);
}
}
}
return sortedList;
}
/**
* Returns <code>true</code> if for each of the <code>keywords</code> any of the {@link #getStrings(Object) values
* to check} contains that keyword.
*
* @param keywords
* the words to filter on
* @return <code>true</code> if the <code>valuesToCheck</code> contains all <code>wordsToFilter</code>,
* <code>false</code> if not
*/
private boolean containsText(T obj, Iterable<String> keywords) {
boolean failed = false;
for (String word : keywords) {
String textAsUppercase = word.toUpperCase().trim();
failed = true;
for (String s : getStrings(obj)) {
if (s != null && s.toUpperCase().contains(textAsUppercase)) {
failed = false;
break;
}
}
if (failed) {
return false;
}
}
return true;
}
}
@@ -0,0 +1,56 @@
package com.sap.sse.common.filter.impl;
import com.sap.sse.common.Util;
/**
* Matches domain objects with a set of keywords. A match is recognized if each of the keywords is contained in at
* least one of the {@link #getStrings(Object) strings}. The typical use for this class is building a disjuctive
* ("AND"-like) keyword matcher where {@link #getStrings(Object)} provides one or more strings extracted from the
* searchable object and its context.
*
* @param <T>
*/
public abstract class KeywordMatcher<T> {
/**
* Subclasses must implement this to extract the strings from an object of type <code>T</code> based on which the
* filter performs its filtering
*
* @param t
* the object from which to extract the searchable strings
* @return the searchable strings
*/
public abstract Iterable<String> getStrings(T t);
public boolean matches(Iterable<String> keywords, T t) {
boolean matchesOrNoKeywords = keywords == null || Util.isEmpty(keywords) || containsText(t, keywords);
return matchesOrNoKeywords;
}
/**
* Returns <code>true</code> if for each of the <code>keywords</code> any of the {@link #getStrings(Object) values
* to check} contains that keyword.
*
* @param keywords
* the words to filter on
* @return <code>true</code> if the <code>valuesToCheck</code> contains all <code>wordsToFilter</code>,
* <code>false</code> if not
*/
private boolean containsText(T obj, Iterable<String> keywords) {
boolean failed = false;
for (String word : keywords) {
String textAsUppercase = word.toUpperCase().trim();
failed = true;
for (String s : getStrings(obj)) {
if (s != null && s.toUpperCase().contains(textAsUppercase)) {
failed = false;
break;
}
}
if (failed) {
return false;
}
}
return true;
}
}