mirror of https://github.com/apache/lucene.git
Contribution of slick Swing models to enable on-the-fly searching of
tables and lists. Created by Jonathan Simon. git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@156591 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4ddfbcffc6
commit
9824226394
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<project name="swing" default="default">
|
||||||
|
|
||||||
|
<description>
|
||||||
|
Swing Models
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<import file="../common.xml"/>
|
||||||
|
|
||||||
|
<target name="list-demo" depends="compile">
|
||||||
|
<java classname="org.apache.lucene.swing.models.ListSearcherSimulator"
|
||||||
|
fork="yes" spawn="yes"
|
||||||
|
classpathref="test.classpath"
|
||||||
|
/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="table-demo" depends="compile">
|
||||||
|
<java classname="org.apache.lucene.swing.models.TableSearcherSimulator"
|
||||||
|
fork="yes" spawn="yes"
|
||||||
|
classpathref="test.classpath"
|
||||||
|
/>
|
||||||
|
</target>
|
||||||
|
</project>
|
|
@ -0,0 +1,97 @@
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Untitled Document</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> </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> </p>
|
||||||
|
<p> </p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,279 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.apache.lucene.store.RAMDirectory;
|
||||||
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
|
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||||
|
import org.apache.lucene.index.IndexWriter;
|
||||||
|
import org.apache.lucene.document.Document;
|
||||||
|
import org.apache.lucene.document.Field;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
|
import org.apache.lucene.search.Query;
|
||||||
|
import org.apache.lucene.search.Hits;
|
||||||
|
import org.apache.lucene.queryParser.MultiFieldQueryParser;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ListDataListener;
|
||||||
|
import javax.swing.event.ListDataEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See table searcher explanation.
|
||||||
|
*
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class ListSearcher extends AbstractListModel {
|
||||||
|
private ListModel listModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reference links between the decorated ListModel
|
||||||
|
* and this list model based on search criteria
|
||||||
|
*/
|
||||||
|
private ArrayList rowToModelIndex = new ArrayList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In memory lucene index
|
||||||
|
*/
|
||||||
|
private RAMDirectory directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached lucene analyzer
|
||||||
|
*/
|
||||||
|
private Analyzer analyzer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Links 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 ROW_NUMBER = "ROW_NUMBER";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since 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 static final String FIELD_NAME = "FIELD_NAME";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache 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 String searchString = null;
|
||||||
|
private ListDataListener listModelListener;
|
||||||
|
|
||||||
|
public ListSearcher(ListModel newModel) {
|
||||||
|
analyzer = new WhitespaceAnalyzer();
|
||||||
|
setListModel(newModel);
|
||||||
|
listModelListener = new ListModelHandler();
|
||||||
|
newModel.addListDataListener(listModelListener);
|
||||||
|
clearSearchingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setListModel(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());
|
||||||
|
}
|
||||||
|
|
||||||
|
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, true, true, true));
|
||||||
|
//add the string representation of the row to the index
|
||||||
|
document.add(new Field(FIELD_NAME, String.valueOf(listModel.getElementAt(row)).toLowerCase(), true, true, true));
|
||||||
|
writer.addDocument(document);
|
||||||
|
}
|
||||||
|
writer.optimize();
|
||||||
|
writer.close();
|
||||||
|
} catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a new search.
|
||||||
|
*
|
||||||
|
* @param searchString Any valid lucene search string
|
||||||
|
*/
|
||||||
|
public void search(String searchString){
|
||||||
|
|
||||||
|
//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.
|
||||||
|
Query query = MultiFieldQueryParser.parse(searchString, fields, analyzer);
|
||||||
|
//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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param hits The new result set to set this list to.
|
||||||
|
*/
|
||||||
|
private void resetSearchResults(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);
|
||||||
|
Field field = document.getField(ROW_NUMBER);
|
||||||
|
rowToModelIndex.add(new Integer(field.stringValue()));
|
||||||
|
}
|
||||||
|
} catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The current lucene analyzer
|
||||||
|
*/
|
||||||
|
public Analyzer getAnalyzer() {
|
||||||
|
return analyzer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param analyzer The new analyzer to use
|
||||||
|
*/
|
||||||
|
public void setAnalyzer(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 boolean isSearching() {
|
||||||
|
return searchString != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearSearchingState() {
|
||||||
|
searchString = null;
|
||||||
|
rowToModelIndex.clear();
|
||||||
|
for (int t=0; t<listModel.getSize(); t++){
|
||||||
|
rowToModelIndex.add(new Integer(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getModelRow(int row){
|
||||||
|
return ((Integer) rowToModelIndex.get(row)).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return (listModel == null) ? 0 : rowToModelIndex.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getElementAt(int index) {
|
||||||
|
return listModel.getElementAt(getModelRow(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ListModelHandler implements ListDataListener {
|
||||||
|
|
||||||
|
public void contentsChanged(ListDataEvent e) {
|
||||||
|
somethingChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void intervalAdded(ListDataEvent e) {
|
||||||
|
somethingChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void intervalRemoved(ListDataEvent e) {
|
||||||
|
somethingChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void somethingChanged(){
|
||||||
|
// If we're not searching, just pass the event along.
|
||||||
|
if (!isSearching()) {
|
||||||
|
clearSearchingState();
|
||||||
|
reindex();
|
||||||
|
fireContentsChanged(ListSearcher.this, 0, getSize());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something has happened to the data that may have invalidated the search.
|
||||||
|
reindex();
|
||||||
|
search(searchString);
|
||||||
|
fireContentsChanged(ListSearcher.this, 0, getSize());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,354 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.apache.lucene.store.RAMDirectory;
|
||||||
|
import org.apache.lucene.document.Document;
|
||||||
|
import org.apache.lucene.document.Field;
|
||||||
|
import org.apache.lucene.analysis.WhitespaceAnalyzer;
|
||||||
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
|
import org.apache.lucene.index.IndexWriter;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
|
import org.apache.lucene.search.Query;
|
||||||
|
import org.apache.lucene.search.Hits;
|
||||||
|
import org.apache.lucene.queryParser.MultiFieldQueryParser;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.TableModelEvent;
|
||||||
|
import javax.swing.event.TableModelListener;
|
||||||
|
import javax.swing.table.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a TableModel that encapsulates Lucene
|
||||||
|
* search logic within a TableModel implementation.
|
||||||
|
* It is implemented as a TableModel decorator,
|
||||||
|
* similar to the TableSorter demo from Sun that decorates
|
||||||
|
* a TableModel and provides sorting functionality. The benefit
|
||||||
|
* of this architecture is that you can decorate any TableModel
|
||||||
|
* implementation with this searching table model -- making it
|
||||||
|
* easy to add searching functionaliy to existing JTables -- or
|
||||||
|
* making new search capable table lucene.
|
||||||
|
*
|
||||||
|
* This decorator works by holding a reference to a decorated ot inner
|
||||||
|
* TableModel. All data is stored within that table model, not this
|
||||||
|
* table model. Rather, this table model simply manages links to
|
||||||
|
* data in the inner table model according to the search. All methods on
|
||||||
|
* TableSearcher forward to the inner table model with subtle filtering
|
||||||
|
* or alteration according to the search criteria.
|
||||||
|
*
|
||||||
|
* Using the table model:
|
||||||
|
*
|
||||||
|
* Pass the TableModel you want to decorate in at the constructor. When
|
||||||
|
* the TableModel initializes, it displays all search results. Call
|
||||||
|
* the search methid with any vaid Lucene search String and the data
|
||||||
|
* will be filtered by the search string. Users can always clear the search
|
||||||
|
* at any time by searching with an empty string. Additionally, you can
|
||||||
|
* add a button calling the clearSearch() method.
|
||||||
|
*
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class TableSearcher extends AbstractTableModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The inner table model we are decorating
|
||||||
|
*/
|
||||||
|
protected TableModel tableModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This listener is used to register this class as a listener to
|
||||||
|
* the decorated table model for update events
|
||||||
|
*/
|
||||||
|
private TableModelListener tableModelListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* these keeps reference to the decorated table model for data
|
||||||
|
* only rows that match the search criteria are linked
|
||||||
|
*/
|
||||||
|
private ArrayList rowToModelIndex = new ArrayList();
|
||||||
|
|
||||||
|
|
||||||
|
//Lucene stuff.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In memory lucene index
|
||||||
|
*/
|
||||||
|
private RAMDirectory directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cached lucene analyzer
|
||||||
|
*/
|
||||||
|
private Analyzer analyzer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Links between this table model and the decorated table model
|
||||||
|
* are maintained through links based on row number. This is a
|
||||||
|
* key constant to denote "row number" for indexing
|
||||||
|
*/
|
||||||
|
private static final String ROW_NUMBER = "ROW_NUMBER";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache 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 String searchString = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tableModel The table model to decorate
|
||||||
|
*/
|
||||||
|
public TableSearcher(TableModel tableModel) {
|
||||||
|
analyzer = new WhitespaceAnalyzer();
|
||||||
|
tableModelListener = new TableModelHandler();
|
||||||
|
setTableModel(tableModel);
|
||||||
|
tableModel.addTableModelListener(tableModelListener);
|
||||||
|
clearSearchingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return The inner table model this table model is decorating
|
||||||
|
*/
|
||||||
|
public TableModel getTableModel() {
|
||||||
|
return tableModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the table model used by this table model
|
||||||
|
* @param tableModel The new table model to decorate
|
||||||
|
*/
|
||||||
|
public void setTableModel(TableModel tableModel) {
|
||||||
|
|
||||||
|
//remove listeners if there...
|
||||||
|
if (this.tableModel != null) {
|
||||||
|
this.tableModel.removeTableModelListener(tableModelListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tableModel = tableModel;
|
||||||
|
if (this.tableModel != null) {
|
||||||
|
this.tableModel.addTableModelListener(tableModelListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
//recalculate the links between this table model and
|
||||||
|
//the inner table model since the decorated model just changed
|
||||||
|
reindex();
|
||||||
|
|
||||||
|
// let all listeners know the table has changed
|
||||||
|
fireTableStructureChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the search results and links to the decorated (inner) table
|
||||||
|
* model from this table model.
|
||||||
|
*/
|
||||||
|
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 < tableModel.getRowCount(); row++){
|
||||||
|
|
||||||
|
//for each row make a new document
|
||||||
|
Document document = new Document();
|
||||||
|
//add the row number of this row in the decorated table model
|
||||||
|
//this will allow us to retrive the results later
|
||||||
|
//and map this table model's row to a row in the decorated
|
||||||
|
//table model
|
||||||
|
document.add(new Field(ROW_NUMBER, "" + row, true, true, true));
|
||||||
|
//iterate through all columns
|
||||||
|
//index the value keyed by the column name
|
||||||
|
//NOTE: there could be a problem with using column names with spaces
|
||||||
|
for (int column=0; column < tableModel.getColumnCount(); column++){
|
||||||
|
String columnName = tableModel.getColumnName(column);
|
||||||
|
String columnValue = String.valueOf(tableModel.getValueAt(row, column)).toLowerCase();
|
||||||
|
document.add(new Field(columnName, columnValue, true, true, true));
|
||||||
|
}
|
||||||
|
writer.addDocument(document);
|
||||||
|
}
|
||||||
|
writer.optimize();
|
||||||
|
writer.close();
|
||||||
|
} catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The current lucene analyzer
|
||||||
|
*/
|
||||||
|
public Analyzer getAnalyzer() {
|
||||||
|
return analyzer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param analyzer The new analyzer to use
|
||||||
|
*/
|
||||||
|
public void setAnalyzer(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a new search.
|
||||||
|
*
|
||||||
|
* @param searchString Any valid lucene search string
|
||||||
|
*/
|
||||||
|
public void search(String searchString){
|
||||||
|
|
||||||
|
//if search string is null or empty, clear the search == search all
|
||||||
|
if (searchString == null || searchString.equals("")){
|
||||||
|
clearSearchingState();
|
||||||
|
fireTableDataChanged();
|
||||||
|
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 = new String[tableModel.getColumnCount()];
|
||||||
|
for (int t=0; t<tableModel.getColumnCount(); t++){
|
||||||
|
fields[t]=tableModel.getColumnName(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
//build a query based on the fields, searchString and cached analyzer
|
||||||
|
//NOTE: This is an area for improvement since the MultiFieldQueryParser
|
||||||
|
// has some weirdness.
|
||||||
|
Query query = MultiFieldQueryParser.parse(searchString, fields, analyzer);
|
||||||
|
//run the search
|
||||||
|
Hits hits = is.search(query);
|
||||||
|
//reset this table model with the new results
|
||||||
|
resetSearchResults(hits);
|
||||||
|
} catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
//notify all listeners that the table has been changed
|
||||||
|
fireTableStructureChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param hits The new result set to set this table to.
|
||||||
|
*/
|
||||||
|
private void resetSearchResults(Hits hits) {
|
||||||
|
try {
|
||||||
|
//clear our index mapping this table model rows to
|
||||||
|
//the decorated inner table 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);
|
||||||
|
Field field = document.getField(ROW_NUMBER);
|
||||||
|
rowToModelIndex.add(new Integer(field.stringValue()));
|
||||||
|
}
|
||||||
|
} catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getModelRow(int row){
|
||||||
|
return ((Integer) rowToModelIndex.get(row)).intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the currently active search
|
||||||
|
* Resets the complete dataset of the decorated
|
||||||
|
* table model.
|
||||||
|
*/
|
||||||
|
private void clearSearchingState(){
|
||||||
|
searchString = null;
|
||||||
|
rowToModelIndex.clear();
|
||||||
|
for (int t=0; t<tableModel.getRowCount(); t++){
|
||||||
|
rowToModelIndex.add(new Integer(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableModel interface methods
|
||||||
|
public int getRowCount() {
|
||||||
|
return (tableModel == null) ? 0 : rowToModelIndex.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColumnCount() {
|
||||||
|
return (tableModel == null) ? 0 : tableModel.getColumnCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnName(int column) {
|
||||||
|
return tableModel.getColumnName(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getColumnClass(int column) {
|
||||||
|
return tableModel.getColumnClass(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCellEditable(int row, int column) {
|
||||||
|
return tableModel.isCellEditable(getModelRow(row), column);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValueAt(int row, int column) {
|
||||||
|
return tableModel.getValueAt(getModelRow(row), column);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueAt(Object aValue, int row, int column) {
|
||||||
|
tableModel.setValueAt(aValue, getModelRow(row), column);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSearching() {
|
||||||
|
return searchString != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TableModelHandler implements TableModelListener {
|
||||||
|
public void tableChanged(TableModelEvent e) {
|
||||||
|
// If we're not searching, just pass the event along.
|
||||||
|
if (!isSearching()) {
|
||||||
|
clearSearchingState();
|
||||||
|
reindex();
|
||||||
|
fireTableChanged(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something has happened to the data that may have invalidated the search.
|
||||||
|
reindex();
|
||||||
|
search(searchString);
|
||||||
|
fireTableDataChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
Decorators for JTable TableModel and JList ListModel encapsulating Lucene indexing and searching functionality. .
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Jakarta Lucene Swing Component Models</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,55 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class BaseListModel extends AbstractListModel {
|
||||||
|
private ArrayList data = new ArrayList();
|
||||||
|
|
||||||
|
public BaseListModel(Iterator iterator) {
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
data.add(iterator.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getElementAt(int index) {
|
||||||
|
return data.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRow(Object toAdd) {
|
||||||
|
data.add(toAdd);
|
||||||
|
fireContentsChanged(this, 0, getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRow(Object toRemove) {
|
||||||
|
data.remove(toRemove);
|
||||||
|
fireContentsChanged(this, 0, getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class BaseTableModel extends AbstractTableModel {
|
||||||
|
private ArrayList columnNames = new ArrayList();
|
||||||
|
private ArrayList rows = new ArrayList();
|
||||||
|
|
||||||
|
public BaseTableModel(Iterator data) {
|
||||||
|
columnNames.add("Name");
|
||||||
|
columnNames.add("Type");
|
||||||
|
columnNames.add("Phone");
|
||||||
|
columnNames.add("Street");
|
||||||
|
columnNames.add("City");
|
||||||
|
columnNames.add("State");
|
||||||
|
columnNames.add("Zip");
|
||||||
|
|
||||||
|
while (data.hasNext()) {
|
||||||
|
Object nextRow = (Object) data.next();
|
||||||
|
rows.add(nextRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColumnCount() {
|
||||||
|
return columnNames.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRowCount() {
|
||||||
|
return rows.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRow(RestaurantInfo info){
|
||||||
|
rows.add(info);
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRow(RestaurantInfo info){
|
||||||
|
rows.remove(info);
|
||||||
|
fireTableDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCellEditable(int rowIndex, int columnIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getColumnClass(int columnIndex) {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||||
|
RestaurantInfo restaurantInfo = (RestaurantInfo) rows.get(rowIndex);
|
||||||
|
if (columnIndex == 0){ // name
|
||||||
|
return restaurantInfo.getName();
|
||||||
|
} else if (columnIndex == 1){ // category
|
||||||
|
return restaurantInfo.getType();
|
||||||
|
} else if (columnIndex == 2){ // phone
|
||||||
|
return restaurantInfo.getPhone();
|
||||||
|
} else if (columnIndex == 3){ // street
|
||||||
|
return restaurantInfo.getStreet();
|
||||||
|
} else if (columnIndex == 4){ // city
|
||||||
|
return restaurantInfo.getCity();
|
||||||
|
} else if (columnIndex == 5){ // state
|
||||||
|
return restaurantInfo.getState();
|
||||||
|
} else if (columnIndex == 6){ // zip
|
||||||
|
return restaurantInfo.getZip();
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
|
||||||
|
//no op
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColumnName(int columnIndex) {
|
||||||
|
return columnNames.get(columnIndex).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,205 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class DataStore {
|
||||||
|
|
||||||
|
private static final String ITALIAN_CATEGORY = "Italian";
|
||||||
|
private static final String CUBAN_CATEGORY = "Cuban";
|
||||||
|
private static final String STEAK_CATEGORY = "Steak";
|
||||||
|
private static int id = 0;
|
||||||
|
|
||||||
|
static Collection restaurants = new ArrayList();
|
||||||
|
static RestaurantInfo pinos = new RestaurantInfo();
|
||||||
|
static RestaurantInfo canolis = new RestaurantInfo();
|
||||||
|
static RestaurantInfo picadillo = new RestaurantInfo();
|
||||||
|
static RestaurantInfo versailles = new RestaurantInfo();
|
||||||
|
static RestaurantInfo laCaretta = new RestaurantInfo();
|
||||||
|
static RestaurantInfo laCaretta2 = new RestaurantInfo();
|
||||||
|
static RestaurantInfo laCaretta3 = new RestaurantInfo();
|
||||||
|
static RestaurantInfo ranchaLuna = new RestaurantInfo();
|
||||||
|
static RestaurantInfo leMerais = new RestaurantInfo();
|
||||||
|
static RestaurantInfo chris = new RestaurantInfo();
|
||||||
|
static RestaurantInfo outback = new RestaurantInfo();
|
||||||
|
static RestaurantInfo outback2 = new RestaurantInfo();
|
||||||
|
static RestaurantInfo outback3 = new RestaurantInfo();
|
||||||
|
static RestaurantInfo outback4 = new RestaurantInfo();
|
||||||
|
|
||||||
|
|
||||||
|
public static Iterator getRestaurants(){
|
||||||
|
return restaurants.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
pinos.setId(getNextId());
|
||||||
|
pinos.setType(ITALIAN_CATEGORY);
|
||||||
|
pinos.setName("Pino's");
|
||||||
|
pinos.setPhone("(305) 111-2222");
|
||||||
|
pinos.setStreet("12115 105th Street ");
|
||||||
|
pinos.setCity("Miami");
|
||||||
|
pinos.setState("FL");
|
||||||
|
pinos.setZip("33176");
|
||||||
|
restaurants.add(pinos);
|
||||||
|
|
||||||
|
canolis.setId(getNextId());
|
||||||
|
canolis.setType(ITALIAN_CATEGORY);
|
||||||
|
canolis.setName("Canoli's");
|
||||||
|
canolis.setPhone("(305) 234-5543");
|
||||||
|
canolis.setStreet("12123 85th Street ");
|
||||||
|
canolis.setCity("Miami");
|
||||||
|
canolis.setState("FL");
|
||||||
|
canolis.setZip("33176");
|
||||||
|
restaurants.add(canolis);
|
||||||
|
|
||||||
|
picadillo.setId(getNextId());
|
||||||
|
picadillo.setType(CUBAN_CATEGORY);
|
||||||
|
picadillo.setName("Picadillo");
|
||||||
|
picadillo.setPhone("(305) 746-7865");
|
||||||
|
picadillo.setStreet("109 12th Street ");
|
||||||
|
picadillo.setCity("Miami");
|
||||||
|
picadillo.setState("FL");
|
||||||
|
picadillo.setZip("33176");
|
||||||
|
restaurants.add(picadillo);
|
||||||
|
|
||||||
|
versailles.setId(getNextId());
|
||||||
|
versailles.setType(CUBAN_CATEGORY);
|
||||||
|
versailles.setName("Cafe Versailles");
|
||||||
|
versailles.setPhone("(305) 201-5438");
|
||||||
|
versailles.setStreet("312 8th Street ");
|
||||||
|
versailles.setCity("Miami");
|
||||||
|
versailles.setState("FL");
|
||||||
|
versailles.setZip("33176");
|
||||||
|
restaurants.add(versailles);
|
||||||
|
|
||||||
|
laCaretta.setId(getNextId());
|
||||||
|
laCaretta.setType(CUBAN_CATEGORY);
|
||||||
|
laCaretta.setName("La Carretta");
|
||||||
|
laCaretta.setPhone("(305) 342-9876");
|
||||||
|
laCaretta.setStreet("348 8th Street ");
|
||||||
|
laCaretta.setCity("Miami");
|
||||||
|
laCaretta.setState("FL");
|
||||||
|
laCaretta.setZip("33176");
|
||||||
|
restaurants.add(laCaretta);
|
||||||
|
|
||||||
|
laCaretta2.setId(getNextId());
|
||||||
|
laCaretta2.setType(CUBAN_CATEGORY);
|
||||||
|
laCaretta2.setName("La Carretta");
|
||||||
|
laCaretta2.setPhone("(305) 556-9876");
|
||||||
|
laCaretta2.setStreet("31224 23rd Street ");
|
||||||
|
laCaretta2.setCity("Miami");
|
||||||
|
laCaretta2.setState("FL");
|
||||||
|
laCaretta2.setZip("33176");
|
||||||
|
restaurants.add(laCaretta2);
|
||||||
|
|
||||||
|
laCaretta3.setId(getNextId());
|
||||||
|
laCaretta3.setType(CUBAN_CATEGORY);
|
||||||
|
laCaretta3.setName("La Carretta");
|
||||||
|
laCaretta3.setPhone("(305) 682-9876");
|
||||||
|
laCaretta3.setStreet("23543 107th Street ");
|
||||||
|
laCaretta3.setCity("Miami");
|
||||||
|
laCaretta3.setState("FL");
|
||||||
|
laCaretta3.setZip("33176");
|
||||||
|
restaurants.add(laCaretta3);
|
||||||
|
|
||||||
|
ranchaLuna.setId(getNextId());
|
||||||
|
ranchaLuna.setType(CUBAN_CATEGORY);
|
||||||
|
ranchaLuna.setName("Rancha Luna");
|
||||||
|
ranchaLuna.setPhone("(305) 777-4384");
|
||||||
|
ranchaLuna.setStreet("110 23rd Street ");
|
||||||
|
ranchaLuna.setCity("Miami");
|
||||||
|
ranchaLuna.setState("FL");
|
||||||
|
ranchaLuna.setZip("33176");
|
||||||
|
restaurants.add(ranchaLuna);
|
||||||
|
|
||||||
|
leMerais.setId(getNextId());
|
||||||
|
leMerais.setType(STEAK_CATEGORY);
|
||||||
|
leMerais.setName("Le Merais");
|
||||||
|
leMerais.setPhone("(212) 654-9187");
|
||||||
|
leMerais.setStreet("11 West 46th Street");
|
||||||
|
leMerais.setCity("New York");
|
||||||
|
leMerais.setState("NY");
|
||||||
|
leMerais.setZip("10018");
|
||||||
|
restaurants.add(leMerais);
|
||||||
|
|
||||||
|
chris.setId(getNextId());
|
||||||
|
chris.setType(STEAK_CATEGORY);
|
||||||
|
chris.setName("Ruth's Chris Seakhouse");
|
||||||
|
chris.setPhone("(305) 354-8885");
|
||||||
|
chris.setStreet("12365 203rd Street ");
|
||||||
|
chris.setCity("Miami");
|
||||||
|
chris.setState("FL");
|
||||||
|
chris.setZip("33176");
|
||||||
|
restaurants.add(chris);
|
||||||
|
|
||||||
|
outback.setId(getNextId());
|
||||||
|
outback.setType(STEAK_CATEGORY);
|
||||||
|
outback.setName("Outback");
|
||||||
|
outback.setPhone("(305) 244-7623");
|
||||||
|
outback.setStreet("348 136th Street ");
|
||||||
|
outback.setCity("Miami");
|
||||||
|
outback.setState("FL");
|
||||||
|
outback.setZip("33176");
|
||||||
|
restaurants.add(outback);
|
||||||
|
|
||||||
|
outback2.setId(getNextId());
|
||||||
|
outback2.setType(STEAK_CATEGORY);
|
||||||
|
outback2.setName("Outback");
|
||||||
|
outback2.setPhone("(305) 533-6522");
|
||||||
|
outback2.setStreet("21 207th Street ");
|
||||||
|
outback2.setCity("Miami");
|
||||||
|
outback2.setState("FL");
|
||||||
|
outback2.setZip("33176");
|
||||||
|
restaurants.add(outback2);
|
||||||
|
|
||||||
|
outback3.setId(getNextId());
|
||||||
|
outback3.setType(STEAK_CATEGORY);
|
||||||
|
outback3.setName("Outback");
|
||||||
|
outback3.setPhone("(305) 244-7623");
|
||||||
|
outback3.setStreet("10117 107th Street ");
|
||||||
|
outback3.setCity("Miami");
|
||||||
|
outback3.setState("FL");
|
||||||
|
outback3.setZip("33176");
|
||||||
|
restaurants.add(outback3);
|
||||||
|
|
||||||
|
outback4.setId(getNextId());
|
||||||
|
outback4.setType(STEAK_CATEGORY);
|
||||||
|
outback4.setName("Outback");
|
||||||
|
outback4.setPhone("(954) 221-3312");
|
||||||
|
outback4.setStreet("10 11th Street ");
|
||||||
|
outback4.setCity("Aventura");
|
||||||
|
outback4.setState("FL");
|
||||||
|
outback4.setZip("32154");
|
||||||
|
restaurants.add(outback4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getNextId(){
|
||||||
|
id++;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.DocumentListener;
|
||||||
|
import javax.swing.event.DocumentEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class ListSearcherSimulator {
|
||||||
|
|
||||||
|
public ListSearcherSimulator() {
|
||||||
|
JFrame frame = new JFrame();
|
||||||
|
frame.setBounds(200,200, 400,250);
|
||||||
|
|
||||||
|
JList list = new JList();
|
||||||
|
JScrollPane scrollPane = new JScrollPane(list);
|
||||||
|
|
||||||
|
final BaseListModel listModel = new BaseListModel(DataStore.getRestaurants());
|
||||||
|
final ListSearcher listSearcher = new ListSearcher(listModel);
|
||||||
|
|
||||||
|
list.setModel(listSearcher);
|
||||||
|
|
||||||
|
final JTextField searchField = new JTextField();
|
||||||
|
searchField.getDocument().addDocumentListener(
|
||||||
|
new DocumentListener(){
|
||||||
|
public void changedUpdate(DocumentEvent e) {
|
||||||
|
listSearcher.search(searchField.getText().trim().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
listSearcher.search(searchField.getText().trim().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
listSearcher.search(searchField.getText().trim().toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
frame.getContentPane().setLayout(new BorderLayout());
|
||||||
|
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JPanel searchPanel = new JPanel();
|
||||||
|
searchPanel.setLayout(new BorderLayout(10,10));
|
||||||
|
searchPanel.add(searchField, BorderLayout.CENTER);
|
||||||
|
searchPanel.add(new JLabel("Search: "), BorderLayout.WEST);
|
||||||
|
|
||||||
|
JPanel topPanel = new JPanel(new BorderLayout());
|
||||||
|
topPanel.add(searchPanel, BorderLayout.CENTER);
|
||||||
|
topPanel.add(new JPanel(), BorderLayout.EAST);
|
||||||
|
topPanel.add(new JPanel(), BorderLayout.WEST);
|
||||||
|
topPanel.add(new JPanel(), BorderLayout.NORTH);
|
||||||
|
topPanel.add(new JPanel(), BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
frame.getContentPane().add(topPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
frame.setTitle("Lucene powered table searching");
|
||||||
|
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
frame.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new ListSearcherSimulator();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class RestaurantInfo {
|
||||||
|
private int id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
private String phone;
|
||||||
|
private String street;
|
||||||
|
private String city;
|
||||||
|
private String state;
|
||||||
|
private String zip;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhone() {
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhone(String phone) {
|
||||||
|
this.phone = phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStreet() {
|
||||||
|
return street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreet(String street) {
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCity(String city) {
|
||||||
|
this.city = city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(String state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getZip() {
|
||||||
|
return zip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZip(String zip) {
|
||||||
|
this.zip = zip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " - " + getPhone();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class TableSearcherSimulator {
|
||||||
|
|
||||||
|
public TableSearcherSimulator() {
|
||||||
|
JFrame frame = new JFrame();
|
||||||
|
frame.setBounds(200,200, 400,250);
|
||||||
|
|
||||||
|
JTable table = new JTable();
|
||||||
|
final BaseTableModel tableModel = new BaseTableModel(DataStore.getRestaurants());
|
||||||
|
final TableSearcher searchTableModel = new TableSearcher(tableModel);
|
||||||
|
|
||||||
|
table.setModel(searchTableModel);
|
||||||
|
JScrollPane scrollPane = new JScrollPane(table);
|
||||||
|
|
||||||
|
final JTextField searchField = new JTextField();
|
||||||
|
JButton searchButton = new JButton("Go");
|
||||||
|
|
||||||
|
ActionListener searchListener = new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
searchTableModel.search(searchField.getText().trim().toLowerCase());
|
||||||
|
searchField.requestFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
searchButton.addActionListener(searchListener);
|
||||||
|
searchField.addActionListener(searchListener);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
frame.getContentPane().setLayout(new BorderLayout());
|
||||||
|
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JPanel searchPanel = new JPanel();
|
||||||
|
searchPanel.setLayout(new BorderLayout(10,10));
|
||||||
|
searchPanel.add(searchField, BorderLayout.CENTER);
|
||||||
|
searchPanel.add(searchButton, BorderLayout.EAST);
|
||||||
|
|
||||||
|
JPanel topPanel = new JPanel(new BorderLayout());
|
||||||
|
topPanel.add(searchPanel, BorderLayout.CENTER);
|
||||||
|
topPanel.add(new JPanel(), BorderLayout.EAST);
|
||||||
|
topPanel.add(new JPanel(), BorderLayout.WEST);
|
||||||
|
topPanel.add(new JPanel(), BorderLayout.NORTH);
|
||||||
|
topPanel.add(new JPanel(), BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
frame.getContentPane().add(topPanel, BorderLayout.NORTH);
|
||||||
|
|
||||||
|
frame.setTitle("Lucene powered table searching");
|
||||||
|
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
frame.show();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new TableSearcherSimulator();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
**/
|
||||||
|
public class TestBasicList extends TestCase {
|
||||||
|
private ListModel baseListModel;
|
||||||
|
private ListSearcher listSearcher;
|
||||||
|
private ArrayList list;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
list = new ArrayList();
|
||||||
|
list.add(DataStore.canolis);
|
||||||
|
list.add(DataStore.chris);
|
||||||
|
|
||||||
|
baseListModel = new BaseListModel(list.iterator());
|
||||||
|
listSearcher = new ListSearcher(baseListModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testRows(){
|
||||||
|
assertEquals(list.size(), listSearcher.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testValueAt(){
|
||||||
|
assertEquals(baseListModel.getElementAt(0), listSearcher.getElementAt(0));
|
||||||
|
assertNotSame(baseListModel.getElementAt(1), listSearcher.getElementAt(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import javax.swing.table.TableModel;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class TestBasicTable extends TestCase {
|
||||||
|
private TableModel baseTableModel;
|
||||||
|
private TableSearcher tableSearcher;
|
||||||
|
private ArrayList list;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
list = new ArrayList();
|
||||||
|
list.add(DataStore.canolis);
|
||||||
|
list.add(DataStore.chris);
|
||||||
|
|
||||||
|
baseTableModel = new BaseTableModel(list.iterator());
|
||||||
|
tableSearcher = new TableSearcher(baseTableModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testColumns(){
|
||||||
|
|
||||||
|
assertEquals(baseTableModel.getColumnCount(), tableSearcher.getColumnCount());
|
||||||
|
assertEquals(baseTableModel.getColumnName(0), tableSearcher.getColumnName(0));
|
||||||
|
assertNotSame(baseTableModel.getColumnName(0), tableSearcher.getColumnName(1));
|
||||||
|
assertEquals(baseTableModel.getColumnClass(0), tableSearcher.getColumnClass(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRows(){
|
||||||
|
assertEquals(list.size(), tableSearcher.getRowCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testValueAt(){
|
||||||
|
assertEquals(baseTableModel.getValueAt(0,0), tableSearcher.getValueAt(0,0));
|
||||||
|
assertEquals(baseTableModel.getValueAt(0,3), tableSearcher.getValueAt(0,3));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import javax.swing.table.TableModel;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class TestSearchingList extends TestCase {
|
||||||
|
private ListModel baseListModel;
|
||||||
|
private ListSearcher listSearcher;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
baseListModel = new BaseListModel(DataStore.getRestaurants());
|
||||||
|
listSearcher = new ListSearcher(baseListModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSearch(){
|
||||||
|
//make sure data is there
|
||||||
|
assertEquals(baseListModel.getSize(), listSearcher.getSize());
|
||||||
|
//search for pino's
|
||||||
|
listSearcher.search("pino's");
|
||||||
|
assertEquals(1, listSearcher.getSize());
|
||||||
|
//clear search and check that
|
||||||
|
listSearcher.search(null);
|
||||||
|
assertEquals(baseListModel.getSize(), listSearcher.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import javax.swing.table.TableModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class TestSearchingTable extends TestCase {
|
||||||
|
private TableModel baseTableModel;
|
||||||
|
private TableSearcher tableSearcher;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
baseTableModel = new BaseTableModel(DataStore.getRestaurants());
|
||||||
|
tableSearcher = new TableSearcher(baseTableModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSearch(){
|
||||||
|
//make sure data is there
|
||||||
|
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
|
||||||
|
//search for pino's
|
||||||
|
tableSearcher.search("pino's");
|
||||||
|
assertEquals(1, tableSearcher.getRowCount());
|
||||||
|
//clear search and check that
|
||||||
|
tableSearcher.search(null);
|
||||||
|
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import javax.swing.table.TableModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class TestUpdatingList extends TestCase {
|
||||||
|
private BaseListModel baseListModel;
|
||||||
|
private ListSearcher listSearcher;
|
||||||
|
|
||||||
|
RestaurantInfo infoToAdd1, infoToAdd2;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
baseListModel = new BaseListModel(DataStore.getRestaurants());
|
||||||
|
listSearcher = new ListSearcher(baseListModel);
|
||||||
|
|
||||||
|
infoToAdd1 = new RestaurantInfo();
|
||||||
|
infoToAdd1.setName("Pino's");
|
||||||
|
|
||||||
|
infoToAdd2 = new RestaurantInfo();
|
||||||
|
infoToAdd2.setName("Pino's");
|
||||||
|
infoToAdd2.setType("Italian");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddWithoutSearch(){
|
||||||
|
assertEquals(baseListModel.getSize(), listSearcher.getSize());
|
||||||
|
int count = listSearcher.getSize();
|
||||||
|
baseListModel.addRow(infoToAdd1);
|
||||||
|
count++;
|
||||||
|
assertEquals(count, listSearcher.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveWithoutSearch(){
|
||||||
|
assertEquals(baseListModel.getSize(), listSearcher.getSize());
|
||||||
|
baseListModel.addRow(infoToAdd1);
|
||||||
|
int count = listSearcher.getSize();
|
||||||
|
baseListModel.removeRow(infoToAdd1);
|
||||||
|
count--;
|
||||||
|
assertEquals(count, listSearcher.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddWithSearch(){
|
||||||
|
assertEquals(baseListModel.getSize(), listSearcher.getSize());
|
||||||
|
listSearcher.search("pino's");
|
||||||
|
int count = listSearcher.getSize();
|
||||||
|
baseListModel.addRow(infoToAdd2);
|
||||||
|
count++;
|
||||||
|
assertEquals(count, listSearcher.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveWithSearch(){
|
||||||
|
assertEquals(baseListModel.getSize(), listSearcher.getSize());
|
||||||
|
baseListModel.addRow(infoToAdd1);
|
||||||
|
listSearcher.search("pino's");
|
||||||
|
int count = listSearcher.getSize();
|
||||||
|
baseListModel.removeRow(infoToAdd1);
|
||||||
|
count--;
|
||||||
|
assertEquals(count, listSearcher.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
package org.apache.lucene.swing.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2005 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import javax.swing.table.TableModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jonathan Simon - jonathan_s_simon@yahoo.com
|
||||||
|
*/
|
||||||
|
public class TestUpdatingTable extends TestCase {
|
||||||
|
private BaseTableModel baseTableModel;
|
||||||
|
private TableSearcher tableSearcher;
|
||||||
|
|
||||||
|
RestaurantInfo infoToAdd1, infoToAdd2;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
baseTableModel = new BaseTableModel(DataStore.getRestaurants());
|
||||||
|
tableSearcher = new TableSearcher(baseTableModel);
|
||||||
|
|
||||||
|
infoToAdd1 = new RestaurantInfo();
|
||||||
|
infoToAdd1.setName("Pino's");
|
||||||
|
infoToAdd1.setType("Italian");
|
||||||
|
|
||||||
|
infoToAdd2 = new RestaurantInfo();
|
||||||
|
infoToAdd2.setName("Pino's");
|
||||||
|
infoToAdd2.setType("Italian");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddWithoutSearch(){
|
||||||
|
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
|
||||||
|
int count = tableSearcher.getRowCount();
|
||||||
|
baseTableModel.addRow(infoToAdd1);
|
||||||
|
count++;
|
||||||
|
assertEquals(count, tableSearcher.getRowCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveWithoutSearch(){
|
||||||
|
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
|
||||||
|
int count = tableSearcher.getRowCount();
|
||||||
|
baseTableModel.addRow(infoToAdd1);
|
||||||
|
baseTableModel.removeRow(infoToAdd1);
|
||||||
|
assertEquals(count, tableSearcher.getRowCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddWithSearch(){
|
||||||
|
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
|
||||||
|
tableSearcher.search("pino's");
|
||||||
|
int count = tableSearcher.getRowCount();
|
||||||
|
baseTableModel.addRow(infoToAdd2);
|
||||||
|
count++;
|
||||||
|
assertEquals(count, tableSearcher.getRowCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveWithSearch(){
|
||||||
|
assertEquals(baseTableModel.getRowCount(), tableSearcher.getRowCount());
|
||||||
|
baseTableModel.addRow(infoToAdd1);
|
||||||
|
tableSearcher.search("pino's");
|
||||||
|
int count = tableSearcher.getRowCount();
|
||||||
|
baseTableModel.removeRow(infoToAdd1);
|
||||||
|
count--;
|
||||||
|
assertEquals(count, tableSearcher.getRowCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue