ca.odell.glazedlists.impl.filter.SearchTerm Maven / Gradle / Ivy
/* Glazed Lists (c) 2003-2006 */
/* http://publicobject.com/glazedlists/ publicobject.com,*/
/* O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.impl.filter;
import ca.odell.glazedlists.impl.GlazedListsImpl;
import ca.odell.glazedlists.matchers.SearchEngineTextMatcherEditor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* A SearchTerm object stores metadata around a single piece of text to be
* located. Search engines like Google capture more information than the simple
* search text to be located. This object tracks three other pieces of metadata
* in addition to the text to be located:
*
*
* - {@link #isNegated()} returns true if the search term should
* NOT appear within the target text
*
*
- {@link #isRequired()} returns true if the search term MUST be
* used and cannot be discarded for any reason. (sometimes search engines
* discard frivolous search terms like "and", "of", and "the".
*
*
- {@link #getField()} controls the TextFilterator that produces the
* values to be searched when locating this SearchTerm. Specifically, a
*
null
Field indicates the TextFilterator of the
* {@link TextMatcher} will be used to produce values to be searched.
* A non-null Field will be used to obtain the TextFilterator that
* produces the values to be searched.
*
*
* @author James Lemieux
*/
public final class SearchTerm implements Serializable {
// the text to be located
private final String text;
// true if this search term should NOT be found in the target text
private final boolean negated;
// true if this search term should be included absolutely
private final boolean required;
// When field is non-null, it contains the TextFilterator to use to extract
// the values this SearchTerm should consider when matching a given object.
// A null value indicates the values extracted by the TextMatcher are to be
// used.
private final SearchEngineTextMatcherEditor.Field field;
/**
* A recyclable list of filter strings extracted by the TextFilterator of
* the {@link #field}.
*/
private final List fieldFilterStrings = new ArrayList();
/**
* Construct a new SearchTerm
with the given text
* that is neither negated nor required.
*/
public SearchTerm(String text) {
this(text, false, false, null);
}
/**
* Construct a new SearchTerm
with the given text
* that is negated and required according to the given booleans.
*/
public SearchTerm(String text, boolean negated, boolean required, SearchEngineTextMatcherEditor.Field field) {
if (text == null)
throw new IllegalArgumentException("text may not be null");
this.text = text;
this.negated = negated;
this.required = required;
this.field = field;
}
/**
* Returns the text to be located within a target text.
*/
public String getText() {
return text;
}
/**
* Returns true if the text must NOT be located within a target
* text; false if the text MUST be located within a target text.
*/
public boolean isNegated() {
return negated;
}
/**
* Returns true
if this SearchTerm
must be
* included within a search and cannot be discarded for any reason. For
* example, even if it contains typically frivolous search text such as
* "the", "and" or "of".
*/
public boolean isRequired() {
return required;
}
/**
* Returns the object that provides a custom TextFilterator to use when
* locating this SearchTerm within an object. When this method returns
* null
it indicates that the TextFilterator of the
* TextMatcher should be used to extract values from a target object.
*/
public SearchEngineTextMatcherEditor.Field getField() {
return field;
}
List getFieldFilterStrings() {
return fieldFilterStrings;
}
/**
* Return a new SearchTerm
with identical information save for
* the given text
.
*/
public SearchTerm newSearchTerm(String text) {
return new SearchTerm(text, isNegated(), isRequired(), getField());
}
/**
* Returns true if the given term
is
* guaranteed to match fewer text strings than this
* SearchTerm; false otherwise. This method is the mirror opposite
* of {@link #isRelaxation(SearchTerm)}.
*
* @param term the SearchTerm to be tested for constrainment
* @return true if the given term
is
* guaranteed to match fewer text strings than this
* SearchTerm; false otherwise
*
* @see #isRelaxation(SearchTerm)
*/
boolean isConstrainment(SearchTerm term) {
// if they're negated state doesn't match then we cannot really compare these search terms
if (isNegated() != term.isNegated()) return false;
// if they have a field that doesn't match then we cannot really compare these search terms
if (!GlazedListsImpl.equal(getField(), term.getField())) return false;
// if the text is equal then no strict constrainment exists
if (getText().equals(term.getText())) return false;
// otherwise constrainment is determined by whether we can locate one's text within the other
return isNegated() ? term.getText().indexOf(getText()) != -1 : getText().indexOf(term.getText()) != -1;
}
/**
* Returns true if the given term
is
* guaranteed to match more text strings than this
* SearchTerm; false otherwise. This method is the mirror opposite
* of {@link #isConstrainment(SearchTerm)}.
*
* @param term the SearchTerm to be tested for constrainment
* @return true if the given term
is
* guaranteed to match more text strings than this
* SearchTerm; false otherwise
*
* @see #isRelaxation(SearchTerm)
*/
boolean isRelaxation(SearchTerm term) {
return term.isConstrainment(this);
}
/** @inheritDoc */
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SearchTerm that = (SearchTerm) o;
if (negated != that.negated) return false;
if (required != that.required) return false;
if (field != null ? !field.equals(that.field) : that.field != null) return false;
if (!text.equals(that.text)) return false;
return true;
}
/** @inheritDoc */
@Override
public int hashCode() {
int result;
result = text.hashCode();
result = 31 * result + (negated ? 1 : 0);
result = 31 * result + (required ? 1 : 0);
result = 31 * result + (field != null ? field.hashCode() : 0);
return result;
}
}