All sorts of good new stuff including category support.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@149 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: Chooser.java,v 1.1 2001/06/05 16:42:38 mdb Exp $
|
// $Id: Chooser.java,v 1.2 2001/06/07 08:37:47 mdb Exp $
|
||||||
|
|
||||||
package robodj.chooser;
|
package robodj.chooser;
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@ import java.util.Properties;
|
|||||||
import com.samskivert.util.PropertiesUtil;
|
import com.samskivert.util.PropertiesUtil;
|
||||||
|
|
||||||
import robodj.Log;
|
import robodj.Log;
|
||||||
|
import robodj.repository.Model;
|
||||||
import robodj.repository.Repository;
|
import robodj.repository.Repository;
|
||||||
import robodj.util.ServerControl;
|
import robodj.util.ServerControl;
|
||||||
|
|
||||||
@@ -25,6 +26,8 @@ public class Chooser
|
|||||||
|
|
||||||
public static Repository repository;
|
public static Repository repository;
|
||||||
|
|
||||||
|
public static Model model;
|
||||||
|
|
||||||
public static ServerControl scontrol;
|
public static ServerControl scontrol;
|
||||||
|
|
||||||
public static void main (String[] args)
|
public static void main (String[] args)
|
||||||
@@ -43,6 +46,8 @@ public class Chooser
|
|||||||
Properties dbprops =
|
Properties dbprops =
|
||||||
PropertiesUtil.getSubProperties(config, "repository.db");
|
PropertiesUtil.getSubProperties(config, "repository.db");
|
||||||
repository = new Repository(dbprops);
|
repository = new Repository(dbprops);
|
||||||
|
model = new Model(repository);
|
||||||
|
|
||||||
} catch (SQLException sqe) {
|
} catch (SQLException sqe) {
|
||||||
Log.warning("Unable to establish communication with music " +
|
Log.warning("Unable to establish communication with music " +
|
||||||
"database: " + sqe);
|
"database: " + sqe);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ChooserFrame.java,v 1.1 2001/06/05 16:42:38 mdb Exp $
|
// $Id: ChooserFrame.java,v 1.2 2001/06/07 08:37:47 mdb Exp $
|
||||||
|
|
||||||
package robodj.chooser;
|
package robodj.chooser;
|
||||||
|
|
||||||
@@ -9,6 +9,7 @@ import java.awt.event.ActionListener;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
import com.samskivert.swing.*;
|
import com.samskivert.swing.*;
|
||||||
|
import robodj.repository.*;
|
||||||
|
|
||||||
public class ChooserFrame
|
public class ChooserFrame
|
||||||
extends JFrame
|
extends JFrame
|
||||||
@@ -29,8 +30,21 @@ public class ChooserFrame
|
|||||||
|
|
||||||
// the top of the UI is the playlist manager section
|
// the top of the UI is the playlist manager section
|
||||||
JTabbedPane tpane = new JTabbedPane();
|
JTabbedPane tpane = new JTabbedPane();
|
||||||
Component elist = new EntryList();
|
EntryList elist;
|
||||||
tpane.addTab("Browse", null, elist, "Browse music database.");
|
Category[] cats = Chooser.model.getCategories();
|
||||||
|
|
||||||
|
// create a tab for each category
|
||||||
|
for (int i = 0; i < cats.length; i++) {
|
||||||
|
elist = new EntryList(cats[i].categoryid);
|
||||||
|
String tip = "Browse entries in '" + cats[i].name + "' category.";
|
||||||
|
tpane.addTab(cats[i].name, null, elist, tip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// and add one for uncategorized entries
|
||||||
|
elist = new EntryList(-1);
|
||||||
|
tpane.addTab("Uncategorized", null, elist,
|
||||||
|
"Browse uncategorized entries.");
|
||||||
|
|
||||||
tpane.setSelectedIndex(0);
|
tpane.setSelectedIndex(0);
|
||||||
top.add(tpane);
|
top.add(tpane);
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
//
|
//
|
||||||
// $Id: EntryList.java,v 1.1 2001/06/05 16:42:38 mdb Exp $
|
// $Id: EntryList.java,v 1.2 2001/06/07 08:37:47 mdb Exp $
|
||||||
|
|
||||||
package robodj.chooser;
|
package robodj.chooser;
|
||||||
|
|
||||||
|
import java.awt.Font;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
|
||||||
import com.samskivert.swing.*;
|
import com.samskivert.swing.*;
|
||||||
import com.samskivert.swing.util.*;
|
import com.samskivert.swing.util.*;
|
||||||
@@ -17,9 +19,9 @@ import robodj.repository.*;
|
|||||||
|
|
||||||
public class EntryList
|
public class EntryList
|
||||||
extends JPanel
|
extends JPanel
|
||||||
implements TaskObserver, ActionListener
|
implements TaskObserver, ActionListener, AncestorListener
|
||||||
{
|
{
|
||||||
public EntryList ()
|
public EntryList (int categoryid)
|
||||||
{
|
{
|
||||||
GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH);
|
GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH);
|
||||||
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||||
@@ -27,7 +29,7 @@ public class EntryList
|
|||||||
|
|
||||||
// create the pane that will hold the buttons
|
// create the pane that will hold the buttons
|
||||||
gl = new VGroupLayout(GroupLayout.NONE);
|
gl = new VGroupLayout(GroupLayout.NONE);
|
||||||
gl.setOffAxisPolicy(GroupLayout.EQUALIZE);
|
gl.setJustification(GroupLayout.TOP);
|
||||||
_bpanel = new JPanel(gl);
|
_bpanel = new JPanel(gl);
|
||||||
|
|
||||||
// give ourselves a wee bit of a border
|
// give ourselves a wee bit of a border
|
||||||
@@ -43,8 +45,15 @@ public class EntryList
|
|||||||
_upbut.addActionListener(this);
|
_upbut.addActionListener(this);
|
||||||
add(_upbut, GroupLayout.FIXED);
|
add(_upbut, GroupLayout.FIXED);
|
||||||
|
|
||||||
// start up the task that reads the CD info from the database
|
// use a special font for our name buttons
|
||||||
TaskMaster.invokeMethodTask("readEntries", this, this);
|
_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void taskCompleted (String name, Object result)
|
public void taskCompleted (String name, Object result)
|
||||||
@@ -84,7 +93,7 @@ public class EntryList
|
|||||||
public Entry[] readEntries ()
|
public Entry[] readEntries ()
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
return Chooser.repository.getEntries("");
|
return Chooser.model.getEntries(_catid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,6 +114,15 @@ public class EntryList
|
|||||||
Chooser.repository.populateSongs(_entry);
|
Chooser.repository.populateSongs(_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the category for the displayed entry.
|
||||||
|
*/
|
||||||
|
public void recategorizeEntry ()
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
Chooser.model.recategorize(_entry, _newcatid);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the proper buttons, etc. for each entry.
|
* Creates the proper buttons, etc. for each entry.
|
||||||
*/
|
*/
|
||||||
@@ -116,6 +134,11 @@ public class EntryList
|
|||||||
// clear out any existing children
|
// clear out any existing children
|
||||||
_bpanel.removeAll();
|
_bpanel.removeAll();
|
||||||
|
|
||||||
|
// adjust our layout policy
|
||||||
|
GroupLayout gl = (GroupLayout)_bpanel.getLayout();
|
||||||
|
gl.setOffAxisPolicy(GroupLayout.EQUALIZE);
|
||||||
|
gl.setOffAxisJustification(GroupLayout.LEFT);
|
||||||
|
|
||||||
// sort our entries
|
// sort our entries
|
||||||
Comparator ecomp = new Comparator() {
|
Comparator ecomp = new Comparator() {
|
||||||
public int compare (Object o1, Object o2) {
|
public int compare (Object o1, Object o2) {
|
||||||
@@ -140,12 +163,18 @@ public class EntryList
|
|||||||
|
|
||||||
// create a browse and a play button
|
// create a browse and a play button
|
||||||
JPanel hpanel = new JPanel();
|
JPanel hpanel = new JPanel();
|
||||||
GroupLayout gl = new HGroupLayout(GroupLayout.NONE);
|
gl = new HGroupLayout(GroupLayout.NONE);
|
||||||
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
gl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||||
gl.setJustification(GroupLayout.LEFT);
|
gl.setJustification(GroupLayout.LEFT);
|
||||||
hpanel.setLayout(gl);
|
hpanel.setLayout(gl);
|
||||||
|
|
||||||
JButton button;
|
JButton button;
|
||||||
|
button = new JButton(entries[i].title);
|
||||||
|
button.setFont(_nameFont);
|
||||||
|
button.setActionCommand("browse");
|
||||||
|
button.addActionListener(this);
|
||||||
|
button.putClientProperty("entry", entries[i]);
|
||||||
|
hpanel.add(button);
|
||||||
|
|
||||||
button = new JButton("Play");
|
button = new JButton("Play");
|
||||||
button.setActionCommand("playall");
|
button.setActionCommand("playall");
|
||||||
@@ -153,14 +182,13 @@ public class EntryList
|
|||||||
button.putClientProperty("entry", entries[i]);
|
button.putClientProperty("entry", entries[i]);
|
||||||
hpanel.add(button);
|
hpanel.add(button);
|
||||||
|
|
||||||
button = new JButton(entries[i].title);
|
|
||||||
button.setActionCommand("browse");
|
|
||||||
button.addActionListener(this);
|
|
||||||
button.putClientProperty("entry", entries[i]);
|
|
||||||
hpanel.add(button);
|
|
||||||
|
|
||||||
_bpanel.add(hpanel);
|
_bpanel.add(hpanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void populateSong (Entry entry)
|
protected void populateSong (Entry entry)
|
||||||
@@ -171,6 +199,20 @@ public class EntryList
|
|||||||
// clear out any existing children
|
// clear out any existing children
|
||||||
_bpanel.removeAll();
|
_bpanel.removeAll();
|
||||||
|
|
||||||
|
// adjust our layout policy
|
||||||
|
((GroupLayout)_bpanel.getLayout()).setOffAxisPolicy(
|
||||||
|
GroupLayout.NONE);
|
||||||
|
|
||||||
|
// create a combo box for the categories
|
||||||
|
JComboBox catcombo =
|
||||||
|
new JComboBox(ModelUtil.catBoxNames(Chooser.model));
|
||||||
|
catcombo.addActionListener(this);
|
||||||
|
catcombo.setActionCommand("categorize");
|
||||||
|
int catid = Chooser.model.getCategory(entry.entryid);
|
||||||
|
int catidx = ModelUtil.getCategoryIndex(Chooser.model, catid);
|
||||||
|
catcombo.setSelectedIndex(catidx+1);
|
||||||
|
_bpanel.add(catcombo);
|
||||||
|
|
||||||
// add a label for the title
|
// add a label for the title
|
||||||
JLabel label = new JLabel(entry.title);
|
JLabel label = new JLabel(entry.title);
|
||||||
_bpanel.add(label);
|
_bpanel.add(label);
|
||||||
@@ -190,8 +232,10 @@ public class EntryList
|
|||||||
// and add buttons for every song
|
// and add buttons for every song
|
||||||
for (int i = 0; i < entry.songs.length; i++) {
|
for (int i = 0; i < entry.songs.length; i++) {
|
||||||
JButton button = new JButton(entry.songs[i].title);
|
JButton button = new JButton(entry.songs[i].title);
|
||||||
|
button.setFont(_nameFont);
|
||||||
button.setActionCommand("play");
|
button.setActionCommand("play");
|
||||||
button.addActionListener(this);
|
button.addActionListener(this);
|
||||||
|
button.setHorizontalAlignment(JButton.LEFT);
|
||||||
button.putClientProperty("song", entry.songs[i]);
|
button.putClientProperty("song", entry.songs[i]);
|
||||||
_bpanel.add(button);
|
_bpanel.add(button);
|
||||||
}
|
}
|
||||||
@@ -218,16 +262,51 @@ public class EntryList
|
|||||||
Chooser.scontrol.append(song.location);
|
Chooser.scontrol.append(song.location);
|
||||||
|
|
||||||
} else if (cmd.equals("up")) {
|
} else if (cmd.equals("up")) {
|
||||||
populateEntries(_entries);
|
// re-read the category beacuse this entry may have been
|
||||||
|
// recategorized
|
||||||
|
TaskMaster.invokeMethodTask("readEntries", this, this);
|
||||||
|
|
||||||
|
} else if (cmd.equals("categorize")) {
|
||||||
|
JComboBox cb = (JComboBox)e.getSource();
|
||||||
|
String catname = (String)cb.getSelectedItem();
|
||||||
|
_newcatid = Chooser.model.getCategoryId(catname);
|
||||||
|
// do the recategorization in a separate task
|
||||||
|
TaskMaster.invokeMethodTask("recategorizeEntry", this, this);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Unknown action event: " + cmd);
|
System.out.println("Unknown action event: " + cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ancestorAdded (AncestorEvent e)
|
||||||
|
{
|
||||||
|
// stick a "loading" label in the list to let the user know
|
||||||
|
// what's up
|
||||||
|
_bpanel.add(new JLabel("Loading..."));
|
||||||
|
|
||||||
|
// start up the task that reads the CD info from the database
|
||||||
|
TaskMaster.invokeMethodTask("readEntries", this, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ancestorRemoved (AncestorEvent e)
|
||||||
|
{
|
||||||
|
// clear out our entry ui elements
|
||||||
|
_bpanel.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ancestorMoved (AncestorEvent e)
|
||||||
|
{
|
||||||
|
// nothing doing
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
protected int _newcatid;
|
||||||
|
|
||||||
|
protected Font _nameFont;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: FinishedPanel.java,v 1.1 2001/03/21 00:41:03 mdb Exp $
|
// $Id: FinishedPanel.java,v 1.2 2001/06/07 08:37:47 mdb Exp $
|
||||||
|
|
||||||
package robodj.importer;
|
package robodj.importer;
|
||||||
|
|
||||||
@@ -54,6 +54,7 @@ public class FinishedPanel
|
|||||||
|
|
||||||
public void wasAddedToFrame (ImporterFrame frame)
|
public void wasAddedToFrame (ImporterFrame frame)
|
||||||
{
|
{
|
||||||
|
frame.addControlButton("Another", "import", this);
|
||||||
frame.addControlButton("Exit", "exit", this);
|
frame.addControlButton("Exit", "exit", this);
|
||||||
|
|
||||||
// keep a handle on this for later
|
// keep a handle on this for later
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: Entry.java,v 1.1 2000/11/08 06:42:57 mdb Exp $
|
// $Id: Entry.java,v 1.2 2001/06/07 08:37:47 mdb Exp $
|
||||||
|
|
||||||
package robodj.repository;
|
package robodj.repository;
|
||||||
|
|
||||||
@@ -20,8 +20,8 @@ public class Entry
|
|||||||
public String title;
|
public String title;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The artist that created the music for this entry or "Various" if it
|
* The artist that created the music for this entry or "Various
|
||||||
* is not a single-artist work.
|
* Artists" if it is not a single-artist work.
|
||||||
*/
|
*/
|
||||||
public String artist;
|
public String artist;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,235 @@
|
|||||||
|
//
|
||||||
|
// $Id: Model.java,v 1.1 2001/06/07 08:37:47 mdb Exp $
|
||||||
|
|
||||||
|
package robodj.repository;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
import com.samskivert.util.IntMap;
|
||||||
|
import com.samskivert.util.IntIntMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model provides an interface to the contents of the repository which
|
||||||
|
* efficiently accesses the database, caches information and preserves a
|
||||||
|
* consistent view of the repository in light of modifications made by the
|
||||||
|
* user (through the model). It is structured so that the client can
|
||||||
|
* maintain no in-memory state and instead fetch content via the model
|
||||||
|
* every time it needs to make use of it.
|
||||||
|
*/
|
||||||
|
public class Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructs a new model instance from the supplied repository.
|
||||||
|
*/
|
||||||
|
public Model (Repository rep)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
_rep = rep;
|
||||||
|
|
||||||
|
// load up our category information
|
||||||
|
_cats = _rep.getCategories();
|
||||||
|
|
||||||
|
// sort them into alphabetical order
|
||||||
|
Arrays.sort(_cats, new Comparator() {
|
||||||
|
public int compare (Object o1, Object o2)
|
||||||
|
{
|
||||||
|
return ((Category)o1).name.compareTo(((Category)o2).name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals (Object other)
|
||||||
|
{
|
||||||
|
return other == this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the categories.
|
||||||
|
*/
|
||||||
|
public Category[] getCategories ()
|
||||||
|
{
|
||||||
|
return _cats;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up the category id of the category with the specified name.
|
||||||
|
*
|
||||||
|
* @return category id of the matching category or -1 if no category
|
||||||
|
* matched.
|
||||||
|
*/
|
||||||
|
public int getCategoryId (String catname)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _cats.length; i++) {
|
||||||
|
if (_cats[i].name.equals(catname)) {
|
||||||
|
return _cats[i].categoryid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a reference to the specified entry id. This call blocks
|
||||||
|
* if database access takes place.
|
||||||
|
*/
|
||||||
|
public Entry getEntry (int entryid)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
Entry entry = (Entry)_entries.get(entryid);
|
||||||
|
if (entry == null) {
|
||||||
|
_entries.put(entryid, entry = _rep.getEntry(entryid));
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array containing of the entries in the specified
|
||||||
|
* category. This call blocks if database access takes place.
|
||||||
|
*/
|
||||||
|
public Entry[] getEntries (int categoryid)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
ArrayList catlist = getCatList(categoryid);
|
||||||
|
Entry[] ents = new Entry[catlist.size()];
|
||||||
|
catlist.toArray(ents);
|
||||||
|
return ents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associates the specified entry with the specified category. An
|
||||||
|
* entry can be mapped into multiple categories.
|
||||||
|
*/
|
||||||
|
public void associateEntry (Entry entry, int categoryid)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
// keep our category mapping up to date
|
||||||
|
ArrayList catlist = getCatList(categoryid);
|
||||||
|
// if the entry's not already in the list, stick it in
|
||||||
|
if (!catlist.contains(entry)) {
|
||||||
|
catlist.add(entry);
|
||||||
|
// update the entry to category map
|
||||||
|
_entmap.put(entry.entryid, categoryid);
|
||||||
|
// and update the database
|
||||||
|
_rep.associateEntry(entry, categoryid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disassociates the specified entry from the specified category.
|
||||||
|
*/
|
||||||
|
public void disassociateEntry (Entry entry, int categoryid)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
// keep our category mapping up to date
|
||||||
|
ArrayList catlist = getCatList(categoryid);
|
||||||
|
// if the entry's already in the list, take it out
|
||||||
|
if (catlist.contains(entry)) {
|
||||||
|
catlist.remove(entry);
|
||||||
|
// update the entry to category map
|
||||||
|
_entmap.remove(entry.entryid);
|
||||||
|
// and update the database
|
||||||
|
_rep.disassociateEntry(entry, categoryid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the category to which this entry is mapped or -1 if it's
|
||||||
|
* mapped to no category.
|
||||||
|
*/
|
||||||
|
public int getCategory (int entryid)
|
||||||
|
{
|
||||||
|
return _entmap.get(entryid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the entry from whatever category it is currently occupying
|
||||||
|
* and adds it to the specified category. If the entry is already in
|
||||||
|
* the specified category, this function does nothing. This is
|
||||||
|
* temporary until we fully implement multi-category support.
|
||||||
|
*/
|
||||||
|
public void recategorize (Entry entry, int categoryid)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
// see if we need to change categories
|
||||||
|
int curcatid = _entmap.get(entry.entryid);
|
||||||
|
if (curcatid != categoryid) {
|
||||||
|
disassociateEntry(entry, curcatid);
|
||||||
|
associateEntry(entry, categoryid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that the entry's songs array is populated. This call blocks
|
||||||
|
* if database access takes place.
|
||||||
|
*/
|
||||||
|
public void populateSongs (Entry entry)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
_rep.populateSongs(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayList getCatList (int categoryid)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
ArrayList catlist = (ArrayList)_catmap.get(categoryid);
|
||||||
|
|
||||||
|
if (catlist == null) {
|
||||||
|
// create a new category list and stick it into the table
|
||||||
|
catlist = new ArrayList();
|
||||||
|
_catmap.put(categoryid, catlist);
|
||||||
|
|
||||||
|
// figure out which entries are in this category
|
||||||
|
int[] entids = _rep.getEntryIds(categoryid);
|
||||||
|
|
||||||
|
// create a select string with the eids that aren't already
|
||||||
|
// loaded
|
||||||
|
StringBuffer query = new StringBuffer();
|
||||||
|
for (int i = 0; i < entids.length; i++) {
|
||||||
|
// make sure the entry to category id mapping table
|
||||||
|
// contains this information
|
||||||
|
_entmap.put(entids[i], categoryid);
|
||||||
|
|
||||||
|
// see if we've cached the entry
|
||||||
|
Entry entry = (Entry)_entries.get(entids[i]);
|
||||||
|
if (entry != null) {
|
||||||
|
// if we have already loaded this entry, stick it into
|
||||||
|
// the category list
|
||||||
|
catlist.add(entry);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// otherwise, append it to the query to be loaded
|
||||||
|
if (query.length() > 0) {
|
||||||
|
query.append(", ");
|
||||||
|
}
|
||||||
|
query.append(entids[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load up these entries if we have any to load
|
||||||
|
if (query.length() > 0) {
|
||||||
|
query.insert(0, "where entryid in (");
|
||||||
|
query.append(")");
|
||||||
|
|
||||||
|
// now load up these entries
|
||||||
|
Entry[] ents = _rep.getEntries(query.toString());
|
||||||
|
for (int i = 0; i < ents.length; i++) {
|
||||||
|
// cache 'em
|
||||||
|
_entries.put(ents[i].entryid, ents[i]);
|
||||||
|
// and stick 'em in the category list
|
||||||
|
catlist.add(ents[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return catlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Repository _rep;
|
||||||
|
protected Category[] _cats;
|
||||||
|
|
||||||
|
protected IntMap _entries = new IntMap();
|
||||||
|
protected IntMap _catmap = new IntMap();
|
||||||
|
protected IntIntMap _entmap = new IntIntMap();
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// $Id: ModelUtil.java,v 1.1 2001/06/07 08:37:47 mdb Exp $
|
||||||
|
|
||||||
|
package robodj.chooser;
|
||||||
|
|
||||||
|
import robodj.repository.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some utility functions.
|
||||||
|
*/
|
||||||
|
public class ModelUtil
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Generates a string array suitable for sticking into a combo box
|
||||||
|
* with the category names.
|
||||||
|
*/
|
||||||
|
public static String[] catBoxNames (Model model)
|
||||||
|
{
|
||||||
|
Category[] cats = model.getCategories();
|
||||||
|
String[] names = new String[cats.length+1];
|
||||||
|
names[0] = "<uncategorized>";
|
||||||
|
for (int i = 0; i < cats.length; i++) {
|
||||||
|
names[i+1] = cats[i].name;
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the specified category in the category array.
|
||||||
|
* Useful for activating a particular category in a combo box, for
|
||||||
|
* example. -1 is returned if no category with the specified id exists
|
||||||
|
* in the category list (but if that's the case, something really
|
||||||
|
* wacky is going on).
|
||||||
|
*/
|
||||||
|
public static int getCategoryIndex (Model model, int categoryid)
|
||||||
|
{
|
||||||
|
Category[] cats = model.getCategories();
|
||||||
|
for (int i = 0; i < cats.length; i++) {
|
||||||
|
if (cats[i].categoryid == categoryid) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
//
|
//
|
||||||
// $Id: Repository.java,v 1.4 2001/06/02 02:22:55 mdb Exp $
|
// $Id: Repository.java,v 1.5 2001/06/07 08:37:47 mdb Exp $
|
||||||
|
|
||||||
package robodj.repository;
|
package robodj.repository;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import com.samskivert.jdbc.MySQLRepository;
|
import com.samskivert.jdbc.MySQLRepository;
|
||||||
|
import com.samskivert.jdbc.JDBCUtil;
|
||||||
import com.samskivert.jdbc.jora.*;
|
import com.samskivert.jdbc.jora.*;
|
||||||
import com.samskivert.util.*;
|
import com.samskivert.util.*;
|
||||||
|
|
||||||
@@ -50,8 +52,8 @@ public class Repository extends MySQLRepository
|
|||||||
"entryid");
|
"entryid");
|
||||||
_stable = new Table(Song.class.getName(), "songs", _session,
|
_stable = new Table(Song.class.getName(), "songs", _session,
|
||||||
"songid");
|
"songid");
|
||||||
_ctable = new Table(Category.class.getName(), "categories", _session,
|
_ctable = new Table(Category.class.getName(), "category_names",
|
||||||
"categoryid");
|
_session, "categoryid");
|
||||||
_cmtable = new Table(CategoryMapping.class.getName(), "category_map",
|
_cmtable = new Table(CategoryMapping.class.getName(), "category_map",
|
||||||
_session, new String[] {"categoryid", "entryid"});
|
_session, new String[] {"categoryid", "entryid"});
|
||||||
}
|
}
|
||||||
@@ -98,7 +100,7 @@ public class Repository extends MySQLRepository
|
|||||||
public Entry[] getEntries (final String query)
|
public Entry[] getEntries (final String query)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
return (Entry[])execute(new Operation () {
|
return (Entry[])execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
// look up the entry
|
// look up the entry
|
||||||
@@ -123,7 +125,7 @@ public class Repository extends MySQLRepository
|
|||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
if (entry.songs == null) {
|
if (entry.songs == null) {
|
||||||
execute(new Operation () {
|
execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
// load up the songs for this entry
|
// load up the songs for this entry
|
||||||
@@ -149,7 +151,7 @@ public class Repository extends MySQLRepository
|
|||||||
public void insertEntry (final Entry entry)
|
public void insertEntry (final Entry entry)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
execute(new Operation () {
|
execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
// insert the entry into the entry table
|
// insert the entry into the entry table
|
||||||
@@ -187,7 +189,7 @@ public class Repository extends MySQLRepository
|
|||||||
public void updateEntry (final Entry entry)
|
public void updateEntry (final Entry entry)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
execute(new Operation () {
|
execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
// update the entry
|
// update the entry
|
||||||
@@ -211,7 +213,7 @@ public class Repository extends MySQLRepository
|
|||||||
public void deleteEntry (final Entry entry)
|
public void deleteEntry (final Entry entry)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
execute(new Operation () {
|
execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
// remove the entry from the entry table and the foreign
|
// remove the entry from the entry table and the foreign
|
||||||
@@ -238,7 +240,7 @@ public class Repository extends MySQLRepository
|
|||||||
public void addSongToEntry (final Entry entry, final Song song)
|
public void addSongToEntry (final Entry entry, final Song song)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
execute(new Operation () {
|
execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
// fill in the appropriate entry id value
|
// fill in the appropriate entry id value
|
||||||
@@ -261,7 +263,7 @@ public class Repository extends MySQLRepository
|
|||||||
public void updateSong (final Song song)
|
public void updateSong (final Song song)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
execute(new Operation () {
|
execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
_stable.update(song);
|
_stable.update(song);
|
||||||
@@ -277,7 +279,7 @@ public class Repository extends MySQLRepository
|
|||||||
public int createCategory (final String name)
|
public int createCategory (final String name)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
execute(new Operation () {
|
execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
Category cat = new Category();
|
Category cat = new Category();
|
||||||
@@ -297,7 +299,7 @@ public class Repository extends MySQLRepository
|
|||||||
public Category[] getCategories ()
|
public Category[] getCategories ()
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
return (Category[])execute(new Operation () {
|
return (Category[])execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
Cursor ccur = _ctable.select("");
|
Cursor ccur = _ctable.select("");
|
||||||
@@ -309,6 +311,64 @@ public class Repository extends MySQLRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches all of the entry ids that are associated with this category
|
||||||
|
* and returns them. If <code>categoryid</code> is -1, it instead
|
||||||
|
* returns all of the entry ids that are not in any category.
|
||||||
|
*/
|
||||||
|
public int[] getEntryIds (final int categoryid)
|
||||||
|
throws SQLException
|
||||||
|
{
|
||||||
|
return (int[])execute(new Operation() {
|
||||||
|
public Object invoke () throws SQLException
|
||||||
|
{
|
||||||
|
if (categoryid >= 0) {
|
||||||
|
String query = "where categoryid=" + categoryid;
|
||||||
|
Cursor cmcur = _cmtable.select(query);
|
||||||
|
List cmlist = cmcur.toArrayList();
|
||||||
|
int[] eids = new int[cmlist.size()];
|
||||||
|
for (int i = 0; i < cmlist.size(); i++) {
|
||||||
|
eids[i] = ((CategoryMapping)cmlist.get(i)).entryid;
|
||||||
|
}
|
||||||
|
return eids;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// i wish i knew how to do this sort of jockeying in
|
||||||
|
// SQL, but I can't be bothered to sort it out for a
|
||||||
|
// data set that isn't going to be so big that it
|
||||||
|
// can't be done in Java
|
||||||
|
IntMap ids = new IntMap();
|
||||||
|
Statement stmt = _session.connection.createStatement();
|
||||||
|
try {
|
||||||
|
// first add all the entryids in the repository
|
||||||
|
String query = "select entryid from entries";
|
||||||
|
ResultSet rs = stmt.executeQuery(query);
|
||||||
|
while (rs.next()) {
|
||||||
|
ids.put(rs.getInt(1), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// now remove those that are mapped to a category
|
||||||
|
query = "select entryid from category_map";
|
||||||
|
rs = stmt.executeQuery(query);
|
||||||
|
while (rs.next()) {
|
||||||
|
ids.remove(rs.getInt(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
JDBCUtil.close(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] eids = new int[ids.size()];
|
||||||
|
Enumeration keys = ids.keys();
|
||||||
|
for (int i = 0; keys.hasMoreElements(); i++) {
|
||||||
|
eids[i] = ((Integer)keys.nextElement()).intValue();
|
||||||
|
}
|
||||||
|
return eids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associates the specified entry with the specified category. An
|
* Associates the specified entry with the specified category. An
|
||||||
* entry can be mapped into multiple categories.
|
* entry can be mapped into multiple categories.
|
||||||
@@ -316,7 +376,7 @@ public class Repository extends MySQLRepository
|
|||||||
public void associateEntry (final Entry entry, final int categoryid)
|
public void associateEntry (final Entry entry, final int categoryid)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
execute(new Operation () {
|
execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
CategoryMapping map =
|
CategoryMapping map =
|
||||||
@@ -333,7 +393,7 @@ public class Repository extends MySQLRepository
|
|||||||
public void disassociateEntry (final Entry entry, final int categoryid)
|
public void disassociateEntry (final Entry entry, final int categoryid)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
execute(new Operation () {
|
execute(new Operation() {
|
||||||
public Object invoke () throws SQLException
|
public Object invoke () throws SQLException
|
||||||
{
|
{
|
||||||
CategoryMapping map =
|
CategoryMapping map =
|
||||||
|
|||||||
Reference in New Issue
Block a user