Fields Summary |
---|
private ListModel | listModel |
private ArrayList | rowToModelIndexThe reference links between the decorated ListModel
and this list model based on search criteria |
private RAMDirectory | directoryIn memory lucene index |
private Analyzer | analyzerCached lucene analyzer |
private static final String | ROW_NUMBERLinks between this list model and the decorated list model
are maintained through links based on row number. This is a
key constant to denote "row number" for indexing |
private static final String | FIELD_NAMESince we only have one field, unlike lists with multiple
fields -- we are just using a constant to denote field name.
This is most likely unnecessary and should be removed at
a later date |
private String | searchStringCache the current search String. Also used internally to
key whether there is an active search running or not. i.e. if
searchString is null, there is no active search. |
private ListDataListener | listModelListener |
Methods Summary |
---|
private void | clearSearchingState()
searchString = null;
rowToModelIndex.clear();
for (int t=0; t<listModel.getSize(); t++){
rowToModelIndex.add(new Integer(t));
}
|
public org.apache.lucene.analysis.Analyzer | getAnalyzer()
return analyzer;
|
public java.lang.Object | getElementAt(int index)
return listModel.getElementAt(getModelRow(index));
|
private int | getModelRow(int row)
return ((Integer) rowToModelIndex.get(row)).intValue();
|
public int | getSize()
return (listModel == null) ? 0 : rowToModelIndex.size();
|
private boolean | isSearching()
return searchString != null;
|
private void | reindex()
try {
// recreate the RAMDirectory
directory = new RAMDirectory();
IndexWriter writer = new IndexWriter(directory, analyzer, true);
// iterate through all rows
for (int row=0; row < listModel.getSize(); row++){
//for each row make a new document
Document document = new Document();
//add the row number of this row in the decorated list model
//this will allow us to retrive the results later
//and map this list model's row to a row in the decorated
//list model
document.add(new Field(ROW_NUMBER, "" + row, Field.Store.YES, Field.Index.TOKENIZED));
//add the string representation of the row to the index
document.add(new Field(FIELD_NAME, String.valueOf(listModel.getElementAt(row)).toLowerCase(), Field.Store.YES, Field.Index.TOKENIZED));
writer.addDocument(document);
}
writer.optimize();
writer.close();
} catch (Exception e){
e.printStackTrace();
}
|
private void | resetSearchResults(org.apache.lucene.search.Hits hits)
try {
//clear our index mapping this list model rows to
//the decorated inner list model
rowToModelIndex.clear();
//iterate through the hits
//get the row number stored at the index
//that number is the row number of the decorated
//tabble model row that we are mapping to
for (int t=0; t<hits.length(); t++){
Document document = hits.doc(t);
Fieldable field = document.getField(ROW_NUMBER);
rowToModelIndex.add(new Integer(field.stringValue()));
}
} catch (Exception e){
e.printStackTrace();
}
|
public void | search(java.lang.String searchString)Run a new search.
//if search string is null or empty, clear the search == search all
if (searchString == null || searchString.equals("")){
clearSearchingState();
fireContentsChanged(this, 0, getSize());
return;
}
try {
//cache search String
this.searchString = searchString;
//make a new index searcher with the in memory (RAM) index.
IndexSearcher is = new IndexSearcher(directory);
//make an array of fields - one for each column
String[] fields = {FIELD_NAME};
//build a query based on the fields, searchString and cached analyzer
//NOTE: This is an area for improvement since the MultiFieldQueryParser
// has some weirdness.
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, analyzer);
Query query =parser.parse(searchString);
//run the search
Hits hits = is.search(query);
//reset this list model with the new results
resetSearchResults(hits);
} catch (Exception e){
e.printStackTrace();
}
//notify all listeners that the list has been changed
fireContentsChanged(this, 0, getSize());
|
public void | setAnalyzer(org.apache.lucene.analysis.Analyzer analyzer)
this.analyzer = analyzer;
//reindex from the model with the new analyzer
reindex();
//rerun the search if there is an active search
if (isSearching()){
search(searchString);
}
|
private void | setListModel(javax.swing.ListModel newModel)
//remove listeners if there...
if (newModel != null) {
newModel.removeListDataListener(listModelListener);
}
listModel = newModel;
if (listModel != null) {
listModel.addListDataListener(listModelListener);
}
//recalculate the links between this list model and
//the inner list model since the decorated model just changed
reindex();
// let all listeners know the list has changed
fireContentsChanged(this, 0, getSize());
|