Added support for looking up entries by artist/title/song.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@590 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
//
|
||||
// $Id: BrowsePanel.java,v 1.1 2001/07/12 23:06:55 mdb Exp $
|
||||
// $Id: BrowsePanel.java,v 1.2 2002/02/22 07:06:33 mdb Exp $
|
||||
|
||||
package robodj.chooser;
|
||||
|
||||
// import java.awt.*;
|
||||
// import java.awt.event.ActionEvent;
|
||||
// import java.awt.event.ActionListener;
|
||||
import javax.swing.*;
|
||||
|
||||
// import com.samskivert.swing.*;
|
||||
import robodj.repository.*;
|
||||
|
||||
public class BrowsePanel extends JTabbedPane
|
||||
@@ -20,13 +16,13 @@ public class BrowsePanel extends JTabbedPane
|
||||
|
||||
// create a tab for each category
|
||||
for (int i = 0; i < cats.length; i++) {
|
||||
elist = new EntryList(cats[i].categoryid);
|
||||
elist = new CategoryEntryList(cats[i].categoryid);
|
||||
String tip = "Browse entries in '" + cats[i].name + "' category.";
|
||||
addTab(cats[i].name, null, elist, tip);
|
||||
}
|
||||
|
||||
// and add one for uncategorized entries
|
||||
elist = new EntryList(-1);
|
||||
elist = new CategoryEntryList(-1);
|
||||
addTab("Uncategorized", null, elist,
|
||||
"Browse uncategorized entries.");
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// $Id: CategoryEntryList.java,v 1.1 2002/02/22 07:06:33 mdb Exp $
|
||||
|
||||
package robodj.chooser;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
import robodj.repository.Entry;
|
||||
|
||||
public class CategoryEntryList extends EntryList
|
||||
{
|
||||
/**
|
||||
* Constructs an entry list for entries in a particular category.
|
||||
*/
|
||||
public CategoryEntryList (int categoryId)
|
||||
{
|
||||
_categoryId = categoryId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads in the entries for this category.
|
||||
*/
|
||||
public Entry[] readEntries ()
|
||||
throws PersistenceException
|
||||
{
|
||||
return Chooser.model.getEntries(_categoryId);
|
||||
}
|
||||
|
||||
protected String getEmptyString ()
|
||||
{
|
||||
return "No entries in this category.";
|
||||
}
|
||||
|
||||
/** The unique identifier of the category we are displaying. */
|
||||
protected int _categoryId;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: ChooserFrame.java,v 1.5 2001/07/13 00:11:05 mdb Exp $
|
||||
// $Id: ChooserFrame.java,v 1.6 2002/02/22 07:06:33 mdb Exp $
|
||||
|
||||
package robodj.chooser;
|
||||
|
||||
@@ -40,6 +40,10 @@ public class ChooserFrame
|
||||
BrowsePanel bpanel = new BrowsePanel();
|
||||
tip = "Browse and select tunes to play.";
|
||||
tpane.addTab("Browse", null, bpanel, tip);
|
||||
|
||||
SearchPanel spanel = new SearchPanel();
|
||||
tip = "Search titles and artists.";
|
||||
tpane.addTab("Search", null, spanel, tip);
|
||||
top.add(tpane);
|
||||
|
||||
// the bottom is the control bar
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: EntryList.java,v 1.9 2001/10/12 18:21:27 mdb Exp $
|
||||
// $Id: EntryList.java,v 1.10 2002/02/22 07:06:33 mdb Exp $
|
||||
|
||||
package robodj.chooser;
|
||||
|
||||
@@ -17,11 +17,10 @@ import com.samskivert.swing.util.*;
|
||||
import robodj.Log;
|
||||
import robodj.repository.*;
|
||||
|
||||
public class EntryList
|
||||
extends JPanel
|
||||
public abstract class EntryList extends JPanel
|
||||
implements TaskObserver, ActionListener, AncestorListener
|
||||
{
|
||||
public EntryList (int categoryid)
|
||||
public EntryList ()
|
||||
{
|
||||
GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH);
|
||||
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||
@@ -48,10 +47,6 @@ public class EntryList
|
||||
// use a special font for our name buttons
|
||||
_nameFont = new Font("Helvetica", Font.PLAIN, 10);
|
||||
|
||||
// keep track of the query that we'll use to populate our entries
|
||||
// display
|
||||
_catid = categoryid;
|
||||
|
||||
// listen to ancestor events
|
||||
addAncestorListener(this);
|
||||
}
|
||||
@@ -90,13 +85,16 @@ public class EntryList
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the entries from the database.
|
||||
* Reads the entries from the database. This will be called on a
|
||||
* separate thread and should be prepared to be called repeatedly
|
||||
* without undue overhead. When the user browses into a song and back
|
||||
* up again, this method is called to repopulate the entries.
|
||||
*/
|
||||
public Entry[] readEntries ()
|
||||
throws PersistenceException
|
||||
{
|
||||
return Chooser.model.getEntries(_catid);
|
||||
}
|
||||
public abstract Entry[] readEntries ()
|
||||
throws PersistenceException;
|
||||
|
||||
/** The string to display when there are no matching results. */
|
||||
protected abstract String getEmptyString ();
|
||||
|
||||
/**
|
||||
* Reads the entries from the database.
|
||||
@@ -190,7 +188,7 @@ public class EntryList
|
||||
|
||||
// if there were no entries, stick a label in to that effect
|
||||
if (_entries.length == 0) {
|
||||
_bpanel.add(new JLabel("No entries in this category."));
|
||||
_bpanel.add(new JLabel(getEmptyString()));
|
||||
}
|
||||
|
||||
// reset our scroll position so that we're displaying the top of
|
||||
@@ -205,6 +203,7 @@ public class EntryList
|
||||
|
||||
// we've removed and added components so we need to revalidate
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
protected void populateSong (Entry entry)
|
||||
@@ -356,7 +355,6 @@ public class EntryList
|
||||
protected JPanel _bpanel;
|
||||
protected JButton _upbut;
|
||||
|
||||
protected int _catid;
|
||||
protected Entry[] _entries;
|
||||
|
||||
protected Entry _entry;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// $Id: QueryEntryList.java,v 1.1 2002/02/22 07:06:33 mdb Exp $
|
||||
|
||||
package robodj.chooser;
|
||||
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
import robodj.repository.Entry;
|
||||
|
||||
public class QueryEntryList extends EntryList
|
||||
{
|
||||
/**
|
||||
* Constructs an entry list to display entries that match a query.
|
||||
*/
|
||||
public QueryEntryList (String query)
|
||||
{
|
||||
_query = query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads in the entries for this query.
|
||||
*/
|
||||
public Entry[] readEntries ()
|
||||
throws PersistenceException
|
||||
{
|
||||
if (_entries == null) {
|
||||
_entries = Chooser.repository.matchEntries(_query);
|
||||
}
|
||||
return _entries;
|
||||
}
|
||||
|
||||
protected String getEmptyString ()
|
||||
{
|
||||
return "No matches to your query.";
|
||||
}
|
||||
|
||||
/** The query with which we're looking up entries. */
|
||||
protected String _query;
|
||||
|
||||
/** A cached copy of our query results. */
|
||||
protected Entry[] _entries;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// $Id: SearchPanel.java,v 1.1 2002/02/22 07:06:33 mdb Exp $
|
||||
|
||||
package robodj.chooser;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.*;
|
||||
|
||||
import com.samskivert.swing.*;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import robodj.repository.*;
|
||||
|
||||
public class SearchPanel extends JPanel
|
||||
implements ActionListener
|
||||
{
|
||||
public SearchPanel ()
|
||||
{
|
||||
GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH);
|
||||
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||
gl.setJustification(GroupLayout.TOP);
|
||||
setLayout(gl);
|
||||
|
||||
add(new JLabel("Enter a word to be matched against the " +
|
||||
"artists, titles and songs:"), GroupLayout.FIXED);
|
||||
|
||||
gl = new HGroupLayout(GroupLayout.STRETCH);
|
||||
JPanel qpanel = new JPanel(gl);
|
||||
_qbox = new JTextField();
|
||||
_qbox.addActionListener(this);
|
||||
_qbox.setActionCommand("query");
|
||||
qpanel.add(_qbox);
|
||||
|
||||
JButton qbutton = new JButton("Query");
|
||||
qbutton.addActionListener(this);
|
||||
qbutton.setActionCommand("query");
|
||||
qpanel.add(qbutton, GroupLayout.FIXED);
|
||||
add(qpanel, GroupLayout.FIXED);
|
||||
}
|
||||
|
||||
public void actionPerformed (ActionEvent e)
|
||||
{
|
||||
if (e.getActionCommand().equals("query")) {
|
||||
String text = _qbox.getText();
|
||||
if (StringUtil.blank(text) || text.equals(_query)) {
|
||||
// ignore empty text or repeat queries
|
||||
return;
|
||||
}
|
||||
|
||||
// make a note of the query
|
||||
_query = text;
|
||||
|
||||
// remove any previous query results
|
||||
if (_qlist != null) {
|
||||
remove(_qlist);
|
||||
_qlist = null;
|
||||
}
|
||||
|
||||
// create and add a query entry list for the query
|
||||
_qlist = new QueryEntryList(_query);
|
||||
add(_qlist);
|
||||
}
|
||||
}
|
||||
|
||||
/** The most recent query. */
|
||||
protected String _query;
|
||||
|
||||
/** The query text box. */
|
||||
protected JTextField _qbox;
|
||||
|
||||
/** The entry list that displays the results of our query. */
|
||||
protected QueryEntryList _qlist;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: Entry.java,v 1.3 2001/07/13 00:10:26 mdb Exp $
|
||||
// $Id: Entry.java,v 1.4 2002/02/22 07:06:33 mdb Exp $
|
||||
|
||||
package robodj.repository;
|
||||
|
||||
@@ -33,6 +33,18 @@ public class Entry
|
||||
/** The songs associated with this entry. */
|
||||
public transient Song[] songs;
|
||||
|
||||
/**
|
||||
* Entry equality is based on entry id.
|
||||
*/
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
if (other instanceof Entry) {
|
||||
return entryid == ((Entry)other).entryid;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the songs array for the song with the specified id and
|
||||
* returns it if found. Returns null otherwise.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
//
|
||||
// $Id: Repository.java,v 1.8 2001/09/21 03:09:01 mdb Exp $
|
||||
// $Id: Repository.java,v 1.9 2002/02/22 07:06:34 mdb Exp $
|
||||
|
||||
package robodj.repository;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
@@ -99,10 +100,10 @@ public class Repository extends JORARepository
|
||||
* @param query a WHERE clause describing which entries should be
|
||||
* selected (ie. 'where title like "%foo%"').
|
||||
*
|
||||
* @return all entries in the table matching the query
|
||||
* parameters. <em>Note</em>: this member function does not populate
|
||||
* the songs arrays of the returned entries. Call
|
||||
* <code>populateSongs</code> on an entry by entry basis for that.
|
||||
* @return all entries in the table matching the query parameters.
|
||||
* <em>Note</em>: this member function does not populate the songs
|
||||
* arrays of the returned entries. Call <code>populateSongs</code> on
|
||||
* an entry by entry basis for that.
|
||||
*/
|
||||
public Entry[] getEntries (final String query)
|
||||
throws PersistenceException
|
||||
@@ -124,6 +125,84 @@ public class Repository extends JORARepository
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all entries for whom the supplied word is contained in the
|
||||
* title or artist text or in the text of any of that entry's songs.
|
||||
*
|
||||
* @param match a string to be case-insensitively matched in the title
|
||||
* or artist text.
|
||||
*
|
||||
* @return all entries in the table matching the query parameters.
|
||||
* <em>Note</em>: this member function does not populate the songs
|
||||
* arrays of the returned entries. Call <code>populateSongs</code> on
|
||||
* an entry by entry basis for that.
|
||||
*/
|
||||
public Entry[] matchEntries (final String match)
|
||||
throws PersistenceException
|
||||
{
|
||||
return (Entry[])execute(new Operation() {
|
||||
public Object invoke (Connection conn, DatabaseLiaison liaison)
|
||||
throws PersistenceException, SQLException
|
||||
{
|
||||
System.out.println("looking up '" + match + "'.");
|
||||
|
||||
PreparedStatement stmt = null;
|
||||
String query;
|
||||
|
||||
try {
|
||||
// look up matching entries
|
||||
query = "select entryid, title, artist, source " +
|
||||
"from entries where title like ? or artist like ?";
|
||||
stmt = conn.prepareStatement(query);
|
||||
stmt.setString(1, "%" + match + "%");
|
||||
stmt.setString(2, "%" + match + "%");
|
||||
|
||||
HashIntMap etable = new HashIntMap();
|
||||
loadEntries(stmt, etable);
|
||||
JDBCUtil.close(stmt);
|
||||
|
||||
// now look up matching songs
|
||||
query = "select entries.entryid, entries.title, " +
|
||||
"entries.artist, entries.source from " +
|
||||
"songs, entries where " +
|
||||
"songs.entryid = entries.entryid and " +
|
||||
"songs.title like ?";
|
||||
stmt = conn.prepareStatement(query);
|
||||
stmt.setString(1, "%" + match + "%");
|
||||
loadEntries(stmt, etable);
|
||||
|
||||
Entry[] entries = new Entry[etable.size()];
|
||||
Iterator iter = etable.values().iterator();
|
||||
for (int i = 0; iter.hasNext(); i++) {
|
||||
entries[i] = (Entry)iter.next();
|
||||
}
|
||||
return entries;
|
||||
|
||||
} finally {
|
||||
JDBCUtil.close(stmt);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads entries from the supplied query and inserts them into the
|
||||
* supplied hash map.
|
||||
*/
|
||||
protected void loadEntries (PreparedStatement stmt, HashIntMap entries)
|
||||
throws SQLException
|
||||
{
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
Entry entry = new Entry();
|
||||
entry.entryid = rs.getInt(1);
|
||||
entry.title = rs.getString(2);
|
||||
entry.artist = rs.getString(3);
|
||||
entry.source = rs.getString(4);
|
||||
entries.put(entry.entryid, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the songs for this entry from the database and inserts them
|
||||
* into its songs array. If the songs are already loaded, this
|
||||
|
||||
Reference in New Issue
Block a user