package prefuse.data.search;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import prefuse.data.Tuple;
import prefuse.data.tuple.DefaultTupleSet;
import prefuse.data.tuple.TupleSet;
import prefuse.util.StringLib;
/**
* SearchTupleSet implementation that treats the query as a regular expression
* to match against all indexed Tuple data fields.
* The regular expression engine provided by the
* standard Java libraries
* ({@link java.util.regex.Pattern java.util.regex.Pattern}) is used; please
* refer to the documentation for that class for more about the regular
* expression syntax.
*
* @author <a href="http://jheer.org">jeffrey heer</a>
* @see prefuse.data.query.SearchQueryBinding
*/
public class RegexSearchTupleSet extends SearchTupleSet {
private String m_query = "";
private boolean m_caseSensitive;
private LinkedHashMap m_source = new LinkedHashMap();
/**
* Create a new, case-insensitive regular expression search tuple set.
*/
public RegexSearchTupleSet() {
this(false);
}
/**
* Create a new regular expression search tuple set.
* @param caseSensitive true to make the indexing case sensitive, false
* otherwise.
*/
public RegexSearchTupleSet(boolean caseSensitive) {
m_caseSensitive = caseSensitive;
}
/**
* @see prefuse.data.search.SearchTupleSet#getQuery()
*/
public String getQuery() {
return m_query;
}
/**
* @see prefuse.data.search.SearchTupleSet#search(java.lang.String)
*/
public void search(String query) {
if ( query == null )
query = "";
if ( !m_caseSensitive )
query = query.toLowerCase();
if ( query.equals(m_query) )
return;
Pattern pattern = null;
try {
pattern = Pattern.compile(query);
} catch ( Exception e ) {
Logger logger = Logger.getLogger(this.getClass().getName());
logger.warning("Pattern compile failed."
+ "\n" + StringLib.getStackTrace(e));
return;
}
Tuple[] rem = clearInternal();
m_query = query;
Iterator fields = m_source.keySet().iterator();
while ( fields.hasNext() ) {
String field = (String)fields.next();
TupleSet ts = (TupleSet)m_source.get(field);
Iterator tuples = ts.tuples();
while ( tuples.hasNext() ) {
Tuple t = (Tuple)tuples.next();
String text = t.getString(field);
if ( !m_caseSensitive )
text = text.toLowerCase();
if ( pattern.matcher(text).matches() )
addInternal(t);
}
}
Tuple[] add = getTupleCount() > 0 ? toArray() : null;
fireTupleEvent(add, rem);
}
/**
* @see prefuse.data.search.SearchTupleSet#index(prefuse.data.Tuple, java.lang.String)
*/
public void index(Tuple t, String field) {
TupleSet ts = (TupleSet)m_source.get(field);
if ( ts == null ) {
ts = new DefaultTupleSet();
m_source.put(field, ts);
}
ts.addTuple(t);
}
/**
* @see prefuse.data.search.SearchTupleSet#unindex(prefuse.data.Tuple, java.lang.String)
*/
public void unindex(Tuple t, String field) {
TupleSet ts = (TupleSet)m_source.get(field);
if ( ts != null ) {
ts.removeTuple(t);
}
}
/**
* Returns true, as unidexing is supported by this class.
* @see prefuse.data.search.SearchTupleSet#isUnindexSupported()
*/
public boolean isUnindexSupported() {
return true;
}
/**
* Removes all search hits and clears out the index.
* @see prefuse.data.tuple.TupleSet#clear()
*/
public void clear() {
m_source.clear();
super.clear();
}
} // end of class RegexSearchTupleSet