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;
|
package robodj.chooser;
|
||||||
|
|
||||||
// import java.awt.*;
|
|
||||||
// import java.awt.event.ActionEvent;
|
|
||||||
// import java.awt.event.ActionListener;
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
// import com.samskivert.swing.*;
|
|
||||||
import robodj.repository.*;
|
import robodj.repository.*;
|
||||||
|
|
||||||
public class BrowsePanel extends JTabbedPane
|
public class BrowsePanel extends JTabbedPane
|
||||||
@@ -20,13 +16,13 @@ public class BrowsePanel extends JTabbedPane
|
|||||||
|
|
||||||
// create a tab for each category
|
// create a tab for each category
|
||||||
for (int i = 0; i < cats.length; i++) {
|
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.";
|
String tip = "Browse entries in '" + cats[i].name + "' category.";
|
||||||
addTab(cats[i].name, null, elist, tip);
|
addTab(cats[i].name, null, elist, tip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// and add one for uncategorized entries
|
// and add one for uncategorized entries
|
||||||
elist = new EntryList(-1);
|
elist = new CategoryEntryList(-1);
|
||||||
addTab("Uncategorized", null, elist,
|
addTab("Uncategorized", null, elist,
|
||||||
"Browse uncategorized entries.");
|
"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;
|
package robodj.chooser;
|
||||||
|
|
||||||
@@ -40,6 +40,10 @@ public class ChooserFrame
|
|||||||
BrowsePanel bpanel = new BrowsePanel();
|
BrowsePanel bpanel = new BrowsePanel();
|
||||||
tip = "Browse and select tunes to play.";
|
tip = "Browse and select tunes to play.";
|
||||||
tpane.addTab("Browse", null, bpanel, tip);
|
tpane.addTab("Browse", null, bpanel, tip);
|
||||||
|
|
||||||
|
SearchPanel spanel = new SearchPanel();
|
||||||
|
tip = "Search titles and artists.";
|
||||||
|
tpane.addTab("Search", null, spanel, tip);
|
||||||
top.add(tpane);
|
top.add(tpane);
|
||||||
|
|
||||||
// the bottom is the control bar
|
// 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;
|
package robodj.chooser;
|
||||||
|
|
||||||
@@ -17,11 +17,10 @@ import com.samskivert.swing.util.*;
|
|||||||
import robodj.Log;
|
import robodj.Log;
|
||||||
import robodj.repository.*;
|
import robodj.repository.*;
|
||||||
|
|
||||||
public class EntryList
|
public abstract class EntryList extends JPanel
|
||||||
extends JPanel
|
|
||||||
implements TaskObserver, ActionListener, AncestorListener
|
implements TaskObserver, ActionListener, AncestorListener
|
||||||
{
|
{
|
||||||
public EntryList (int categoryid)
|
public EntryList ()
|
||||||
{
|
{
|
||||||
GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH);
|
GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH);
|
||||||
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||||
@@ -48,10 +47,6 @@ public class EntryList
|
|||||||
// use a special font for our name buttons
|
// use a special font for our name buttons
|
||||||
_nameFont = new Font("Helvetica", Font.PLAIN, 10);
|
_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
|
// listen to ancestor events
|
||||||
addAncestorListener(this);
|
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 ()
|
public abstract Entry[] readEntries ()
|
||||||
throws PersistenceException
|
throws PersistenceException;
|
||||||
{
|
|
||||||
return Chooser.model.getEntries(_catid);
|
/** The string to display when there are no matching results. */
|
||||||
}
|
protected abstract String getEmptyString ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the entries from the database.
|
* 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 there were no entries, stick a label in to that effect
|
||||||
if (_entries.length == 0) {
|
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
|
// 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
|
// we've removed and added components so we need to revalidate
|
||||||
revalidate();
|
revalidate();
|
||||||
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void populateSong (Entry entry)
|
protected void populateSong (Entry entry)
|
||||||
@@ -356,7 +355,6 @@ public class EntryList
|
|||||||
protected JPanel _bpanel;
|
protected JPanel _bpanel;
|
||||||
protected JButton _upbut;
|
protected JButton _upbut;
|
||||||
|
|
||||||
protected int _catid;
|
|
||||||
protected Entry[] _entries;
|
protected Entry[] _entries;
|
||||||
|
|
||||||
protected Entry _entry;
|
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;
|
package robodj.repository;
|
||||||
|
|
||||||
@@ -33,6 +33,18 @@ public class Entry
|
|||||||
/** The songs associated with this entry. */
|
/** The songs associated with this entry. */
|
||||||
public transient Song[] songs;
|
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
|
* Scans the songs array for the song with the specified id and
|
||||||
* returns it if found. Returns null otherwise.
|
* 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;
|
package robodj.repository;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
@@ -99,10 +100,10 @@ public class Repository extends JORARepository
|
|||||||
* @param query a WHERE clause describing which entries should be
|
* @param query a WHERE clause describing which entries should be
|
||||||
* selected (ie. 'where title like "%foo%"').
|
* selected (ie. 'where title like "%foo%"').
|
||||||
*
|
*
|
||||||
* @return all entries in the table matching the query
|
* @return all entries in the table matching the query parameters.
|
||||||
* parameters. <em>Note</em>: this member function does not populate
|
* <em>Note</em>: this member function does not populate the songs
|
||||||
* the songs arrays of the returned entries. Call
|
* arrays of the returned entries. Call <code>populateSongs</code> on
|
||||||
* <code>populateSongs</code> on an entry by entry basis for that.
|
* an entry by entry basis for that.
|
||||||
*/
|
*/
|
||||||
public Entry[] getEntries (final String query)
|
public Entry[] getEntries (final String query)
|
||||||
throws PersistenceException
|
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
|
* Loads the songs for this entry from the database and inserts them
|
||||||
* into its songs array. If the songs are already loaded, this
|
* into its songs array. If the songs are already loaded, this
|
||||||
|
|||||||
Reference in New Issue
Block a user