blob: 49389012f349865ecb71df6879bca6c960e91353 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Lucene Powered Swing Data Models</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<h1><strong> Lucene Powered Swing Data Models </strong></h1>
<p><strong>by Jonathan Simon </strong></p>
<p>&nbsp;</p>
<p><strong>What it is.</strong></p>
<p>This package contains classes that help you easily integrate Lucene based searching
into your Swing components. Currently there are classes to index and search
JTables and JLists. This is done using model decorators rather than custom models
to make it easier to search current models as well as new ones. </p>
<p><em>These models do not actually contain any data</em>. Rather, the ListModel
decorator (ListSearcher) and the TableModel decorator (TableSearcher) take a
model in the constructor and delegate all calls to it (after a little alteration,
but we'll get to that). That said, these are not full fledged models themselves.
You still have to have another model to decorate with the searching models.
If you are adding searching to a pre-existing model, you can use your pre-existing
model directly. Otherwise, you can implement a model from scratch or use a pre-existing
one to get started. </p>
<p><strong>What it isn't. </strong></p>
<p>A complete component: These are just models. They are not complete components
with search fields and buttons laid out like a searchable interface. You still
have to build that since the UI changes drastically between applciations.</p>
<p>A complete model: There are just model decorators. You can't just set the model
of a JList or JTable to one of these models, and you can't add data directly
to these models. </p>
<p>A front end for a lucene index: In other words, you can't use these classes
to point a JTable directly to a Lucene index. Although that's interesting in
its own right, this is not that. </p>
<p><strong>Usage: </strong></p>
<p>Coding to both models nearly identical. They both take the model to decorate
at construction time. Here is the code from the demo to decorate a JTable model
with the TableSearcher and set it as the table model. </p>
<pre><code>//make a new JTable
JTable table = new JTable();
//make my base model, the model with the data
BaseTableModel tableModel = new BaseTableModel(DataStore.getRestaurants());
//decorate the tableModel with the TableSearcher
TableSearcher searchTableModel = new TableSearcher(tableModel);
//set the TableModel in the table to the TableSearcher
table.setModel(searchTableModel);
</code></pre>
<p>Initially, you won't notice a difference. This is because there is no active
search which displays all data from the underlying model. You search by calling
the <code>search</code>() method passing a search string. This filters the data
set down without changing the underlying data model -- one of the main reasons
for decorating in the first place. Any valid Lucene search string should work
(see notes for more info on this). You'll probaby have some code somewhere like
this in your app to connect a text field and search button to the model. </p>
<pre><code>//create components
final JTextField searchField = new JTextField();
JButton searchButton = new JButton("Go");
//make an action listener
ActionListener searchListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
searchTableModel.search(searchField.getText().trim().toLowerCase());
}
};
//register listeners
searchButton.addActionListener(searchListener);
searchField.addActionListener(searchListener);</code></pre>
<p>You also might want to have a clear search button, working the same way. But
to keep things simple, if you search will a <code>null </code>String or an empty
String, the search clears and you will once again see all of your data. </p>
<p><strong>Demo notes:</strong> </p>
<p>The list demo does real time searching. In other words, as you type, searches
run and the result set updates. The table demo has a search button, and only
searches when the button is clicked. They both work, I just implemented them
this way to show the different UI metaphors and that they both work.</p>
<p><strong>Implementation notes: </strong></p>
<p>This code started as a proof of concept so it's not a <em>fully</em> featured
model. Don't get me wrong, it <em>fully</em> works, but it could use some improvement
that it will hopefully get over time. I just wanted to get it out there and
get people using it. I'm also trying to keep everything as simple as possible.
Here are some of the issues. </p>
<ul>
<li>You can't change the model after the Searcher is constructed. </li>
<li>The search model decorators <em>do</em> update when the decorated model
is updated, but not in a very efficient way. The whole search model is reindexed
when anything changes. This is a definite scaling issue. </li>
<li>The indexing and searching logic needs to be generally more configurable
to allow custom tailoring of searched and indexing. </li>
<li>The TableSearcher uses column names to index column values. This could be
an issue with multiple word column names. </li>
<li>The ListSearcher uses MultiFieldQueryParser even though its not really indexing
multiple fields. </li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>
</html>